How to get audio buffersize through Audio Unit RemoteIO

Hi, I’m trying to get the iOS hardware buffer size (e.g 512, 1024) and bring that number to ofApp.mm file so I can use it.

I found that this function “static OSStatus soundOutputStreamRenderCallback()” is getting the realtime bufferSize value (this function is located in “SoundOutputStream.h”).

The funny thing is this bufferSize dynamically changes depending on the other audio app that is already running in the background. So, If other previously opened synth app uses 512 bufferSize, than my app will start running with 512 bufferSize no matter what bufferSize I set in the beginning.

This is totally fine in general, but since I’m using ofxPd, the Pd’s bufferSize (ticksPerBuffer) does not dynamically change whereas ofSoundStream’s bufferSize gets changed. This leads my app to produce distorted noisy sound or crash because of this mismatch in the bufferSize.

So what I’m trying to do is to get the real-time bufferSize through AU RemoteIO and re-init ofxPd with the new bufferSize whenever there’s a change.

But since I’m not really experienced with objective-C, I couldn’t figure out how to bring the bufferSize(int) from “SoundOutputStream.h” to use it in ofApp.mm file.

I would really really appreciate if someone could help me out with this. please.

You can check the buffer size in your ofApp’s audioRecieved and audioRequested functions. You don’t have to do this directly in Obj-C: https://github.com/danomatika/ofxPd/blob/master/pdExampleIOS/src/ofApp.mm#L373

Check that the buffer size matches the buffer size ofxPd is using (aka ticksperbuffer * block size). If they are different, compute the new ticksperbuffer and reinit ofxPd. You might have to reset all of your settings and reload the currently patch. I don’t remember of f the top of my head, so try it without resetting first.

1 Like

Thank you so much for your answer!
I will try that today! :grinning:

I finally fixed the problem by following @danomatika’s suggestion!

My code is as below.

in ofApp.h file,

int ticksPerBuffer = 16; //default ticksPerBuffer
int curBufferSize = -1; //current bufferSize

in ofApp.mm file,

//-------------------------------------------------------------
void ofApp::setup() {

//setup OF sound stream
ofSoundStreamSetup(2, 1, this, 44100, ofxPd::blockSize()*ticksPerBuffer, 3);
}

//--------------------------------------------------------------
void ofApp::audioRequested(float * output, int bufferSize, int nChannels) {

if (bufferSize == curBufferSize) { //if the new bufferSize is same as the current one
    
    pd.audioOut(output, bufferSize, nChannels);
}
else { //if the new bufferSize is different from the current one, init pd with different ticksPerBuffer
    
    ticksPerBuffer = bufferSize / 64; //calculate new ticksPerBuffer
    
   if (pd.isInited()) {
       
       pd.unsubscribeAll();
       pd.removeReceiver(*this);
       pd.removeMidiReceiver(*this);
    }
    
    if(!pd.init(2, 1, 44100, ticksPerBuffer, false)) {
        OF_EXIT_APP(1);
    }
    
    // subscribe to receive source names
    pd.subscribe("blahblah1");
    pd.subscribe("blahblah2");
    
    // add message receiver, required if you want to receieve messages
    pd.addReceiver(*this);   // automatically receives from all subscribed sources
    
    // add midi receiver, required if you want to recieve midi messages
    pd.addMidiReceiver(*this);  // automatically receives from all channels
    
    pd.start();//turn pd dsp on
    
    curBufferSize = bufferSize; //set the updated bufferSize
  }

}

I tried several times to get it working.
This even works when bufferSize changes while the patch is already running. I could still run the patch without closing and re-opening the patch after the re-init. I don’t know why though.

Thank you very much for your help @danomatika! I owe you so much.
Maybe you can add the code to ofxPd iOS examples for other users? it’s up to you though.
Thank you!! :smiley:

Try the reinit branch on ofxPd: https://github.com/danomatika/ofxPd/tree/reinit

As suggested, it automatically reinits if the buffer size or num channels changes in audioIn()/audioOut(). As you noticed, this should work without having to reload patches or setup receivers, etc.

Let me know if it works.

Thank you for your work @danomatika

I tried your branch and it works fine if I don’t open other audio apps in the background.

But I found 2 issues when I use it with other audio apps(that use different buffer size).

  1. If I open other audio app(e.g ‘Music IO’ app which runs in 256 buffer size) first, then open my app(1024 buffer size), when I open a pd patch in my app, the audio works fine but it ignores receiving messages from the pd patch in the beginning.
    So for example, if my patch sends “Hello World” message to OF right after opening the patch using [loadbang], the OF doesn’t receive this message. However, delaying the message using [delay 1000] worked.

  2. If I open my app and a pd patch first, then open other audio app while the patch is running, the patch’s audio stops. It doesn’t crash though. I think the patch is closing when it re-inits with different buffer size.

All of these issues mentioned didn’t happen in my previous setup which I posted above.
To be honest, I don’t really know why that one worked and this one doesn’t.

If you want to test the things yourself on iOS, you can download an app called “Music IO (MIDI)” which is free.
It’s a good app to test with since it uses both audio and MIDI.
I’m also willing to try and report you any problems if I find any.

I hope you find a working solution. Many users will appreciate it.
Thank you very much.

Ok, I made an update. Pull and try the reinit branch again.

1 Like

Thank you @danomatika
I tried your updated branch but the first issue (ignoring receiving the message from patch in the beginning) still occurs.
The only difference is in the second issue that now the patch’s audio doesn’t stop but OF no longer receives any messages from the patch. Maybe it happens because I didn’t re-subscribe sources after the re-init?

No, it doesn’t unsubscribe anything now. My tests were working but I was only using the example. I’ll look into it again.

1 Like

Everything appears to be working fine for me. I send a counter value every second to OF in the test patch. I’m opening the example, starting Music I/O, and getting the patch audio and counter messages correctly the whole time. This is on an iPad 2 running iOS 8.

Are you opening a new patch later on after opening the patch or are the messages you’re not receiving being sent from the patch initially loaded when starting your app? My initial patch is sending things to OF just fine.

Also tested with latest Animoog app that let’s you set the preferred buffer size.