Using AudioConverter to create compressed audio
Using AudioConverter to create compressed audio
- Subject: Using AudioConverter to create compressed audio
- From: Neil Clayton <email@hidden>
- Date: Thu, 24 Jan 2008 18:48:06 +1300
- Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys
I'm attempting to use AudioConverter to create compressed data from
PCM data.
The input ASBD comes out from the AU that is receiving the data (I'll
be passing a copy of the data this AU receives, so in effect splitting
off at that point and compressing the same thing), The output ASBD is
from the QT SCAudio component. The audio converter initializes OK,
and I'm able to successfully set it's magic cookie.
At this stage I'm compressing PCM to AAC.
I'm using MTCoreAudio to buffer the incoming data from AU. I've taken
out error checking to reduce the size of this msg.
- (void) queueDataForCompression:(const AudioTimeStamp *)timestamp
numFrames:(UInt32)inNumberFrames data:(AudioBufferList *)ioData {
if(converterThreadRunning) {
unsigned written = [audioBuffer writeFromAudioBufferList:ioData
maxFrames:inNumberFrames rateScalar:1.0 waitForRoom:NO];
} else {
[self log:@"Audio not queued, the converter isn't running"];
}
}
The converter thread goes like this:
while(running) {
// Continually call the input proc, in order to feed more data to
the audio converter
NSAutoreleasePool *innerpool = [NSAutoreleasePool new];
@try {
AudioBufferList fillBufList;
fillBufList.mNumberBuffers = 1;
fillBufList.mBuffers[0].mNumberChannels = inASBD.mChannelsPerFrame;
fillBufList.mBuffers[0].mDataByteSize = theOutputBufSize;
fillBufList.mBuffers[0].mData = outputBuffer;
UInt32 ioOutputDataPackets = numPackets;
OSStatus err = AudioConverterFillComplexBuffer(audioConverter,
ConverterInputProc,
self,
&ioOutputDataPackets,
&fillBufList,
packetDescriptions);
if(err) {
if(err == -1) {
// No data available yet - that's fine - wait a bit and try again
[self log:@"Waiting for audio data"];
[NSThread sleepForTimeInterval:0.10];
} else {
[self log:@"Error filling audio buffer with data, %@", [NSString
osTypeToString:err]];
}
} else {
// Write the converted data to the movie file
[self log:@"Audio converter returned %ld packets",
ioOutputDataPackets];
}
} @finally {
[innerpool release];
}
}
The outputBuffer is a block of memory previously allocated, about 32k.
The AudioConverter input call back is:
- (OSStatus) _converterInputProc:(UInt32*)ioNumberDataPackets buffer:
(AudioBufferList*)buffer description:
(AudioStreamPacketDescription**)description {
OSStatus err = noErr;
// [self log:@"Converter proc called, num packets: %ld, with %ld
buffers, of size: %ld", *ioNumberDataPackets, buffer->mNumberBuffers,
buffer->mBuffers[0].mDataByteSize];
UInt32 inBuffer = [audioBuffer count];
if(inBuffer == 0) {
// We have no frames, return an error result
[self log:@"No frames to return - returning sensible error"];
buffer->mBuffers[0].mData = 0;
buffer->mBuffers[0].mDataByteSize = 0;
*ioNumberDataPackets = 0;
return -1;
}
// We're not providing compressed/VBR data, so no packet descriptions
if(description) {
*description = nil;
}
// The maximum number of packets we'd be able to supply (our buffer
is maxNumPackets frames)
UInt32 maxPackets = maxNumPackets / inASBD.mFramesPerPacket;
if (*ioNumberDataPackets > maxPackets) {
*ioNumberDataPackets = maxPackets;
}
// Copy some data from our queue, to the buffer we intend to have to
the AudioConverter
UInt32 numFramesToGet = inASBD.mFramesPerPacket * *ioNumberDataPackets;
[self log:@"Will get max packets: %ld, which is %ld frames",
maxPackets, numFramesToGet];
unsigned read = [audioBuffer
readToAudioBufferList:audioConverterBuffer maxFrames:numFramesToGet
waitForData:NO];
for(int i = 0; i < MIN(audioConverterBuffer->mNumberBuffers, buffer-
>mNumberBuffers); i++) {
buffer->mBuffers[i].mData = audioConverterBuffer->mBuffers[i].mData;
buffer->mBuffers[i].mDataByteSize = audioConverterBuffer-
>mBuffers[i].mDataByteSize;
buffer->mBuffers[i].mNumberChannels = audioConverterBuffer-
>mBuffers[i].mNumberChannels;
}
// Tell it how may we REALLY read
*ioNumberDataPackets = read / inASBD.mFramesPerPacket;
[self log:@"Read %ld from queue to the temporary buffer, telling
convert it has %ld packets", read, *ioNumberDataPackets];
return err;
}
So here I copy some frames from the internal queue, and then make the
passed in buffer reference that queue (the AudioBufferList passed by
the audio buffer appear to have the right number of buffers (2) for
the PCM data, but are not initialized in any other way).
So the flow is AU -> Internal conversion queue -> AudioBufferList ->
AudioConverter.
Where in the last case the audio converter always receives a reference
to the AudioBufferList data pointers. It's always PCM data going in.
This appears to all go as planned - except that I get
kAudioConverterErr_InvalidInputSize back from the call to
AudioConverterFillComplexBuffer.
Is there something obvious I'm doing wrong?
--- my analysis of the output log ---
The log below shows it running, and the converter waits for data since
none is available. Then Thread1 places some data into the queue, at
which point the AC begins to call the audio callback requesting input
data. The callback reports that the maximum is being passed back
(4096 frames). The next callback requests only 33 (the first callback
requested 4129 frames).
So the second callback then returns to the thread calling
AudioConverterFillComplexBuffer (we can see this because we don't
observe "Audio converter returned X packets" in the log). Thus I
think the AC is calling the callback two times in a row to get the
remaining 33 packets it was after in the first place.
After this second callback we see the 'insz' failure.
2008-01-24 18:47:01.487 CoreAudioRecorder[41375:1071f] [Thread 2]
[CAQTRecorder] - No frames to return - returning sensible error
2008-01-24 18:47:01.491 CoreAudioRecorder[41375:1071f] [Thread 2]
[CAQTRecorder] - Waiting for audio data
2008-01-24 18:47:01.499 CoreAudioRecorder[41375:10a03] [Thread 1]
[CAQTRecorder] - Wrote 512 frames to the converter queue
2008-01-24 18:47:01.510 CoreAudioRecorder[41375:10a03] [Thread 1]
[CAQTRecorder] - Wrote 512 frames to the converter queue
2008-01-24 18:47:01.522 CoreAudioRecorder[41375:10a03] [Thread 1]
[CAQTRecorder] - Wrote 512 frames to the converter queue
2008-01-24 18:47:01.533 CoreAudioRecorder[41375:10a03] [Thread 1]
[CAQTRecorder] - Wrote 512 frames to the converter queue
2008-01-24 18:47:01.545 CoreAudioRecorder[41375:10a03] [Thread 1]
[CAQTRecorder] - Wrote 512 frames to the converter queue
2008-01-24 18:47:01.556 CoreAudioRecorder[41375:10a03] [Thread 1]
[CAQTRecorder] - Wrote 512 frames to the converter queue
2008-01-24 18:47:01.568 CoreAudioRecorder[41375:10a03] [Thread 1]
[CAQTRecorder] - Wrote 512 frames to the converter queue
2008-01-24 18:47:01.580 CoreAudioRecorder[41375:10a03] [Thread 1]
[CAQTRecorder] - Wrote 512 frames to the converter queue
2008-01-24 18:47:01.591 CoreAudioRecorder[41375:10a03] [Thread 1]
[CAQTRecorder] - Wrote 512 frames to the converter queue
2008-01-24 18:47:01.592 CoreAudioRecorder[41375:1071f] [Thread 2]
[CAQTRecorder] - Requesting more than 4096 packets (4129), REDUCING
WHAT WILL BE RETURNED
2008-01-24 18:47:01.592 CoreAudioRecorder[41375:1071f] [Thread 2]
[CAQTRecorder] - Will get 4096 frames
2008-01-24 18:47:01.593 CoreAudioRecorder[41375:1071f] [Thread 2]
[CAQTRecorder] - Read 4096 from queue to the temporary buffer, telling
convert it has 4096 packets
2008-01-24 18:47:01.593 CoreAudioRecorder[41375:1071f] [Thread 2]
[CAQTRecorder] - Will get 33 frames
2008-01-24 18:47:01.593 CoreAudioRecorder[41375:1071f] [Thread 2]
[CAQTRecorder] - Read 33 from queue to the temporary buffer, telling
convert it has 33 packets
2008-01-24 18:47:01.595 CoreAudioRecorder[41375:1071f] [Thread 2]
[CAQTRecorder] - Error filling audio buffer with data, insz
2008-01-24 18:47:01.597 CoreAudioRecorder[41375:1071f] [Thread 2]
[CAQTRecorder] - Will get 4096 frames
2008-01-24 18:47:01.597 CoreAudioRecorder[41375:1071f] [Thread 2]
[CAQTRecorder] - Read 479 from queue to the temporary buffer, telling
convert it has 479 packets
2008-01-24 18:47:01.599 CoreAudioRecorder[41375:1071f] [Thread 2]
[CAQTRecorder] - Error filling audio buffer with data, insz
2008-01-24 18:47:01.603 CoreAudioRecorder[41375:1071f] [Thread 2]
[CAQTRecorder] - No frames to return - returning sensible error
2008-01-24 18:47:01.603 CoreAudioRecorder[41375:10a03] [Thread 1]
[CAQTRecorder] - Wrote 512 frames to the converter queue
2008-01-24 18:47:01.603 CoreAudioRecorder[41375:1071f] [Thread 2]
[CAQTRecorder] - Waiting for audio data
--
Regards,
Neil Clayton
_______________________________________________
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