Re: Examples for AudioFileStream and AudioConverter?
Re: Examples for AudioFileStream and AudioConverter?
- Subject: Re: Examples for AudioFileStream and AudioConverter?
- From: Nick Zitzmann <email@hidden>
- Date: Wed, 10 Sep 2008 12:26:46 -0600
Apparently nobody had any sample code, so I'm posting my code in the
hope that someone will tell me what I need to do to get this to work.
Again, I can get the AudioFileStream working just fine, but I'm doing
AudioConverterFillComplexBuffer() completely wrong, and I need to know
how to do this correctly.
The MP3 data I get from the application can be anywhere from less than
a kilobyte to several megabytes in size, and is often in VBR format.
The data is stored inside an internal data structure's
srcBasicDescription, which is an AudioStreamBasicDescription.
SDFillOutASBDForLPCM() is a function that internally calls
FillOutASBDForLPCM() in the CoreAudio headers using the same
arguments. I just did that so I can keep C and C++ code segregated.
What am I doing wrong here and how do I correct it?
typedef struct
{
UInt32 numberBytes;
UInt32 numberDataPackets;
const void *inputData;
AudioStreamPacketDescription *packetDescriptions;
UInt32 sizePerPacket;
UInt32 numberChannels;
} SDComplexBufferInfo;
static void SDPropertyListenerProc(void *inClientData,
AudioFileStreamID inAudioFileStream, AudioFileStreamPropertyID
inPropertyID, UInt32 *ioFlags)
{
SwfdecMacOSXAudioDecoder *decoder = (SwfdecMacOSXAudioDecoder
*)inClientData;
UInt32 size;
OSStatus err;
if (inPropertyID == kAudioFileStreamProperty_DataFormat)
{
size = (UInt32)sizeof(AudioStreamBasicDescription);
err = AudioFileStreamGetProperty(inAudioFileStream, inPropertyID,
&size, &decoder->srcBasicDescription);
if (err != noErr)
swfdec_audio_decoder_error(SWFDEC_AUDIO_DECODER(decoder), "Failed
to get basic description of audio: %d", err);
}
else if (inPropertyID ==
kAudioFileStreamProperty_PacketSizeUpperBound) // this will probably
never be reached, since the MP3 format doesn't have packet tables
{
size = (UInt32)sizeof(UInt32);
err = AudioFileStreamGetProperty(inAudioFileStream, inPropertyID,
&size, &decoder->srcSizePerPacket);
if (err != noErr)
swfdec_audio_decoder_error(SWFDEC_AUDIO_DECODER(decoder), "Failed
to get packet size: %d", err);
}
}
OSStatus SDConverterComplexInputDataProc(AudioConverterRef
inAudioConverter, UInt32 *ioNumberDataPackets, AudioBufferList
*ioData, AudioStreamPacketDescription **outDataPacketDescription, void
*inUserData)
{
SDComplexBufferInfo *info = (SDComplexBufferInfo *)inUserData;
UInt32 maxPackets = info->numberBytes/info->sizePerPacket;
if (*ioNumberDataPackets > maxPackets)
*ioNumberDataPackets = maxPackets;
ioData->mBuffers[0].mData = (void *)info->inputData;
ioData->mBuffers[0].mDataByteSize = info->numberBytes;
ioData->mBuffers[0].mNumberChannels = info->numberChannels;
if (outDataPacketDescription)
{
if (info->packetDescriptions)
*outDataPacketDescription = info->packetDescriptions;
else
*outDataPacketDescription = NULL;
}
return noErr;
}
static void SDPacketsProc(void *inClientData, UInt32 inNumberBytes,
UInt32 inNumberPackets, const void *inInputData,
AudioStreamPacketDescription *inPacketDescriptions)
{
SwfdecMacOSXAudioDecoder *decoder = (SwfdecMacOSXAudioDecoder
*)inClientData;
OSStatus err;
AudioStreamBasicDescription outputFormat;
UInt32 outputSizePerPacket;
const UInt32 outputBufferSize = 32768;
unsigned char *outputBuffer = malloc(outputBufferSize*sizeof(unsigned
char));
UInt32 numOutputPackets;
SwfdecBuffer *buffer;
SDComplexBufferInfo inBufferInfo;
SDFillOutASBDForLPCM(&outputFormat, 44100.0, 2, 16, 16, false, false);
outputSizePerPacket = outputFormat.mBytesPerPacket; // should always
be non-zero since we're not using VBR
numOutputPackets = outputBufferSize/outputSizePerPacket;
if (decoder->audioConverter == NULL)
{
err = AudioConverterNew(&decoder->srcBasicDescription,
&outputFormat, &decoder->audioConverter);
if (err != noErr)
{
swfdec_audio_decoder_error(SWFDEC_AUDIO_DECODER(decoder), "Couldn't
create audio converter: %d", err);
return;
}
}
inBufferInfo.numberBytes = inNumberBytes;
inBufferInfo.numberDataPackets = inNumberPackets;
inBufferInfo.inputData = inInputData;
inBufferInfo.packetDescriptions = inPacketDescriptions;
inBufferInfo.numberChannels = decoder-
>srcBasicDescription.mChannelsPerFrame;
if (decoder->srcBasicDescription.mBytesPerPacket == 0) // true if VBR
{
if (decoder->srcSizePerPacket == 0) // true if MP3, since this is
not known for MP3 files
{
UInt32 size = (UInt32)sizeof(UInt32);
err = AudioConverterGetProperty(decoder->audioConverter,
kAudioConverterPropertyMaximumInputPacketSize, &size,
&inBufferInfo.sizePerPacket); // why does this apparently always
return 8192?
}
else
inBufferInfo.sizePerPacket = decoder->srcSizePerPacket; // VBR audio
}
else
inBufferInfo.sizePerPacket = decoder-
>srcBasicDescription.mBytesPerPacket; // CBR audio
while (1)
{
AudioBufferList fillBufferList;
UInt32 ioOutputDataPackets = numOutputPackets;
fillBufferList.mNumberBuffers = 1;
fillBufferList.mBuffers[0].mNumberChannels =
outputFormat.mChannelsPerFrame;
fillBufferList.mBuffers[0].mDataByteSize = outputBufferSize;
fillBufferList.mBuffers[0].mData = outputBuffer;
err = AudioConverterFillComplexBuffer(decoder->audioConverter,
SDConverterComplexInputDataProc, &inBufferInfo, &ioOutputDataPackets,
&fillBufferList, NULL);
if (err != noErr)
{
swfdec_audio_decoder_error(SWFDEC_AUDIO_DECODER(decoder), "Couldn't
fill the converter's buffer: %d", err);
return;
}
if (ioOutputDataPackets == 0)
break;
}
buffer = swfdec_buffer_new_for_data(outputBuffer, outputBufferSize);
swfdec_buffer_queue_push(decoder->queue, buffer);
}
Nick Zitzmann
<http://seiryu.home.comcast.net/>
S/MIME signature available upon request
_______________________________________________
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