domande ExtAudioFileConvert
-
19-09-2019 - |
Domanda
sto facendo qualche progresso di prendere un (mp3) suono compressa e salvarlo come PCM. Inoltre, ho voluto dividere il file originale in blocchi che sono lunghe 2 secondi, all'interno dello stesso processo. Mi sembra di avere successo, ma io sono un po 'confuso sul perché.
Mentre leggevo blocchi di audio e scrivere i file fuori, controllo per vedere se sto per scrivere un pezzo che avrebbe fatto il mio file supera il mio limite di 2 secondo. Se è così, scrivo abbastanza per arrivare a 2 secondi, chiudere il file, e quindi aprire un nuovo file e scrivere il resto nel nuovo file, e quindi leggere più dati. Qualcosa di simile a questo:
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);
Ecco le mie domande (ho cercato di etichettare la relativa riga):
A: C'è un modo migliore per trovare l'offset nel mio tampone in modo da non erroneamente codice duro qualche valore in là? Per esempio, c'è un modo benedetta per ottenere i dati di correzione dal numero di telaio?
B: Se ExtAudioFileWrite sta facendo la conversione da compressa decompresso, quindi i dati che sto scrivendo non è ancora stato decompresso (giusto?), Quindi non dovrebbe ho dovuto preoccuparsi di giocare con i numeri di telaio e offset quando ho occupo di dati compressi? Dovrei essere invece la conversione del file prima, sia in un file PCM o nella memoria, e poi dividere quel PCM?
Grazie!
-mahboud
ps.
Il clientFormat è definito come segue:
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
Soluzione
E 'difficile rispondere correttamente senza vedere un po' più di codice. Ma, supponendo clientFormat è un formato PCM Interleaved:
B) ExtAudioFileWrite non esegue la conversione da compressa decompresso, ExtAudioFileRead does- a seconda di quale formato cliente è stata impostata. Ipotizzando un file sorgente MP3 e una a 16 bit 44.1 KHz formato PCM cliente "standard", chiamate a ExtAudioFileRead convertirà dai byte MP3 ai dati PCM. Questo viene fatto sotto il cofano utilizzando AudioFile e le API AudioConverter.
A) Questo è un po 'difficile da rispondere senza vedere come srcBuffer è definito (presumo un array di int16_t). Se si lavora con i dati PCM, cosa si sta facendo sembra OK. Si potrebbe anche usare newNumFrames * * clientFormat.mBytesPerFrame clientFormat.mChannelsPerFrame, ma assumendo dati PCM a 16 bit, mBytesPerFrame == mBytesPerPacket == 2. Se si stava lavorando con dati non CBR si avrebbe bisogno di preoccuparsi con le descrizioni dei pacchetti, ma che non sembra essere il caso.