Re: Playing multiple sounds
Re: Playing multiple sounds
- Subject: Re: Playing multiple sounds
- From: William Stewart <email@hidden>
- Date: Fri, 24 Aug 2007 12:27:02 -0700
On 24/08/2007, at 7:23 AM, Andreas Falkenhahn wrote:
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?
You must be opening the mixer as a version 1 AU. The component IDs
for the stereo mixer are:
type - aumx
sub - smxr
manu - appl
any AU of type 'aunt' is deprecated and should not be used.
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
Probably the best place for you to look at is the Open AL
implementation on Mac OS X. The source for this is available at
http://openal.org and it does all of these kinds of things that you
are describing.
Bill
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:
40mac.com
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:
40airsoftsoftwair.de
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
--
mailto:email@hidden
tel: +1 408 974 4056
________________________________________________________________________
__
"Much human ingenuity has gone into finding the ultimate Before.
The current state of knowledge can be summarized thus:
In the beginning, there was nothing, which exploded" - Terry Pratchett
________________________________________________________________________
__
_______________________________________________
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