Hi everyone,
I’m trying to create a simple command-line application with JUCE that plays white noise using AudioDeviceManager. However, while AudioDeviceManager::playTestSound() works and I hear the test sound, my custom AudioIODeviceCallback is never called and no audio is generated.
Here’s a minimal example of my setup:
#include <juce_core/juce_core.h>
#include <juce_audio_devices/juce_audio_devices.h>
#include <juce_events/juce_events.h>
#include <thread>
#include <chrono>
class WhiteNoiseCallback : public juce::AudioIODeviceCallback
{
public:
void audioDeviceIOCallback(const float** /*inputChannelData*/,
int /*numInputChannels*/,
float** outputChannelData,
int numOutputChannels,
int numSamples)
{
for (int channel = 0; channel < numOutputChannels; ++channel)
{
float* buffer = outputChannelData[channel];
if (buffer != nullptr)
{
for (int i = 0; i < numSamples; ++i)
{
// White Noise: -0.25 .. +0.25
buffer[i] = juce::Random::getSystemRandom().nextFloat() * 0.5f - 0.25f;
}
}
}
}
void audioDeviceAboutToStart(juce::AudioIODevice* device) override
{
juce::Logger::writeToLog("Audio device started: " + device->getName());
}
void audioDeviceStopped() override
{
juce::Logger::writeToLog("Audio device stopped.");
}
};
int main (int argc, char* argv[])
{
juce::ignoreUnused(argc, argv);
juce::ScopedJuceInitialiser_GUI juceInit;
juce::ConsoleApplication app;
juce::AudioDeviceManager deviceManager;
WhiteNoiseCallback noiseCallback;
auto error = deviceManager.initialiseWithDefaultDevices(0, 2);
if (error.isNotEmpty())
{
std::cerr << "Audio Init Error: " << error << std::endl;
return 1;
}
deviceManager.playTestSound();
if (auto* device = deviceManager.getCurrentAudioDevice())
{
std::cout << "Using device: " << device->getName() << std::endl;
std::cout << "Sample Rate: " << device->getCurrentSampleRate() << std::endl;
std::cout << "Buffer Size: " << device->getCurrentBufferSizeSamples() << " samples" << std::endl;
std::cout << "Active outputs: " << device->getActiveOutputChannels().toInteger() << std::endl;
}
if (juce::MessageManager::getInstance()->isThisTheMessageThread())
std::cout << "We are in the MessageThread" << std::endl;
else
std::cout << "We are NOT in the MessageThread" << std::endl;
deviceManager.addAudioCallback(&noiseCallback);
std::cout << "Playing white noise for 5 seconds..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(5));
deviceManager.removeAudioCallback(&noiseCallback);
std::cout << "Done." << std::endl;
return 0;
}
What I’ve tried so far:
- Using ScopedJuceInitialiser_GUI to initialize JUCE in a CLI app
- Checking that the audio device is opened and has 2 output channels
- Confirmed that playTestSound() works and produces sound
Issue:
Despite the device being initialized correctly, the audioDeviceIOCallback is never invoked and no white noise is heard.
Question:
Does anyone know why the callback is not called in this CLI setup and how I can make the AudioDeviceManager trigger my callback correctly?
Thanks in advance for any guidance!
