Re: Decoding compressed to LPCM
Re: Decoding compressed to LPCM
- Subject: Re: Decoding compressed to LPCM
- From: Jens Alfke <email@hidden>
- Date: Mon, 21 Apr 2008 16:07:27 -0700
On 21 Apr '08, at 12:22 PM, Aurélien Ammeloot wrote:
This code works for converting big endian AIFF to little endian WAV.
But it doesn't work from a compressed audio file AAC or MP3 to
little endian WAV. I've tried step-by-step debugging and it seems
ExtAudioFileCreateNew(...) fails in the latter cases.
To pipe samples from the input to the output, both ends have to have
the same client data format. You're not doing that.
In other words, reading from an ExtAudioFile converts from the file
data format to the client data format.
Writing to an ExtAudioFile converts from the client data format to the
file data format.
Here's some code I've used in one of my projects to convert between
file formats (I used it for MP3-to-AAC, or to change bit-rates.)
The variables starting with "_" are instance variables that have
already been set up elsewhere.
The code uses some private utilities of mine, so it won't all compile
directly, but it should show you how to do the task.
—Jens
- (void) main
{
ExtAudioFileRef infile=NULL, outfile=NULL;
char *srcBuffer = NULL;
CFAbsoluteTime time = 0;
try{
// first open the input file
OSStatus err = ExtAudioFileOpenURL ((CFURLRef)_inputURL,
&infile);
XThrowIfError (err, "ExtAudioFileOpen");
// get the input file format
AudioStreamBasicDescription inputFormat;
UInt32 size = sizeof(inputFormat);
err = ExtAudioFileGetProperty(infile,
kExtAudioFileProperty_FileDataFormat, &size, &inputFormat);
XThrowIfError (err, "ExtAudioFileGetProperty
kExtAudioFileProperty_FileDataFormat");
// Fill in the output format
if( _outputFormat.mSampleRate == 0 ) {
_outputFormat.mSampleRate = inputFormat.mSampleRate;
_outputFormat.mChannelsPerFrame =
inputFormat.mChannelsPerFrame;
if( _outputFormat.mFormatID != kAudioFormatLinearPCM ) {
// use AudioFormat API to fill out the rest.
size = sizeof(_outputFormat);
err =
AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL,
&size, &_outputFormat);
XThrowIfError (err, "AudioFormatGetProperty
kAudioFormatProperty_FormatInfo");
}
}
// create the output file
UInt32 flags = _allowsOverwrite ?kAudioFileFlags_EraseFile :0;
err = ExtAudioFileCreateWithURL ((CFURLRef)_outputURL,
_outputFileType, &_outputFormat, NULL, flags, &outfile);
XThrowIfError (err, "ExtAudioFileCreateNew");
// get and set the client format - it should be lpcm
AudioStreamBasicDescription clientFormat;
if( inputFormat.mFormatID == kAudioFormatLinearPCM )
clientFormat = inputFormat;
else if( inputFormat.mFormatID == kAudioFormatLinearPCM )
clientFormat = _outputFormat;
else {
// Compressed-to-compressed conversion; make an lpcm
intermediary
clientFormat = inputFormat;
clientFormat.mFormatID = kAudioFormatLinearPCM;
clientFormat.mFormatFlags = kAudioFormatFlagsCanonical;
clientFormat.mBitsPerChannel = 8 * sizeof(AudioSampleType);
clientFormat.mFramesPerPacket = 1;
clientFormat.mBytesPerFrame =
inputFormat.mChannelsPerFrame * sizeof(AudioSampleType);
clientFormat.mBytesPerPacket = clientFormat.mBytesPerFrame;
}
size = sizeof(clientFormat);
err = ExtAudioFileSetProperty(infile,
kExtAudioFileProperty_ClientDataFormat, size, &clientFormat);
XThrowIfError (err, "ExtAudioFileSetProperty inFile,
kExtAudioFileProperty_ClientDataFormat");
size = sizeof(clientFormat);
err = ExtAudioFileSetProperty(outfile,
kExtAudioFileProperty_ClientDataFormat, size, &clientFormat);
XThrowIfError (err, "ExtAudioFileSetProperty outFile,
kExtAudioFileProperty_ClientDataFormat");
// set the bit-rate of the output file, if specified:
if( _outputBitRate > 0 ) {
AudioConverterRef outConverter;
size = sizeof(outConverter);
err = ExtAudioFileGetProperty(outfile,
kExtAudioFileProperty_AudioConverter, &size, &outConverter);
XThrowIfError (err, "ExtAudioFileGetProperty outFile,
kExtAudioFileProperty_AudioConverter");
err = AudioConverterSetProperty(outConverter,
kAudioConverterEncodeBitRate,
sizeof(_outputBitRate),
&_outputBitRate);
XThrowIfError (err, "AudioConverterSetProperty,
kAudioConverterEncodeBitRate");
CFArrayRef config = NULL;
err = ExtAudioFileSetProperty(outfile,
kExtAudioFileProperty_ConverterConfig, sizeof(config), &config);
XThrowIfError (err, "ExtAudioFileSetProperty outFile,
kExtAudioFileProperty_ConverterConfig");
}
// set up buffers
const UInt32 kSrcBufSize = 32*1024;
char *srcBuffer = new char[kSrcBufSize];
// do the read and write - the conversion is done on and by
the write call
time = TimeIntervalSinceBoot();
int nBuffers;
for( nBuffers=0; true; nBuffers++ )
{
if( self.isCancelled )
XThrowIfError(userCanceledErr,"canceled");
AudioBufferList fillBufList;
fillBufList.mNumberBuffers = 1;
fillBufList.mBuffers[0].mNumberChannels =
inputFormat.mChannelsPerFrame;
fillBufList.mBuffers[0].mDataByteSize = kSrcBufSize;
fillBufList.mBuffers[0].mData = srcBuffer;
// client format is always linear PCM - so here we
determine how many frames of lpcm
// we can read/write given our buffer size
UInt32 numFrames = (kSrcBufSize /
clientFormat.mBytesPerFrame);
err = ExtAudioFileRead (infile, &numFrames, &fillBufList);
XThrowIfError (err, "ExtAudioFileRead");
if (!numFrames) {
// this is our termination condition
NSLog(@"ConvertAudioFile: EOF after %i buffers (err=
%i,numFrames=%i)",nBuffers,err,numFrames);
break;
}
err = ExtAudioFileWrite/*Async*/(outfile, numFrames,
&fillBufList);
XThrowIfError (err, "ExtAudioFileWrite");
if( ! _startedWriting )
self.startedWriting = YES;
}
}catch( OSStatus err ) {
_error = err;
}
// close
delete[] srcBuffer;
if( outfile ) ExtAudioFileDispose(outfile);
if( infile ) ExtAudioFileDispose(infile);
}
Attachment:
smime.p7s
Description: S/MIME cryptographic signature
_______________________________________________
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