2009-11-10 5 views
2

En tant que projet jetable pour que l'iPhone me mette à jour avec Objective C et les bibliothèques iPhone, j'ai essayé de créer une application qui jouera différents types de bruit aléatoire.Jouer de l'audio généré sur un iPhone

J'ai construit le bruit sous la forme d'un tableau de flottants normalisés à partir de [-1,1].

Où je suis coincé est en jouant que les données générées. Il semble que cela devrait être assez simple, mais j'ai regardé en utilisant AudioUnit et AVAudioPlayer, et aucun d'entre eux ne semble optimal. AudioUnit nécessite apparemment quelques centaines de lignes de code pour faire cette tâche simple, et AVAudioPlayer semble exiger que je convertisse l'audio en quelque chose que CoreAudio peut comprendre (au mieux, cela signifie que LPCM est placé dans un fichier WAV). Est-ce que je néglige quelque chose, ou est-ce vraiment la meilleure façon de lire des données sonores stockées sous forme de tableau?

Répondre

3

Voici un code pour utiliser AudioQueue, que j'ai modifié à partir de l'exemple SpeakHere. Je genre de collais les bonnes parties, donc il peut y avoir quelque chose ballants ici ou là, mais cela devrait être un bon point de départ si vous souhaitez utiliser cette approche:

AudioStreamBasicDescription format; 
memset(&format, 0, sizeof(format)); 
format.mSampleRate = 44100; 
format.mFormatID = kAudioFormatLinearPCM; 
format.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked; 
format.mChannelsPerFrame = 1; 
format.mBitsPerChannel = 16; 
format.mBytesPerFrame = (format.mBitsPerChannel/8) * format.mChannelsPerFrame; 
format.mFramesPerPacket = 1; 
format.mBytesPerPacket = format.mBytesPerFrame * format.mFramesPerPacket; 

AudioQueueRef queue; 

AudioQueueNewOutput(&format, 
      AQPlayer::AQOutputCallback, 
      this, // opaque reference to whatever you like 
      CFRunLoopGetCurrent(), 
      kCFRunLoopCommonModes, 
      0, 
      &queue); 

const int bufferSize = 0xA000; // 48K - around 1/2 sec of 44kHz 16 bit mono PCM   
for (int i = 0; i < kNumberBuffers; ++i) 
    AudioQueueAllocateBufferWithPacketDescriptions(queue, bufferSize, 0, &mBuffers[i]); 

AudioQueueSetParameter(queue, kAudioQueueParam_Volume, 1.0); 

UInt32 category = kAudioSessionCategory_MediaPlayback; 
AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(category), &category); 

AudioSessionSetActive(true); 

// prime the queue with some data before starting 
for (int i = 0; i < kNumberBuffers; ++i) 
    OutputCallback(queue, mBuffers[i]); 

AudioQueueStart(queue, NULL); 

Le code fait référence ci-dessus pour ce rappel de sortie. Chaque fois que ce rappel s'exécute, remplissez le tampon transmis avec votre audio généré. Ici, je le remplis de bruit aléatoire.

void OutputCallback(void* inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inCompleteAQBuffer) { 
    // Fill 
    //AQPlayer* that = (AQPlayer*) inUserData; 
    inCompleteAQBuffer->mAudioDataByteSize = next->mAudioDataBytesCapacity; 
    for (int i = 0; i < inCompleteAQBuffer->mAudioDataByteSize; ++i) 
     next->mAudioData[i] = rand(); 
    AudioQueueEnqueueBuffer(queue, inCompleteAQBuffer, 0, NULL); 
} 
+0

Grumdrig, pourriez-vous développer votre réponse? J'ai du mal à assembler les pièces. Vous semblez utiliser des variables locales d'une fonction dans l'autre comme s'il s'agissait de variables membres d'un objet plus grand (par exemple. 'Queue'). Aussi, je ne sais pas si 'AQPlayer :: AQOutputCallback' et votre exemple' OutputCallback' sont supposés être la même fonction/méthode. Enfin, de quoi et d'où provient l'objet 'next' dans votre exemple de méthode de rappel? J'apprécierais grandement tout aperçu supplémentaire/code révisé que vous pourriez fournir. –

+0

Peu importe, je l'ai compris. http://stackoverflow.com/questions/2270218/playing-audio-on-the-iphone-decoded-by-third-party-library/2274549#2274549 –

0

On dirait que vous venez d'une plate-forme qui a un générateur de sons intégré simple. L'iPhone n'a rien de tel. Il est plus facile de jouer des sons simples à partir de fichiers audio. AudioUnit est pour réellement traiter et générer de la vraie musique. Donc, oui, vous avez besoin d'un fichier audio pour jouer un son simplement.

Questions connexes