2009-08-20 24 views
3

我很努力地將記錄的pcm/caf文件(通過AudioQueue錄製)轉換爲m4a文件。我應該可以通過「AudioConverter.h」以某種方式實現,但看起來並不容易。尋找一些示例代碼音頻轉換用iPhone caf => m4a

如果你看過一個例子或者有一個代碼片段,它會很棒,如果你可以發佈它。

感謝您的幫助

湯姆

回答

5

這裏從我在現實生活的生產代碼用於轉換音頻文件的代碼片段:

- (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; 
} 
+2

你能否提供一些工作代碼.. – Saurabh 2010-08-26 12:09:32

+1

從哪裏我可以得到像SoundDocumentCore幾個類庫? – jfalexvijay 2011-01-26 05:14:58

+0

嘿什麼「SoundDocumentCore」在上面的代碼? – Saurabh 2011-05-12 13:11:39

0

你設置的「質量」和使用kAudioConverterEncodeBitRate的相同屬性值的「比特率」 - 這是不正確的,因爲編解碼器質量是使用kAudioConverterCodecQuality設置的。你不會注意到,如果這個返回錯誤是因爲你沒有檢查它,那麼你覆蓋了錯誤值。

我建議看一下ConvertFile蘋果示例,演示如何正確執行此操作並處理分層的AAC格式和啓動信息。

http://developer.apple.com/library/mac/#samplecode/ConvertFile/

+0

Stackoverflow不是一個基於線程的論壇。這是以問答爲重點。這意味着如果你想對anser發表評論,你必須在評論中這樣做,而不是單獨回答。你的答案部分是對以前答案的評論,所以應該發表評論。因爲3年前您最後一次看到您,所以我會將您的答案複製到評論中。 – 2014-02-24 12:00:39

0

有附帶自由DiracLE時間http://dirac.dspdimension.com拉伸庫的示例代碼。我一直在我的代碼中使用他們的EAFWrite類,因爲它很好地包裝了整個AudioFile/ExtAudioFile API業務。