ExtAudioFileConvert вопросы

Я делаю некоторые успехи в том, чтобы взять сжатый (mp3) звук и сохранить его как PCM. Кроме того, я хотел разбить исходный файл на куски по 2 секунды в рамках одного процесса. Я, кажется, добился успеха, но я немного смущен тем, почему.

Когда я читаю блоки аудио и записываю файлы, я проверяю, не собираюсь ли я написать фрагмент, из-за которого мой файл превысит 2-секундный лимит. Если это так, я пишу достаточно, чтобы добраться до 2 секунд, закрыть файл, а затем открыть новый файл и записать остаток в новый файл, а затем прочитать больше данных. Что-то вроде этого:

framesInTimedSegment += numFrames;
if ((framesInTimedSegment  > (2.0 * sampleRate)) && (j < 5)) {
    UInt32 newNumFrames = numFrames;
    numFrames = framesInTimedSegment - (2.0 * sampleRate);
    newNumFrames -= numFrames;
// Question A
    UInt32 segmentOffset = newNumFrames * numChannels * 2;
    error = ExtAudioFileWrite(segmentFile, newNumFrames, &fillBufList);
// Question B
       // handle this error!  We might have an interruption
    if (segmentFile) ExtAudioFileDispose(segmentFile);
    XThrowIfError(ExtAudioFileCreateWithURL(urlArray[++j], kAudioFileCAFType, &dstFormat, NULL, kAudioFileFlags_EraseFile, &breakoutFile), "ExtAudioFileCreateWithURL failed! - segmentFile");
    size = sizeof(clientFormat);
    XThrowIfError(ExtAudioFileSetProperty(segmentFile, kExtAudioFileProperty_ClientDataFormat, size, &clientFormat), "couldn't set destination client format"); 
    fillBufList.mBuffers[0].mData = srcBuffer + segmentOffset;
    fillBufList.mBuffers[0].mDataByteSize = numFrames * fillBufList.mBuffers[0].mNumberChannels * 2;
    framesInTimedSegment = numFrames;
}
error = ExtAudioFileWrite(segmentFile, numFrames, &fillBufList);

Вот мои вопросы (я попытался пометить соответствующую строку):

О: Есть ли лучший способ найти смещение в моем буфере, чтобы ошибочно не закодировать туда какое-то значение? Например, есть ли благословенный способ получить смещение данных от номера кадра?

B: Если ExtAudioFileWrite выполняет преобразование из сжатого в распакованный, то данные, которые я записываю, еще не были распакованы (правильно?), так что не должен ли я беспокоиться об игре с номерами кадров и смещениями, когда я имею дело с сжатые данные? Должен ли я вместо этого сначала преобразовать файл либо в файл PCM, либо в память, а затем разделить этот файл PCM?

Спасибо!

-махбуд

ps.

clientFormat определяется следующим образом:

        clientFormat = dstFormat;

и формат dst:

        dstFormat.mFormatID = outputFormat;
        dstFormat.mChannelsPerFrame = srcFormat.NumberChannels();
        dstFormat.mBitsPerChannel = 16;
        dstFormat.mBytesPerPacket = dstFormat.mBytesPerFrame = 2 * dstFormat.mChannelsPerFrame;
        dstFormat.mFramesPerPacket = 1;
        dstFormat.mFormatFlags = kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsSignedInteger; // little-endian

person mahboudz    schedule 08.01.2010    source источник


Ответы (1)


Трудно ответить правильно, не видя еще немного кода. Но, предполагая, что clientFormat является чередующимся форматом PCM:

Б) ExtAudioFileWrite не выполняет преобразование из сжатого в распакованный, ExtAudioFileRead делает - в зависимости от того, какой формат клиента вы установили. Предполагая исходный файл MP3 и «стандартный» 16-битный клиентский формат PCM 44,1 кГц, вызовы ExtAudioFileRead будут преобразовывать байты MP3 в данные PCM. Это делается с помощью API-интерфейсов AudioFile и AudioConverter.

A) На этот вопрос сложно ответить, не видя, как определяется srcBuffer (я предполагаю, что это массив int16_t). Если вы работаете с данными PCM, все выглядит нормально. Вы также можете использовать newNumFrames * clientFormat.mBytesPerFrame * clientFormat.mChannelsPerFrame, но предполагая 16-битные данные PCM, mBytesPerFrame == mBytesPerPacket == 2. Если вы работали с данными, отличными от CBR, вам нужно было бы позаботиться об описаниях пакетов, но это не похоже на то.

person sbooth    schedule 08.01.2010
comment
Очень хороший ответ... Приведенный выше код — это единственные изменения, которые я внес в ExtAudioFileConvert.cpp из примера Apple, iPhoneExtAudiofileConvertTest, возможно, вы знакомы с ним. Скажите, правильно ли я понимаю: Если бы я читал MP3 и писал PCM, то преобразование происходит в файле ExtAudioFileRead. Если бы я читал PCM и писал MP3, то преобразование происходит в ExtAudioFileWrite. Это правильно? Я добавил формат клиента в исходный вопрос. - person mahboudz; 08.01.2010
comment
Это правильно. ExtAudioFileRead преобразует собственный формат файла в формат клиента, а ExtAudioFileWrite из формата клиента в выходной формат файла. - person sbooth; 09.01.2010
comment
Ненавижу задавать еще один вопрос, но из примера Apple кажется, что следует беспокоиться о прерываниях ExtAudioWrite, а не ExtAudioRead. Это правильно? Возможно, мне придется опубликовать это в списке рассылки CoreAudio. - person mahboudz; 14.01.2010
comment
У меня нет никакого основного звука на iPhone, извините. - person sbooth; 14.01.2010