我用asoundlib.h
写了以下简单示例:
#include <alsa/asoundlib.h>
#include <sys/fcntl.h>
#include <unistd.h>
typedef struct sound_device_config_t sound_device_config_t;
struct sound_device_config_t{
unsigned int rate;
unsigned int periods;
snd_pcm_uframes_t period_size;
unsigned int channels;
snd_pcm_format_t sample_format;
};
static void _configure_device(snd_pcm_t **pcm_handle_ptr, const char *sd);
int main(int argc, char * argv[]){
sound_device_config_t *cfg_ptr = malloc(sizeof(sound_device_config_t));
cfg_ptr -> channels = 2;
cfg_ptr -> period_size = 2048;
cfg_ptr -> periods = 2;
cfg_ptr -> rate = 44100;
cfg_ptr -> sample_format = SND_PCM_FORMAT_S16_LE;
snd_pcm_t *pcm_handle;
_configure_device(&pcm_handle, "plughw:1,0");
return 0;
}
在_configure_device
文件末尾实现main.c
的位置,如下所示:
static void _configure_device(snd_pcm_t **pcm_handle_ptr, const char *sd_name){
snd_pcm_hw_params_t *hwparams;
snd_pcm_stream_t stream = SND_PCM_STREAM_CAPTURE;
snd_pcm_t *pcm_handle = *pcm_handle_ptr;
snd_pcm_hw_params_alloca(&hwparams);
const char * device_name = strdup(sd_name);
int err;
if((err = snd_pcm_open(&pcm_handle, device_name, stream, 0)) < 0){
fprintf(stderr, "Something went wrong. Result code = %d\n", err);
fprintf(stderr, "Error details: %s\n", snd_strerror(err));
return;
}
if((err = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0){
fprintf(stderr, "Initialization failed wit error %d\n", err);
fprintf(stderr, "Error details: %s\n", snd_strerror(err));
return;
}
int rate = 44100;
int exact_rate;
int direction;
int periods = 2;
snd_pcm_uframes_t period_size = 8192;
if((err = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0){
fprintf(stderr, "Error setting access. Details: %s\n", snd_strerror(err));
return;
} else {
printf("Setting access to SND_PCM_ACCESS_RW_INTERLEAVED: %s\n", snd_strerror(err));
}
if((err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE)) < 0){
fprintf(stderr, "Error setting format. Details: %s\n", snd_strerror(err));
return;
} else {
printf("Setting format to SND_PCM_FORMAT_S16_LE: %s\n", snd_strerror(err));
}
exact_rate = rate;
if((err = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &exact_rate, &direction)) < 0){
fprintf(stderr, "Error setting sample rate to %d. Details: %s\n", exact_rate, snd_strerror(err));
return;
} else if(rate != exact_rate){
fprintf(stderr, "The rate %d is not supported by your hardware.\n\
Setting rate to the nearest supported %d instead.\n", rate, exact_rate);
} else {
printf("Setting rate to %d: %s\n", rate, snd_strerror(err));
}
if((err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, 2))){
fprintf(stderr, "Error setting number of channels. Details: %s\n", snd_strerror(err));
return;
} else {
printf("Setting channels to 2: %s\n", snd_strerror(err));
}
if((err = snd_pcm_hw_params_set_periods(pcm_handle, hwparams, periods, direction))){
fprintf(stderr, "Error setting periods to %d. Details: %s\n", periods, snd_strerror(err));
return;
} else {
printf("Setting periods to %d: %s\n", periods, snd_strerror(err));
}
if((err = snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, (period_size * periods) >> 2)) < 0){
fprintf(stderr, "Error setting buffer size. Details: %s\n", snd_strerror(err));
return;
} else {
printf("Setting buffer size status: %s\n", snd_strerror(err));
}
if((err = snd_pcm_hw_params(pcm_handle, hwparams)) < 0){
fprintf(stderr, "Cannot set the configured params. Details: %s\n", snd_strerror(err));
return;
} else {
printf("Params are successfully applied to the pcm device\n");
}
}
它不起作用。当我运行此代码时,将显示以下内容:
Setting access to SND_PCM_ACCESS_RW_INTERLEAVED: Success
Setting format to SND_PCM_FORMAT_S16_LE: Success
Setting rate to 44100: Success
Setting channels to 2: Success
Setting periods to 2: Success
Error setting buffer size. Details: Invalid argument
但是,当我删除sound_device_config_t
的配置分配和初始化(我打算用来配置声音设备,目前不使用)时,它可以正常工作:
int main(int argc, char * argv[]){
snd_pcm_t *pcm_handle;
_configure_device(&pcm_handle, "plughw:1,0");
}
打印
Setting access to SND_PCM_ACCESS_RW_INTERLEAVED: Success
Setting format to SND_PCM_FORMAT_S16_LE: Success
Setting rate to 44100: Success
Setting channels to 2: Success
Setting periods to 2: Success
Setting buffer size status: Success
Params are successfully applied to the pcm device
这看起来有些神奇。我删除了一个在任何地方都不使用的对象的分配,它会影响程序的行为。
也许我在这里错过了一些UB?