【发布时间】:2018-04-07 14:25:44
【问题描述】:
我发现当我调用 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(¶ms);
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
【问题讨论】:
-
每次函数调用后检查错误。
-
我有。在发布之前,我取出了检查以减小代码的大小。即使我有错误或没有错误,我仍然感到困惑。为什么代码的行为要依赖于设置参数前后获取数据?