Controlling two microphones in OF

Hello,

I have a soundcard with multiple inputs, and I would like to control two microphones and get sound spectrum for both at the same time. Any clues in how to do that? I am working on Mac X-code if this really matters…

If someone could point me into the right direction it would be great.

Many thanks!

Cheers,
Edu

hey eduard

there’s no way to do that with the current ofSoundStream since it doesn’t allow to specify devices or open several at the same time.

i did this addon some time ago that encapsulates the same functionality as ofSoundStream in an object so you can specify wich device to open or open several at the same time:

http://forum.openframeworks.cc/t/soundstream-requests/2245/0

the problem is its for rtAudio 3 and 0061 comes with rtAudio 4 but porting it should be pretty easy if you take a look at ofSoundStream.cpp

if you do so please post the changes ; )

Thanks Arturo!

I’ll give it a look and will keep you posted about my progress :slight_smile:

Cheers,
Edu

Hi Arturo,

I realized that to do what I need I might have enough with the current ofSoundStream. I think if I set up my multichannel device as system default I might be able to control both mono inputs (left and right) attached to two microphones.

However, I started porting the add-on and I have done most of the stuff (I think). I can create an instance and correctly list al devices and preselect one, but as soon as I try to use the setup method, I got a linking complier error related to the callback function (symbols not found ofxSoundStream.o). I will continue looking at this when I have time, but If you think you can guess what’s going on, would be cool. I haven’t spent a lot of time yet and I might be doing something completely wrong, but these are the interesting related parts of it:

  
  
// rtAudio callback  
int 	ofxSoundStreamCallback(void *outputBuffer, void *inputBuffer, unsigned int bufferSize, double streamTime, RtAudioStreamStatus status, void *ofStream);  
int 	ofSoundStreamCallback(void *outputBuffer, void *inputBuffer, unsigned int bufferSize, double streamTime, RtAudioStreamStatus status, void *ofStream){  
	return ((ofxSoundStream*)ofStream)->receiveAudioBuffer(inputBuffer, bufferSize);  
}  
  

  
  
void ofxSoundStream::setup(int nOutputs, int nInputs, ofBaseApp * OFSA, unsigned int sampleRate, unsigned int bufferSize, unsigned int nBuffers){  
	RtAudio::StreamParameters inputParams;  
	RtAudio::StreamParameters outputParams;  
	RtAudio::StreamOptions streamOptions;  
	  
	inputParams.deviceId = deviceID;  
	inputParams.nChannels = nInputs;  
	  
	outputParams.deviceId = deviceID;  
	outputParams.nChannels = nOutputs;  
	  
	streamOptions.numberOfBuffers = nBuffers;  
  
	nInputChannels 		=  nInputs;  
	nOutputChannels 	=  nOutputs;  
	OFSAptr 			=  OFSA;  
  
	bufferSize = ofNextPow2(bufferSize);	// must be pow2  
  
	if(audio)  
		close();  
  
	audio = new RtAudio();  
	try {  
		audio->openStream(	&outputParams, &inputParams, RTAUDIO_FLOAT32,  
						  sampleRate, &bufferSize, &ofxSoundStreamCallback, this, &streamOptions);  
	} catch (RtError &error) {  
		error.printMessage();  
		//std::exit(EXIT_FAILURE); // need case here  
	}  
  
	try {  
		//audio->setStreamCallback(&ofSoundStreamCallback, this);  
		audio->startStream();  
	} catch (RtError &error) {  
		error.printMessage();  
	}  
}  
  

My guess is that what is wrong is the “this” reference of the callback, since the function expects a void* userData, see here:

http://www.music.mcgill.ca/~gary/rtaudio/classRtAudio.html#afacc99740fa4c5606fb35467cdea6da8

I’ll continue looking into it though…

Cheers,
Edu

Hello Arturo,

I was doing a few things quite wrong :slight_smile: (OF 0061)

There’s only one structural problem that makes the addon a bit useless: It would be necessary to include the device ID in the audioReceived handler so we can identify which device is actually calling it in case you want to have multiple instances of ofxSoundStream. It would be even better to be able to add custom listeners.

Any suggestions on how to work around this?

Best,
Eduard

ofxSoundStream.zip

By the way, just a minor update with following additional function:

setDeviceByName(string deviceName);

This can be handful if you want to avoid identifying the ID manually. Example of use:

myOFXSoundStream.setDeviceByName(“M-Audio: FireWire 410 Multichannel”);

Cheers,
Edu

ofxSoundStream.zip

hey, that’s great!

didn’t realize about the id, i suppose it will need a different kind of callback, i suppose having a ofxAudioEventArgs class that has the same vars as ofAudioEventArgs and adds the id will be the solution.

Hi Arturo,

of course! Events! Like the MIDI :wink:
Ok, I did another fix and now events work properly (where not castng properly although audioReceived was being called properly).

Now everything works if I use ofAddEventListener, however when I try to create my own EventArgs Object (see code below), I have a very strange compiler error from POCO no match for operator ‘+=’ (event += …)

  
  
class ofxAudioEventArgs: public ofAudioEventArgs{  
public:  
	int 	deviceID;  
	string		deviceName;  
};  
  
  

Everything else looks good to me (quite similar to ofxMidi). Any help? Do you know what’s going on?

Thanks!!
Edu

i think you just need to declare the events as:

ofEvent

to be able to call them passing an ofxAudioEventArgs.

Hi Arturo,

actually I am doing it already like this. I am a bit stuck in this problem, would be great if you have an idea about what is happening.

This is how I declare the events:

  
  
ofEvent<ofxAudioEventArgs> 	audioReceivedEvent;  
ofEvent<ofxAudioEventArgs> 	audioRequestedEvent;  
  

This is how the event is invoked:

  
  
audioEventArgs.buffer = fPtrIn;  
audioEventArgs.bufferSize = bufferSize;  
audioEventArgs.nChannels = nInputChannels;  
audioEventArgs.deviceID = deviceID;  
audioEventArgs.deviceName = getDeviceName();  
ofNotifyEvent( audioReceivedEvent, audioEventArgs, this);  
  

getDeviceByName returns the current device name (it works). When I replace ofxAudioEventArgs for ofAudioEventArgs everywhere (removing the deviceID and deviceName of course), everything works fine. As soon as I replace everything for my own ofxAudioEventArgs I get the folloeing error in POCO:

error: no match for ‘operator+=’ in ‘event += Poco::delegate(TObj*, void (TObj::*)(TArgs&)) with-TObj-=-testApp,-TArgs-=-ofAudioEventArgs

Any clues? I have to get back to “regular” work now, but will try to get back to it this evening.

Many thanks,
Edu

Hey Arturo,

I found the silly mistake causing the compiler error! So stupid :slight_smile:

Cheers,
Edu

ofxSoundStream.zip

hey! could anybody give a simple example about the usage of ofxsoundstream?
say, how can i get the data? where should i call receiveAudioBuffer()?
thanks~

Hey yaya,

I have the add-on at GitHub including an example of usage (Xcode project).

Best way to use this is with an event listener so you can identify which device the sound is coming from.

http://github.com/jocabola/ofxSoundStream

cheers,
Edu

[quote author=“jocabola”]Hey yaya,

I have the add-on at GitHub including an example of usage (Xcode project).

Best way to use this is with an event listener so you can identify which device the sound is coming from.

http://github.com/jocabola/ofxSoundStream

cheers,
Edu[/quote]
thanks man. it works!

for other people who may need this, just a minor change in testApp’s audioInputListener()

  
  
void testApp::audioInputListener(ofxAudioEventArgs &args){	  
	// samples are "interleaved"  
	if(args.deviceID == deviceID2){  
		for (int i = 0; i < args.bufferSize; i++){  
			left2[i] = args.buffer[i*2];  
			right2[i] = args.buffer[i*2+1];  
		}  
	}  
	if (args.deviceID == deviceID)  
	{  
		for (int i = 0; i < args.bufferSize; i++){  
			left[i] = args.buffer[i*2];  
			right[i] = args.buffer[i*2+1];  
		}  
	}  
}  
  

and of course, you need to declare deviceID and deviceID2 in testApp.h
a complete one including tespApp.h and testApp.cpp is attached

src.rar

this is great, extremely useful and a good addition to the addons family, thanks jocabola!

Hi, i’m a begginer at OF. I’m trying to record 2 sources of audio (2 mic’s) with libsndfile and ofxSoundStream posted in this thread.

I can record 1 input of audio with ofSoundStream built in OF but i want 2 inputs. So i tried this code, but when i try to save the content of any buffer of any device it records a noise… and also when i put a counter inside audioInputListener(ofxAudioEventArgs &args) and print it, it ouputs in a speed slower than a counter in the audioReceived function when i used ofSoundStream… why this is happenning?
i’m using the example provided by jacobola, it shows 2 graphics and it can differentiate the 2 inputs but the content of the buffers are wrong or something… i don’t know… help please.

Hello,

I haven’t tried this actually. When I created the extension I just used for real-time sound spectrum analysis which worked fine.

I’ll give it a look as soon as possible.

Cheers,
Edu

thank you jacobola i keep waiting for your response… it seems that the application receive sound in a slow way rather than when i used audioReceived function… i saw the code but i don’t know why…

Btw, do you mind posting your code? I hope I can take a look into this sooner than later, but I am very busy right now :confused:

ok, here it is the sources. I couldn’t upload the libsndfile (to record audio) but it is here http://www.mega-nerd.com/libsndfile/[attachment=0:zm6igpsl]src.zip[/attachment:zm6igpsl]

src.zip