如何用ALSA播放短音

时间:2016-11-03 10:22:33

标签: c linux audio alsa

我正在尝试在小型C程序中通过if __name__ == "__main__": controller1 = ThreadController(name="foo") controller2 = ThreadController(name="bar") def signal_handler(signal, frame): print("Stopping threads and exiting...") controller1.stop() controller2.stop() sys.exit(0) signal.signal(signal.SIGINT, signal_handler) controller1.start() controller2.start() 生成可变长度的短音。我尝试过的一些例子在播放一秒钟的声音时效果很好但是任何比这短的声音都没有发出任何声音。

我正在用正弦波填充缓冲区,如下所示:

ALSA

设置pcm设备参数:

#define BUFFER_LEN 44100
int freq = 700;             //audio frequency
int fs = 44100;             //sampling frequency
float buffer [BUFFER_LEN];
for (k=0; k<BUFFER_LEN; k++) {
   buffer[k] = (sin(2*M_PI*freq/fs*k));                                 
}

回放:

if ((err = snd_pcm_set_params(handle,
                              SND_PCM_FORMAT_FLOAT,
                              SND_PCM_ACCESS_RW_INTERLEAVED,
                              1,
                              44100,
                              1,
                              500000)) < 0) {
printf("Playback open error: %s\n", snd_strerror(err));
exit(EXIT_FAILURE);
}

但是,如果我想改变它来播放音调,比如四分之一秒(即将frames = snd_pcm_writei(handle, buffer, BUFFER_LEN); 改为11025),说话者就不会再发出声音了。

我尝试将类型从浮动更改为短路,将BUFFER_LEN设置为其他值,并尝试使用正弦波填充缓冲区的不同方法。

如果有的话,我会在扬声器中听到一点'双'声,但不是我所期待的。该程序不会出现段错或崩溃,但我很困惑如何让ALSA播放更短的样本。

我不知道我是否需要使用一些精确的帧或缓冲区大小,但我对建议非常开放。

1 个答案:

答案 0 :(得分:2)

您的应用程序将样本写入缓冲区,并且缓冲区中的硬件读取样本和播放它们是异步运行的两个不同进程。

如果缓冲区中没有足够的可用空间用于您尝试写入的样本量,则snd_pcm_writei()将等待,直到有足够的空间可用。但是当snd_pcm_writei()返回时,可能还没有播放完整的样本缓冲区。

要等到缓冲区为空,请使用snd_pcm_drain()