Multichannel audio in MaxForLive!


    this is an attempt to get multichannel m4l-devices in LIVE,
    for example to create m4l-instruments with more than 2 outputs.
    unlike plugsend~/plugreceive~,this approach sports relatively low,fixed latency.
    the minimum possible latency is the size of your audio buffer minus 64 samples.
    you get a 'live-pack' with 3 live-sets and 3 devices, more or less a construction kit.
    - '1 device sending to 4 buses' is an example where 1 m4l-device sends 8 channels of audio to 4 stereo 'buses'.
    - '4 buses send and receive' has 4 m4l-devices sending to 4 indepedent 'buses'.
    -'bufsend phase test' shows that receiving audio sent on the same 'bus' in different tracks is actually phase-accurate.
    the concept behind is a circular buffer that gets written to in the 'sender'
    and is read out in the 'receiver'.the 'receiver' gets synced once the 'sender' is activated,
    or the latency is adjusted.
    if you set the latency too low,all you get is trash.
    ...done with max7, but working with max6 as well.

    • Oct 26 2015 | 12:57 pm
      nice!
    • Oct 26 2015 | 1:06 pm
      Sounds interesting, but the file unzips to something I can't read or use (on OS X...) I made an attempt long ago with a rack sending to outputs independently and, that way I could move the sounds in space to up to 8 speakers, but it was a bit complicated, usually I prefer to work just in Max, Live is even not authorized anymore on my machine...;-)
    • Oct 26 2015 | 9:57 pm
      It's a .ALP - it installs into Live
    • Oct 26 2015 | 11:13 pm
      Beautiful!
    • Oct 28 2015 | 11:32 am
      Hi RBRT, thank you for posting. Unfortunately it only seems to work with 4 mono channels so far, because buffer~ has a limitation to 4 channels. I couldn't believe this at first, but it seems to be true. Maybe there is a workaround if you use the "replace" message with an 8 channel buffer. But I don't have any 2048 samples - 8 channel file to try. Does someone know, if there are plans to drop this limitation? A few months ago I worked out a bus system for M4L with a similar approach - with automatic latency compensation (I made different devices for different buffer settings). This worked great for a small amount of sender/receiver pairs, but if I used a bit more devices, it started to crackle (without any obvious reason, because CPU was quite low). Did you try your technology in more than one input/output device?
    • Oct 28 2015 | 2:50 pm
      hi MVF,
      I'm going to post an update soon that will work with several buffers instead of one 8-channel buffer. interesting you have been working on the same 'string' - could you send me a link? I didn't try yet with more than one 'sender',I will do so too.
      rbrt
    • Oct 28 2015 | 4:09 pm
      I find I get the first two channels only, and tried loading some other files too. Would there be a reason for that?
      does this work by interleaving the audio on the main buffer, i.e. creating a buffer that holds
      a0, b0, c0, d0, a1, b1, c1, d1, a2, b2, c2, etc... ?
    • Oct 29 2015 | 11:32 am
      @ everybody:ummm forget about the 8-channel buffer,ok? here's a new version,working with independently nameable 'buses', it's meant to be more of an actual 'construction kit' than the version before. also,it's working with max 6.1 now.
      @VENETIAN:interleaving the buffer is a good idea! @MVF : with your approach,did you find a way to get the 'audio buffer size' from within m4l?
    • Oct 29 2015 | 2:17 pm
      FWIW, I implemented something similar for Oscillot a couple of months ago. AFAIK, there is currently no way to get Live's audio buffer size, but I found a way to measure the offset between the source and target track, so you can adjust the readout of the buffer accordingly and even compensate the latency to some degree, by adding an artificial latency to the receiver device. I think in Oscillot we've settled on 512 samples. I have to look into the exact implementation again. It's been a few months and a lot of head-scratching, so I don't remember very well what I actually did. ;) I can probably extract the code and post it here.
      Cheers, Nico
    • Oct 29 2015 | 2:24 pm
      hey Nico, that would be cool! I've also been taking the path to measure the actual offset between source and target before (I was trying to get plugsend~/receive~ to have predicable latencies , which involved some very brutish scripting) but it didn't work too well...
    • Oct 29 2015 | 8:02 pm
      @RBRT: My biggest problem was/is to synchronize sender and receiver with a steady latency. I worked not with gen~ but with count~, poke~ and index~. My approach was to send a start bang for count~ (per normal send/receive object). This startbang was initiated in the sender, so it got to the receivers with a delay (I assume one vectorsize = 64 samples in Live?). My rolling buffer has to have at least the size of the AudioBufferSize in Live. In case of rollingbuffersize of 512 Samples I set a plugin delay for the receiver (patcher inspector) of 520 samples. This works (and is not dependant to the buffersize). But: My problem is, that I never could explain, why this works with 520 samples for a rolling buffer with 512 samples ;) I tested this with a phase swapped signal (done with Lives Utility effect). It's fine if the senders' through signal and the received signal cancel each other out. The second problem is/was, that this works mostly, but not everytime. Also, if I used several (more than 10) sender/receiver at once it began to crackle (CPU was low). @Nico: If you could share your measurement system, it would be great! I then could "repair" my bus system and share it here, too.
    • Oct 30 2015 | 1:30 pm
      @MVF: ..I've been trying something related with plugsend~/receive~, I used edge~ and timer.at first I tried cpuclock,but the results were even more inaccurate. just like you,I ran into the myterious 8 millisecond-thingy,and general unstable behaviour. obviously,for whatever reason,it doesn't work with 'generic' msp,I simply don't know why... surprisingly,it seems to work using gen~