我正在努力将录制的pcm/caf文件(通过AudioQueue录制)转换为m4a文件.我应该可以使用"AudioConverter.h",但似乎并不容易.
如果您已经看过一个示例或者有一个代码片段,那么如果您可以发布它就会很棒.
谢谢你的帮助
汤姆
这里是我在实际生产代码中用于转换音频文件的代码片段:
- (BOOL)convertWithDocument:(SoundDocumentCore*)document selection: (SoundSelection*)selection saveTo:(NSString*)path fileType:(UInt32)fileType progress:(ProgressSheet*)progress { OSStatus err; ExtAudioFileRef eafRef; UInt32 n; UInt32 dataFormat = [self dataFormat]; SInt32 bitRate = [self bitRate]; // -- Data Source -- // Calculate offsets from selection, if any UInt64 offset = 0, length = [document numFrames]; SInt32 trackOffset = 0, numTracks = [document numTracks]; if (selection != nil) { trackOffset = [selection firstTrack]; numTracks = [selection numTracks]; offset = round ([selection startTime] * [document sampleRate]); length = round ([selection duration] * [document sampleRate]); } // -- Extended Audio File -- NSString *parentPath = [path stringByDeletingLastPathComponent]; NSString *fileName = [self flipColonsAndSlashes:[path lastPathComponent]]; FSRef parentDir; AudioStreamBasicDescription inputFormat, outputFormat; // Create FSRef from path err = FSPathMakeRef ((const UInt8*)[parentPath fileSystemRepresentation], &parentDir, nil); if (err != noErr) {if (mVerbose) NSLog(@"-[AudioFile convertWithDocument:] FSPathMakeRef() error %d", err); return NO;} // Delete the existing file [[NSFileManager defaultManager] removeFileAtPath: path handler:nil]; // Set up the input and output data formats inputFormat.mSampleRate = [document sampleRate]; inputFormat.mFormatID = kAudioFormatLinearPCM; inputFormat.mFormatFlags = kLinearPCMFormatFlagIsFloat | kAudioFormatFlagsNativeEndian; inputFormat.mBytesPerFrame = sizeof(float) * numTracks; inputFormat.mFramesPerPacket = 1; inputFormat.mBytesPerPacket = inputFormat.mBytesPerFrame * inputFormat.mFramesPerPacket; inputFormat.mChannelsPerFrame = numTracks; inputFormat.mBitsPerChannel = 32; inputFormat.mReserved = 0; [self getFileDataFormat: &outputFormat]; // Create an audio file and then wrap it with ExtAudioFile AudioFileID audioFileID; FSRef audioFileRef; err = AudioFileCreate(&parentDir, (CFStringRef) fileName, fileType, &outputFormat, nil, &audioFileRef, &audioFileID); if (err != noErr) {if (mVerbose) NSLog(@"-[AudioFile convertWithDocument:] AudioFileCreate() error %d", err); return NO;} // Add user data [self addUserDataToAudioFile:audioFileID]; // Wrap it in ExtAudioFile err = ExtAudioFileWrapAudioFileID(audioFileID, YES, &eafRef); if (err != noErr) {if (mVerbose) NSLog(@"-[AudioFile convertWithDocument:] ExtAudioFileWrapAudioFileID() error %d", err); return NO;} //err = ExtAudioFileCreateNew (&parentDir, (CFStringRef) fileName, fileType, &outputFormat, nil, &eafRef); //if (err != noErr) {if (mVerbose) NSLog(@"-[AudioFile convertWithDocument:] ExtAudioFileCreateNew() error %d", err); return NO;} // Set the client data format err = ExtAudioFileSetProperty (eafRef, kExtAudioFileProperty_ClientDataFormat, sizeof (AudioStreamBasicDescription), &inputFormat); if (err != noErr) {if (mVerbose) NSLog(@"-[AudioFile convertWithDocument:] ExtAudioFileSetProperty() error %d", err); return NO;} // -- AudioConverter Setup -- AudioConverterRef converter; n = sizeof (converter); err = ExtAudioFileGetProperty (eafRef, kExtAudioFileProperty_AudioConverter, &n, &converter); if (err != noErr) {if (mVerbose) NSLog(@"-[AudioFile convertWithDocument:] ExtAudioFileGetProperty() error %d", err); return NO;} // Set quality UInt32 quality = kAudioCodecQuality_Max; err = AudioConverterSetProperty(converter, kAudioConverterEncodeBitRate, sizeof (quality), &quality); // Set bit rate if ((bitRate != 0) && (dataFormat == kAudioFormatMPEG4AAC)) { err = AudioConverterSetProperty(converter, kAudioConverterEncodeBitRate, sizeof (bitRate), &bitRate); if (err != noErr) {if (mVerbose) NSLog(@"-[AudioFile convertWithDocument:] AudioConverterSetProperty() error %d", err);} } // Resynchronize ExtAudioFile with AudioConverter n = 0; err = ExtAudioFileSetProperty (eafRef, kExtAudioFileProperty_ConverterConfig, sizeof (n), &n); if (err != noErr) {if (mVerbose) NSLog(@"-[AudioFile convertWithDocument:] ExtAudioFileSetProperty() error %d", err);} // -- Write Data -- const UInt32 maxBufferSize = 256 * 1024L; SInt64 remain = length; UInt32 frameSize = inputFormat.mBytesPerFrame; UInt32 maxNumFrames = maxBufferSize / frameSize; NSMutableData *bufferListData = [NSMutableData dataWithLength: 16]; AudioBufferList *bufferList = [bufferListData mutableBytes]; NSData *bufferData; NSAutoreleasePool *pool; BOOL success = YES; // Loop while ((remain > 0) && (success == YES)) { pool = [[NSAutoreleasePool alloc] init]; // Calculate number of frames to write n = (remain < maxNumFrames)? remain : maxNumFrames; // Get sample data from document bufferData = [document interleavedDataAtOffset: offset numFrames: n firstTrack: trackOffset numTracks: numTracks]; // Set up audio buffer list bufferList->mNumberBuffers = 1; bufferList->mBuffers[0].mNumberChannels = numTracks; bufferList->mBuffers[0].mDataByteSize = [bufferData length]; bufferList->mBuffers[0].mData = (void*) [bufferData bytes]; // Write data to disk err = ExtAudioFileWrite (eafRef, n, bufferList); if (err != noErr) {if (mVerbose) NSLog(@"-[AudioFile convertWithDocument:] ExtAudioFileWrite() error %d", err);} [pool release]; // Update counters offset += n; remain -= n; // Update progress window [progress setMarkValue: [progress markValue] + n]; if ([progress isCancelled]) success = NO; } // -- Clean Up -- err = ExtAudioFileDispose (eafRef); if (err != noErr) {if (mVerbose) NSLog(@"-[AudioFile convertWithDocument:] ExtAudioFileDispose() error %d", err);} err = AudioFileClose (audioFileID); if (err != noErr) {if (mVerbose) NSLog(@"-[AudioFile convertWithDocument:] AudioFileClose() error %d", err);} return success; }