Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 多线程环境中值的平滑转换_C++_Multithreading_Concurrency_Thread Priority - Fatal编程技术网

C++ 多线程环境中值的平滑转换

C++ 多线程环境中值的平滑转换,c++,multithreading,concurrency,thread-priority,C++,Multithreading,Concurrency,Thread Priority,如何以另一个线程确定的速度平滑地将值从x转换为y 让我试着用我的具体问题来解释,因为它很好地说明了这一点 我正在开发一个音频播放应用程序。当您突然暂停到声音API的采样流,从而在随后的采样之间创建一个大值差(即,将正弦波更改为零),您将获得一个弹出声音 为了避免这种情况,您需要将音量从当前值平滑过渡到零 PortAudio,im使用的库,在后台线程上处理音频,该线程在需要数据或有数据时使用回调函数。带有声音样本和音量值的缓冲区都是此回调的参数,因此我无法控制读取它们的频率。 在以下情况下,您如何

如何以另一个线程确定的速度平滑地将值从x转换为y

让我试着用我的具体问题来解释,因为它很好地说明了这一点

我正在开发一个音频播放应用程序。当您突然暂停到声音API的采样流,从而在随后的采样之间创建一个大值差(即,将正弦波更改为零),您将获得一个弹出声音

为了避免这种情况,您需要将音量从当前值平滑过渡到零

PortAudio,im使用的库,在后台线程上处理音频,该线程在需要数据或有数据时使用回调函数。带有声音样本和音量值的缓冲区都是此回调的参数,因此我无法控制读取它们的频率。

在以下情况下,您如何实现音量转换:

  • 音频线程上没有线程优先级控制(可能是最高线程之一),因此无法控制读取频率。
  • 无法真正阻止回调,因为它会导致音频错误
  • 数据保护不是必需的-不会产生明显的错误
谢谢

编辑:

我觉得我没有深入到足够的细节中,因为我害怕过度说明这个问题。我想把它具体化一些

基本上,数据流可以用以下方式描述:

Loader(异步生产者)->Buffer->Player(异步消费者)

更困难的是,缓冲区的工作方式类似于队列(为了将来实现无锁队列和数据完整性),因此我无法触摸音频数据来修改其中的一部分以使其具有传输性

这可能是一个设计缺陷,疏忽或只是隧道视觉对我来说,所以这可能会发生变化

此外,我想离开缓冲区,只处理原始数据,因为播放器对象负责实际播放,我觉得音量控制是它的职责

可以使用以下示例代码描述简化的回调:

static int bufferCallback(const void *inputBuffer, void *outputBuffer,
              unsigned long framesPerBuffer,
              const PaStreamCallbackTimeInfo *timeInfo,
              PaStreamCallbackFlags statusFlags,
              void *userData)
{
    /* Cast data passed through stream to our structure. */
    simple_player<float> *data = (simple_player<float> *)userData;
    float *out = (float *)outputBuffer;
    unsigned int i;
    (void)inputBuffer; /* Prevent unused variable warning. */

    float into;
    i = 0;
    unsigned int more;
    while (i < framesPerBuffer)
    {
        more = data->buffer->get(into);
        if (!more)
        {
            return paContinue;
        }
        *out = clip::soft_clip(into*data->volume);
        out++;
        more = data->buffer->get(into);

        if (!more)
        {
            return paContinue;
        }
        *out = clip::soft_clip(into*data->volume);
        out++;
        i++;
    }
    return paContinue;
}

您提供的缓冲区的大小不可以控制吗?缓冲区大小不相关。我指的是音频的音量。缓冲区包含音频数据,对吗?根据比特率,可以计算从缓冲区播放的实际音频的长度,这可以控制调用回调函数的频率。我误解了什么吗?啊,我明白了。不幸的是,PortAudio只会在感觉上和感觉上消耗尽可能多的缓冲区。回调在准备好处理数据时调用,具体取决于底层主机api、操作系统和硬件,然后仅消耗由上述因素确定的数量,并且只有在回调中我才能获得它想要消耗的数量。您正在提供音频数据。与突然将其设置为零不同,您需要提供振幅稳定减小的采样(直到它们达到零)。这些值可以通过将正常采样值乘以一个系数来生成,该系数从1.0开始,随着时间的推移平滑地变为0.0(您应该能够计算自请求“停止”后经过的时间)。其中一个常见的功能是“smoothstep”;另一个是“smootherstep”-您提供了经过的总淡出时间间隔的一部分,它返回一个乘数。是否可以控制您提供的缓冲区的大小?缓冲区大小不相关。我指的是音频的音量。缓冲区包含音频数据,对吗?根据比特率,可以计算从缓冲区播放的实际音频的长度,这可以控制调用回调函数的频率。我误解了什么吗?啊,我明白了。不幸的是,PortAudio只会在感觉上和感觉上消耗尽可能多的缓冲区。回调在准备好处理数据时调用,具体取决于底层主机api、操作系统和硬件,然后仅消耗由上述因素确定的数量,并且只有在回调中我才能获得它想要消耗的数量。您正在提供音频数据。与突然将其设置为零不同,您需要提供振幅稳定减小的采样(直到它们达到零)。这些值可以通过将正常采样值乘以一个系数来生成,该系数从1.0开始,随着时间的推移平滑地变为0.0(您应该能够计算自请求“停止”后经过的时间)。其中一个常见的功能是“smoothstep”;另一个是“smootherstep”-您提供已通过的总淡出时间间隔的一部分,它返回一个乘数。
static int bufferCallback(const void *inputBuffer, void *outputBuffer,
              unsigned long framesPerBuffer,
              const PaStreamCallbackTimeInfo *timeInfo,
              PaStreamCallbackFlags statusFlags,
              void *userData)
{
    /*Callback body*/
    if(data->volume!=data->target_volume)
    {
        data->volume+=data->volume_delta;
    }
    return paContinue;
}