Linux麦克风录音实战

news/2024/11/26 20:30:22/

在 Linux 上使用麦克风进行录音可以通过多种方式实现,包括使用命令行工具、图形界面应用程序以及编程接口。下面我将介绍几种常见的方法,从简单的命令行工具到使用 PortAudio 库进行编程。

一. 使用arecord命令行工具

arecord 是 ALSA(Advanced Linux Sound Architecture)提供的一个命令行工具,可以用来录制音频。以下是基本步骤:
步骤 1: 检查麦克风设备:首先,确保你的麦克风设备已经被系统识别。你可以使用 arecord -l 命令来列出所有可用的录音设备。

arecord -l

输出示例:
在这里插入图片描述
这里card 3和device 0是要使用的麦克风设备。
步骤 2: 录制音频
使用 arecord 命令进行录音,并指定设备和输出文件格式。例如,录制一个 10 秒的音频文件:

arecord -D hw:3,0 -f cd -d 10 output.wav
  • -D hw:0,0:指定设备 card 0, device 0。
  • -f cd:指定采样格式为 CD 质量(16-bit, 44.1 kHz, stereo)。
  • -d 10:录制时间 10 秒。
  • output.wav:输出文件名。

二. 使用 PortAudio 编程库

PortAudio 是一个跨平台的音频 I/O 库,支持多种编程语言。以下是一个使用 C++ 和 PortAudio 进行麦克风录音的示例。
步骤一:安装PortAudio
首先,安装PortAudio库

sudo apt-get install portaudio19-dev

或者编译portaudio库的源代码

git clone https://github.com/PortAudio/portaudio.git
cd portaudio
./configure
make
make install

步骤二:编写录音程序
创建一个 C++ 文件(例如 recorder.cc),并编写录音代码。

// 引入portaudio库
#include <portaudio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>// 采样频率44100hz
#define SAMPLE_RATE 44100
// 每个缓冲区的帧数
#define FRAMES_PER_BUFFER 1024
// 录制的时间长度
#define RECORD_SECONDS 10// WAV 文件头结构
typedef struct {char riff[4];            // "RIFF"int filesize;            // 文件大小减8char wave[4];            // "WAVE"char fmt_chunk_marker[4]; // "fmt "int fmt_chunk_len;       // 格式块长度 (16)short audio_format;      // 音频格式 (1 for PCM)short num_channels;      // 声道数 (1 for mono, 2 for stereo)int sample_rate;         // 采样率 (例如 44100)int byte_rate;           // 每秒字节数 (sample_rate * num_channels * (bits_per_sample/8))short frame_size;        // 每个样本的字节数 (num_channels * (bits_per_sample/8))short bits_per_sample;   // 每个样本的位数 (例如 16)char data_chunk_header[8]; // "data"int data_bytes;          // 数据字节数 (frame_count * frame_size)
} WavHeader;// 回调函数
// portaudio会在每次有新的音频数据时调用这个函数
int recordCallback(const void *inputBuffer, void *outputBuffer,unsigned long framesPerBuffer,const PaStreamCallbackTimeInfo* timeInfo,PaStreamCallbackFlags statusFlags,void *userData) {FILE *file = (FILE *)userData;fwrite(inputBuffer, sizeof(short), framesPerBuffer, file);return paContinue;
}int main() {PaStream *stream;PaError err;FILE *file;// 初始化 PortAudioerr = Pa_Initialize();if (err != paNoError) {fprintf(stderr, "Pa_Initialize: %s\n", Pa_GetErrorText(err));return 1;}// 打开文件file = fopen("output.wav", "wb");if (!file) {fprintf(stderr, "无法打开输出文件\n");Pa_Terminate();return 1;}// 设置 WAV 文件头WavHeader header = {0};strcpy(header.riff, "RIFF");strcpy(header.wave, "WAVE");strcpy(header.fmt_chunk_marker, "fmt ");header.fmt_chunk_len = 16;header.audio_format = 1;header.num_channels = 1;header.sample_rate = SAMPLE_RATE;header.byte_rate = SAMPLE_RATE * header.num_channels * 2;header.frame_size = header.num_channels * 2;header.bits_per_sample = 16;strcpy(header.data_chunk_header, "data");header.data_bytes = SAMPLE_RATE * RECORD_SECONDS * header.frame_size;// 计算文件大小header.filesize = 36 + header.data_bytes;// 写入 WAV 文件头fwrite(&header, sizeof(WavHeader), 1, file);// 设置输入参数PaStreamParameters inputParameters;// 在 PortAudio 中,设备 ID 通常与 arecord 命令列出的 card 编号对应。inputParameters.device = 3;  // 指定设备 ID---对应arecord -l输出的card 3inputParameters.channelCount = 1;inputParameters.sampleFormat = paInt16;inputParameters.suggestedLatency = Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency;inputParameters.hostApiSpecificStreamInfo = NULL;// 打开音频流err = Pa_OpenStream(&stream, &inputParameters, NULL, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, recordCallback, file);if (err != paNoError) {fprintf(stderr, "Pa_OpenStream: %s\n", Pa_GetErrorText(err));fclose(file);Pa_Terminate();return 1;}// 启动音频流err = Pa_StartStream(stream);if (err != paNoError) {fprintf(stderr, "Pa_StartStream: %s\n", Pa_GetErrorText(err));Pa_CloseStream(stream);fclose(file);Pa_Terminate();return 1;}// 录音printf("录音中... (按任意键停止)\n");getchar();// 停止音频流err = Pa_StopStream(stream);if (err != paNoError) {fprintf(stderr, "Pa_StopStream: %s\n", Pa_GetErrorText(err));Pa_CloseStream(stream);fclose(file);Pa_Terminate();return 1;}// 关闭音频流Pa_CloseStream(stream);// 更新 WAV 文件头中的数据大小header.data_bytes = ftell(file) - 44;header.filesize = 36 + header.data_bytes;fseek(file, 0, SEEK_SET);fwrite(&header, sizeof(WavHeader), 1, file);// 关闭文件fclose(file);// 终止 PortAudioPa_Terminate();printf("录音完成。\n");return 0;
}

步骤3:编译和运行
使用 g++ 编译代码:

g++ recorder.cc -o recorder -lportaudio
./recorder

使用cmake编译代码
编写 CMakeLists.txt

   cmake_minimum_required(VERSION 3.10)# 项目名称project(Recorder)# 查找 PortAudio 库find_package(PortAudio REQUIRED)# 添加可执行文件add_executable(recorder recorder.cc)# 链接 PortAudio 库target_link_libraries(recorder PRIVATE ${PORTAUDIO_LIBRARIES})# 设置可执行文件的输出目录set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)

编写 CMakeLists.txt后,执行命令

   mkdir buildcd buildcmake ..make./bin/recorder

http://www.ppmy.cn/news/1550136.html

相关文章

CSS笔记(一)炉石传说卡牌设计1

目标 我要通过html实现一张炉石传说的卡牌设计 问题 其中必须就要考虑到各个元素的摆放&#xff0c;形状的调整来达到满意的效果。通过这个联系来熟悉一下CSS的基本操作。 1️⃣ 基本概念 在CSS里面有行元素&#xff0c;块元素&#xff0c;内联元素&#xff0c;常见的行元…

深入探索:C++红黑树原理与实现

文章目录 一、红黑树的概念二、红黑树的规则三、红黑树与AVL树性能对比四、红黑树框架的搭建五、红黑树的插入逻辑1. 大体框架2. 初始颜色的设置3. 颜色的调整1&#xff09;通过具体的情况对颜色调整进行框架认识2&#xff09;通过抽象图对颜色调整加深理解情况一&#xff1a;u…

《硬件架构的艺术》笔记(五):低功耗设计

介绍 能量以热量形式消耗&#xff0c;温度升高芯片失效率也会增加&#xff0c;增加散热片或风扇会增加整体重量和成本&#xff0c;在SoC级别对功耗进行控制就可以减少甚至可能消除掉这些开支&#xff0c;产品也更小更便宜更可靠。本章描述了减少动态功耗和静态功耗的各种技术。…

设计模式-创建型-单例模式

1.概念 该设计模式保证全局只有一个实例对象可以使用&#xff0c;并且自动实例化&#xff0c;向外部提供一个使用接口。 2.作用 保证某些对象在项目中只有一份。 3.应用场景 比如&#xff1a; 全局的计数器——web页面文章阅读计数 全局的资源共享——用户登录后各个页面之…

CircuitBreaker机制详解:Elasticsearch中的资源管理

CircuitBreaker机制详解:Elasticsearch中的资源管理 在现代软件架构中,熔断器(CircuitBreaker)是一种重要的模式,用于防止系统过载并保护系统稳定性。在Elasticsearch中,熔断器机制尤其关键,因为它们帮助管理资源使用,防止节点因资源耗尽而崩溃。本文将深入探讨Elasti…

C51相关实验

C51相关实验 LED (P2 / 0~7)蜂鸣器 (P2^5)数码管 (P0 0~7 段 &#xff0c;P2 2~4 位)独立按键 &#xff08;P3^1 P3^0 P3^2 P3^3&#xff09;直流电机 (J47 5v 01~04)综合实验矩阵按键 (P1组 0~7) LED (P2 / 0~7) //功能&#xff1a;1.让开发板的LED全亮&#xff0c;2,点亮某一…

嵌入式系统与单片机工作原理详解

随着现代科技的发展&#xff0c;嵌入式系统已经深入到我们日常生活中的方方面面。无论是智能家居、汽车电子&#xff0c;还是工业控制、医疗设备&#xff0c;都离不开嵌入式系统的支持。而单片机作为嵌入式系统的核心组件&#xff0c;是实现这些功能的关键之一。本文将详细介绍…

前端---HTML(一)

HTML_网络的三大基石和html普通文本标签 1.我们要访问网络&#xff0c;需不需要知道&#xff0c;网络上的东西在哪&#xff1f; 为什么我们写&#xff0c;www.baidu.com就能找到百度了呢&#xff1f; 我一拼ping www.baidu.com 就拼到了ip地址&#xff1a; [119.75.218.70]…