尝试了一下alsa录音播放的编程。


网上大部分文章比较老,最近这几年已经有新的接口了,一个snd_pcm_set_params函数搞定大部分参数设置

简单一点,例子说话

1。启动录音,第一打开第二设置

#define DEVICE "default"

int
StartPCMRecording(AUDIO_RECORD *pAudioRecord) { int rc, size, dir; snd_pcm_t *handle; snd_pcm_hw_params_t *params; snd_pcm_uframes_t frames, ret; /* Open PCM device for record. */ rc = snd_pcm_open(&handle, DEVICE, SND_PCM_STREAM_CAPTURE, 0); if (rc!=0) printf("%d, return %d, %s \n",__LINE__,rc,snd_strerror(rc)); #if 0 /* Allocate a hardware parameters object. */ rc = snd_pcm_hw_params_malloc(&params); if (rc!=0) printf("%d, return %d, %s \n",__LINE__,rc,snd_strerror(rc)); /* Fill it in with default values. */ rc = snd_pcm_hw_params_any(handle, params); if (rc!=0) printf("%d, return %d, %s \n",__LINE__,rc,snd_strerror(rc)); /* Signed 16-bit little-endian format */ rc = snd_pcm_hw_params_set_format(handle, params, FORMAT); if (rc!=0) printf("%d, return %d, %s \n",__LINE__,rc,snd_strerror(rc)); /* One channels (stereo) */ rc = snd_pcm_hw_params_set_channels(handle, params, CHANNLE); if (rc!=0) printf("%d, return %d, %s \n",__LINE__,rc,snd_strerror(rc)); rc = snd_pcm_hw_params_set_access (handle, params,SND_PCM_ACCESS_RW_INTERLEAVED ); if (rc!=0) printf("%d, return %d, %s \n",__LINE__,rc,snd_strerror(rc)); /* 16000 sampling rate */ rc = snd_pcm_hw_params_set_rate(handle, params, SAMPLE_RATE, 0); if (rc!=0) printf("%d, return %d, %s \n",__LINE__,rc,snd_strerror(rc)); frames = FRAMES_SIZE; rc = snd_pcm_sw_params_set_avail_min(handle,params,frames); if (rc!=0) printf("%d, return %d, %s \n",__LINE__,rc,snd_strerror(rc)); /* Write the parameters to the driver */ rc = snd_pcm_hw_params(handle, params); if (rc!=0) printf("%d, return %d, %s \n",__LINE__,rc,snd_strerror(rc)); #endif //int snd_pcm_set_params(snd_pcm_t *pcm, // snd_pcm_format_t format, // snd_pcm_access_t access, // unsigned int channels, // unsigned int rate, // int soft_resample, // unsigned int latency); snd_pcm_set_params(handle,SND_PCM_FORMAT_S16_LE,SND_PCM_ACCESS_RW_INTERLEAVED,1,48000,0,500000);

从上面看到,以前设置pcm参数的一大堆函数调用已经简化成一个

snd_pcm_set_params()

2。录音代码

int read_from_pcm(void *pDevice, void *pData, int samples)
{
    int ret;
    snd_pcm_t *handle = (snd_pcm_t *)pDevice;
    int nData=samples;

    //snd_pcm_wait(handle,20) ;
    ret = snd_pcm_readi(handle, pData, nData);
    return samples;
}

3。结束代码

        snd_pcm_drain(handle);
        snd_pcm_close(handle);

4。播放也类似,总共5个函数,open/setting/write/close

void startPlaying(){
    /* Open PCM device for playback. */
    rc = snd_pcm_open(&handle,DEVICE, SND_PCM_STREAM_PLAYBACK, 0);
    printf("[StartPCMPlaying]:snd_pcm_open return value is %d\n",rc);
    //int snd_pcm_set_params(snd_pcm_t *pcm,
    //                   snd_pcm_format_t format,
    //                   snd_pcm_access_t access,
    //                  unsigned int channels,
    //                   unsigned int rate,
    //                   int soft_resample,
    //                   unsigned int latency);
    snd_pcm_set_params(handle,SND_PCM_FORMAT_S16_LE,SND_PCM_ACCESS_RW_INTERLEAVED,1,48000,1,500000);
#if 0    
    /* Allocate a hardware parameters object. */
    rc = snd_pcm_hw_params_malloc(&params);
    if (rc!=0) printf("%d, return %d, %s \n",__LINE__,rc,snd_strerror(rc));

    /* Fill it in with default values. */
    rc=snd_pcm_hw_params_any(handle, params);
    if (rc!=0) printf("%d, return %d, %s \n",__LINE__,rc,snd_strerror(rc));

    /* Signed 16-bit little-endian format */
    rc=snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
    if (rc!=0) printf("%d, return %d, %s \n",__LINE__,rc,snd_strerror(rc));

    /* Two channels (stereo) */
    rc=snd_pcm_hw_params_set_channels(handle, params, 1);
    if (rc!=0) printf("%d, return %d, %s \n",__LINE__,rc,snd_strerror(rc));

    /* 44100 bits/second sampling rate (CD quality) */
    int val = 16000;
    rc=snd_pcm_hw_params_set_rate_near(handle, params,     &val, &dir);
    if (rc!=0) printf("%d, return %d, %s \n",__LINE__,rc,snd_strerror(rc));

    rc = snd_pcm_hw_params_set_access (handle, params,SND_PCM_ACCESS_RW_INTERLEAVED );
    if (rc!=0) printf("%d, return %d, %s \n",__LINE__,rc,snd_strerror(rc));


    rc = snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
    if (rc!=0) printf("%d, return %d, %s \n",__LINE__,rc,snd_strerror(rc));

    /* Write the parameters to the driver */
    rc = snd_pcm_hw_params(handle, params);
    if (rc < 0)
    {
        fprintf(stderr, "unable to set hw parameters: %s\n",
                snd_strerror(rc));
        exit(1);
    }
 #endif   
}

void write_to_pcm(void *pDevice, void *pData, int frames)
{
    int nlen = frames ;
    int rc = snd_pcm_writei(pDevice, pData, nlen);
}

void int StopPlaying(void *pDevice)
{
    snd_pcm_drain(pDevice;
    snd_pcm_close(pDevice);
}

 其中device可以用arecord -l 或aplay -l查看

通常用default是比较通用的选择,有耳麦用耳麦没耳麦用笔记本的

相关