A40i使用笔记:QT使用alsa采集音频pcm信息

这篇具有很好参考价值的文章主要介绍了A40i使用笔记:QT使用alsa采集音频pcm信息。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、前言

目的是实现一种效果,就是在音频识别时,能够实时显示当前人员说话的声音幅度,通过波形曲线的形式显示出来。如下效果(非我实现)

A40i使用笔记:QT使用alsa采集音频pcm信息

还可以实现在实时采集的同时,将需要的数据保存成指定格式文件,如csv,wav,pcm等。 

目前函数模式是存储为pcm格式,如需转成其他格式需要使用不同的库函数或者按照协议格式重写

二、环境

全志A40i

linux3.10

alsa

三、正文

从硬件上首先要具备Audio音频部分,这里硬件支持的话具备硬件电路接口就不同多说什么了,其次就主要是软件层次了

首先要在linux上使用音频采集,就要使用alsa库,交叉安装alsa库的方式也有很多

有的平台环境上和硬件上都默认是已经包含的了,可以通过find -name libasound.so查看

这里我是用的是qt交叉编译程序,一开始总是没有找到libasound库,后来把lib去掉才能正常识别

在pro文件中加入

LIBS +=   -L/root/workspace/allwinner/A40i/bsp/lichee/out/sun8iw11p1/linux/common/buildroot/host/usr/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/ -lasound

头文件中加入

#include <alsa/asoundlib.h>

至此,我终于能够在我的编译环境中正常不报错的编译程序了,但是才刚刚入坑,后面的问题一把又一把的出现,每次都是以为解决当前的问题后面就都不是问题了,结果,,,哎,都是泪

我是用的源码如下:

void menu::on_btn_Ingames_2_clicked()
{



    snd_pcm_t *handle;//PCM句柄
    snd_pcm_hw_params_t *params;//配置硬件参数结构体(PCM硬件配置空间容器)

//    snd_pcm_close(handle);
    int ret = snd_pcm_open(&handle,"hw:/dev/snd/controlC0",SND_PCM_STREAM_CAPTURE,0);//SND_PCM_STREAM_PLAYBACK 或 SND_PCM_STREAM_CAPTURE,分别表示播放和录音的PCM流
    if(ret < 0){
        fprintf(stderr,"unable to open pcm device: %s\n",snd_strerror(ret));
        exit(1);
    }
    else{
        qDebug()<<QString("open pcm device:%1").arg(snd_strerror(ret));
    }
    //params申请内存(使用标准alloca分配无效的snd_pcm_hw_参数)
    snd_pcm_hw_params_alloca(&params);
    //使用pcm设备初始化hwparams(用PCM的完整配置空间填充参数)
   snd_pcm_hw_params_any(handle,params);
   //设置多路数据在buffer中的存储方式
       //SND_PCM_ACCESS_RW_INTERLEAVED每个周期(period)左右声道的数据交叉存放
   snd_pcm_hw_params_set_access(handle,params,SND_PCM_ACCESS_RW_INTERLEAVED);//SND_PCM_ACCESS_RW_INTERLEAVED//SND_PCM_ACCESS_RW_NONINTERLEAVED
    //设置16位采样格式
   snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE);
   //设置声道数1
   ret = snd_pcm_hw_params_set_channels(handle,params,1);
   if(ret <0){
       fprintf(stderr,"Error setting channels.\n");
       exit(1);
   }
   else
      qDebug()<<"set channels ok";


   int dir=0;
   int rate = 44100; /* Sample rate */
   unsigned int exact_rate;   /* Sample rate returned by */
   //设置采样率44100,如果采样率不支持,会用硬件支持最接近的采样率
   exact_rate=rate;
   ret = snd_pcm_hw_params_set_rate_near(handle,params,&exact_rate,0);
  if(ret <0){
      fprintf(stderr,"Error setting rate.\n");
      exit(1);
  }
  else
     qDebug()<<"set rate ok";
  if (rate != exact_rate) {
    fprintf(stderr, "The rate %d Hz is not supported by your hardware.\n Using %d Hz instead.\n", rate, exact_rate);
  }
  else
      qDebug()<<"best rate is "<<QString::number(exact_rate);



//    int periods = 2; //2      /* Number of periods */
//    /* Set number of periods. Periods used to be called fragments. */
//   ret = snd_pcm_hw_params_set_periods(handle,params,periods,0);
//   if(ret <0){
//       fprintf(stderr,"Error setting periods.\n");
//       exit(1);
//   }
//   else
//      qDebug()<<"set periods ok ,periods is "<<QString::number(periods);


   long unsigned int frames = 128;//32
//    //设置周期大小(将配置空间限制为最接近目标的周期大小)
//   snd_pcm_hw_params_set_period_size_near(handle,params,&frames,0);//0
//   qDebug()<<"frames near "<<QString::number(frames);


//   snd_pcm_uframes_t periodsize = 4096;
//   if (snd_pcm_hw_params_set_buffer_size(handle, params, (periodsize * periods)>>2) < 0) {
//         fprintf(stderr, "Error setting buffersize.\n");
//         exit(1);
//       }
//   else
//       qDebug()<<"set buffersize ok";

//让这些参数作用于PCM设备(安装从配置空间和SND_PCM_PREPARE选自配置空间的PCM硬件配置)
   ret = snd_pcm_hw_params(handle,params);
   if(ret <0){
       fprintf(stderr,"unable toset hw params: %s\n",snd_strerror(ret));
       exit(1);
   }
   else
       qDebug()<<"set hw params ok";


   //
//long unsigned int frames = 0;//32
 //从配置空间中提取周期大小。
   snd_pcm_hw_params_get_period_size(params,&frames,0);
   int size = frames *4;
   qDebug()<<"frames is "<<QString::number(frames)<<",size is "<<QString::number(size);

   char* pcmBuff = (char*)malloc(size);
//从配置空间中提取周期时间
   unsigned int val =0;
   snd_pcm_hw_params_get_period_time(params,&val,0);
   qDebug()<<"val is "<<QString::number(val);
//打开输出文件
   FILE* pFile;
   pFile = fopen("test.pcm","wb");

  int index=0;
   while(index<10)
   {
        //从PCM读取交错帧
       ret = snd_pcm_readi(handle,pcmBuff,frames);
       if(ret == -EPIPE){//发生暂停事件(Stream被暂停并等待应用程序恢复)
           fprintf(stderr,"overrun.... \n");
           snd_pcm_prepare(handle);
       }
       else if(ret < 0){
           fprintf(stderr,"error read: %s\n",snd_strerror(ret));
           exit(1);
       }
       else if(ret != frames ){
           fprintf(stderr,"less read: %s\n",ret);
       }

       ret = fwrite(pcmBuff,sizeof(char),size,pFile);
       if(ret != size){
           fprintf(stderr,"less write: %s\n",ret);
       }
       printf("%d\n",index);
       index++;

   }

   snd_pcm_drain(handle);
   snd_pcm_close(handle);

   free(pcmBuff);
   fclose(pFile);


   printf("audio capture exit.. \n");


   ui->label_44->setText(QString::number(qrand()%100));





}

各位看官先不要着急ctrl+c,这里源码未经过最终调试,因为我在第一步snd_pcm_open就卡住了,哭晕。

第一步解决了第二部又出现问题,真是一步一个坎啊,总共需要配置10多个函数,每个函数都要搞明白具体含义是什么,才能具体调试,上述代码是暂时能够简单录制声音,并生成pcm文件,通过audacity-win-2.2.2.exe软件可以播放录制的pcm声音。

程序执行打印信息

A40i使用笔记:QT使用alsa采集音频pcm信息

pcm文件解析播放声音A40i使用笔记:QT使用alsa采集音频pcm信息

接下来就是详细梳理分析每个使用到的函数功能作用,并加上注释去消化理解,不知不觉凌晨2点了,下面(等哟时间的)功能还差将读取的数据解析细化出来每个帧含义,将数据分类显示成曲线和生成其他格式文件。


第二天20230418和19凌晨更新

不知不觉有时凌晨2点,每天都是计划12点之前睡觉,然后一调试总是有各种各样的问题,就要去抓紧解决,否则又要多耽误一天,不过功夫不负有心人,目前所有的问题基本算是都解决了,比如开机崩溃问题,存储数据格式问题,格式解析问题,曲线刷新问题,采集数据问题等等

这个项目由于部分原因,不能把最终的源码开放出来,这里就说一下思路吧

1.音频采集必须单独开启一个线程,和主线程绑定信号进行交互通信

2.性能差的主板不建议实时刷新曲线,因为在主线程刷新曲线会造成现成数据通讯阻塞,从而导致数据有几十甚至几百甚至全部数据失真,因为进程阻塞,新的数据没有传递过来,数据还在刷新,就丢失了原始数据,后来我为了实时看数据曲线,专门改成了3秒刷新一次曲线

3.数据最终采集后存储表格的话也需要注意,因为xlsx表格上限104万行, 采样频率44.1khz之后每秒采集44100个采样点,基本24秒左右表格一列就存储到上限了,这时候如果不处理的话再继续存储数据也会丢失

下面附上我实现的最终效果图

A40i使用笔记:QT使用alsa采集音频pcm信息

这张图片是采集数据总曲线,导出的pcm数据用软件复现曲线,导出的csv用wps复现曲线,完全一致

 A40i使用笔记:QT使用alsa采集音频pcm信息

此图也是基本实现了我想要的效果图,如前言那张图片

 A40i使用笔记:QT使用alsa采集音频pcm信息

 wps复现曲线图

四、结语

有时候项目没有调完就写上博客了,为什么呢,所以这个文章的内容主要时干嘛的呢

第一:记录前期环境准备和铺路方式,后续在走就能少走点弯路

第二:立下此flag,以后要解决,以后解决更新此文

第三:把我的问题发布出来,如果有同道中人遇到此问题或有解决方式,可以互相探讨解决。

第四:分享给可能进度还没有到达我这一步的新人们,互相沟通互相交流i互相学习

未完待续


20230419 完文章来源地址https://www.toymoban.com/news/detail-420073.html

到了这里,关于A40i使用笔记:QT使用alsa采集音频pcm信息的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • ALSA学习(2)——pcm设备逻辑

    参考学习地址: https://www.cnblogs.com/jason-lu/archive/2013/06/07/3123750.html PCM是英文Pulse-code modulation的缩写,中文译名是脉冲编码调制.我们知道在现实生活中,人耳听到的声音是模拟信号,PCM就是要把声音从模拟转换成数字信号的一种技术,他的原理简单地说就是利用一个固定的频率对模

    2023年04月12日
    浏览(36)
  • Qt/C++音视频开发69-保存监控pcm音频数据到mp4文件/监控录像/录像存储和回放/264/265/aac/pcm等

    用ffmpeg做音视频保存到mp4文件,都会遇到一个问题,尤其是在视频监控行业,就是监控摄像头设置的音频是PCM/G711A/G711U,解码后对应的格式是pcm_s16be/pcm_alaw/pcm_mulaw,将这个原始的音频流保存到mp4文件是会报错的,在调用avformat_write_header写文件头的时候提示(-22) Invalid argument,

    2024年04月11日
    浏览(58)
  • 【FFmpeg】ffmpeg 命令行参数 ⑦ ( 使用 FFmpeg 提取 PCM 音频数据 | PCM 音频格式 | 提取 PCM 音频格式常用参数 | 查询文档方法 )

    PCM 全称 \\\" Pulse Code Modulation \\\" , 脉冲编码调制 , 该 音频数据 是未经压缩的 采样裸数据 , 只有 知道该数据的 采样率 / 采样位数 / 通道数 才能将该音频数据播放出来 ; PCM 数据是 最原始的音频数据 , 音频内容完全无损 , 但是 PCM 数据体积庞大 , 对 PCM 音频数据压缩 分为 无损压缩

    2024年04月11日
    浏览(50)
  • 使用autodl服务器,在A40显卡上运行, Yi-34B-Chat-int4模型,并使用vllm优化加速,显存占用42G,速度18 words/s

    https://www.bilibili.com/video/BV1gu4y1c7KL/ 使用autodl服务器,在A40显卡上运行, Yi-34B-Chat-int4模型,并使用vllm优化加速,显存占用42G,速度18 words/s 2020年,英伟达发布 A40 专业显卡,配备 48GB 显存。 采用了 GA102 GPU,拥有 10752 个 CUDA 核心。而 A40 是用于服务器的。A40 都配备了四个 DP

    2024年02月04日
    浏览(54)
  • Qt音视频开发40-ffmpeg采集桌面并录制

    之前用ffmpeg打通了各种视频文件和视频流以及本地摄像头设备的采集,近期有个客户需求要求将整个桌面屏幕采集下来,并可以录制保存成MP4文件,以前也遇到过类似的需求,由于没有搞过,也没有精力去摸索和测试,所以也就一直耽搁着,近期刚好这个需求又来了,定下心

    2023年04月25日
    浏览(66)
  • Linux ALSA音频工具aplay、arecord、amixer的使用方法

    ALSA 是Advanced Linux Sound Architecture的缩写,先进的Linux音频架构,为Linux操作系统提供音频和MIDI功能。 aplay是播放命令。 -t, 指定输出数据格式,默认是wave格式,还支持raw,voc,au,后两种格式不懂。 -D,指定播放设备,设备名的格式为hw:0,0,表示0号card的0号device。 -c,指定c

    2024年02月06日
    浏览(39)
  • NVDIA GPU参数列表: 3090,4090, A40, A30,V100, A100, A800性能参数

    GeForce RTX 4090    GeForce RTX 3090 Ti (左)   GeForce RTX 3090(右)   A40: The NVIDIA A40 accelerates the most demanding visual computing workloads from the data center, combining the latest NVIDIA Ampere architecture RT Cores, Tensor Cores, and CUDA® Cores with 48 GB of graphics memory. From powerful virtual workstations accessible from an

    2024年02月06日
    浏览(50)
  • 【音频应用】Linux之ALSA音频应用编程

    上文: 【音频驱动】Linux之ALSA声卡、WAV文件相关概念 使用alsa-libs和alsa-utils实现.wav格式文件的播放与录制,了解Linux中声卡的应用层设备节点。介绍了使用alsa-libs应用编程步骤。 高级Linux声音体系结构(ALSA)为Linux操作系统提供音频和MIDI功能。 ALSA具有以下显著特征: 高效支持所

    2024年02月05日
    浏览(43)
  • 音频开发之ALSA框架

    ALSA(Advanced Linux Sound Architecture)是Linux操作系统上用于提供音频和MIDI功能的软件架构。它为Linux系统提供了强大的音频支持,包括音频录制、播放和处理,它设计用于提供高性能、低延迟、高质量的音频处理,并为开发者提供了一组API和工具。 ALSA的涉及本身比较复杂,如果

    2024年01月23日
    浏览(100)
  • alsa框架与音频芯片移植基础

    Alsa是Advanced Linux Sound Architecture的缩写,即高级Linux声音架构,在Linux操作系统上提供了对音频和MIDI的支持。在Linux 2.6的内核版本后,Alsa目前已经成为了linux的主流音频体系结构。 除了 alsa-driver,ALSA 包含在用户空间的 alsa-lib 函数库,具有更加友好的编程接口,并且完全兼容于

    2024年02月09日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包