gpt4 book ai didi

audio - ALSA 播放中断,没有 snd_pcm_hw_params_get_* 调用

转载 作者:行者123 更新时间:2023-12-02 23:33:10 27 4
gpt4 key购买 nike

我发现当我对 snd_pcm_hw_params_get_* 进行一些调用时,一个简单的 ALSA 播放程序的行为会有所不同。职能。我的程序反复播放缓冲区中的正弦波。当我包括电话时,我得到了我所期望的纯音。但是,当我删除调用时,我会听到一连串的哔哔声。这让我很担心,因为我不希望检索数据的调用与声音的播放方式有任何关系。我在便宜的 USB 声卡和我的(可能更好的)内部声卡上都得到了这种行为。

这是代码:

#define GETPARAMS


int main() {
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
const char name[] = "hw:0,0";

int dir;

snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
snd_pcm_access_t access = SND_PCM_ACCESS_RW_INTERLEAVED;
snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
unsigned int rate = 48000;
unsigned int channels = 2;
unsigned int periods = 4;
snd_pcm_uframes_t periodsize = 2048;
int num_frames = 2*periodsize;


snd_pcm_hw_params_alloca(&params);
snd_pcm_open(&handle, name, stream, 0);
snd_pcm_hw_params_any(handle, params);

#ifdef GETPARAMS
printf("\nparameters before setting:\n");
snd_pcm_hw_params_get_rate(params, &rate, &dir);
printf(" rate = %d, dir = %d\n", rate, dir);
snd_pcm_hw_params_get_channels(params, &channels);
printf(" channels = %d\n", channels);
snd_pcm_hw_params_get_periods(params, &periods, &dir);
printf(" periods = %d, dir = %d\n", periods, dir);
snd_pcm_hw_params_get_buffer_size(params, &periodsize);
printf(" periodsize = %ld\n", periodsize);
#endif

snd_pcm_hw_params_set_access(handle, params, access);
snd_pcm_hw_params_set_format(handle, params, format);
snd_pcm_hw_params_set_rate_near(handle, params, &rate, &dir);
snd_pcm_hw_params_set_channels(handle, params, 2);
snd_pcm_hw_params_set_periods(handle, params, periods, 0);
snd_pcm_hw_params_set_buffer_size(handle, params, num_frames);
snd_pcm_hw_params(handle, params);

#ifdef GETPARAMS
printf("\nparameters after setting:\n");
snd_pcm_hw_params_get_rate(params, &rate, &dir);
printf(" rate = %d, dir = %d\n", rate, dir);
snd_pcm_hw_params_get_channels(params, &channels);
printf(" channels = %d\n", channels);
snd_pcm_hw_params_get_periods(params, &periods, &dir);
printf(" periods = %d, dir = %d\n", periods, dir);
snd_pcm_hw_params_get_buffer_size(params, &periodsize);
printf(" periodsize = %ld\n\n", periodsize);
#endif

int16_t *data = (int16_t*)calloc(2*periodsize, sizeof(int16_t));
loadpage(data, 2*periodsize);

snd_pcm_sframes_t frames;
snd_pcm_prepare(handle);
for (int i=0; i<8; i++) {
frames = snd_pcm_writei(handle, data, num_frames);
if (frames < 0)
frames = snd_pcm_recover(handle, frames, 0);
if (frames < 0) {
printf("snd_pcm_writei failed: %s\n", snd_strerror(frames));
}
if (frames > 0 && frames < num_frames)
printf("short write (expected %d, write %li)\n", num_frames, frames);
}

snd_pcm_close(handle);
free(data);
}
loadpage()填充缓冲区。当我注释掉 #define GETPARAMS我听到一连串短促的哔哔声。当我包含它时,我会得到一个纯音。

这是 GETPARAMS 时的输出被定义为:
parameters before setting:
rate = 48000, dir = 32766
channels = 2
periods = 4, dir = 32766
periodsize = 2048

parameters after setting:
rate = 48000, dir = 0
channels = 2
periods = 4, dir = 0
periodsize = 4096

最佳答案

您不得调用snd_pcm_hw_param_get_*()如果参数尚未设置,则函数,因为那时配置空间包含参数的多个潜在值。

打印 hw_params 的当前状态容器,使用 snd_pcm_hw_params_dump() :

snd_output_t *output;

snd_output_stdio_attach(&output, stdout, 0);

...

snd_pcm_hw_params_dump(params, output);

...

snd_output_close(output);

无论如何,问题在于 periods 的初始值, periodsize , 和 num_frames不一致,并且 _get_调用用恰好一致的其他值覆盖这些变量。

我不知道您实际要使用什么值,但请注意,周期大小和缓冲区大小以帧为单位测量,并且一帧包含所有 channel 的所有样本,即在这种情况下,一帧有四个字节。

关于audio - ALSA 播放中断,没有 snd_pcm_hw_params_get_* 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49684021/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com