Сгенерируйте синусоиду для воспроизведения среднего C с помощью PortAudio

У меня возникли проблемы с генерацией определенных частот в PortAudio, всякий раз, когда я пытаюсь изменить частоту внутри sin(n * FREQ * 2 * PI / SAMPLE_RATE), частота остается прежней, однако звук, похоже, меняется по тембру, чем выше значение частоты, которое я ввожу, тем уродливее звук, еще та же частота. Это то, что у меня есть в моем цикле patestCallback:

static int patestCallback( const void *inputBuffer, void *outputBuffer,
                           unsigned long framesPerBuffer,
                           const PaStreamCallbackTimeInfo *timeInfo,
                           PaStreamCallbackFlags statusFlags,
                           void *userData )
{
   paTestData *data = (paTestData*)userData;
   float *out = (float*)outputBuffer;

   (void) timeInfo;
   (void) statusFlags;
   (void) inputBuffer;
   unsigned long n = 0;
   for(unsigned long i = 0; i<framesPerBuffer;i++,n++){
      float v = sin ( 261.626 * 2 * M_PI * ((float) n / (float) TABLE_SIZE) );
      *out++ = v;
      *out++ = v;
   }

   return paContinue;
}

person Nicholas Smith    schedule 13.02.2013    source источник


Ответы (1)


Простое решение:

static unsigned long n = 0;

В настоящее время вы сбрасываете n при каждом вызове функции, что приводит к щелчкам в начале каждого нового буфера и к тем ужасным звукам, которые вы слышите. Чем больше период синуса отличается от длины буфера, тем уродливее это звучит.

person André Bergner    schedule 13.02.2013
comment
Это предложение должно работать (+1). Другое решение может состоять в том, чтобы сделать n частью userData. Это может быть лучше, если вам когда-нибудь понадобится сбросить его извне или получить несколько обратных вызовов или что-то в этом роде. - person Bjorn Roche; 13.02.2013
comment
Ну конечно; естественно. В идеале userData должен быть структурой или классом, содержащим состояние фактического звукового движка. - person André Bergner; 13.02.2013
comment
Хорошо, я поместил все это в структуру, она прекрасно работает, спасибо! ... Я думаю, что у меня проблемы с осмыслением того, как работает portaudio, поэтому он постоянно вызывает patestCallback после каждого цикла framePerBuffer? Кроме того, можно ли записать на выходе 3 или 4 синусоидальных волны, чтобы я мог составлять аккорды? - person Nicholas Smith; 14.02.2013
comment
Да, конечно, просто добавьте несколько синусов вместе с разной частотой. Тем не менее, функция sin() грубой силы очень обширна. Существуют более эффективные методы рекурсивного интегрирования синуса. - person André Bergner; 14.02.2013
comment
О, хорошо, это цель таблицы в большинстве примеров portaudio верна? - person Nicholas Smith; 15.02.2013