2010-12-06 2 views
4

Я недавно заметил, что в iOS можно использовать OpenAL для изменения высоты тона.iOS: Pitch Shifting & Piping выход из OpenAL в буфер

Я смотрю звук игрока банка Hollance. он занимает 15 или около того фортепианных нот, разбрызгиваемых по диапазону, и играет любую заметку, выясняя, какой образец он ближе всего, и сдвиг тона, который пробует соответствующую сумму. Это код, который делает это:

- (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; 
      } 
     } 
    } 
} 

вы можете увидеть эту линию делает шаг сдвига:

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

, к сожалению, это не хорошо для игры в пачку нот одновременно, как это занимает слишком много ЦПУ. это динамическое изменение тона.

Я хочу создать буфер для каждой ноты пианино и заполнить эти буферы, используя эту технологию сдвига тона. но я не вижу, как получить openAL для воспроизведения звука в буфер, а не для воспроизведения его через динамики.

есть ли способ для вывода вывода alSourcePlay (source-> sourceId);

в буфер?

Если я не могу этого сделать, каковы мои варианты? Я попытался использовать smbPitchShift из статьи DSPDimension, но это не дает хорошей верности: фаза атаки фортепианной ноты действительно потеряна. Думаю, я мог бы использовать бесплатную версию Dirac3 ... (у меня нет денег на полную версию на данный момент, но я думаю, что бесплатная версия позволяет Mono-обработку, поэтому я могу ее взломать). есть ли другой вариант?

EDIT: У меня с тех пор тестировался Dirac3, и он разделяет ту же проблему. он, похоже, нападает на атаку. кажется, что переключение Shift от OpenAL каким-то образом делает то, что Dirac3 не делает.

+1

Я люблю вопросы с иллюстративным источником коды! Большое спасибо за это, это очень помогло мне! :) – cregox 2011-01-10 14:37:43

+0

Не забудьте поднять его тогда;) – 2011-01-11 04:50:47

ответ

4

alSourcePlayv позволяет воспроизводить несколько источников одновременно - максимальное количество источников зависят от платформы, но 32 на прошивке (ответили на яблоко ядро-аудиосписок, для полноты)

Смежные вопросы