Re: Playing multiple sounds
Re: Playing multiple sounds
- Subject: Re: Playing multiple sounds
- From: "Andreas Falkenhahn" <email@hidden>
- Date: Fri, 24 Aug 2007 15:01:08 +0200
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