Pass data to helper app(for midi timing)?

  1. 5 weeks ago
    Edited 5 weeks ago

    I see this code in another post about methods to improve midi timing. I need an app for a specific role that can't be done with my other programs like Logic. The goal is the have a 2 track sequence plus a metronome player, so 3 tracks playing at once. Using thread1 for metronome and thread2 for playing back chords is not usable. After hours of reading everything I can find I see some examples using an external app to do some work which claims better timing. This example does not allow for testing my own midi notes. Question: Is there a way to pass a helper app an array(ie sequence(0)) as taking time to save an array( midi track), BPM, plus start time to disk would produce unwanted additional latency. Second: Can a helper app be stopped by the main app. In their example they just have the help app die when it's done.

    Ideally I want to send an array for midi playback, and give it a start time of currentTime + offset so that it gives the helper time to start and wait for a time ie 200ms in the future. Then the main app can allow recording midi on top of the other track and both be in sync against a known clock time. Likewise, send the helper app a start time, BPM, and have it play a metronome sound until the helper is told to quit. If there is no way to communicate from Main>helper to tell it to stop, and give it BPM, StartTime, anArray, then this wont work. Any suggestion welcome.

    Load this example in a windowless app, call the app from main via this method:

     
    Sub Thread1Run(Sender as Thread)
      dim s as new shell
      dim f as FolderItem = GetFolderItem("").child("notes.app")
      s.Execute("open "+f.ShellPath)
    End Sub

    (notes.app:)

     Noteplayer1 = New NotePlayer
      NotePlayer1.Instrument = 1
      // Notes for Do Re Mi Fa So La Ti Do
      // see http://en.wikipedia.org/wiki/Do-Re-Mi from The Sound of Music http://en.wikipedia.org/wiki/The_Sound_of_Music
      // (C, D, E, F, G, A, B, C)
      Dim doReMi(7) As Integer
      doReMi = Array(60, 62, 64, 65, 67, 69, 71, 60)
      For Each note As Integer In doReMi
        NotePlayer1.PlayNote(note, 100)
        // Pause to let note play
        App.SleepCurrentThread(500)
      Next
      quit
  2. Edited 5 weeks ago

    Copy array to clipboard ?

    What if a helper app was always running. Scanning the copy buffer for a play command, bpm, starttime, stop.

  3. So in testing using a separate app as a metronome using a thread for counting off 1000ms, there was significant improvement when going back to the main app and playing a piano track and launching the separate app with the metronome. I find that running 2 threads in the same app unusable for music. The main app copies "Play" into the clipboard. The helper is in a loop watching the clipboard. I don't notice any lag time from pressing the record or play button to the helper starting. It's not noticable the lag time from pressing play on the main app to getting the metronome started on the helper.

    Next I tried launching a metronome in the main app and the helper app. There is a slight flam( low milliseconds between the sounds). I think that by copying the current time + an offset and including that value in the clipboard will allow both the main and helper app to start more precisely on the clock by syncing on a future timestamp, I predict it will get rid of most the flam. After that I'll try launching an additional helper app and see how it works with one helper playing a metronome and another app playing chords, while the main app plays another instrument.

    This is the code in the separate helper app.

    Var c As New Clipboard
    Var s As String
    s = c.Text
    c.Close
    dim starttime as int64 
    dim t0 as int64
    dim t1 as int64
    StartTime  = microseconds / 1000
    t0 = microseconds / 1000
    dim BPM as integer = 60
    dim RecordLength as integer 
    NotePlayer1.Instrument = 116    '16385
    RecordLength = 0
    While RecordLength < 500   //Tick off metronome 10 times
      While s <>"Play"
        s = c.Text
        c.Close
      Wend
      While s = "Play"
        //NotePlayer1.Reverb = false
        NotePlayer1.PlayNote(60, 100)
        NotePlayer1.PlayNote(60, 0)
        RecordLength = RecordLength + 1
        t0 = 0    'clear from previous
        t1 = 0    'clear from previous
        t0 = (microseconds / 1000)
        Do until t1  >= (60 / BPM) * 1000
          t1 = (microseconds / 1000) - t0
        loop
        s = c.Text
        c.Close
      Wend
    Wend
  4. Sam R

    Oct 20 Pre-Release Testers, Xojo Pro, Third Party Store Hengchun, Pingtung, Taiwan

    Personally I would use shared memory for sharing the data; are you intending to ship on the Mac App Store?

  5. Edited 5 weeks ago

    I don’t know about shared memory. I’ll look into it. Thanks. I don’t know if Mac App Store is an option at this stage.

  6. 4 weeks ago

    Beatrix W

    Oct 20 Pre-Release Testers, Third Party Store Europe (Germany)

    Shared memory can easily be used with the MBS plugin. But you really only need that if you exchange a lot of data between main app and helper app. Otherwise, a simple communication with some type of json is much simpler.

  7. Douglas H

    Oct 20 Pre-Release Testers, Xojo Pro

    @Beatrix W Otherwise, a simple communication with some type of json is much simpler.

    Out of curiosity, what is your preferred "simple communication" for json? Using stdin/stdout? IPC? TCP sockets? Something like Aloe?

  8. Beatrix W

    Oct 21 Pre-Release Testers, Third Party Store Europe (Germany)

    Json over TCP. This is what I use: https://github.com/sworteu/JSONRPCSocket .

  9. Douglas H

    Oct 21 Pre-Release Testers, Xojo Pro

    Thanks. I'm always interested in alternative viewpoints. I've been using a combination of Aloe Express and Shared Memory where I felt that was appropriate. Aloe has worked out better for me than IPC, and easier than rolling everything myself. Most of the payloads have been JSON though (using POST), but not necessarily conforming to the JSON-RPC spec.

    The ReadMe for that GitHub project says in bold "NOT WORKING YET" but has no updates in about two years. You have found it to be stable though in the current commit?

  10. Beatrix W

    Oct 21 Pre-Release Testers, Third Party Store Europe (Germany)

    The "NOT WORKING YET" seems quite misleading. The code IS working and it's stable.

  11. Karen A

    Oct 21 Pre-Release Testers

    @Sam R Personally I would use shared memory for sharing the data;

    Can that be done with declared for both Mac and Windows? if so any understandable (by a non expert) references on how to set it up?

    Thanks,
    -karen

  12. Karen A

    Oct 21 Pre-Release Testers

    @Douglas H I've been using a combination of Aloe Express and Shared Memory where I felt that was appropriate.

    That is something i have been thinking about, but don't know anything about setting up and using shared memory... but it seems the most logical way to maximize throughput with helpers for a server with Xojo.

    - Karen

  13. Sam R

    Oct 21 Pre-Release Testers, Xojo Pro, Third Party Store Hengchun, Pingtung, Taiwan

    @Karen A Can that be done with declared for both Mac and Windows? if so any understandable (by a non expert) references on how to set it up?

    I have done it for macOS; but not Windows. I didn’t actually use it as I ended up writing an Objective-C plugin that uses GCD to do the processing. Aside from figuring out how to do what I wanted in Obj-C, multi-core programming is insanly simple with GCD. I would go as far as to say shockingly simple compared to the hoops we have to do to get helper apps working, and the performance gain is core-1 fold (8 core processor nets you a 7x factor). I’m only crunching numbers, so YMMV on what you’re doing.

    I’d like to see some GCD support in Xojo, and quite frankly I think it’s much needed in today’s age of throwing more and more cores into processors. I read that theres already 56 core processors available.

  14. Kevin G

    Oct 22 Pre-Release Testers, Xojo Pro Gatesheed, England

    @Sam R I’d like to see some GCD support in Xojo, and quite frankly I think it’s much needed in today’s age of throwing more and more cores into processors. I read that theres already 56 core processors available.

    I’m sure better support for concurrency would be welcomed by all. It is sad that in 2019 we are still stuck on one core when using Xojo even though more cores is clearly the future of CPUs. I imagine it would also help to solve IDE performance issues such as the woeful code editor performance which seems to be partly caused by the autocomplete code blocking the main thread.

  15. Douglas H

    Oct 22 Pre-Release Testers, Xojo Pro

    @Karen A That is something i have been thinking about, but don't know anything about setting up and using shared memory... but it seems the most logical way to maximize throughput with helpers for a server with Xojo.

    - Karen

    I use the MBS plugins

  16. Karen A

    Oct 22 Pre-Release Testers

    @Kevin G I’m sure better support for concurrency would be welcomed by all. It is sad that in 2019 we are still stuck on one core when using Xojo even though more cores is clearly the future of CPUs. I imagine it would also help to solve IDE performance issues such as the woeful code editor performance which seems to be partly caused by the autocomplete code blocking the main thread.

    i don't know if the engineers they have now have the right background for doing it, but I think providing good Xplatform support for using multiple cores, would have provided a much better ROI than API 2.0 or the Xojo framework.

    - Karen

  17. John M

    Oct 22 Pre-Release Testers, Xojo Pro New York / New Jersey

    @Beatrix W Shared memory can easily be used with the MBS plugin. But you really only need that if you exchange a lot of data between main app and helper app. Otherwise, a simple communication with some type of json is much simpler.

    I took a look at the MBS shared memory docs and their example, but I don't really understand how they work - is it possible to have more than one shared memory block? Or do you set up the data in the shared memory block that the helper app parses? And then how does the helper app return the result (or whatever) - by modifying the data in the shared memory block? And how does the parent app know when the helper app is done? By polling a location in the memory block?

    Ideally, I'd like to have as many as 3 or 4 helper apps processing data. Is there an example somewhere - or docs that explain better how to use this for sharing?

  18. Norman P

    Oct 22 Pre-Release Testers, Xojo Pro Outside

    @Kevin G I’m sure better support for concurrency would be welcomed by all. It is sad that in 2019 we are still stuck on one core when using Xojo even though more cores is clearly the future of CPUs. I imagine it would also help to solve IDE performance issues such as the woeful code editor performance which seems to be partly caused by the autocomplete code blocking the main thread.

    would more cores help - maybe - figuring how to segment it into multiple tasks would be the trick here
    a lot of it has to do with autocomplete just using a completely wrong method to do what its doing that doesnt match what the compiler would do

  19. Douglas H

    Oct 22 Pre-Release Testers, Xojo Pro

    Yes you can have as many shared memory blocks as you like. You just need to name them uniquely.

    I based my implementation by looking at the MBS examples included with the plugins. The basic code of which is also available at the example links near the bottom of the page here

    Note that with macOS, a named shared memory location will exist until reboot or you explicitly remove it, even if no app is holding a reference to it. I believe under Windows, that is not true. But I could remember that wrong -- for now I have only used it in macOS.

  20. Karen A

    Oct 22 Pre-Release Testers
    Edited 4 weeks ago

    @John M I took a look at the MBS shared memory docs and their example, but I don't really understand how they work - is it possible to have more than one shared memory block?

    Looking at the MBS docs I would say yes.

    Or do you set up the data in the shared memory block that the helper app parses?

    That depend on exactly what one is doing... It could work that way

    And then how does the helper app return the result (or whatever) - by modifying the data in the shared memory block?

    it could.

    And how does the parent app know when the helper app is done? By polling a location in the memory block?

    I would think sending messages through TCP sockets so you get a data available event message to know when the helper is done

    Ideally, I'd like to have as many as 3 or 4 helper apps processing data. Is there an example somewhere - or docs that explain better how to use this for sharing?

    I don't think so... logically at a high level what needs to be done is straight forward, but the devil is always in the details.

    -Karen

  21. Newer ›

or Sign Up to reply!