Iphone ExtAudioFileWrite生成不可用的m4a aac文件

Iphone ExtAudioFileWrite生成不可用的m4a aac文件,iphone,core-audio,Iphone,Core Audio,我正在尝试将单线pcm文件转换为aac文件。经过一番努力,我终于用下面的设置将其输出,但现在该文件无法播放。我真的不知道该去哪里找——我找到的所有例子都和我已经找到的相似 我看到的所有示例都有destFormat.mBytesPerPacket=0,但我当时无法将其写入(写入时得到-66567,这将解析为kExtAudioFileError\u MaxPacketSizeUnknown) 您需要在目标文件上设置客户端数据格式,以匹配源文件上的客户端格式。您现在设置它的方式目标文件希望您将其交给A

我正在尝试将单线pcm文件转换为aac文件。经过一番努力,我终于用下面的设置将其输出,但现在该文件无法播放。我真的不知道该去哪里找——我找到的所有例子都和我已经找到的相似

我看到的所有示例都有destFormat.mBytesPerPacket=0,但我当时无法将其写入(写入时得到-66567,这将解析为kExtAudioFileError\u MaxPacketSizeUnknown)


您需要在目标文件上设置客户端数据格式,以匹配源文件上的客户端格式。您现在设置它的方式目标文件希望您将其交给AAC,而您不是。

核心音频确实令人迷惑,错误结果通常与真正的错误无关。我看到的最明显的问题是22000的抽样率对于AAC来说是无效的。部分有效采样率为32000、44100或48000。我不确定是否支持其他格式,但通常情况下,它们甚至是这些数字的倍数或可被这些数字整除。

您必须设置
kExtAudioFileProperty\u ClientDataFormat
才能编码为非pcm格式(根据文档)。客户端格式是您希望在应用程序(通常是pcm)中处理音频数据的格式。

这里发布了一个很好的示例:


这并不完全是您想要的,但它将在m4a中读取->转换为pcm->更改音量->然后保存回m4a。

我放弃并使用AVAssetExportSession解决了这个问题。疯狂的核心音频是如此神秘。我试过了,似乎没有什么不同。也许我做错了?我基本上在源文件上使用了同一行,但目标文件取代了源文件。@John:也许你是说
22050
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);