Re: Playing multiple sounds
Re: Playing multiple sounds
- Subject: Re: Playing multiple sounds
- From: "Andreas Falkenhahn" <email@hidden>
- Date: Fri, 24 Aug 2007 16:23:00 +0200
Some further questions:
1. According to Doug Wyatt from the Core Audio team at Apple
kAudioUnitProperty_SetInputCallback is (and I quote) " *very* deprecated; only use
I can imagine is if you're only using the Apple AU's and must support 10.1."
cf. source: http://lists.apple.com/archives/coreaudio-api/2004/Jul/msg00091.html
Instead, I should use kAudioUnitProperty_SetRenderCallback. But I can't use it
on my mixer! If I do something like
err = AudioUnitSetProperty(mixerAudioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, <bus>, &callback, sizeof(AURenderCallback);
I get a kAudioUnitErr_InvalidProperty error. So what is it with SetInputCallback
now? Should I use it or not? Is there a better way?
2. How to start/stop a sound bus? I have to ask this seemingly stupid question,
because the documentation is really bad, and raises more questions than it
answers. So my guess is that for starting a sound on bus <n> on the mixer I just
have to start a callback on bus <n>, which feeds the PCM data that shall be
played. So I'd do the following:
cb.inputProc = mixerProc;
cb.inputProcRefCon = <info of sound to be played so that mixerProc feeds the right data>;
AudioUnitSetProperty(mixerAudioUnit, kAudioUnitProperty_SetInputCallback, kAudioUnitScope_Input, <n>, &cb, sizeof(AudioUnitInputCallback));
But when I want to stop the sound on bus <n> now.... how do I kill the callback?
Or do I have to have callbacks for all busses running all the time and just feeding
in zeros when no sound is playing? But this seems like a waste of resources.
Please, someone help me to understand all this. Thanks!
Andreas
On 24.08.2007 at 15:01 Andreas Falkenhahn wrote:
>Thanks for your help. I'm getting there.... but very slowly. The sound
>plays now
>but it is choppy, and I don't know what I'm doing wrong.
>
>I've set up a very basic test environment. It's really nothing
>complicated. I'm trying
>to play a 8 bit sampled, mono, 13964hz sound through the default audio
>device
>using bus 0 of 8 busses in total. The code currently plays the sound and
>then
>crashes. I know that. It's just that I want to keep it brief. I will make
>all this code
>beautiful as soon as I hear my sound correctly.
>
>It's really not much code:
>
>UInt8 *g_sound = <pointer to PCM sound data here>;
>
>OSStatus ACComplexInputProc(AudioConverterRef inAudioConverter, UInt32
>*ioNumberDataPackets, AudioBufferList *ioData,
>AudioStreamPacketDescription **outDataPacketDescription, void* userData)
>{
> ioData->mBuffers[0].mData = g_sound;
> ioData->mBuffers[0].mDataByteSize = *ioNumberDataPackets;
>
> g_sound = g_sound + *ioNumberDataPackets; // Yes I know this will crash
>at sound end
> return noErr;
>}
>
>OSStatus myMixerInputCallback(void *inRefCon, AudioUnitRenderActionFlags
>inActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber,
>AudioBuffer *ioData)
>{
> AudioBufferList myList;
> UInt32 inNumFrames = ioData->mDataByteSize; // for my 8 bit mono sound
>a frame is just a byte
>
> // keep all other busses quiet for now
> if(inBusNumber != 0) {
> memset(ioData->mData, 0, ioData->mDataByteSize);
> return noErr;
> }
>
> myList.mNumberBuffers = 1;
> myList.mBuffers[0] = *ioData;
>
> AudioConverterFillComplexBuffer(converter, ACComplexInputProc, NULL,
>&inNumFrames, &myList, NULL);
>
> *ioData = myList.mBuffers[0];
>
> return noErr;
>}
>
>That's all. The mixer is connected to the default audio unit. I have 8
>busses on the
>mixer but only bus 0 is currently filled with data as you can see above.
>All other
>busses get their data cleared out using memset() so they should be silent.
>
>As I said, the sound is played and clearly audible, but it is choppy and a
>bit too slow.
>If I remove the 7 other busses completely from the mixer so that I have
>only one input
>proc left, the sound is still choppy, but not as bad as when the 7 other
>busses are active,
>but it is still choppy.
>
>I'm really clueless about this. Is it really such an exotic task that I'm
>trying to do
>here? Just to put a bunch of sounds with different sample rates and PCM
>encodings
>through the default audio device? Why is all this so difficult? I've
>already spent many
>hours on this and still feel like being far far away from a nice, smooth
>audio playback
>with Core Audio :-(
>
>It's really all very low-level, and I have no idea why the sound is choppy
>now. I'm
>clueless where this problem comes from.
>
>Please help someone! Thanks!
>
>Andreas
>
>On 23.08.2007 at 15:53 Mark Pauley wrote:
>
>>>
>>> 1. Install a render callback on my audio unit using SetRenderCallback
>>> in AudioUnitSetProperty(). (Question: But my audio unit is already
>>> configured
>>> to use the mixer unit as the input source. Can I still set a render
>>> callback
>>> on it now? Doesn't this somewhat conflict with each other? This
>>> confuses me
>>> a little.)
>>>
>>Hm, good point. For some reason I was assuming that the mixers used
>>buffer lists, not buffers.
>>If they use buffers and there's no v2.0 mixers, then you'll have to
>>stick with stuffing AudioBuffer pointers into AudioBufferList structs,
>>you can do this easily by:
>>
>>/*
>>typedef struct AudioBufferList {
>>UInt32 mNumberBuffers;
>>AudioBuffer mBuffers[1];
>>} AudioBufferList;
>>*/
>>...
>>// AudioBuffer myBuffer is a param
>>AudioBufferList myList = {1, &myBuffer};
>>
>>then pass myList on as necessary.
>>
>>
>>> 2. Install eight input callbacks on my mixer unit using
>>> SetInputCallback
>>> in AudioUnitSetProperty() using busses 0 to 7.
>>Yes, it's in these callbacks that you'll be dispatching the converters.
>>As you're setting up the mixer bus callbacks, you'll want to create a
>>new converter for each bus with the input format being the format
>>you'll be supplying and the output format being the format you want to
>>give to the mixer and register the AudioConverterFillBufferCallback
>>for each of those converters.
>>You can just store the converter as part of the refcon you stuff into
>>the callback struct, when you get the callback on any bus, you pull
>>bytes from the respective converter which you will unpack from the
>>refcon we give you in the mixer callback, which in turn pulls from the
>>converter callback, which is where you put the sound in the buffer.
>>
>>It's in the converter callback that you will actually supply the
>>signals of differing format, the converter slurps them up and they
>>come out the other side all the same format. The mixer just muxes the
>>8 separate signals into one signal.
>>
>>> I still don't think I have understood this correctly :(
>>
>>You're getting there, don't give up!
>>:)
>>
>>Here's a (crappy) diagram:
>>
>>source 1 -> converter 1 \
>>source 2 -> converter 2 \ \
>>source 3 -> converter 3 \ \ \
>>source 4 -> converter 4-(mixer)->output->speakers
>>
>>Imagine that your converters are like physical cable converters, and
>>then see electrons getting pulled, with the speakers doing the
>>pulling. It's like that but with samples.
>>:D
>>
>>So it's like your mixer only has rca inputs, but your synths / mics /
>>amps all have like 1/8'' or 1/4'' or XLR or whatever, so for each of
>>those you've got to change them to rca.
>>
>>
>>so to recap:
>>
>>1) get an output unit
>>2) get a mixer
>>3) connect the mixer to the output unit
>>4) for each of the busses on the mixer
>> a) create a converter for that bus
>> b) make an input callback function that pulls from a converter
>>stored in the refcon (could probably share this function among all
>>busses, the converters will end up calling different callbacks)
>> c) make a converter fill bytes function for the bus and set it as
>>the callback of the converter, this is where the source signal is
>>piped in
>>
>>
>>_Mark
>>
>>>
>>>
>>> Andreas
>>>
>>> _______________________________________________
>>> Do not post admin requests to the list. They will be ignored.
>>> Coreaudio-api mailing list (email@hidden)
>>> Help/Unsubscribe/Update your Subscription:
>>>
>>> This email sent to email@hidden
>
>
>
>--
>"Remember: It's nice to be important but it's more important to be nice!"
>
>
> _______________________________________________
>Do not post admin requests to the list. They will be ignored.
>Coreaudio-api mailing list (email@hidden)
>Help/Unsubscribe/Update your Subscription:
>
>This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden