2010-12-06 5 views
4

J'ai récemment remarqué qu'il est possible dans iOS d'utiliser OpenAL pour changer de pitch.iOS: Sortie Pitch Shifting & Piping d'OpenAL dans un buffer

Je regarde le lecteur de banque de sons de Hollance. il prend environ 15 notes de piano éparpillées à travers la gamme, et joue n'importe quelle note en déterminant quel échantillon il est le plus proche de, et en transposant cet échantillon d'une quantité appropriée. Ceci est le code qui le fait:

- (void) noteOn: (int) midiNoteNumber 
      gain: (float) gain 
{ 
    if (!initialized) 
    { 
     NSLog(@"SoundBankPlayer is not initialized yet"); 
     return; 
    } 

    int sourceIndex = [self findAvailableSource]; 
    if (sourceIndex != -1) 
    { 
     alGetError(); // clear any errors 

     Note* note = notes + midiNoteNumber; 
     if (note->bufferIndex != -1) 
     { 
      Buffer* buffer = buffers + note->bufferIndex; 
      Source* source = sources + sourceIndex; 

      source->noteIndex = midiNoteNumber; 

      alSourcef(source->sourceId, AL_PITCH, note->pitch/buffer->pitch); 
      alSourcei(source->sourceId, AL_LOOPING, AL_FALSE); 
      alSourcef(source->sourceId, AL_REFERENCE_DISTANCE, 100.0f); 
      alSourcef(source->sourceId, AL_GAIN, gain); 

      float sourcePos[] = { note->panning, 0.0f, 0.0f }; 
      alSourcefv(source->sourceId, AL_POSITION, sourcePos); 

      alSourcei(source->sourceId, AL_BUFFER, AL_NONE); 
      alSourcei(source->sourceId, AL_BUFFER, buffer->bufferId); 
      ALenum error; 
      if ((error = alGetError()) != AL_NO_ERROR) 
      { 
       NSLog(@"Error attaching buffer to source: %x", error); 
       return; 
      } 

      alSourcePlay(source->sourceId); 
      if ((error = alGetError()) != AL_NO_ERROR) 
      { 
       NSLog(@"Error starting source: %x", error); 
       return; 
      } 
     } 
    } 
} 

vous pouvez voir cette ligne ne le pitch shifting:

 alSourcef(source->sourceId, AL_PITCH, note->pitch/buffer->pitch); 

c'est malheureusement pas bon pour jouer un paquet de notes en même temps, car il prend trop CPU. c'est le pitch qui change dynamiquement. Ce que je veux, c'est créer un tampon pour chaque note de piano, et remplir ces tampons en utilisant cette technologie de pitch shifting. mais je ne vois pas comment ouvrir le son dans un buffer au lieu de le jouer à travers les enceintes.

est-il un moyen de canaliser la sortie de alSourcePlay (source-> sourceId);

dans un tampon?

Si je ne peux pas faire cela, quelles sont mes options? J'ai essayé d'utiliser smbPitchShift de l'article DSPDimension, mais cela ne donne pas une bonne fidélité: la phase d'attaque de la note de piano est vraiment perdue. Je suppose que je pourrais utiliser la version gratuite de Dirac3 ... (je n'ai pas d'argent pour la version complète pour le moment, mais je pense que la version gratuite permet le traitement Mono, donc je peux bidouiller ça). Y a-t-il une autre option?

EDIT: J'ai depuis testé Dirac3, et il partage le même problème. il semble envelopper l'attaque. il semble que le pitch shifter d'OpenAL fasse quelque chose que Dirac3 ne fait pas.

+1

I love questions avec la source d'illustration codes! Merci beaucoup pour ça, ça m'a beaucoup aidé! :) – cregox

+0

Ne pas oublier de le cogner alors;) –

Répondre

4

alSourcePlayv vous permet de jouer plusieurs sources en même temps - le nombre maximum de sources est dépendant de la plateforme, mais est 32 sur iOS (une réponse sur la liste Trognon de pomme-audio, ici pour être complet)

+1

Je vous dois une bière, Wil;) –