阿尔萨 snd_pcm_writei

发布于 2024-11-05 19:02:33 字数 410 浏览 0 评论 0原文

我注意到 pcm.c 和扬声器测试.c 中的正弦发生器在循环中生成一个新的正弦缓冲区。所以它不断地重新创建相同的缓冲区。我想播放缓冲区而不是每次都重新创建它以节省一些 CPU 时间。但是,当我尝试通过首先构建缓冲区然后将相同的缓冲区发送到 snd_pcm_writei 来运行代码时,我在每个缓冲区的末尾听到一点点击声。然而,当它每次都被重建然后发送到 snd_pcm_writei 时,缓冲区末尾没有一点点击。为什么每次播放前都需要重建正弦缓冲区,以免出现点击噪音?

有任何帮助吗?

来自 pcm.c:

while (1) {
    generate_sine(areas, 0, period_size, &phase);
    ptr = samples;
    cptr = period_size;

I noticed that the sine generator in pcm.c and speaker-test.c generate a new sine buffer in a loop. So it constantly recreates the same buffer. I wanted to play the buffer without recreating it every time to save some cpu time. However, When I tried to run the code by building the buffer first and then send the same buffer to the snd_pcm_writei I get a little clicky sound at the end of each buffer. However when it gets rebuilt every time and then sent to snd_pcm_writei there is no little click at the end of the buffer. Why is it required to rebuild the sine buffer every time before playing it so as not get the click noise?

Any help would be appreciated?

from pcm.c:

while (1) {
    generate_sine(areas, 0, period_size, &phase);
    ptr = samples;
    cptr = period_size;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

赴月观长安 2024-11-12 19:02:33

您假设每次都会生成相同的正弦波,但由于使用了相位变量并且正弦波并不总是完全适合缓冲区,因此每次迭代都会生成不同的正弦波,稍微移动了一下。

不是每次都生成正弦波会导致正弦波“中断”。

我将尝试使用锯齿波而不是正弦波进行一些可视化。想象一下缓冲区大小为 16,波形值范围从 A 到 H。

// Old way
  phase = 0        phase = 2        phase = 4
ABCDEFGHGFEDCBAB|CDEFGHGFEDCBABCD|EFGHGFEDCBABCDEF....

// New way
  phase = 0        phase = 0        phase = 0
ABCDEFGHGFEDCBAB|ABCDEFGHGFEDCBAB|ABCDEFGHGFEDCBAB....

请注意,缓冲区边缘周围只有小块声音“格式错误”(例如 AB|AB 而不是 <代码>AB|CD)。这就是为什么大多数时候听起来都是正确的,但中间却有一些令人不安的短促“咔哒”声。

对于某些罕见的情况,如果缓冲区长度是波长的倍数,或者当相位与之前迭代中的值相同时,您可能确实会跳过生成缓冲区,但您不能这样做每次都会。

编辑:查看 generate_sine 函数看看phase是如何改变的:

static void generate_sine(const snd_pcm_channel_area_t *areas, 
                          snd_pcm_uframes_t offset,
                          int count, double *_phase)
{
    static double max_phase = 2. * M_PI;
    double phase = *_phase;
    double step = max_phase*freq/(double)rate;

    [...]

             phase += step;
             if (phase >= max_phase)
                    phase -= max_phase;
     }
     *_phase = phase;
}

EDIT2:这张图片可能是一个更好/更清晰的可视化:

在此处输入图像描述

You're assuming there's the same sine wave generated every time, but since there's a phase variable used and the sine wave won't always fit exactly in the buffer, a different sine wave is generated in each iteration, shifted a bit.

Not generating the sine wave every time leads to an "break" in the sine wave.

I'll try some visualization with a sawtooth wave instead of a sine wave. Imagine the buffer size being 16 and the wave values ranging from A to H.

// Old way
  phase = 0        phase = 2        phase = 4
ABCDEFGHGFEDCBAB|CDEFGHGFEDCBABCD|EFGHGFEDCBABCDEF....

// New way
  phase = 0        phase = 0        phase = 0
ABCDEFGHGFEDCBAB|ABCDEFGHGFEDCBAB|ABCDEFGHGFEDCBAB....

Note that there are only small pieces around the buffer edges where the sound is "malformed" (for example AB|AB instead of AB|CD). This is why it sounds correct most of the time with some disturbing short "clicks" in between.

For some rare cases, if the buffer length is a multiple of the wave length or when phase has the same value as in the iteration before, you might indeed skip generating the buffer, but you can't do it every time.

EDIT: Look at the generate_sine function to see how phase is changed:

static void generate_sine(const snd_pcm_channel_area_t *areas, 
                          snd_pcm_uframes_t offset,
                          int count, double *_phase)
{
    static double max_phase = 2. * M_PI;
    double phase = *_phase;
    double step = max_phase*freq/(double)rate;

    [...]

             phase += step;
             if (phase >= max_phase)
                    phase -= max_phase;
     }
     *_phase = phase;
}

EDIT2: This image might be a better/clearer visualization:

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文