Вопрос

Я добился некоторого прогресса в получении сжатого звука (mp3) и сохранении его в формате PCM.Кроме того, я хотел разделить исходный файл на куски длительностью 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);

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

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

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

Спасибо!

-махбуд

пс.

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

        clientFormat = dstFormat;

и dstFormat:

        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
Это было полезно?

Решение

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top