自学内容网 自学内容网

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

在这里插入图片描述

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

📢本篇将介绍如何调用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);
}

原文地址:https://blog.csdn.net/qq_33487044/article/details/145150442

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!