Linux 音视频入门到实战专栏(音频篇)基于alsa api的音频播放/录制流程

server/2025/1/17 6:23:07/

在这里插入图片描述

文章目录

  • 一、简介
    • 1.1、音频播放流程
    • 1.2、音频录制流程
  • 二、播放音频示例
  • 三、录制音频示例

沉淀、分享、成长,让自己和他人都能有所收获!😄

📢本篇将介绍如何调用alsa api来进行音频数据的播放和录制。

一、简介

1.1、音频播放流程


音频播放流程主要包括打开设备、设置参数、写入数据和关闭设备等步骤。

步骤 1: 打开音频设备
使用 snd_pcm_open() 函数打开 PCM 设备。通常,设备类型为 SND_PCM_STREAM_PLAYBACK。

snd_pcm_t *handle;
int err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
if (err < 0) {fprintf(stderr, "PCM device open error: %s\n", snd_strerror(err));return -1;
}

步骤 2: 配置设备参数
使用 snd_pcm_set_params() 设置音频参数,如采样率、通道数、采样格式和缓冲区大小等。

err = snd_pcm_set_params(handle,SND_PCM_FORMAT_S16_LE,    // 采样格式,16位小端字节序SND_PCM_ACCESS_RW_INTERLEAVED, // 交错访问2,                      // 通道数,立体声44100,                  // 采样率1,                      // 1个周期即为一个音频块500000);                // 500ms超时
if (err < 0) {fprintf(stderr, "PCM set params error: %s\n", snd_strerror(err));return -1;
}

步骤 3: 播放音频数据
使用 snd_pcm_writei() 将音频数据写入设备。

short buffer[128];
while (1) {// 填充音频数据到缓冲区err = snd_pcm_writei(handle, buffer, 128);if (err == -EPIPE) {// 如果缓冲区溢出,重新准备设备snd_pcm_prepare(handle);} else if (err < 0) {fprintf(stderr, "Write error: %s\n", snd_strerror(err));}
}

步骤 4: 关闭音频设备
播放结束后,关闭 PCM 设备。

snd_pcm_close(handle);

1.2、音频录制流程


音频录制的流程类似,包括打开设备、配置参数、读取数据和关闭设备等步骤。

步骤 1: 打开音频设备
使用 snd_pcm_open() 打开 PCM 设备,设备类型为 SND_PCM_STREAM_CAPTURE。

snd_pcm_t *handle;
int err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0);
if (err < 0) {fprintf(stderr, "PCM device open error: %s\n", snd_strerror(err));return -1;
}

步骤 2: 配置设备参数
使用 snd_pcm_set_params() 设置音频参数,类似播放时的设置。

err = snd_pcm_set_params(handle,SND_PCM_FORMAT_S16_LE,    // 采样格式SND_PCM_ACCESS_RW_INTERLEAVED, // 交错访问2,                      // 通道数44100,                  // 采样率1,                      // 1个周期500000);                // 500ms超时
if (err < 0) {fprintf(stderr, "PCM set params error: %s\n", snd_strerror(err));return -1;
}

步骤 3: 读取音频数据
使用 snd_pcm_readi() 从 PCM 设备中读取音频数据。

short buffer[128];
while (1) {err = snd_pcm_readi(handle, buffer, 128);if (err == -EPIPE) {// 如果发生溢出,重新准备设备snd_pcm_prepare(handle);} else if (err < 0) {fprintf(stderr, "Read error: %s\n", snd_strerror(err));}// 处理读取的数据
}

步骤 4: 关闭音频设备
录制完成后,关闭 PCM 设备。

snd_pcm_close(handle);

二、播放音频示例

播放音频主要流程为:

  1. 打开设备
  2. 设置参数
  3. 写入数据
  4. 关闭设备
#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h>void main (int argc, char *argv[])
{int i;int err;short buf[128];snd_pcm_t *playback_handle;snd_pcm_hw_params_t *hw_params;if ((err = snd_pcm_open (&playback_handle, argv[1], SND_PCM_STREAM_PLAYBACK, 0)) < 0) {fprintf (stderr, "cannot open audio device %s (%s)\n", argv[1],snd_strerror (err));exit (1);}if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n",snd_strerror (err));exit (1);}if ((err = snd_pcm_hw_params_any (playback_handle, hw_params)) < 0) {fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n",snd_strerror (err));exit (1);}if ((err = snd_pcm_hw_params_set_access (playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {fprintf (stderr, "cannot set access type (%s)\n",snd_strerror (err));exit (1);}if ((err = snd_pcm_hw_params_set_format (playback_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {fprintf (stderr, "cannot set sample format (%s)\n",snd_strerror (err));exit (1);}if ((err = snd_pcm_hw_params_set_rate_near (playback_handle, hw_params, 44100, 0)) < 0) {fprintf (stderr, "cannot set sample rate (%s)\n",snd_strerror (err));exit (1);}if ((err = snd_pcm_hw_params_set_channels (playback_handle, hw_params, 2)) < 0) {fprintf (stderr, "cannot set channel count (%s)\n",snd_strerror (err));exit (1);}if ((err = snd_pcm_hw_params (playback_handle, hw_params)) < 0) {fprintf (stderr, "cannot set parameters (%s)\n",snd_strerror (err));exit (1);}snd_pcm_hw_params_free (hw_params);if ((err = snd_pcm_prepare (playback_handle)) < 0) {fprintf (stderr, "cannot prepare audio interface for use (%s)\n",snd_strerror (err));exit (1);}for (i = 0; i < 10; ++i) {if ((err = snd_pcm_writei (playback_handle, buf, 128)) != 128) {fprintf (stderr, "write to audio interface failed (%s)\n",snd_strerror (err));exit (1);}}snd_pcm_close (playback_handle);exit (0);
}

三、录制音频示例


录制音频与写入基本类似,只是写入改为读取。

#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h>void main (int argc, char *argv[])
{int i;int err;short buf[128];snd_pcm_t *capture_handle;snd_pcm_hw_params_t *hw_params;if ((err = snd_pcm_open (&capture_handle, argv[1], SND_PCM_STREAM_CAPTURE, 0)) < 0) {fprintf (stderr, "cannot open audio device %s (%s)\n", argv[1],snd_strerror (err));exit (1);}if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n",snd_strerror (err));exit (1);}if ((err = snd_pcm_hw_params_any (capture_handle, hw_params)) < 0) {fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n",snd_strerror (err));exit (1);}if ((err = snd_pcm_hw_params_set_access (capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {fprintf (stderr, "cannot set access type (%s)\n",snd_strerror (err));exit (1);}if ((err = snd_pcm_hw_params_set_format (capture_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {fprintf (stderr, "cannot set sample format (%s)\n",snd_strerror (err));exit (1);}if ((err = snd_pcm_hw_params_set_rate_near (capture_handle, hw_params, 44100, 0)) < 0) {fprintf (stderr, "cannot set sample rate (%s)\n",snd_strerror (err));exit (1);}if ((err = snd_pcm_hw_params_set_channels (capture_handle, hw_params, 2)) < 0) {fprintf (stderr, "cannot set channel count (%s)\n",snd_strerror (err));exit (1);}if ((err = snd_pcm_hw_params (capture_handle, hw_params)) < 0) {fprintf (stderr, "cannot set parameters (%s)\n",snd_strerror (err));exit (1);}snd_pcm_hw_params_free (hw_params);if ((err = snd_pcm_prepare (capture_handle)) < 0) {fprintf (stderr, "cannot prepare audio interface for use (%s)\n",snd_strerror (err));exit (1);}for (i = 0; i < 10; ++i) {if ((err = snd_pcm_readi (capture_handle, buf, 128)) != 128) {fprintf (stderr, "read from audio interface failed (%s)\n",snd_strerror (err));exit (1);}}snd_pcm_close (capture_handle);exit (0);
}

http://www.ppmy.cn/server/159016.html

相关文章

学习微信小程序的下拉列表控件-picker

1、创建一个空白工程 2、index.wxml中写上picker布局&#xff1a; <!--index.wxml--> <view class"container"><picker mode"selector" range"{{array}}" bindchange"bindPickerChange"><view class"pick…

10k 、100k NTC热敏电阻阻值表与温度关系

常用的热敏电阻有10k,100k阻值。 所谓的10k&#xff0c;100k是指该热敏电阻在摄氏25度的时候所对应的阻值。 还有一个重要的参数就是热敏电阻的B值&#xff0c;这个B值网上有很多资料和解读&#xff0c;其实可以把它理解成是该热敏电阻阻值随温度的变化率&#xff0c;他对温度…

【Linux】常见指令(一)

Linux常见指令 01.whoami02.pwd03.ls04.mkdir05.cd 本文LInux环境为&#xff0c;使用XShell远程登陆到Linux。 具体如何环境搭建&#xff0c;大家可以查看其他博客。 01.whoami whoami 指令用来查看当前账户是谁。 如上图所示&#xff0c;使用whoami指令&#xff0c;查看到现在…

MATLAB语言的面向对象编程

MATLAB语言的面向对象编程 引言 MATLAB&#xff0c;作为一种高效且功能强大的数值计算环境&#xff0c;以其丰富的数学工具箱和强大的绘图功能被广泛应用于工程、科学研究及教育领域。近年来&#xff0c;随着软件开发需求的不断增加&#xff0c;MATLAB也引入了面向对象编程&a…

使用Python和FFmpeg批量转换视频为GIF

使用Python和FFmpeg批量转换视频为GIF 我们来继续昨天的项目&#xff0c;但是昨天所说的是单个视频转pdf&#xff0c;要实现批量转化&#xff0c;还需进行参数的调整 批量转换视频为GIF的示例代码 下面是一个Python脚本示例&#xff0c;展示了如何遍历一个目录中的所有视频文…

《鸿蒙Next旅游应用:人工智能赋能个性化与智能导览新体验》

随着鸿蒙Next的推出&#xff0c;旅游应用迎来了全新的发展机遇&#xff0c;借助人工智能技术能为用户带来更出色的个性化推荐和智能导览服务。 鸿蒙Next与人工智能融合优势 鸿蒙Next拥有强大的分布式能力和原生智能体验。其能打破设备界限&#xff0c;实现多设备协同&#xf…

2024年第十二期 | CCF ODC《开源战略动态月报》

点击蓝字 关注我们 CCF Opensource Development Committee 导 读 2024年第十一期CCF ODC《开源战略动态月报》共摘选45篇文章&#xff0c;分为8个版块&#xff1a;ODC专栏、开源政策、理论观点、产业动态、技术项目、开源组织与机构、开源报告通讯会议以及RISC-V专栏&#xff0…

【大数据】机器学习------决策树

一、基本流程 决策树是一种基于树结构的分类和回归方法&#xff0c;它通过对特征空间进行划分&#xff0c;每个内部节点表示一个特征测试&#xff0c;每个分支代表一个测试输出&#xff0c;每个叶节点代表一个类别或回归值。 特征选择&#xff1a;根据某种准则&#xff08;如信…