Simple AudioDeviceManager question


#1

I’m getting started on JUCE and am starting with something very, very simple. I am not making an application but just want to use the audio classes in a DLL for my app.

So I simply build a .lib for JUCE, and include that in a barebones DLL code. I put the juce source in, add the .lib, and I #include juce.h and I’m off and running.

I want to start off by getting getAvailableAudioDeviceNames() form the AudioDevice Manager. So I write a little code that simply starts like this…

AudioDeviceManager* a = new AudioDeviceManager();

It all compiles, but when the code hits this place, I get an assertion in ChangeBroadcaster() adn MessageListener(). The note is:

// are you trying to create a messagelistener before or after juce has been intialised??

Does JUCE have to been initilised? And why am I getting these assertions?


#2

You need to call initialiseJuce_NonGUI() or initialiseJuce_GUI() depending on whether you need to GUI stuff or not.

See the docs:
http://www.rawmaterialsoftware.com/juce/api/juce__Initialisation_8h.html

There’s also a note in there regarding other issues for DLLs on Windows.


#3

Thanks Martin, much appreciated! That worked.


#4

Hello,

I’m using CSL and Juce. Trying to get a simple console app up and running the first time. I am OS X / XCode if it matters.

I am taking the code from http://fastlabinc.com/CSL/ CSL Example and just putting it in my main function.

I have everything compiled and running, but I am hitting the following assertion.

ChangeBroadcaster::ChangeBroadcaster() throw()
{
    // are you trying to create this object before or after juce has been intialised??
    jassert (MessageManager::instance != 0);

After doing some reading I added initialiseJuce_NonGUI(); as the first call in my function, but I am still getting the assertion. Full code at bottom.

Any advice?
thanks
Lucas

#include <iostream>

#define DEBUG

#include "CSL_Core.h"
#include "JUCEIO.h"
#include "Envelope.h"
#include "WaveShaper.h"

using namespace csl;

int main (int argc, char * const argv[]) {

	
	initialiseJuce_NonGUI();	
	
	float frq = 440.0f;                  // float values for freq and dur
	float dur = 0.2f;
	JUCEIO theIO(96000, 512, 0, 0, 0, 2); // create a JUCE IO object
	Sine car, mod(frq);                  // declare 2 oscillators: carrier and modulator
	// amplitude env = std ADSR
	ADSR a_env(dur, 0.1, 0.1, (dur - 0.6), 1); 
	// index env = time/value breakpoints
	Envelope i_env(dur, 0, 0, 0.1, 2, 0.2, 1, 2.2, 8, dur, 0);
	a_env.setScale(0.2);                 // make ampl envelope quieter
	i_env.setScale(frq * 3.0f);          // multiply index envelope by mod freq * 3 (index depth)
	mod.setScale(i_env);                 // scale the modulator by its envelope
	mod.setOffset(frq);                  // add in the base freq
	car.setFrequency(mod);               // set the carrier's frequency
	car.setScale(a_env);                 // scale the carrier's output by the amplitude envelope
  
	logMsg("CSL playing FM...");         // print a message and play
	theIO.setRoot(car);                  // set the IO's root to be the FM carrier
	theIO.open();                        // open the IO
	theIO.start();                       // start the driver callbacks and it plays!
	
	a_env.trigger();                     // reset the envelopes to time 0
	i_env.trigger();   
	
	sleepSec(dur + 0.25);                // sleep for dur plus a bit
	
	logMsg("CSL done.");
	theIO.stop();                        // stop the driver and close down
	theIO.close();
	
}

#5

If you’re hitting the assertion, then surely a quick glance at its stack-trace will show where it’s getting called from? Perhaps you’ve got a static object somewhere that’s being initialised before main() is called?

P.S. it’s better practice to use the RAII-based ScopedJuceInitialiser_NonGUI class for initialisation.


#6

Perhaps more of a question for the CSL people… i.e., how is their demo set up to work?


#7

thanks for the quick response.

I changed to ScopedJuceInitialiser_NonGUI().
Also took a look at the debugger and the exception is coming from

JUCEIO theIO(96000, 512, 0, 0, 0, 2); // create a JUCE IO object

An AudioDeviceManager is part of JUCEIO, and in the constructor audioDeviceManager.initialize(…) is called, but this is all done after I call ScopedJuceInitialiser.


#8

I’ll check w/ them


#9

Sorry, I should have noticed what you’re doing there - the ChangeBroadcaster stuff can’t be used in a non-GUI app. Lots of the audio code relies on the event loop running, so you need to write a proper UI app, not a command-line one.


#10

This makes sense. Out of curiosity, does the event loop run without any constraints or can you manage the speed?
In OpenFrameworks you can configure the refresh rate to try and ensure there is no tearing on the screen. If audio playback is controlled from the event loop then I am guessing it must run full speed to keep up with audio, or is the audio split off into a different thread?

If the audio is split into a different thread, how difficult would it be to pull it out? I would really like to see OpenFrameworks simply pulling in the Juce audio capabilities. Alternatively I’ll be communicating between my two programs via sockets.


#11

No, you’re totally misunderstanding what I mean by an event loop there. I’m not talking about refreshing the screen like in a game - all GUI apps run a loop to dispatch incoming OS events, and as long as that’s running, JUCE classes will work just fine, even if some other framework is actually in charge.


#12

got it! let me go try a few things. thanks


#13

I’m still very much confused.

I tried in my simple app listed above to use ScopedJuceInitialiser_GUI(), hoping it would set up the event loop and I could just go and do my own things. This appears to be wrong, and I think it makes sense because I set up no DocumentWindow etc.

What I’m confused about is the following. In OpenFrameworks functionality is more or less broken down into
update()
draw()

Which loops at a given frame rate. I’d like to have a Juce VST host that I can send midi signals to from within update, but I don’t get how it’s possible.
Would it make sense if I create a JuceGUI app with no real window and some exposed functions like MIDI_Signal() and then I can just use the juce ‘app’ as an object? I feel like in order to do this I’d have to see where the actual main() in a GUI juce app resides and pull that functionality out and into my apps initialize.

does any of this make sense? thanks again


#14

If you’re running a GUI app you can’t write your own main() - just use the JUCEApplication in the normal way.