使用端口音频将多种音频音调到声卡

  • 本文关键字:音频 声卡 audio portaudio
  • 更新时间 :
  • 英文 :


我正在尝试为声卡生成音调(频率:1950 Hz,持续时间:40 毫秒,电平:-30 db,右声道(立体声),在 steam 1 上)。最终,我想播放其中两个音调(一个转到通道 1,一个转到通道 2)。

任何帮助或指导将不胜感激。

谢谢DW


嗨,比约恩,我试过这个,但我没有得到我所期望的频率(加上似乎声音不干净)。任何想法出了什么问题?我非常感谢任何帮助。

#define SAMPLE_RATE   (44100)
#define TABLE_SIZE   (200)
float FREQUENCY = 422;
...
for(int i=0; i<TABLE_SIZE; i++ )
{
    data.sine[i] = (float) sin( (double)i * ((2.0 * M_PI)/(double)SAMPLE_RATE) * FREQUENCY );
}
data.left_phase = 0;
data.right_phase = 0;
...
... in callback function ...
for(unsigned long i = 0; i < framesPerBuffer; i++ )
{   
  // fill output buffer with sin wave
  *out++ = data->amp * data->sine[data->left_phase];  // left     
  *out++ = data->amp * data->sine[data->right_phase]; // right                  
  data->left_phase += 1;    
  if( data->left_phase >= TABLE_SIZE ) 
    data->left_phase -= TABLE_SIZE;           
  data->right_phase += 1; 
  if( data->right_phase >= TABLE_SIZE ) 
    data->right_phase -= TABLE_SIZE;
} 

PortAudio 有生成音调的示例代码,您只需要弄清楚频率即可。例如,请参阅此答案:

[端口音频]传输和检测频率 - 视窗

更新:

与其尝试存储正弦数据表,不如使用以下公式简单地计算回调中的正弦值:

振幅[n] = sin( n * 期望频率 * 2 * pi/采样率 )

所以(未经测试)你的代码将看起来像这样:

typedef struct
{
    long n;
} MyData;
float FREQUENCY = 422;
static int MyCallback(  
                    const void *inputBuffer, 
                    void *outputBuffer,
                    unsigned long framesPerBuffer,
                    const PaStreamCallbackTimeInfo* timeInfo,
                    PaStreamCallbackFlags statusFlags,
                    void *userData 
                  )
{   
    MyData *data = (MyData*)userData;
    float *out = (float*)outputBuffer;    
    (void) timeInfo; /* Prevent unused variable warnings. */
    (void) statusFlags;
    (void) inputBuffer;     
    for(unsigned long i = 0; i < framesPerBuffer; i++ )
    {               
        // fill output buffer with sin wave
        float v = sin( data->n * FREQUENCY * 2 * PI / (float) SAMPLERATE )
        *out++ = v; // left         
        *out++ = v; // right
    }   
    return paContinue;
}

这段代码并非没有问题:例如,最终 n 将"环绕",我不确定随着输入变大,sin 是否仍然准确和有效。尽管如此,这是一个很好的起点,如果您只需要在现代硬件上生成几秒钟的音调,那么这确实是您所需要的。如果您需要更花哨的东西,请先将其工作,然后您可以担心使用 LUT 使其更高效、更强大。

最新更新