Re: Playing PCM buffers
Re: Playing PCM buffers
- Subject: Re: Playing PCM buffers
- From: Sean Harding <email@hidden>
- Date: Thu, 5 Jun 2003 11:22:42 -0700
Hi Chris. Thanks for your response. This does help. I suppose I thought it
was more of an audio problem than a general programming problem because I
expected CoreAudio to have a built-in "play buffer and return" method which
would make the solution very easy. It's not a big setback to me that it
doesn't have such a method -- now that I know, I can work on achieving the
funcionality I need via different tactics. I just felt that I was missing
something.
What you describe is fairly similar to what I've implemented so far. The
whole process is happening in a feeder thread anyway because I didn't want
the main thread bogged down with choosing characters and waiting for them to
be done playing. What I have now is working pretty well. I do have a one
character delay in changes taking effect, but I haven't been terribly
concerned about it. It's important to me that I have as close as possible
to exact timing on the length of the characters and the spaces between
them -- more important than having user changes take effect immediately.
It seemed more reliable to shove PCM data of the exact character (based
on the speed and sample rate) into a buffer and then play that than to
time it on the fly. This may be a false impression. I'll play
around with it a little bit and see if doing it on the fly causes any
problems.
Thanks again for your input.
sean
On Wed Jun 04 at 03:48:25 PM, Chris Reed wrote:
>
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.
>
>
--
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.