Comment lire correctement décodé échantillons PCM sur iOS à l'aide de AVAssetReader — actuellement décodage incorrect

Je suis actuellement en train de travailler sur une application dans le cadre de mon Baccalauréat en Informatique. L'application permettra de corréler les données de l'iPhone matériel (accéléromètre, gps) et de la musique qui se joue.

Le projet en est encore à ses balbutiements, après avoir travaillé pendant 2 mois seulement.

Le moment que je suis maintenant, et où j'ai besoin d'aide, est la lecture d'échantillons PCM à partir de morceaux de la bibliothèque itunes, et de les lire à l'aide de et audio unit.
Actuellement, la mise en œuvre, je voudrais travailler effectue les opérations suivantes: choisit une chanson au hasard à partir d'iTunes, et lit des échantillons à partir de quand il le faut, et les stocke dans une mémoire tampon, permet de l'appeler sampleBuffer. Plus tard dans le modèle de consommation de l'unité audio (qui a une table de mixage et un remoteIO de sortie) a un rappel où j'ai tout simplement copier le nombre requis d'échantillons de sampleBuffer dans le tampon spécifié dans la fonction de rappel. Ce que je puis entendre dans les haut-parleurs est quelque chose de pas tout à fait ce que j'attends; je peux reconnaître que c'est la lecture de la chanson cependant, il semble qu'elle n'est pas correctement décodées et il a beaucoup de bruit! J'ai joint une image de la première ~une demi-seconde (24576 échantillons @ 44.1 kHz), et cela ne ressemble pas à un normall à la recherche de la sortie.
Avant d'entrer dans la liste, j'ai vérifié que le fichier n'est pas corrompu, de même j'ai écrit des scénarios de test pour la mémoire tampon (donc je sais que la mémoire tampon ne modifie pas les exemples), et bien que cela pourrait ne pas être la meilleure façon de le faire (certains diront d'aller de l'audio file d'attente de la route), je veux réaliser diverses manipulations sur les échantillons ainsi que la modification de la chanson avant qu'il est fini, le réarrangement ce morceau est joué, etc. En outre, peut-être il ya certains paramètres incorrects dans l'unité audio, toutefois, le graphique qui affiche les échantillons (qui montre les échantillons sont décodés de manière incorrecte) est pris directement à partir de la mémoire tampon, donc je suis seulement maintenant, pour résoudre le pourquoi de la lecture à partir du disque et de décodage ne fonctionne pas correctement. Droit maintenant, je tiens simplement à obtenir un jouer par le biais de travail.
Cant poster des images, car les nouvelles de stackoverflow, donc voici le lien de l'image: http://i.stack.imgur.com/RHjlv.jpg

D'inscription:

C'est là que j'ai paramétré la audioReadSettigns qui sera utilisé pour la AVAssetReaderAudioMixOutput

//Set the read settings
    audioReadSettings = [[NSMutableDictionary alloc] init];
    [audioReadSettings setValue:[NSNumber numberWithInt:kAudioFormatLinearPCM]
                         forKey:AVFormatIDKey];
    [audioReadSettings setValue:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
    [audioReadSettings setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey];
    [audioReadSettings setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey];
    [audioReadSettings setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsNonInterleaved];
    [audioReadSettings setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey];

Maintenant la liste de code suivant est une méthode qui reçoit un NSString avec le persistant_id de la chanson:

-(BOOL)setNextSongID:(NSString*)persistand_id {
assert(persistand_id != nil);
MPMediaItem *song = [self getMediaItemForPersistantID:persistand_id];
NSURL *assetUrl = [song valueForProperty:MPMediaItemPropertyAssetURL];
AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:assetUrl 
options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] 
forKey:AVURLAssetPreferPreciseDurationAndTimingKey]];
NSError *assetError = nil;
assetReader = [[AVAssetReader assetReaderWithAsset:songAsset error:&assetError] retain];
if (assetError) {
NSLog(@"error: %@", assetError);
return NO;
}
CMTimeRange timeRange = CMTimeRangeMake(kCMTimeZero, songAsset.duration);
[assetReader setTimeRange:timeRange];
track = [[songAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
assetReaderOutput = [AVAssetReaderAudioMixOutput assetReaderAudioMixOutputWithAudioTracks:[NSArray arrayWithObject:track]
audioSettings:audioReadSettings];
if (![assetReader canAddOutput:assetReaderOutput]) {
NSLog(@"cant add reader output... die!");
return NO;
}
[assetReader addOutput:assetReaderOutput];
[assetReader startReading];
//just getting some basic information about the track to print
NSArray *formatDesc = ((AVAssetTrack*)[[assetReaderOutput audioTracks] objectAtIndex:0]).formatDescriptions;
for (unsigned int i = 0; i < [formatDesc count]; ++i) {
CMAudioFormatDescriptionRef item = (CMAudioFormatDescriptionRef)[formatDesc objectAtIndex:i];
const CAStreamBasicDescription *asDesc = (CAStreamBasicDescription*)CMAudioFormatDescriptionGetStreamBasicDescription(item);
if (asDesc) {
//get data
numChannels = asDesc->mChannelsPerFrame;
sampleRate = asDesc->mSampleRate;
asDesc->Print();
}
}
[self copyEnoughSamplesToBufferForLength:24000];
return YES;
}

Le tableau qui suit présente la fonction(void)copyEnoughSamplesToBufferForLength:

-(void)copyEnoughSamplesToBufferForLength:(UInt32)samples_count {
[w_lock lock];
int stillToCopy = 0;
if (sampleBuffer->numSamples() < samples_count) {
stillToCopy = samples_count;
}
NSAutoreleasePool *apool = [[NSAutoreleasePool alloc] init];
CMSampleBufferRef sampleBufferRef;
SInt16 *dataBuffer = (SInt16*)malloc(8192 * sizeof(SInt16));
int a = 0;
while (stillToCopy > 0) {
sampleBufferRef = [assetReaderOutput copyNextSampleBuffer];
if (!sampleBufferRef) {
//end of song or no more samples
return;
}
CMBlockBufferRef blockBuffer = CMSampleBufferGetDataBuffer(sampleBufferRef);
CMItemCount numSamplesInBuffer = CMSampleBufferGetNumSamples(sampleBufferRef);
AudioBufferList audioBufferList;
CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(sampleBufferRef,
NULL,
&audioBufferList,
sizeof(audioBufferList),
NULL,
NULL,
0,
&blockBuffer);
int data_length = floorf(numSamplesInBuffer * 1.0f);
int j = 0;
for (int bufferCount=0; bufferCount < audioBufferList.mNumberBuffers; bufferCount++) {
SInt16* samples = (SInt16 *)audioBufferList.mBuffers[bufferCount].mData;
for (int i=0; i < numSamplesInBuffer; i++) {
dataBuffer[j] = samples[i];
j++;
}
}
CFRelease(sampleBufferRef);
sampleBuffer->putSamples(dataBuffer, j);
stillToCopy = stillToCopy - data_length;
}
free(dataBuffer);
[w_lock unlock];
[apool release];
}

Maintenant la sampleBuffer va mal décodé échantillons. Quelqu'un peut m'aider pourquoi est-ce donc? Ce qui se passe pour les différents fichiers sur ma bibliothèque iTunes (mp3, aac, wav, etc).
Toute aide serait grandement appréciée, en outre, si vous avez besoin de toute autre inscription de mon code, ou peut-être que la sortie ressemble, je vais la joindre par demande. J'ai été assis sur le passé la semaine à essayer de le déboguer et n'ai trouvé aucune aide en ligne-tout le monde semble être doign à ma manière, mais il semble que je suis seule à avoir ce problème.

Merci pour toute aide!

Peter

OriginalL'auteur Peter | 2012-02-20