2010-08-24 3 views
1

J'ai presque fini de travailler sur une fonctionnalité de bruit blanc pour une de mes applications utilisant NSSound pour lire une boucle de 10 secondes codée AAC bruit blanc pré-enregistré.Un framework de type NSSound qui fonctionne, mais qui ne nécessite pas de courbe d'apprentissage abrupte

[sound setLoops: YES] 

devrait être tout ce qui est nécessaire, non?

Cela fonctionne comme un charme, mais j'ai remarqué qu'il y a une pause audible entre la fin du fichier sonore et le redémarrage .. une sorte de "plop" son. Ceci n'est pas présent lors de la lecture en boucle des fichiers audio originaux et après une heure ou deux d'essayer de comprendre cela, je suis arrivé à la conclusion que NSSound est nul et que la pause audible est un artefact de la synchronisation du thread d'arrière-plan privé jouer le son. Cela semble être en quelque sorte dépendant de la boucle d'exécution principale, ce qui provoque l'écart audible entre la fin et le redémarrage du son. Je connais très peu de choses sur le son et c'est une caractéristique très mineure, donc je ne veux pas entrer dans les profondeurs de CoreAudio juste pour jouer un fragment de son 10s en boucle .. alors je suis allé à la poursuite d'une belle alternative , mais rien ne semble tout à fait en forme:

  • Core Audio: overkill total, mais au moins un cadre standard
  • AudioQueue: compliqué, avec exemple de code de C !?
  • MusicKit/SndKit: courbe d'apprentissage aussi énorme, basé sur beaucoup de choses open source, etc.

j'ai vu que AVFoundation sur iOS 4 serait une belle façon de jouer des sons, mais qui est seulement prévue pour le Mac OS X 10.7 ..

Existe-t-il un moyen facile d'utiliser le bouclage fiable du son sur Mac OS X 10.5+?

Existe-t-il un exemple de code pour AudioQueue ou Core Audio qui supprime la douleur de les utiliser à partir d'une application Objective-C?

Toute aide serait très apprécié ..

Meilleures salutations,

Frank

Répondre

2

Utilisez QTKit. Créez un QTMovie pour le son, réglez-le en boucle et laissez-le jouer.

+0

Isn 't QTKit 32 bits et non-garbage collectable? Mes applications sont toutes éditées au format 64 bits. –

+0

D'accord. Le plus difficile avec QTKit est de l'inclure dans votre projet (ce qui prend quelques secondes). –

+0

Je l'ai vu travailler avec QTKit .. Je pensais que QuickTime ne peut pas fonctionner en 64 bits ou dans un mode de collecte de déchets, il ne valait pas la peine d'essayer QTKit non plus .. mais il semble fonctionner très bien. Merci. –

0

Malheureusement, il y a beaucoup de douleur lorsque le développement d'applications audio sur OS X. La courbe d'apprentissage est très raide parce que la documentation est assez clairsemée.

Si cela ne vous dérange pas Objective-C++ j'ai écrit un cadre pour ce genre de chose: SFBAudioEngine. Si vous voulez jouer un son avec mon code voici comment vous pouvez le faire:

DSPAudioPlayer *player = new DSPAudioPlayer(); 
player->Enqueue((CFURLRef)audioURL); 
player->Play(); 

Looping est également possible.

+0

Merci pour aider. Je vais mettre la solution QTKit de Mike à l'épreuve pour voir que ça fonctionne vraiment bien, mais à moins que quelque chose d'inattendu ne sorte, je m'en tiendrai probablement à mes humbles besoins ... mais on ne sait jamais :-) –

2

Juste pour les archives.

QTKit souffre également d'un écart entre la fin d'un play through et le début de la suivante. Il semble être lié à la réinitialisation des données (peut-être relire à partir du disque?) D'une certaine façon.Il est beaucoup plus visible lorsque vous utilisez le format m4a beaucoup plus petit mais très compressé que lorsque vous lisez des fichiers aiff non compressés mais il est toujours là.

La solution que j'ai trouvé est d'utiliser les services de file d'attente audio:

http://developer.apple.com/mac/library/documentation/MusicAudio/Conceptual/AudioQueueProgrammingGuide/AQPlayback/PlayingAudio.html#//apple_ref/doc/uid/TP40005343-CH3-SW1

et

http://developer.apple.com/mac/library/samplecode/AudioQueueTools/Listings/aqplay_cpp.html#//apple_ref/doc/uid/DTS10004380-aqplay_cpp-DontLinkElementID_4

La file d'attente audio appelle une fonction de rappel qui prépare et enqueues le tampon suivant , donc quand vous atteignez la fin du fichier actuel, vous devez recommencer depuis le début. Cela donne une lecture complètement sans bande.

Il y a deux pièges dans l'exemple de code dans la documentation. Le premier est un bug réel (je vais contacter DTS à ce sujet afin qu'ils puissent le corriger). Avant d'allouer et d'amorçage des tampons audio, la structure personnalisée doit activer la lecture sinon la mémoire tampon audio ne se apprêté et rien est joué:

aqData.mIsRunning = 1; 

Le deuxième Gotcha est que le code ne fonctionne pas à Cocoa, mais comme outil autonome, de sorte que le code connecte la file d'attente audio à une nouvelle boucle d'exécution et implémente effectivement la boucle d'exécution elle-même comme la dernière étape du programme. Au lieu de passer CFRunLoopGetCurrent(), il suffit de passer NULL qui provoque l'exécution de l'AudioQueue dans sa propre boucle d'exécution.

result = AudioQueueNewOutput (        // 1 
        &aqData.mDataFormat,        // 2 
        HandleOutputBuffer,        // 3 
        &aqData,           // 4 
        NULL, //CFRunLoopGetCurrent(),       // 5 
        kCFRunLoopCommonModes,       // 6 
        0,            // 7 
        &aqData.mQueue         // 8 
        ); 

J'espère que cela peut sauver les pauvres hères essayer de faire la même chose à l'avenir un peu de temps :-)

Questions connexes