Alsa-lib实现播放wav音频

1.alsa-lib移植

例程中使用的alsa-lib库是1.2.6版本的,目前最新的release版本已经到1.2.7版本了,可以根据自身需求下载。

具体下载链接可以访问下面alsa官网的下载链接

https://www.alsa-project.org/files/pub/lib/

下载完alsa-lib库后,我们解压后进入文件夹然后执行下列命令,进行交叉编译

mkdir builds
./configure --prefix=$PWD/builds --host=arm cc=arm-linux-gnueabihf-gcc
make
make install

所有的lib库和头文件都会在builds文件夹下,执行file + lib库,查看交叉编译是否完成,下列是32bit 小端模式,表示交叉编译完成

/project/alsa-lib-1.2.6$ file build/lib/libasound.so.2.0.0
build/lib/libasound.so.2.0.0: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, BuildID[sha1]=568ab75e8ab65df19ba5f34b536694ee4449ce6f, not stripped

2.播放wav音频

alsa-lib具体的播放音频步骤如下,可以参照官网的例程

1.相关变量定义

2.申请hwparams变量内存 snd_pcm_hw_params_alloca(&pcm->hwparams)

3.打开pcm设备snd_pcm_open

4.初始化hwparams的结构体空间

5.设置数据的属性

​ 1.设置数据的读写模式(一般音频双通道分交错访问模式)

​ 2.设置数据的采样格式(每bit的样本长度)

​ 3.设置数据的通道数

​ 4.设置数据的采样速率

​ 5.设置数据的采样周期

​ 每帧的大小 = 采样格式 * 通道数 / 8bit

​ 特定的周期内的帧数 = 周期大小 * 周期数 / 每帧的大小

​ 比如 某个音频的 采样格式是SND_PCM_FORMAT_S16_LE , 通道数是 2 ,所以一帧的音频大小是 16 x 2 /8 = 4个字节,

周期数为20,周期大小为8192,这个周期内帧数一共有 20 x 8192 >> 2 = 40960 帧

6.申请存放buff的空间 (按帧数计算)snd_pcm_hw_params_set_buffer_size

7.读取音频数据

8.调用snd_pcm_writei 进行播放

具体的代码在,这个例程只实现了播放wav文件,后续继续更新其他功能

git@github.com:lilixinxin/Alsa_example.git

alsa-lib的封装的结构体

typedef struct pcm_params {

    char pcm_card_name[64];

    snd_pcm_t *pcm_handle;

    snd_pcm_stream_t stream_direction;

    snd_pcm_hw_params_t *hwparams;

    int channel_num;

    int periods;

    snd_pcm_format_t sample_format;

    snd_pcm_access_t access_type;

    int sample_rate;

    int period_szie;

    int frames;
}Pcm_params;

初始化alsa 相关参数


int Alsa_Dev_init(Pcm_params *pcm)
{
    int ret;

    snd_pcm_hw_params_alloca(&pcm->hwparams);

    if(snd_pcm_open(&pcm->pcm_handle, pcm->pcm_card_name, pcm->stream_direction, 0) < 0)
    {
        fprintf(stderr, "Error opening PCM device %s\n", pcm->pcm_card_name);
        return -1;
    }

    if (snd_pcm_hw_params_any(pcm->pcm_handle, pcm->hwparams) < 0) {
      fprintf(stderr, "Can not configure this PCM device.\n");
      return -1;
    }

    if (snd_pcm_hw_params_set_access(pcm->pcm_handle, pcm->hwparams, pcm->access_type) < 0) {

        fprintf(stderr, "Can not set hw params access\n");
        return -1;
    }

    if(snd_pcm_hw_params_set_format(pcm->pcm_handle, pcm->hwparams, pcm->sample_format) < 0)
    {
        fprintf(stderr, "snd_pcm_hw_params_set_format fail\n");
        return -1;

    }

    if(snd_pcm_hw_params_set_channels(pcm->pcm_handle, pcm->hwparams, pcm->channel_num) < 0)
    {
        fprintf(stderr, "snd_pcm_hw_params_set_channels fail\n");
        return -1;
    }

    if(snd_pcm_hw_params_set_periods(pcm->pcm_handle, pcm->hwparams, pcm->periods, 0) < 0)
    {
        fprintf(stderr, "snd_pcm_hw_params_set_periods fail\n");
        return -1;
    }

    if(snd_pcm_hw_params_set_rate_near(pcm->pcm_handle, pcm->hwparams, &pcm->sample_rate, 0) < 0)
    {
        fprintf(stderr, "snd_pcm_hw_params_set_rate_near fail\n");
        return -1;
    }

    if (snd_pcm_hw_params_set_buffer_size(pcm->pcm_handle, pcm->hwparams, pcm->frames) < 0) {
      fprintf(stderr, "Error setting buffersize.\n");
      return(-1);
    }

    if (snd_pcm_hw_params(pcm->pcm_handle, pcm->hwparams) < 0) {
      fprintf(stderr, "Error setting HW params.\n");
      return(-1);
    }

    return 0;

}

int Alsa_Playback(Pcm_params *pcm, char **buf)
{
    int pcmreturn;
    while ((pcmreturn = snd_pcm_writei(pcm->pcm_handle, buf, pcm->frames)) < 0) {
            snd_pcm_prepare(pcm->pcm_handle);
            fprintf(stderr, "<<<<<<<<<<<<<<< Buffer Underrun >>>>>>>>>>>>>>>\n");
      }
    return 0;
}

实现播放


    int buffsize = pcm.period_szie * pcm.periods;
    buff = (char *)malloc(buffsize);
    if(buff == NULL)
    {
        fprintf(stderr, "malloc fail\n");
        return -1;

    }

    while(1)
    {
        ret = fread(buff, 1, buffsize, fp);
        printf("read buff len, :%d\n", ret);
        if(ret == 0){
            printf("end of music file input! \n");
           exit(1);
        }

        if(ret < 0){
            printf("read pcm from file! \n");
            exit(1);
        }
        while ((ret = snd_pcm_writei(pcm.pcm_handle, buff, pcm.frames)) < 0) {
            snd_pcm_prepare(pcm.pcm_handle);
            fprintf(stderr, "<<<<<<<<<<<<<<< Buffer Underrun >>>>>>>>>>>>>>>\n");
      }

    }

Original: https://blog.csdn.net/qq_39678541/article/details/125204110
Author: Linux小南
Title: Alsa-lib实现播放wav音频

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/524789/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球