Multi audio tones to sound card using portaudio

对着背影说爱祢 提交于 2019-12-01 12:05:07

问题


I am trying to generate a tone to the sound card (Frequency: 1950 hz, duration: 40 ms, level: -30 db, right-channel (stereo), on steam 1). Eventually, I would like to play two of these tones (one goes to channel 1 and one goes to channel 2).

Any help or direction is greatly appreciated.

Thanks, DW


Hi Bjorn, I tried this but I am not getting the what I am expecting as a frequency (plus seems sound is not clean). Any ideas what's wrong? I greatly appreciate any help.

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

回答1:


PortAudio has sample code for generating tones, you just need to figure out the frequency. See for example this answer:

[portaudio]Transmit and Detect frequency - Windows

Update:

Rather than trying to store a table of sine data, simply calculate the sine value in the callback using this formula:

amplitude[n] = sin( n * desiredFreq * 2 * pi / samplerate )

so (untested) your code will look something like this:

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

This code is not without problems: eg. eventually n will "wrap around" and I'm not sure if sin remains accurate and efficient as the input gets larger. Nevertheless it's a good starting point, and if you just need to generate a few seconds of a tone on modern hardware, this is really all you need. If you need something fancier, get this working first, then you can worry about making it more efficient and robust with a LUT.



来源:https://stackoverflow.com/questions/12612951/multi-audio-tones-to-sound-card-using-portaudio

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!