Determina il numero di fotogrammi in un Core Audio AudioBuffer
-
29-09-2019 - |
Domanda
Sto tentando di accedere ai dati grezzi di un file audio su iPhone/iPad.Ho il seguente codice che è un inizio di base lungo il percorso di cui ho bisogno.Tuttavia sono perplesso su cosa fare una volta che ho un AudioBuffer.
AVAssetReader *assetReader = [AVAssetReader assetReaderWithAsset:urlAsset error:nil];
AVAssetReaderTrackOutput *assetReaderOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:[[urlAsset tracks] objectAtIndex:0] outputSettings:nil];
[assetReader addOutput:assetReaderOutput];
[assetReader startReading];
CMSampleBufferRef ref;
NSArray *outputs = assetReader.outputs;
AVAssetReaderOutput *output = [outputs objectAtIndex:0];
int y = 0;
while (ref = [output copyNextSampleBuffer]) {
AudioBufferList audioBufferList;
CMBlockBufferRef blockBuffer;
CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(ref, NULL, &audioBufferList, sizeof(audioBufferList), NULL, NULL, 0, &blockBuffer);
for (y=0; y<audioBufferList.mNumberBuffers; y++) {
AudioBuffer audioBuffer = audioBufferList.mBuffers[y];
SInt16 *frames = audioBuffer.mData;
for(int i = 0; i < 24000; i++) { // This sometimes crashes
Float32 currentFrame = frames[i] / 32768.0f;
}
}
}
Essenzialmente non so come sapere quanti fotogrammi contiene ciascun buffer, quindi non posso estrarre in modo affidabile i dati da essi.Sono nuovo nel lavorare con dati audio grezzi, quindi sono aperto a qualsiasi suggerimento su come leggere al meglio la proprietà mData della struttura AudioBuffer.Inoltre, non ho fatto molto con i puntatori void in passato, quindi anche un aiuto in questo contesto sarebbe fantastico!
Soluzione
audioBuffer.mDataByteSize indica la dimensione del buffer.conosci questo?Nel caso in cui non l'avessi fatto, non avresti potuto guardare la dichiarazione della struttura AudioBuffer.Dovresti sempre guardare i file di intestazione e i documenti.
Affinché mDataByteSize abbia senso è necessario conoscere il formato dei dati.Il conteggio dei valori di output è mDataByteSize/sizeof(outputType).Tuttavia, sembri confuso riguardo al formato: devi averlo specificato da qualche parte.Prima di tutto lo tratti come un firmato int a 16 bit
SInt16 *frames = audioBuffer.mData
quindi lo tratti come float a 32 bit
Float32 currentFrame = frames[i] / 32768.0f
nel frattempo presumi che ci siano 24000 valori, ovviamente questo si bloccherà se non ci sono esattamente 24000 valori a 16 bit.Inoltre, ti riferisci ai dati come "frame", ma ciò che intendi veramente sono campioni.Ogni valore che chiami "currentFrame" è un campione dell'audio."Frame" si riferisce in genere a un blocco di campioni come .mData
Quindi, presupponendo che il formato dei dati sia 32 bit Float (e tieni presente che non ho idea se lo sia, potrebbe essere 8 bit int o 32 bit Fixed per quanto ne so)
for( int y=0; y<audioBufferList.mNumberBuffers; y++ )
{
AudioBuffer audioBuffer = audioBufferList.mBuffers[y];
int bufferSize = audioBuffer.mDataByteSize / sizeof(Float32);
Float32 *frame = audioBuffer.mData;
for( int i=0; i<bufferSize; i++ ) {
Float32 currentSample = frame[i];
}
}
Nota, sizeof(Float32) è sempre 4, ma l'ho lasciato per essere chiari.