首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PortAudio输出

PortAudio输出
EN

Stack Overflow用户
提问于 2021-01-20 09:08:26
回答 1查看 444关注 0票数 0

我正在努力学习PortAudio,我正在学习doc/src/教程中的教程,这是writing_a_callback.dox中的代码

代码语言:javascript
复制
typedef struct
{
    float left_phase;
    float right_phase;
}   
paTestData;

/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/ 
static int patestCallback( const void *inputBuffer, void *outputBuffer,
                           unsigned long framesPerBuffer,
                           const PaStreamCallbackTimeInfo* timeInfo,
                           PaStreamCallbackFlags statusFlags,
                           void *userData )
{
    /* Cast data passed through stream to our structure. */
    paTestData *data = (paTestData*)userData; 
    float *out = (float*)outputBuffer;
    unsigned int i;
    (void) inputBuffer; /* Prevent unused variable warning. */
    
    for( i=0; i<framesPerBuffer; i++ )
    {
        *out++ = data->left_phase;  /* left */
        *out++ = data->right_phase;  /* right */

        /* Generate simple sawtooth phaser that ranges between -1.0 and 1.0. */
        data->left_phase += 0.01f;
        /* When signal reaches top, drop back down. */
        if( data->left_phase >= 1.0f ) data->left_phase -= 2.0f;

        /* higher pitch so we can distinguish left and right. */
        data->right_phase += 0.03f;
        if( data->right_phase >= 1.0f ) data->right_phase -= 2.0f;
    }
    return 0;
}

它很好,但我有几个问题:

  1. 我有一个带有两个struct变量的float,但是PortAudio如何知道哪个是左边的,哪个是右边的
  2. 在这个例子中,我传递给输出缓冲区、频率、音量或其他什么东西,以及如何告诉PortAudio关于其他的东西,例如,如果我传递频率,我如何告诉它来调整音量。

也许我错过了什么但是..。我不知道

任何帮助的尝试都会受到赞赏。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-01-29 02:39:29

我来帮你解释一下:

此结构定义用于控制生成信号的“状态”。left_phase用于存储左侧通道的下一个示例值。right_phase存储右通道的下一个值。

代码语言:javascript
复制
typedef struct
{
    float left_phase;
    float right_phase;
}   
paTestData;

这是在PortAudio中注册的回调函数。PortAudio将数据从输入流(麦克风)传递到inputBuffer以供用户处理。用户将数据传递给发送到声卡输出流(扬声器)的outputBufferuserData是在注册回调时传递的一些值或结构。在本例中,它是paTestData的一个实例。

代码语言:javascript
复制
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/ 
static int patestCallback( const void *inputBuffer, void *outputBuffer,
                           unsigned long framesPerBuffer,
                           const PaStreamCallbackTimeInfo* timeInfo,
                           PaStreamCallbackFlags statusFlags,
                           void *userData )
{
    /* Cast data passed through stream to our structure. */
    paTestData *data = (paTestData*)userData; 
    float *out = (float*)outputBuffer;
    unsigned int i;
    (void) inputBuffer; /* Prevent unused variable warning. */

这个for循环是产生信号的地方,每次一个帧。framesPerBuffer (部分由用户在注册回调时确定,部分由OS确定)控制生成了多少样例。循环的每一次迭代生成两个音频数据样本。对于立体声流,样品是交错的。第一个示例进入左侧通道。第二个样本进入正确的通道。

代码语言:javascript
复制
    for( i=0; i<framesPerBuffer; i++ )
    {
        *out++ = data->left_phase;  /* left */
        *out++ = data->right_phase;  /* right */

        /* Generate simple sawtooth phaser that ranges between -1.0 and 1.0. */
        data->left_phase += 0.01f;
        /* When signal reaches top, drop back down. */
        if( data->left_phase >= 1.0f ) data->left_phase -= 2.0f;

        /* higher pitch so we can distinguish left and right. */
        data->right_phase += 0.03f;
        if( data->right_phase >= 1.0f ) data->right_phase -= 2.0f;
    }
    return 0;
}

此代码由for循环控制频率和幅度(体积)。每个样本表示该时间段的信号的幅度(由采样率决定)。在这种情况下,频率由值0.01f0.03f决定。幅值由if( data->left_phase >= 1.0f ) data->left_phase -= 2.0f;确定,左通道由if( data->right_phase >= 1.0f ) data->right_phase -= 2.0f;确定,右侧通道由if( data->right_phase >= 1.0f ) data->right_phase -= 2.0f;确定。

代码语言:javascript
复制
data->left_phase += 0.01f;
/* When signal reaches top, drop back down. */
if( data->left_phase >= 1.0f ) data->left_phase -= 2.0f;

/* higher pitch so we can distinguish left and right. */
data->right_phase += 0.03f;
if( data->right_phase >= 1.0f ) data->right_phase -= 2.0f;

正如代码注释中所描述的那样,for循环生成一种称为锯齿波的周期函数。频率取决于“牙齿”之间的距离。如果信号每秒有1000个齿,一个1000赫兹的音调是generated.The的振幅是由牙齿有多高决定的。如果峰到峰的距离(从下到上)为-1到1,即为1的振幅(浮点样本为100%)。这也是0 db,或单位增益。您可以使用定义的在本文中方程从信号幅度计算db。(见声学。)一个很好的练习是生成一个不同的波形,如方波三角波正弦波。它们每个都会产生具有独特特性的音高。

在代码中,左相位每个样本的幅值为0.01,从-1增加到1/ 200。频率由该波形与音频流的采样率之间的关系决定。如果采样率为48 kHz,那么每个样本代表1/48000秒长的一段时间。在这种情况下,信号频率为240 Hz (48000 / 200)。

为了更好地理解这一点,您可以将此算法放入电子表格并绘制点,或者更好地将其绘制到python中,并使用绘图库来可视化波形。你也可以把它写在纸上。X值是时间,y值是振幅.我还建议你读一读脉冲码调制(PCM)inputBufferoutputBuffer是PCM数据的缓冲区(数组)。它也是WAV文件中使用的编码。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65806332

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档