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
Vous devez vous connecter pour publier un commentaire.
Actuellement, je travaille aussi sur un projet qui consiste à extraire des échantillons audio à partir de la Bibliothèque iTunes dans AudioUnit.
La audiounit rendre retour d'appel est inclus pour votre référence. Le format d'entrée est défini comme SInt16StereoStreamFormat.
J'ai fait usage de Michael Tyson tampon circulaire de mise en œuvre - TPCircularBuffer comme le tampon de stockage. Très facile à utiliser et à comprendre!!! Merci Michael!
Qu'est-ce que kUnitSize? et qu'est-ce que kTotalBufferSize?
Dans mon cas, j'ai utilisé le paramètre suivant
#define kUnitSize sizeof(AudioSampleType) #define kBufferUnit 655360 #define kTotalBufferSize kBufferUnit * kUnitSize
pouvez-vous s'il vous plaît laissez-nous savoir si ce code fonctionne avec iOS? basé sur mon peu de recherches jusqu'à présent sur les appareils audio, il semble que iOS a beaucoup moins de audio de l'unité de fonctionnalités que son homologue OSX
Vous de vérifier que le tampon circulaire a au moins 32768 disponible avant le remplissage, et c'est le même nombre CMSampleBufferGetTotalSampleSize retourne, mais je me demande si cette taille pourrait jamais être différent pour quelque raison que ce soit. Aucune signification particulière pour elle étant ce qu'elle est?
OriginalL'auteur infiniteloop
Je suppose que c'est le genre de fin, mais vous pouvez essayer cette bibliothèque:
https://bitbucket.org/artgillespie/tslibraryimport
Après l'utilisation de cette option pour enregistrer l'audio dans un fichier, vous pouvez traiter les données avec le rendu des rappels à partir de MixerHost.
OriginalL'auteur Totoro
Si j'étais vous, je voudrais utiliser kAudioUnitSubType_AudioFilePlayer de lire le fichier et accéder à ses échantillons avec les unités de rendu de rappel.
Ou
Utilisation ExtAudioFileRef pour extraire les échantillons directement à un tampon.
Je n'ai pas beaucoup d'expérience avec la bibliothèque itune, j'ai peur. Est-ce à aider à bien? subfurther.com/blog/2010/12/13/...
OriginalL'auteur dubbeat