Re: Playing PCM buffers
Re: Playing PCM buffers
- Subject: Re: Playing PCM buffers
- From: Chris Reed <email@hidden>
- Date: Wed, 4 Jun 2003 15:48:25 -0500
Hi Sean,
It sounds like you've got the basic idea down. It's really not much of
an audio problem, but more of a general programming problem. It sounds
like you've got the audio output part down fine.
Basically what you want after installing your IOProc is this.
The IOProc will read from (preferably non-blocking) queue of buffers.
It copies as much data from the buffer at the head of the queue into
the output buffer as possible. Any time it runs out, it drops the queue
head and continues with the next queue head. If there are no items in
the queue, it outputs silence.
To be notified when a buffer (character) is finished playing, the
IOProc will have to signal back to the main or another thread using a
(also preferably nonblocking) signalling mechanism. If you're using
Cocoa, you can probably get away with performSelectorOnMainThread:...
from the IOProc. The IOProc will signal each time it finishes with the
queue head and moves on to the next.
Your character-playing loop will really be broken up into several
functions.
When it first starts, you add a buffer to the to-be-played queue that
the IOProc is watching. Then the function or method that gets notified
by the IOProc that a buffer is finished will add the next buffer to the
queue.
But... there are problems with this whole setup. Mostly, there will be
a full buffer's latency for playing a new character. So you'll probably
hear a slight, annoying delay. Reducing output buffer size will reduce
this latency, but at the cost of increased CPU usage.
Really what you want to do is synthesise the morse code either within
the IOProc or in a feeder thread, going from characters to audio
directly. This will let you respond immediately to changes made by the
user to pitch or other options.
Hope this helps
cheers
-chris
On Tuesday, June 3, 2003, at 04:42 PM, Sean Harding wrote:
Since my last message, I still haven't really found what I'm looking
for
in the documentation. I'm sure this means I'm either not looking in the
right place or misunderstanding something I've read that would
actually help
me. This is the first audio-related code I've written on any platform,
and I
just recently started working with Cocoa as well, so I have much to
learn.
In any case, maybe if I give a better explanation of exactly what I
want
to do, someone here can give me a nudge in the right direction. I've
experimented quite a bit and still have not come up with exactly the
results I want.
I'm writing an application that generates morse code. It generates the
tones
in real time (a character is chosen just before the sound for it is
played)
and users can adjust parameters of that code as it is being generated.
Here's some pseudocode for what I'd like:
while( condition ){
// put PCM data for one morse character into someBuffer based
// on user-set params
bufferSize = generatePCMData(someBuffer);
< do some stuff >
// play that data
playPCMDataOnDefaultOutputDevice(someBuffer,bufferSize);
}
The key points here are that I have buffers of PCM audio data that can
be
any length (in my app, they'll range from a fraction of a second to
several
seconds) and that I don't want playPCMDataOnDefaultOutputDevice() to
return
until all of the sound in the buffer has been played. My app needs to
know
immediately when all of the buffer has been played so that it can take
actions based on that.
I do have reasons to play a bunch of short buffers in succession rather
than putting it all into one long buffer at the beginning and playing
that.
The most important is the user interaction I mentioned earlier. Users
can
change things such as speed and pitch on the fly, so I don't know what
the
next bit of audio needs sound like until immediately before playing
it. Also, a full 5 or 10 minute buffer of data would use a fair amount
of
memory.
I've been able to pretty easily play sound from a PCM buffer by just
doing AudioDeviceAddIOProc()/AudioDeviceStart() and having my IOProc
read
from the buffer each time around. However, this doesn't give me a
reliable
way to know immediately when the buffer has been fully played. It also
gives
me a gut feeling that it's just not the "right" way to solve the
problem,
but it's about the closest I've come so far.
I apologize for using so many words to ask what is likely an elementary
question. But I've been stuck on this problem for a while and any
guidance
you can give would be greatly appreciated.
Thanks.
sean
--
Sean Harding -- email@hidden -- http://dogcow.org/s/ -- KD7UAY
Seattle, WA, USA
_______________________________________________
coreaudio-api mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/coreaudio-api
Do not post admin requests to the list. They will be ignored.
_______________________________________________
coreaudio-api mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/coreaudio-api
Do not post admin requests to the list. They will be ignored.