ExtAudioFileWrite создает непригодные файлы m4a aac - PullRequest
2 голосов
/ 04 ноября 2010

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

Ответы [ 4 ]

1 голос
/ 09 марта 2012

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

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

1 голос
/ 19 января 2012

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

0 голосов
/ 22 ноября 2010

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

0 голосов
/ 04 ноября 2010

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

...