2010-11-04 57 views
2

我想將單聲道線性pcm文件轉換爲aac文件。經過很多努力,我終於用下面的設置把它輸出,但現在文件不能播放。我真的不知道去哪裏看 - 我發現的所有例子都與我已有的類似。ExtAudioFileWrite產生不可用的m4a aac文件

我看過的所有示例都有destFormat.mBytesPerPacket = 0,但是我不能寫它然後(我得到一個-66567寫入,它解析爲kExtAudioFileError_MaxPacketSizeUnknown)。

ExtAudioFileRef sourceFile = 0; 
ExtAudioFileRef destinationFile = 0; 
OSStatus  error = noErr; 

AudioStreamBasicDescription srcFormat, destFormat; 
UInt32 size = sizeof(srcFormat); 
error = ExtAudioFileOpenURL((CFURLRef)self.track.location, &sourceFile); 
if(error != noErr) 
    NSLog(@"conversion error: %i", error); 
error = noErr; 

ExtAudioFileGetProperty(sourceFile, kExtAudioFileProperty_FileDataFormat, &size, &srcFormat); 

destFormat.mFormatID = kAudioFormatMPEG4AAC; 
destFormat.mSampleRate = 22000; 
destFormat.mFormatFlags = 0; 
destFormat.mBytesPerPacket = 2; // must have a value or won't write apparently 
destFormat.mFramesPerPacket = 0; 
destFormat.mBytesPerFrame = 0; 
destFormat.mChannelsPerFrame = 1; 
destFormat.mBitsPerChannel = 0; 
destFormat.mReserved = 0; 

//create the output file 

NSString *destURL = [self.track.location absoluteString]; 
NSLog(@"source url: %@", destURL); 
destURL = [destURL substringToIndex:([destURL length] - 3)]; //remove caf extension 
NSLog(@"source url with no extension: %@", destURL); 
destURL = [NSString stringWithFormat:@"%@m4a",destURL]; //add acc extension 
NSLog(@"dest url with correct extension: %@", destURL); 
NSURL *destinationURL = [NSURL URLWithString:destURL]; 

size = sizeof(destFormat); 
AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, nil, &size, &destFormat); 

error = ExtAudioFileCreateWithURL((CFURLRef)destinationURL, kAudioFileM4AType, &destFormat, NULL, kAudioFileFlags_EraseFile, &destinationFile); 
if(error != noErr) 
    NSLog(@"conversion error: %i", error); 
error = noErr; 

//canonical format 
AudioStreamBasicDescription clientFormat; 
clientFormat.mFormatID = kAudioFormatLinearPCM; 
clientFormat.mSampleRate = 22000; 
int sampleSize = sizeof(AudioSampleType); 
clientFormat.mFormatFlags = kAudioFormatFlagsCanonical; 
clientFormat.mBitsPerChannel = 8 * sampleSize; 
clientFormat.mChannelsPerFrame = 1; 
clientFormat.mFramesPerPacket = 1; 
clientFormat.mBytesPerPacket = sampleSize; 
clientFormat.mBytesPerFrame = sampleSize; 
clientFormat.mFormatFlags |= kAudioFormatFlagIsNonInterleaved; 

//set the intermediate format to canonical on the source file for conversion (?) 
ExtAudioFileSetProperty(sourceFile, kExtAudioFileProperty_ClientDataFormat, size, &clientFormat); 

//get the converter 
AudioConverterRef audioConverter; 
size = sizeof(audioConverter); 
error = ExtAudioFileGetProperty(destinationFile, kExtAudioFileProperty_AudioConverter, &size, &audioConverter); 
if(error != noErr) 
    NSLog(@"error getting converter: %i", error); 
error = noErr; 

/*UInt32 bitRate = 64000; 
error = AudioConverterSetProperty(audioConverter, kAudioConverterEncodeBitRate, sizeof(bitRate), &bitRate); 
if(error != noErr) 
    NSLog(@"error setting bit rate: %i", error); 
error = noErr;*/ 

// set up buffers 
UInt32 bufferByteSize = 32768; 
char srcBuffer[bufferByteSize]; 

NSLog(@"converting..."); 

int i=0; 
while (true) { 
    i++; 
    AudioBufferList fillBufList; 
    fillBufList.mNumberBuffers = 1; 
    fillBufList.mBuffers[0].mNumberChannels = 1; 
    fillBufList.mBuffers[0].mDataByteSize = bufferByteSize; 
    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 = bufferByteSize/clientFormat.mBytesPerFrame; 

    error = ExtAudioFileRead(sourceFile, &numFrames, &fillBufList); 
    if(error != noErr) 
     NSLog(@"read error: %i run: %i", error, i); 

    if (!numFrames) { 
     // this is our termination condition 
     error = noErr; 
     break; 
    } 

    //this is the actual conversion 
    error = ExtAudioFileWrite(destinationFile, numFrames, &fillBufList); 

    if(error != noErr) 
     NSLog(@"conversion error: %i run: %i", error, i); 
} 

if (destinationFile) ExtAudioFileDispose(destinationFile); 
if (sourceFile) ExtAudioFileDispose(sourceFile); 
+0

我通過放棄和使用AVAssetExportSession來解決這個問題。瘋狂的核心音頻是這樣的神祕。 – John 2010-11-04 05:11:30

回答

0

您需要在目標文件上設置客戶端數據格式以匹配源文件上的客戶端格式。你現在設置的方式是目標文件,希望你把它交給AAC,而你不是。

+0

我試過了,似乎沒有什麼區別。也許我做錯了?我基本上在源文件中使用了相同的行,但是使用目標文件代替sourceFile。 – John 2010-11-05 01:33:13

0

核心音頻確實很神祕,錯誤結果通常與真正的錯誤沒有多大關係。我看到的最明顯的問題是22000的採樣率對於AAC是不合法的。一些有效的採樣率是32000,44100或48000.我不確定其他人是否支持,但通常他們甚至是倍數或可被這些數字整除。

+0

@約翰:也許你的意思是'22050'? – 2011-04-09 23:04:30

1

您必須設置kExtAudioFileProperty_ClientDataFormat才能編碼爲非pcm格式(根據文檔)。客戶端格式是您想要處理應用中的音頻數據的格式(通常爲pcm)。

相關問題