Change device buffer size in prepareToPlay - JUCEApplication

OK, I made that:

AudioDeviceManager::AudioDeviceSetup currentAudioSetup;
deviceManager.getAudioDeviceSetup (currentAudioSetup);
currentAudioSetup.bufferSize = 256;
String ret = deviceManager.setAudioDeviceSetup(currentAudioSetup, true);
DBG(ret);

But still nothing happens. Actually what DBG(ret); does?

I also tried that: std::cout << DBG(ret) << std::endl; But it gives me error.

that: std::cout << ret << std::endl; doesn’t give me error, but just nothing happens on the console, just endl; is executed.

Well this is completely right :wink:
DBG just outputs the string passed to the stderr stream of your console. I have no Windows experience (I think on Windows, a GUI app has no terminal output by default or something like that, but better ask the experts for that), but on MacOS with xCode oder CLion there should be some console window where all calls to DBG appear.

This can’t work, but this should work:
std::cout << ret.toRawUTF8() << std::endl;
This will do almost the same, but the result will be printed to stdout, not to stderr. Furthermore, any calls to DBG will just be ignored in a release build later.

OK, that std::cout << ret.toRawUTF8() << std::endl; also doesn’t give me error, but also just nothing happens, empty console (by the way I am also on xCode on High Sierra)

Alright, a quick look at the docs for AudioDeviceManager::setAudioDeviceSetup points out:

Returns
an error message if anything went wrong, or an empty string if it worked ok.

So it seems as if configuring your hardware was successful. I don’t know why your expected block size still stays the same… step through the code with the debugger, maybe you’ll find the answer!

OK, I will try, thanks. I will inform about the results :slight_smile:

Returns
an error message if anything went wrong, or an empty string if it worked ok.

OK, I made that:

currentAudioSetup.bufferSize = -500.99;
deviceManager.setAudioDeviceSetup (currentAudioSetup, true);
DBG(ret);

std::cout << ret.toRawUTF8() << std::endl;

And it also give me nothing in the console . So I claim documentation lies. Because for sure there couldn’t be buffer size like minus 500.99 :slight_smile:

Where are you even putting that code? If it’s in prepareToPlay, it’s too late, the audio device set up that is going to be used is already determined and attempting changes likely doesn’t do anything.

I told on the beginning verything I am putting in the constructor of MainComponent class

I think the test case you created was pretty meaningless.

First: AudioDeviceManager::AudioDeviceSetup::bufferSize is an int. What behavior do you expect by assigning a non-integer double value (-500.99)? Usual behavior is that the value will get truncated to -500, so in fact you are assigning -500 to bufferSize here. Now if you take a look into the docs for AudioDeviceManager::AudioDeviceSetup::bufferSize, they say:

This buffer size is used for both the input and output devices. A value of 0 indicates the default buffer size.

If you set a breakpoint in your code and step into the setAudioDeviceSetup call, you’ll reach this line of code: https://github.com/WeAreROLI/JUCE/blob/d4762f1d9a8b4cd39d669997dd09df3f215a7fc6/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp#L567

Here you see that it first checks if the buffer size passed is > 0. If not the default buffer size is chosen. So this means, passing a negative buffer size is treated equal to passing a buffer size of zero. However this is only obvious from looking at the code and more important: This is undefined behaviour. The documentation doesn’t say anything about a negative buffer size, so you could expect anything to happen. This should just clarify that passing an undefined value is not the best idea for spotting the error in this case.

However, what could help is to use your debugger, as said multiple times. I found the AudioDeviceManager::chooseBestBufferSize function by just scrolling through the code, however you would have reached this point by yourself by just setting a breakpoint at String ret = deviceManager.setAudioDeviceSetup (currentAudioSetup, true); and then stepping in that function and follow it line by line. But now as this line of code was spotted, I’d advise you to just set a breakpoint directly into chooseBestBufferSize and see what happens inside this function. In case the if-branch will be taken, the hardware will support your desired buffer size, in case it won’t this will show you that your hardware doesn’t.

I know this feeling of not knowing where to look for an error or an explanation from the times back when I got started and I’m still learning myself and stumble upon problems that seem clear for others out here, so I hope this will help you to first fix or understand your problem and then second teach you some general good practice on how to narrow down the source of some unexpected behaviour!

2 Likes

Audio applications don’t work that way. You don’t change the buffer size to fit your DSP code. You fit your DSP code to fit the audio system. That’s why in other threads people told you to use patterns like a FIFO to gather enough samples to make your DSP work with that.

The audio device is always free to give you any buffer size it is able to produce. Some even switch it on the fly, when resources become scarce.
In your AudioDeviceManager::AudioSetup you just state your preference, some drivers are programmed to obey, some are not. But it is not considered an error, like you verified in your code.

Even if the driver obeys when starting up, the value you get in prepareToPlay is as stated in the docs and in all audio APIs as well, it is an estimate, that will never exceed, but can be less.

To learn what your options are, print the values from AudioIODevice::getAvailableBufferSizes(). You can only pick from those.

Daniel, thanks for reply. But:
Of course I use something like FIFO. And it works. No matter what buffer size I set for my code it works perfectly. But I have still the same device buffer size. On my Mac it is 512. But when I run my code on Windows, there is always buffer size set to 441. And my app crashes. But I can’t use computer with windows to change the code, just test my app (it’s computer in my job), that’s why I want to be able to change device buffer size on my Mac, to be able to test my app with various device buffer size. I still have no idea how to do that.

Use an AudioDeviceSelectorComponent. You would need to add that to your application anyway if it is going to be used by other people. (Obviously changing the buffer size should in principle work from code too, but that’s not really something you could rely on for actual products. Various things can cause a certain buffer size to fail on different computers, so the size has to be adjustable by the end user.)

Great thanks, but still I have no idea how to use it. I know JUCE has good documentation. But I checked the AudioDeviceSelectorComponent and it’s very complicated. I’ve already spent to my issue more than one day. It’s very depressing feeling. I don’t know what to do. I also tried to study AudioSettingsDemo juce example project. But there I don’t even see where is any AudioAppComponent? In my application main class is MainComponent which inherits from AudioAppComponent. But in the AudioSettingsDemo project the main class is AudioSettingsDemo and it inherits from Component, not from AudioAppComponent. It’s totally mess for me in my brain. Have no idea how to understand it.

The easiest way to use it, is to make it a member of your MainContentComponent like this:
AudioDeviceSelectorComponent adsc;
Since that class does not have a default constructor, you will have to call the constructor with the initialization list of your MainContentComponents constructor
Example:

MainContentComponent () : adsc(deviceManager, 2, 2, 2, 2, false, false, false, false)
{
    // constructor
   addAndMakeVisible(adsc);
   adsc.setBounds(0, 0, 300, 300);
}

Adding it to your component and setting the bounds.

However, you might want to create only a button instead, which launches an DialogWindow with a AudioDeviceSelectorComponent inside.

Edit: This edit is just so stress out, that a DialogWindow is what you want, however, for testing purposes, the first solution is just fine.

Hey Daniel !!!
Great, Great Great THANKS!!! it works.
But… :slight_smile:
As I mentioned on my computer in job, there is by default buffer size = 441. So I would like to be able to test my app, also with that value of buffer size. But AudioDeviceSelectorComponent gives me just list with possible choices of buffer sizes, but there is no 441. Is it possible to put on that list other buffer sizes?

I think you can only ask for a buffersize your audiodevice supports, so whatever strange audioInterface supports 441, you will need that one connected to your system. But maybe you could use a virtual audiodevice for that?

Thanks Daniel. I’ve just found out that on Windows the error was not caused by buffer size. I just set build mode to Release, and there are no errors, everything works perfect. Now I am affraid if I can leave it like that? On Debug mode I get error with “vector out of range”. But in release mode there is no problems. So can I leave it like that? Or better repair everything in debug mode?