ExtAudioFileWrite создает непригодные для использования файлы m4a aac

Я пытаюсь преобразовать монолинейный файл PCM в файл 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);

person John    schedule 04.11.2010    source источник
comment
Я работал над этим, отказавшись и используя AVAssetExportSession. Безумие, что основной звук такой загадочный.   -  person John    schedule 04.11.2010


Ответы (4)


Вы должны установить kExtAudioFileProperty_ClientDataFormat для кодирования в форматы, отличные от PCM (согласно документации). Формат клиента — это формат, в котором вы хотите работать с аудиоданными в своем приложении (обычно pcm).

person Dominik Seibold    schedule 19.01.2012

Хороший пример опубликован здесь: Использование AVMutableAudioMix для регулировки громкости дорожек в активе

Это не совсем то, что вам нужно, но оно будет читаться в m4a -> конвертировать в pcm -> изменять громкость -> затем сохранять обратно в m4a.

person Dex    schedule 09.03.2012

Вам необходимо установить формат данных клиента в целевом файле, чтобы он соответствовал формату клиента в исходном файле. То, как вы его настроили сейчас, файл назначения ожидает, что вы передадите ему AAC, а это не так.

person sbooth    schedule 04.11.2010
comment
Я так пробовал, разницы вроде нет. Может я неправильно делал? В основном я использовал ту же строку в исходном файле, но с файлом назначения вместо исходного файла. - person John; 05.11.2010

Core Audio действительно загадочен, и результаты ошибок обычно имеют мало общего с тем, что действительно не так. Наиболее очевидная проблема, которую я вижу, заключается в том, что частота дискретизации 22000 не подходит для AAC. Некоторые из допустимых частот дискретизации — 32000, 44100 или 48000. Я не уверен, поддерживаются ли другие, но обычно они кратны или без остатка делятся на эти числа.

person lucius    schedule 22.11.2010
comment
@John: Возможно, вы имели в виду 22050? - person Peter Hosey; 10.04.2011