有谁对音频设备的读写相对了解的,进来看看。(紧急,非常感谢)

juckciy 2011-10-11 09:02:33
看看下面这个写pcm数据的函数。
为什么要是出现WARNING: AUDIOWRITE: Underrun occurred. Preparing pcm..,网上查了下,说是送的数据不够就会出现,设备播空了。好像跟period(硬件中中断间的间隔时间)有关系,新手不太懂,请高手帮忙分析下原因。
int DRV_audioWrite(DRV_AudioHndl *hndl, void *pInBuf, int writeSamples)
{
int rc;
DRV_AudioObj *pObj;

if(hndl==NULL)
return OSA_EFAIL;

if(hndl->hndl==NULL)
return OSA_EFAIL;

pObj = (DRV_AudioObj *)hndl->hndl;

while (writeSamples > 0)
{
rc = snd_pcm_writei(pObj->sound_handle, pInBuf, writeSamples);

if (rc == -EPIPE)
{
/* EPIPE means overrun */
OSA_printf("WARNING: AUDIOWRITE: Underrun occurred. Preparing pcm..\n");
if (snd_pcm_prepare(pObj->sound_handle) < 0) {
OSA_ERROR("Failed to recover from underrun\n");
}

//return 0;
}
else{
if( rc < 0 )
{
OSA_ERROR("error from write : %s\n",snd_strerror(rc));
if (snd_pcm_prepare(pObj->sound_handle) < 0) {
OSA_ERROR("Failed to recover from snd_strerror\n");
}
}

return rc;
}
if (rc == -EPIPE) {
//memset(pInBuf, 0x7F, writeSamples*2*2);
//printf("rc != writeSamples\n");
}
else {
printf("write success\n");
writeSamples -= rc;
}
}
}
下面是打开音频设备的代码。
Audioplayconfig.samplingRate = rbuf.sampleRate; //8000
Audioplayconfig.deviceId = 0;
Audioplayconfig.numChannels = 1;
Audioplayconfig.buff_Of_Samples = 640;
Audioplayconfig.bufferSize = 1280;

rc = DRV_audioplayOpen(&gAUDIOPLAY_ctrl.audioHndl, &Audioplayconfig);
if(rc != OSA_SOK)
{snd_msg(snd_msg_qid);
return rc;
}
int DRV_audioOpen(DRV_AudioHndl *hndl, DRV_AudioConfig *config)
{

int rc = 0;
unsigned int val = 0;
int dir = 0;
unsigned int buffer_time = 0;
snd_pcm_uframes_t frames;
snd_pcm_uframes_t buffer_frames;
snd_pcm_hw_params_t *sound_params = NULL;
DRV_AudioObj *pObj;

hndl->hndl = OSA_memAlloc(sizeof(DRV_AudioObj));
if( hndl->hndl == NULL )
{
OSA_ERROR("OSA_memAlloc fail \n");
goto error_exit;
}

pObj = (DRV_AudioObj*)hndl->hndl;
memset(pObj,0,sizeof(DRV_AudioObj));

/* Open PCM device for record. */
rc = snd_pcm_open(&(pObj->sound_handle), "default", SND_PCM_STREAM_CAPTURE, 0);
if (rc < 0)
{
OSA_ERROR("unable to open pcm device: %s\n", snd_strerror(rc));
goto error_exit;
}

/* Allocate a hardware parameters object. */
snd_pcm_hw_params_alloca(&sound_params);

/* Fill it in with default values. */
snd_pcm_hw_params_any(pObj->sound_handle, sound_params);

/* Set the desired hardware parameters. */

/* Sampling rate*/
val = config->samplingRate;
snd_pcm_hw_params_set_rate_near(pObj->sound_handle, sound_params, &val, &dir);
if (val != config->samplingRate)
{
OSA_ERROR("Rate doesn't match (requested %iHz, get %iHz)\n", config->samplingRate, val);
goto error_exit;
}

/* Signed 16-bit little-endian format */
snd_pcm_hw_params_set_format(pObj->sound_handle, sound_params, SND_PCM_FORMAT_S16_LE);
/* Interleaved mode */
snd_pcm_hw_params_set_access(pObj->sound_handle, sound_params, SND_PCM_ACCESS_RW_INTERLEAVED);
/* Num channels */
snd_pcm_hw_params_set_channels(pObj->sound_handle, sound_params, config->numChannels);

/* Set period size of frames. */
frames = config->buff_Of_Samples;
snd_pcm_hw_params_set_period_size_near(pObj->sound_handle, sound_params, &frames, &dir);

/* set the buffer time */
if( buffer_time )
{
rc = snd_pcm_hw_params_set_buffer_time_near(pObj->sound_handle, sound_params, &buffer_time, &dir);
if (rc < 0) {
OSA_ERROR("Unable to set buffer time %i for playback: %s\n", buffer_time, snd_strerror(rc));
goto error_exit;
}
}
else{
buffer_frames = frames*4;
snd_pcm_hw_params_set_buffer_size_near(pObj->sound_handle, sound_params, &buffer_frames);
}

/* Write the parameters to the driver */
rc = snd_pcm_hw_params(pObj->sound_handle, sound_params);
if (rc < 0)
{

OSA_ERROR("unable to set hw parameters: %s\n",
snd_strerror(rc));
goto error_exit;
}

/* Use a buffer large enough to hold one period */
snd_pcm_hw_params_get_period_size(sound_params, &frames, &dir);

snd_pcm_hw_params_get_period_time(sound_params, &val, &dir);
.....
}
请问是为什么?我怀疑是打开采集设备的某个参数设置得不对。现在用的默认值。TI dm365的codec代码。
...全文
202 2 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
juckciy 2011-10-13
  • 打赏
  • 举报
回复
顶一个,难道有这么难么?看来是没人回答 了,谁随便回复个,送分结贴!
juckciy 2011-10-11
  • 打赏
  • 举报
回复
刚刚调试有个重大发现,在打开音频设备的地方改为Audioplayconfig.samplingRate = gAUDIOPLAY_ctrl.curPlaySampleRate;
Audioplayconfig.deviceId = 0;
Audioplayconfig.numChannels = 1;
Audioplayconfig.buff_Of_Samples = 1280;
Audioplayconfig.bufferSize = 1280;

snd_pcm_writei就不会出现underrun了。声音一切都正常,但大约有2s的延时。snd_pcm_writei一直在打error from write : Failed to recover from snd_strerror.为什么?那位大侠在理论方面指点下,没接触过音频的新手在这里谢谢了。

70,023

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧