嵌入式linux中PCM音频编程实践

    嵌入式设备中经常需要用的音频,音频设备最原始的数据格式就是PCM,也就是大家常见的WAV,在linux中,音频编程使用最多的就是alsa框架,下面就来看一下pcm音频的编程实例吧。

    首先需要包含头文件:

#include  

定义产量与结构体

snd_pcm_t 			*alsaplayhdl;
snd_pcm_t 			*alsacapturehdl;


snd_mixer_t 		*mixerfd;
snd_mixer_elem_t 	*elem;

pthread_mutex_t alsa_play_mutex;
pthread_mutex_t alsa_cap_mutex;

snd_pcm_hw_params_t *dispalsa_hwparams;
snd_pcm_sw_params_t *dispalsa_swparams;

snd_pcm_hw_params_t *capturehwparams;
snd_pcm_sw_params_t *captureswparams;

定义设备号:

#define ALSADEVNAME "default"

打开设备:

void open_dev(void)
{
	int ret = -1;

	ret = snd_pcm_open(&alsaplayhdl,ALSADEVNAME,SND_PCM_STREAM_PLAYBACK,0);
	if(ret < 0)
	{
		printf("open alsa display failture\n");
	}
}
关闭设备:

void close_dev(void)
{
    int ret = -1;
    pthread_t tid;
    if(alsaplayhdl != NULL)
    {
        snd_pcm_drop(alsaplayhdl);
        ret = snd_pcm_close(alsaplayhdl);
        if(ret < 0)
        {
            printf("alsa close dev failture\n");
        }
        alsaplayhdl = NULL;
    }

}

写入音频数据

int alsa_write(char* buf, int length)
{
    int frames;
    int ret=0;
    int write = 0,size;
	long int audiodisplay[2];
    audiodisplay[0]++;                                           //正常情况下,alsa_write_audiobuf()调用一次,sysglobaldata_status.audiodisplay[0]的值增加1。如果该值长久没有变化时表明声音播放异常
    frames = snd_pcm_writei(alsaplayhdl, buf, length/2);
    if(frames ==  -EPIPE)
    {
        printf("apps write buff too Slow!-EPIPE\n");
        snd_pcm_prepare(alsaplayhdl);
        frames = snd_pcm_writei(alsaplayhdl, buf, length/2);
    }
    else if(frames < 0)
    {
        printf("snd_pcm_writei call failure:%s\n", snd_strerror(ret));
        frames = snd_pcm_recover(alsaplayhdl, frames, 0);
    }
    ret = frames*2;
err:
    return ret;
}

读取设备音频数据

int alsa_read(char* buf, int length)
{
	int frames;
	int ret = -1;
	int read;

	pthread_mutex_lock(&alsa_cap_mutex);
	frames = snd_pcm_avail(alsacapturehdl);
	if(frames <= 0)
	{
		goto err;
	}
	read = frames *2 > length ? length : frames * 2;
	frames = snd_pcm_readi(alsacapturehdl, buf, read/2);
	if(frames < 0)
	{
		goto err;
	}
	ret = frames * 2;
err:
	pthread_mutex_unlock(&alsa_cap_mutex);
	return ret;
}

打开混音器

int open_mixer(void)
{
	int ret;
	unsigned char		mixercount;
	if(mixercount <= 0)
	{
		ret = snd_mixer_open(&mixerfd,0);                       // 打开混音器
		if(ret < 0)
		{
			printf("alsa mixer open failture\n");
			return -1;
		}
		ret = snd_mixer_attach(mixerfd,"default"); 				// 先设定为默认
		if(ret < 0)
		{
			printf("alsa mixer attach failture\n");
			return -2;
		}
		ret = snd_mixer_selem_register(mixerfd,NULL,NULL);    		 // 注册混音器
		if(ret < 0)
		{
			printf("alsa mixer register failture\n");
			return -3;
		}
		ret = snd_mixer_load(mixerfd);
		if(ret < 0)
		{
			printf("alsa mixer load failture\n");
			return -4;
		}
		mixercount = 0;
	}
	mixercount ++;
	return mixercount;
}

设置设备音量

int set_volume(int volume) 
{
    int err;  
    int orig_volume = 0;  
    static snd_ctl_t *handle = NULL;  
    snd_ctl_elem_info_t *info;  
    snd_ctl_elem_id_t *id;  
    snd_ctl_elem_value_t *control;  
    unsigned int count;  
    snd_ctl_elem_type_t type;  

    snd_ctl_elem_info_alloca(&info);  
    snd_ctl_elem_id_alloca(&id);  
    snd_ctl_elem_value_alloca(&control);      
    snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
    snd_ctl_elem_id_set_name(id, "Mic Capture Volume");  
          
    if ((err = snd_ctl_open(&handle, "default", 0)) < 0) {  
        printf("open ctl device failed\n");       
        return -1;  
    }   
             
    snd_ctl_elem_info_set_id(info, id);  
    if ((err = snd_ctl_elem_info(handle, info)) < 0) {  
        printf("snd_ctl_elem_info failed\n");
        snd_ctl_close(handle);  
        handle = NULL;  
        return -1;  
    }  
    type = snd_ctl_elem_info_get_type(info);  
    count = snd_ctl_elem_info_get_count(info);  
    snd_ctl_elem_value_set_id(control, id);  
      
    if (!snd_ctl_elem_read(handle, control)) {  
        orig_volume = snd_ctl_elem_value_get_integer(control, 0);  
    }  
      
    if(volume != orig_volume) {  
        //snd_ctl_elem_value_set_integer(control, 0, static_cast(volume));  
        snd_ctl_elem_value_set_integer(control, 0,volume);  
        snd_ctl_elem_value_set_integer(control, 1,volume);  
        if ((err = snd_ctl_elem_write(handle, control)) < 0) 
	{  
            printf("snd_ctl_elem_write failed\n");
            snd_ctl_close(handle);  
            handle = NULL;  
            return -1;  
        }  
    }   
    snd_ctl_close(handle);  
    handle = NULL;  
    return 1;  
}


你可能感兴趣的:(linux)