• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Playing multiple sounds
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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


  • Follow-Ups:
    • Re: Playing multiple sounds
      • From: "Andreas Falkenhahn" <email@hidden>
References: 
 >Playing multiple sounds (From: "Andreas Falkenhahn" <email@hidden>)
 >Re: Playing multiple sounds (From: Mark Pauley <email@hidden>)
 >Re: Playing multiple sounds (From: Mark Pauley <email@hidden>)
 >Re: Playing multiple sounds (From: "Andreas Falkenhahn" <email@hidden>)
 >Re: Playing multiple sounds (From: Mark Pauley <email@hidden>)
 >Re: Playing multiple sounds (From: "Andreas Falkenhahn" <email@hidden>)
 >Re: Playing multiple sounds (From: "Andreas Falkenhahn" <email@hidden>)

  • Prev by Date: Re: RawAudioFileComponent example crash
  • Next by Date: Re: Playing multiple sounds
  • Previous by thread: Re: Playing multiple sounds
  • Next by thread: Re: Playing multiple sounds
  • Index(es):
    • Date
    • Thread