2010-11-28 56 views
7

J'essaie d'accéder aux données brutes pour un fichier audio sur l'iPhone/iPad. J'ai le code suivant qui est un début de base sur le chemin dont j'ai besoin. Cependant, je suis perplexe sur ce qu'il faut faire une fois que j'ai un AudioBuffer.Déterminer le nombre de trames dans un AudioBuffer Audio Core

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

Essentiellement, je ne sais pas comment dire combien de cadres chaque tampon contient donc je ne peux pas extraire de manière fiable les données de leur part. Je suis nouveau à travailler avec des données audio brutes ainsi je suis ouvert à toutes les suggestions dans la façon de lire au mieux la propriété mData de la structure AudioBuffer. Je n'ai pas non plus fait grand-chose avec des pointeurs vides dans le passé, donc aider dans ce contexte serait génial aussi! AudioBuffer.mDataByteSize vous indique la taille de la mémoire tampon.

+0

Excellente question! Votre question a aidé à résoudre mon problème similaire. – user523234

+0

vous fuyez blockBuffer –

Répondre

13

Le savais-tu? Juste au cas où vous ne l'avez pas vous ne pouvez pas avoir regardé la déclaration de struct AudioBuffer. Vous devriez toujours regarder les fichiers d'en-tête ainsi que les docs.

Pour que mDataByteSize ait du sens, vous devez connaître le format des données. Le nombre de valeurs de sortie est mDataByteSize/sizeof (outputType). Cependant, vous semblez confus au sujet du format - vous devez l'avoir spécifié quelque part. Tout d'abord vous traiter comme un 16bit signé int

SInt16 *frames = audioBuffer.mData

vous traiter comme 32 bits flottant

Float32 currentFrame = frames[i]/32768.0f

inbetween vous présumait qu'il existe des 24000 valeurs, bien sûr, cette volonté planter s'il n'y a pas exactement 24000 valeurs 16bit. En outre, vous vous référez aux données en tant que «cadres», mais ce que vous voulez vraiment dire, ce sont des échantillons. Chaque valeur que vous appelez "currentFrame" est un échantillon de l'audio. Donc, en supposant que le format de données est 32bit Float (et s'il vous plaît noter, je ne sais pas si c'est le cas, il pourrait être 8 bits int, ou 32 bits fixe) 32 bits pour tout ce que je sais)

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]; 
    } 
} 

Notez, sizeof (Float32) est toujours 4, mais je l'ai laissé pour être clair.

+0

audioBuffer.mDataByteSize/sizeof (Float32) était la partie dont j'avais besoin merci! – macinjosh

+0

Si vous cliquez sur AudioBuffer, xcode devrait sauter à la déclaration stricte dans le fichier d'en-tête. Utile pour vérifier ce que vous traitez. – hooleyhoop

+4

Une digression, mais la définition Core Audio d'une image est un échantillon sur tous les canaux. – sbooth