Re: writing aiff file to disk
Re: writing aiff file to disk
- Subject: Re: writing aiff file to disk
- From: Robert Grant <email@hidden>
- Date: Thu, 8 Jan 2004 08:09:29 -0500
Hi Berend,
The problem with recording live audio to a file is that you have to
buffer the audio between the audio record thread and the file writer
thread. You can't simply write the data from the audio record thread
because the file writing can block causing drop outs in your audio.
(And the same is true with reading audio files for playback)
I've just been tackling this problem myself and have got a working
solution for recording.
Here are the steps I use (using AudioUnits and an AUGraph) - I use an
AudioConverter because I want the recorded audio to be 16 bit signed
integer rather than 32 bit float:
Prepare the recorder (This is very similar to the Writing an AIFF file
example on the Swiki).
Create the format of the audio file (AudioStreamBasicDescription)
Create the format of the audio stream (I get the
kAudioUnitProperty_StreamFormat of the *input* to the OutputUnit (I
don't get the output format because it's in the device's native format
which is unpredictable - could be interleaved, 24 bit signed integer
for example - the input is always 32 bit float deinterleaved).
Create the AudioFile to receive the data
Create the AudioConverter to convert the data
Create a circular buffer to carry the data between threads - this can
be implemented without locks because there's only one writer and
reader. (I use a buffer with 100 slots - where each slot has two 2K
buffers)
Start the recorder
Kick off a file writer thread that keeps converting and writing
buffers until recording is stopped.
The converter callback is the one that keeps an eye on the circular
buffer returning buffers as they become available.
Attach a RenderNotifyProc to the output bus of the penultimate unit
In the callback proc watch for PostRender notifications (the reason
for this is that this is the rendered audio data in the canonical
format - unlike the PostRendered buffers in the OutputUnit)
If you get a PostRender notification copy the buffers to your
circular buffer and bump up the write head to the next slot to let the
reader know there's a buffer available. If you end up catching up to
the read head flag an error and throw away (or overwrite) buffers but
don't stop and wait!
This should happily record for as long as you have disk space.
At the end of recording remember to close your audio file and clean up.
I'm sure there will be lots of comments on this approach - but it works
for me...
Hope that helps,
Robert.
On Jan 8, 2004, at 7:35 AM, Berend Schmid wrote:
Hi,
I'm actually triying to use the AudioFile header for reading/writing my
audio file.
The part where I'm stuck is, how do I get the data from my input device
to be written to disk.
I turned the whole thing around, reading an audio file to play it back
through my output device, to an idea of how things work. But, what a
surprise, I'm again stuck with getting the data from my file to being
played by the output device. I'd like to use the HAL-api for the whole
process.
I also looked at a sample code at
http://www.mat.ucsb.edu:8000/CoreAudio/90, where exactly the part I
don't get isn't covered.
thanks for the replay (the last and hopefully the next one),
Berend
Am 08.01.2004 um 01:33 schrieb john:
Hi Berend,
Here's a snippet of ObjC sample code for writing a basic stereo 16bit
44100 AIFF header. The audio data can come right after the header.
- (void)writeAIFFHeader: (unsigned long)audioLength
{
NSMutableData *theAiffFormat = [NSMutableData data];
UInt8 theRate[10] = {0x40, 0x0E,
0xAC, 0x44, 0, 0, 0, 0, 0, 0};
unsigned long fileLength = (audioLength + 42);
unsigned long chunkSize = 0;
unsigned short channels = 2;
unsigned long frames = (audioLength / 4);
unsigned short bits = 16;
unsigned long offset = 0;
unsigned long blockSize = 0;
// seek to the beginning
[myFileHandle seekToFileOffset: 0];
// set up the FORM part
[theAiffFormat appendBytes: "FORM" length: 4];
[theAiffFormat appendBytes: &fileLength length: 4];
// set up the AIFF part
[theAiffFormat appendBytes: "AIFF" length: 4];
// update the chunk size for the next part
chunkSize = 18;
// now setup the COMM part
[theAiffFormat appendBytes: "COMM" length: 4];
[theAiffFormat appendBytes: &chunkSize length: 4];
[theAiffFormat appendBytes: &channels length: 2];
[theAiffFormat appendBytes: &frames length: 4];
[theAiffFormat appendBytes: &bits length: 2];
[theAiffFormat appendBytes: theRate length: 10];
// update the chunk size for the next part
chunkSize = (8 + audioLength);
// now do the SSND part
[theAiffFormat appendBytes: "SSND" length: 4];
[theAiffFormat appendBytes: &chunkSize length: 4];
[theAiffFormat appendBytes: &offset length: 4];
[theAiffFormat appendBytes: &blockSize length: 4];
// write the data
[myFileHandle writeData: theAiffFormat];
}
Hope this helps.
-- John
Hi, everyone!
I'm trying to write an AIFF file to disk. I'm getting more and more
confused because there seem to be a lot of different ways you can
actually do this. Anyway, everything I tried didn't work.
Also the sample projects are more confusing than helpful.
Can anyone help me out giving me some code snippets on how to do it?
The audio coming from my input device should be recorded.
thanks,
Berend
_______________________________________________
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.