Pergunta

Eu estou fazendo algum progresso em tomar um som comprimido (mp3) e salvá-lo como PCM. Além disso, eu queria dividir o arquivo original em pedaços que são 2 segundos de duração, dentro do mesmo processo. Parece-me ser bem sucedido, mas estou um pouco confuso sobre o porquê.

Como eu li blocos de áudio e gravar os arquivos para fora, eu verificar para ver se eu estou prestes a escrever um pedaço que faria meu arquivo exceder a minha 2 segundo limite. Se assim for, eu escrevo o suficiente para chegar a 2 segundos, feche o arquivo e, em seguida, abra um novo arquivo e escrever o restante para o novo arquivo, e depois ler mais dados. Algo parecido com isto:

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);

Aqui estão as minhas perguntas (Tentei rotular a linha relevante):

A: Existe uma maneira melhor para encontrar o deslocamento em meu tampão então eu não erroneamente rígido código algum valor lá dentro? Por exemplo, há uma maneira abençoada para obter os dados deslocado do número do quadro?

B: Se ExtAudioFileWrite está fazendo a conversão de comprimido para descompactados, em seguida, os dados que eu estou escrevendo ainda não foi descompactado, então eu não deveria ter que se preocupar com a brincar com números de quadro e deslocamentos quando eu (certo?) estou lidando com dados comprimidos? Devo vez ser converter o arquivo primeiro, seja para um arquivo PCM ou na memória, e depois dividir esse PCM?

Obrigado!

-mahboud

ps.

O clientFormat é definido da seguinte forma:

        clientFormat = dstFormat;

e 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
Foi útil?

Solução

É difícil responder corretamente sem ver um pouco mais de código. Mas, supondo que clientFormat é um formato PCM intercalada:

B) ExtAudioFileWrite não executa a conversão de comprimido para descomprimido, ExtAudioFileRead does- dependendo do formato em que o cliente tiver definido. Assumindo um arquivo de origem MP3 e um formato de cliente PCM "padrão" de 16 bits 44,1 KHz, chamadas para ExtAudioFileRead irá converter do MP3 bytes para dados de PCM. Isso é feito sob a capa usando AudioFile e APIs AudioConverter.

A) Isto é um pouco difícil de responder sem ver como srcBuffer é definido (eu assumo um conjunto de int16_t). Se você estiver trabalhando com dados de PCM, o que você está fazendo parece ok. Você também pode usar newNumFrames * clientFormat.mBytesPerFrame * clientFormat.mChannelsPerFrame, mas assumindo dados PCM de 16 bits, mBytesPerFrame == mBytesPerPacket == 2. Se você estava trabalhando com dados não-CBR você precisaria se preocupar com as descrições de pacotes, mas que não parece ser o caso.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top