'ALSA driver's buffer is TOO large
I'm using a USB sound card to create a real-time Linux player. The APP is developed based on ALSA's API.
I found that the driver's buffer is too large. I don't know how to reduce the buffer size via userspace.
For example, when I initialize ALSA by 16-bit stereo 44100Hz, the total buffer size will be 256 frames(snd_pcm_hw_params_get_period_size) * 1024 periods(snd_pcm_hw_params_get_periods). So that the total buffer time is 256*1024/44100=5.94(seconds). That's too large for my REAL-TIME use case!
my exp 01: I've been trying to reduce to periods counts by snd_pcm_hw_params_test_periods, but the driver's buffer size (frames*periods) is ALL THE SAME!
here's my sample code
bool init(const std::string &PCM_DEVICE, const int channels, const int rate) {
unsigned int pcm;
unsigned int tmp;
snd_pcm_hw_params_t* params = nullptr;
/* Open the PCM device in playback mode */
if (pcm = snd_pcm_open(&pcm_handle_, PCM_DEVICE.c_str(), SND_PCM_STREAM_PLAYBACK, 0) < 0) {
printf("ERROR: Can't open \"%s\" PCM device. %s\n", PCM_DEVICE, snd_strerror(pcm));
return false;
}
/* Allocate parameters object and fill it with default values*/
snd_pcm_hw_params_alloca(¶ms);
snd_pcm_hw_params_any(pcm_handle_, params);
/* Set parameters */
if (pcm = snd_pcm_hw_params_set_access(pcm_handle_, params,
SND_PCM_ACCESS_RW_INTERLEAVED) < 0)
printf("ERROR: Can't set interleaved mode. %s\n", snd_strerror(pcm));
if (pcm = snd_pcm_hw_params_set_format(pcm_handle_, params,
SND_PCM_FORMAT_S16_LE) < 0)
printf("ERROR: Can't set format. %s\n", snd_strerror(pcm));
if (pcm = snd_pcm_hw_params_set_channels(pcm_handle_, params, channels) < 0)
printf("ERROR: Can't set channels number. %s\n", snd_strerror(pcm));
if (pcm = snd_pcm_hw_params_set_rate_near(pcm_handle_, params, (unsigned int*)&rate, 0) < 0)
printf("ERROR: Can't set rate. %s\n", snd_strerror(pcm));
/* Write parameters */
if (pcm = snd_pcm_hw_params(pcm_handle_, params) < 0)
printf("ERROR: Can't set harware parameters. %s\n", snd_strerror(pcm));
/* Resume information */
printf("PCM name: '%s'\n", snd_pcm_name(pcm_handle_));
printf("PCM state: %s\n", snd_pcm_state_name(snd_pcm_state(pcm_handle_)));
snd_pcm_hw_params_get_channels(params, &tmp);
printf("channels: %i ", tmp);
if (tmp == 1)
printf("(mono)\n");
else if (tmp == 2)
printf("(stereo)\n");
snd_pcm_hw_params_get_rate(params, &tmp, 0);
printf("rate: %d bps\n", tmp);
/* Allocate buffer to hold single period */
snd_pcm_hw_params_get_period_size(params, &frames_, 0);
LOGI << "frames_ = " << frames_;
buffSize_ = frames_ * channels * 2 /* 2 -> sample size */;
buff_.resize(buffSize_);
snd_pcm_hw_params_get_period_time(params, &tmp, NULL);
snd_pcm_hw_params_get_periods(params, &tmp, NULL); // https://www.alsa-project.org/wiki/FramesPeriods
LOGI << "periods_ =" << tmp;
return true;
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
