IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> tinyalsa录音功能实现 -> 正文阅读

[移动开发]tinyalsa录音功能实现

tinyalsa录音功能实现,通道转换功能实现,并保存为本地pcm文件,依赖tinyalsa库

1. C++实现

#include <iostream>
#include <cstring>
#include <unistd.h>
#include <stdio.h>
#include "example/tinyalsa/include/tinyalsa/pcm.h"

struct pcm *pcm;
char *pcm_buffer;
char *pcm_buffer_4ch;

unsigned int card =0;      //声卡号
unsigned int device = 0;   //声卡设备
unsigned int flags = PCM_IN //声卡标志
struct pcm_config  config;  //音频配置信息

int pcm_size;
int pcm_size_4ch;
int channel_num = 6;       //通道数
int sample_rate = 16000;   //采样率

FILE *file1;
FILE *file2;

int AudioInit(){
  if (nullptr != pcm) {
    return 0;
  }

  file1 = fopen("1.pcm", "wb");
  if(!file1){
    std::cout << "open file1 failed!" << std::endl;
  }

  file2 = fopen("2.pcm", "wb");
  if(!file2){
    std::cout << "open file2 failed!" << std::endl;
  }

  // alas init
  memset(&config, 0, sizeof(config));
  config.channels = channel_num;
  config.rate = sample_rate;
  config.period_size = 16 * 16;   //16ms * (16000 / 1000)
  config.period_count = 4;        //每次读取4次中断的音频
  config.format = PCM_FORMAT_S32_LE;   //位深为32
  config.start_threshold = 0;
  config.stop_threshold = 0;
  config.silence_threshold = 0;

  // audio init
  pcm = pcm_open(card, device, flags, &config, 0);
  if(NULL == pcm || !pcm_is_ready(pcm)){
    return -1;
  } 

  //buffer_size = period_size * period_count
  int buffer_size = pcm_get_buffer_size(pcm);   
  std::cout << "buffer size is " << buffer_size << std::endl;
  pcm_size = pcm_frames_to_bytes(pcm, buffer_size);
  std::cout << "pcm bytes size is " << pcm_size << std::endl;
  pcm_buffer = reinterpret_cast<char *>(malloc(pcm_size));
  std::cout << "sizeof(pcm_buffer) is " << sizeof(pcm_buffer) << std::endl;

  // 32bit -> 16bit  6ch -> 4ch 
  pcm_size_4ch = pcm_size / 6 / 2 * 4;     
  pcm_buffer_4ch = reinterpret_cast<char *>(malloc(pcm_size_4ch));

  if (NULL == pcm_buffer || NULL == pcm_buffer_4ch) {
    std::cout << "unable to allocate pcm bytes" << std::endl;
    free(pcm_buffer);
    free(pcm_buffer_4ch);
    int ret = pcm_close(pcm);
    return 1;
  }
}

void Ch6_ch4(const char *pcm_buffer, int pcm_size, char *pcm_buffer_4ch){
  //32bit -> 16bit 小端模式取高16位,丢弃低16位 6ch -> 4ch
  for(int i = 0; i < pcm_size / 6 / 4; i++){
    pcm_buffer_4ch[i * 8] = pcm_buffer[i * 24 + 2];
    pcm_buffer_4ch[i * 8 + 1] = pcm_buffer[i * 24 + 3];
    pcm_buffer_4ch[i * 8 + 2] = pcm_buffer[i * 24 + 18];
    pcm_buffer_4ch[i * 8 + 3] = pcm_buffer[i * 24 + 19];
    pcm_buffer_4ch[i * 8 + 4] = 0;
    pcm_buffer_4ch[i * 8 + 5] = 0;
    pcm_buffer_4ch[i * 8 + 6] = 0;
    pcm_buffer_4ch[i * 8 + 7] = 0;
  }
}

void AudioRecord(){
  int frames_read = 0;
  int count = 100; //读取100次,100 * 64ms = 6.4s
  while (count--) {
    // 每次读取64ms
    frames_read = pcm_readi(pcm, pcm_buffer, pcm_get_buffer_size(pcm));
    if (frames_read != pcm_get_buffer_size(pcm)) {
      usleep(64 * 1000);
      continue;
    } 
    fwrite(pcm_buffer, 1, pcm_size, file1);
    Ch6_ch4(pcm_buffer, pcm_size, pcm_buffer_4ch);
    fwrite(pcm_buffer_4ch, 1, pcm_size_4ch, file2);
  }
}

void AudioEnd(){
  free(pcm_buffer);
  free(pcm_buffer_4ch);
  pcm_close(pcm);
  fclose(file1);
  fclose(file2);
}

int main(int argc, char **argv){
  std::cout << "hello lch!" << std::endl;
  AudioInit();
  AudioRecord();
  AudioEnd();
  std::cout << "end lch!" << std::endl;
  return 0;
}

2. CMakelists.txt

include_directories(${PROJECT_SOURCE_DIR})
link_directories(${PROJECT_SOURCE_DIR}/example/tinyalsa/lib)
set(SDK_AUDIO_DEMO_SRC
        ${PROJECT_SOURCE_DIR}/example/audio.cpp)
add_executable(sdk_test_audio ${SDK_AUDIO_DEMO_SRC})
target_link_libraries(sdk_test_audio tinyalsa)

3. 输出结果
在这里插入图片描述

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-07-09 17:36:08  更:2021-07-09 17:36:16 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 9:43:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码