文章目录
- 一、简介
- 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);
二、播放音频示例
播放音频主要流程为:
- 打开设备
- 设置参数
- 写入数据
- 关闭设备
#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);
}