这个函数是在linux下播放音频数据使用alsa libs。但是有一个问题,发送数据少于设置params。
int main()
{
int rc = 0;
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
int dir = 0;
char *buffer;
int size=0;
int val = 0;
int frames = 0;
int min,max;
int period_time;
snd_pcm_sframes_t delay,buffer_size,period_size,avail;
//through kill signal to statistics the number of send data
signal(SIGUSR1, sigproc_status);
rc = snd_pcm_open(&handle,"default",SND_PCM_STREAM_PLAYBACK,0);
if(rc < 0)
{
printf("unable to open pcm device\n");
return -1;
}
snd_pcm_hw_params_alloca(¶ms);
snd_pcm_hw_params_any(handle,params);
snd_pcm_hw_params_set_access(handle,params,SND_PCM_ACCESS_RW_INTERLEAVED);
//set 16bit
snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE);
//set two channels
snd_pcm_hw_params_set_channels(handle,params,2);
val = 44100;
//set rate is 44.1k
snd_pcm_hw_params_set_rate_near(handle,params,&val,&dir);
rc = snd_pcm_hw_params(handle,params);
if(rc < 0)
{
printf("unable to set params\n");
return -1;
}
snd_pcm_hw_params_current(handle,params);
snd_pcm_hw_params_get_period_time(params, &period_time,NULL);
frames = 32;
snd_pcm_hw_params_get_period_size(params,&frames,&dir);
size = frames*4;
buffer = (char *)malloc(size);
while(1)
{
len = len + size;
rc = snd_pcm_writei(handle,buffer,frames);
if(rc == -EPIPE)
{
printf("underrun occur\n");
snd_pcm_prepare(handle);
}
}
}
period_time = 21333帧= 940,所以(1000000/21333)* 940 * 4 = 176252bytes 但是params是44100 * 4 = 176400bytes 所以我们需要每秒丢弃一些字节。 如何发送更多字节?
您使用的是dmix
的默认配置,需要从44.1 kHz重新采样到48 kHz。 ALSA的内部重采样器始终适用于整个周期,因此您不得不使用的周期大小为1024 * 44.1 / 48 = 940(向下舍入)。
要强制使用941的周期大小,请使用频率为44110。
如果你想避免重新采样,如果可能的话,打开设备plughw:0
而不是default
,但是你失去了多客户端混合功能。 (然后你应该根据你的要求配置缓冲区/周期大小。)