在tinyalsa上抓取音频

我们经常会遇到这样的问题,应用读取到的音频有问题,需要在tinyalsa里面读取音频来确认是底层音频有问题,还是应用处理之后存在的问题。

所以,这个patch就出现了

代码的逻辑很简单,主要是在pcm_read的时候,同时把这个数据写入一个文件里面,这个只能在调试的时候使用,如果一直使用会导致这个文件会一直变大,到最后系统因为没有存储出现问题的。

现在写android代码已经不使用android.mk了,代替它的是android.bp,如果需要包含头文件,也需要在这里面修改。相关的文章网上一箩筐,我就不说了。

有个指针的处理,我觉得是比较巧妙的,大家如果喜欢研究代码的话,欢迎去github看看源码。

如果对代码还是不理解,可以去看看tinycap.c,里面的解析录音操作虽然简单,但是对我们帮助挺大的。

代码修改的diff如下

diff --git a/external/tinyalsa/Android.bp b/external/tinyalsa/Android.bp
old mode 100644
new mode 100755
index 090d91c0f8..79a6ceaee2
--- a/external/tinyalsa/Android.bp
+++ b/external/tinyalsa/Android.bp
@@ -9,6 +9,7 @@ cc_library {"mixer.c","pcm.c",],
+    shared_libs: ["liblog"],cflags: ["-Werror", "-Wno-macro-redefined"],export_include_dirs: ["include"],local_include_dirs: ["include"],
diff --git a/external/tinyalsa/pcm.c b/external/tinyalsa/pcm.c
old mode 100644
new mode 100755
index 4ae321bf93..de0deab9d0
--- a/external/tinyalsa/pcm.c
+++ b/external/tinyalsa/pcm.c
@@ -35,11 +35,17 @@#include <unistd.h>#include <poll.h>+#include <stdint.h>
+#include <signal.h>
+#include <time.h>
+#include <sys/ioctl.h>#include <sys/mman.h>#include <sys/time.h>#include <limits.h>+#include <android/log.h>
+#include <linux/ioctl.h>#define __force#define __bitwise
@@ -48,6 +54,10 @@#include <tinyalsa/asoundlib.h>+#define LOG_TAG "TINYALSA_QIFA"
+#define ALOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, fmt, ##args)
+#define ALOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, fmt, ##args)
+#define PARAM_MAX SNDRV_PCM_HW_PARAM_LAST_INTERVAL/* Logs information into a string; follows snprintf() in that
@@ -242,6 +252,10 @@ static void param_init(struct snd_pcm_hw_params *p)struct pcm {int fd;
+    //int fd_test;
+    FILE *fd_test;
+    unsigned int size_test;
+    void *test_buffer;unsigned int flags;int running:1;int prepared:1;
@@ -566,6 +580,7 @@ int pcm_read(struct pcm *pcm, void *data, unsigned int count)x.frames = count / (pcm->config.channels *pcm_format_to_bits(pcm->config.format) / 8);+    ALOGE("x.frames:%ld count:%d",x.frames,count);for (;;) {if (!pcm->running) {if (pcm_start(pcm) < 0) {
@@ -583,6 +598,12 @@ int pcm_read(struct pcm *pcm, void *data, unsigned int count)}return oops(pcm, errno, "cannot read stream data");}
+
+        if (fwrite(x.buf, 1, count, pcm->fd_test) != count) {
+            fprintf(stderr,"Error capturing sample\n");
+            ALOGE("Error capturing sample");
+        }
+return 0;}}
@@ -864,6 +885,8 @@ int pcm_close(struct pcm *pcm)if (pcm->fd >= 0)close(pcm->fd);
+    if (pcm->fd_test >= 0)
+        fclose(pcm->fd_test);pcm->prepared = 0;pcm->running = 0;pcm->buffer_size = 0;
@@ -872,6 +895,8 @@ int pcm_close(struct pcm *pcm)return 0;}+
+struct pcm *pcm_open(unsigned int card, unsigned int device,unsigned int flags, struct pcm_config *config){
@@ -900,7 +925,12 @@ struct pcm *pcm_open(unsigned int card, unsigned int device,oops(pcm, errno, "cannot open device '%s'", fn);return pcm;}
-
+    /*weiqifa*/
+    pcm->fd_test = fopen("/sdcard/ref_temp.pcm", "wb");
+    if (!pcm->fd_test) {
+        fprintf(stderr, "Unable to create file /sdcard/ref_temp.pcm\n");
+    } else ALOGD("creat /sdcard/ref_temp.pcm file success");
+if (fcntl(pcm->fd, F_SETFL, fcntl(pcm->fd, F_GETFL) &~O_NONBLOCK) < 0) {oops(pcm, errno, "failed to reset blocking mode '%s'", fn);
(END)int running:1;int prepared:1;
@@ -566,6 +580,7 @@ int pcm_read(struct pcm *pcm, void *data, unsigned int count                                                                                                                              )x.frames = count / (pcm->config.channels *pcm_format_to_bits(pcm->config.format) / 8);+    ALOGE("x.frames:%ld count:%d",x.frames,count);for (;;) {if (!pcm->running) {if (pcm_start(pcm) < 0) {
@@ -583,6 +598,12 @@ int pcm_read(struct pcm *pcm, void *data, unsigned int coun                                                                                                                              t)}return oops(pcm, errno, "cannot read stream data");}
+
+        if (fwrite(x.buf, 1, count, pcm->fd_test) != count) {
+            fprintf(stderr,"Error capturing sample\n");
+            ALOGE("Error capturing sample");
+        }
+return 0;
:int running:1;int prepared:1;
@@ -566,6 +580,7 @@ int pcm_read(struct pcm *pcm, void *data, unsigned int count)x.frames = count / (pcm->config.channels *pcm_format_to_bits(pcm->config.format) / 8);+    ALOGE("x.frames:%ld count:%d",x.frames,count);for (;;) {if (!pcm->running) {if (pcm_start(pcm) < 0) {
@@ -583,6 +598,12 @@ int pcm_read(struct pcm *pcm, void *data, unsigned int count)}return oops(pcm, errno, "cannot read stream data");}
+
+        if (fwrite(x.buf, 1, count, pcm->fd_test) != count) {
+            fprintf(stderr,"Error capturing sample\n");
+            ALOGE("Error capturing sample");
+        }
+return 0;}}
@@ -864,6 +885,8 @@ int pcm_close(struct pcm *pcm)if (pcm->fd >= 0)close(pcm->fd);
+    if (pcm->fd_test >= 0)
+        fclose(pcm->fd_test);pcm->prepared = 0;pcm->running = 0;pcm->buffer_size = 0;
@@ -872,6 +895,8 @@ int pcm_close(struct pcm *pcm)return 0;}+
+struct pcm *pcm_open(unsigned int card, unsigned int device,unsigned int flags, struct pcm_config *config){
@@ -900,7 +925,12 @@ struct pcm *pcm_open(unsigned int card, unsigned int device,oops(pcm, errno, "cannot open device '%s'", fn);return pcm;}
-
+    /*weiqifa*/
+    pcm->fd_test = fopen("/sdcard/ref_temp.pcm", "wb");
+    if (!pcm->fd_test) {
+        fprintf(stderr, "Unable to create file /sdcard/ref_temp.pcm\n");
+    } else ALOGD("creat /sdcard/ref_temp.pcm file success");
+if (fcntl(pcm->fd, F_SETFL, fcntl(pcm->fd, F_GETFL) &~O_NONBLOCK) < 0) {oops(pcm, errno, "failed to reset blocking mode '%s'", fn);
weiqifa@bsp-ubuntu1804:~/is13-sdk$

核心代码在pcm.c里面

int pcm_read(struct pcm *pcm, void *data, unsigned int count)
{struct snd_xferi x;if (!(pcm->flags & PCM_IN))return -EINVAL;x.buf = data;x.frames = count / (pcm->config.channels *pcm_format_to_bits(pcm->config.format) / 8);ALOGE("x.frames:%ld count:%d",x.frames,count);for (;;) {if (!pcm->running) {if (pcm_start(pcm) < 0) {fprintf(stderr, "start error");return -errno;}}if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_READI_FRAMES, &x)) {pcm->prepared = 0;pcm->running = 0;if (errno == EPIPE) {/* we failed to make our window -- try to restart */pcm->underruns++;continue;}return oops(pcm, errno, "cannot read stream data");}if (fwrite(x.buf, 1, count, pcm->fd_test) != count) {fprintf(stderr,"Error capturing sample\n");ALOGE("Error capturing sample");}return 0;}
}

x.buf 是一个指针,但是这个指针用的是从应用程序传下来的地址,所以在这里面也不需要给 x.buf分配空间,具体可以参考tinycap的做法。

在tinycap,还会给音频文件写入一个header,我们这里没有写入,没有太大的关系,打开音频的时候直接导入原始音频就可以了。

xxx:/ # ls -al /sdcard/ref_temp.pcm
-rw-rw---- 1 root sdcard_rw 79298560 2021-01-08 15:24 /sdcard/ref_temp.pcm
xxx:/ #

完整代码如下:

https://github.com/weiqifa0/tinyalsa


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/466634.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32——GPIO(1)

STM32——GPIO 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 【对单片机的操作就是控制IO口】 一、GPIO&#xff08;通用输入输出口&#xff09; 1、选定需要的引脚&#xff08;对应哪一个IO口&#xff09;&#xff1b; 2、配置需要的功能&#xf…

【opencv学习笔记八】创建TrackBar轨迹条

createTrackbar这个函数我们以后会经常用到&#xff0c;它创建一个可以调整数值的轨迹条&#xff0c;并将轨迹条附加到指定的窗口上&#xff0c;使用起来很方便。首先大家要记住&#xff0c;它往往会和一个回调函数配合起来使用。先看下他的函数原型&#xff1a; int createTra…

父母悄悄给自己买房,我很生气,要怎么调整心态?

——问题我是独生子&#xff0c;今年满24岁刚上研一&#xff08;普通211&#xff09;。家庭四川小城市&#xff0c;情况一般&#xff0c;父母二人体制内月薪总计一万元以内&#xff0c;家里积蓄20W-30W&#xff0c;公积金情况不清楚。从小母子关系比较僵硬&#xff0c;母亲小学…

语音处理入门——语音的声学处理

语音的声学处理通常称为特征提取或者信号分析&#xff0c;特征是表示语音信号的一个时间片的矢量。常见的特征类型有LPC&#xff08;线性预测编码&#xff09;特征和PLP&#xff08;感知线性预测编码&#xff09;&#xff0c;该特征称为声谱特征&#xff0c;使用形成波形的不同…

基础呀基础,用二极管防止反接,你学会了吗?

使用新的电源&#xff0c;第一次给设备供电时&#xff0c;要特别注意电源的正负极性标注。比如电源适配器&#xff0c;铭牌上面有标注插头的极性。这个符号说明插头的里面是正极&#xff0c;外面是负极&#xff0c;即“内正外负”。但是也有反过来的&#xff0c;下面这款是“内…

李宏毅的可解释模型——三个任务

1、问题 观看了李宏毅老师的机器学习进化课程之可解释的机器学习&#xff0c;课程中对主要是针对黑盒模型进行白盒模型转化的技巧和方法进行了简单介绍&#xff0c;详细细节可以参考《Interpretable Machine Learning》。像一些线性模型、树形模型是可解释的ML model&#xff…

柔性数组和环形队列之间的故事

之前的文章&#xff0c;讲解了柔性数组&#xff0c;有很多人留言&#xff0c;提到一些问题。刚好&#xff0c;之前发关于环形队列的文章有些问题&#xff0c;这次刚好拿出来一起说一下&#xff0c;并用柔性数组实现一个环形队列。柔性数组的上一篇文章环形队列C语言实现文章1、…

STM32——时钟系统

STM32——时钟系统 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 一、时钟树 普通的MCU&#xff0c;一般只要配置好GPIO 的寄存器&#xff0c;就可以使用了。STM32为了实现低功耗&#xff0c;设计了非常复杂的时钟系统&#xff0c;必须开启外设时钟才…

目标检测发展路程(一)——Two stage

目标检测是计算机视觉领域中非常重要的一个研究方向&#xff0c;它是将图像或者视频中目标与其他不感兴趣的部分进行区分&#xff0c;判断是否存在目标&#xff0c;确定目标位置&#xff0c;识别目标种类的任务&#xff0c;即定位分类。传统的目标检测模型有VJ.Det[1,2],HOG.De…

都2021年了,c/c++开发竟然还能继续吃香??

年后就迎来了金三银四&#xff0c;你准备好2021年的跳槽涨薪计划了吗&#xff1f;今天我就来给大家分享&#xff0c;c/c作为老牌开发常青树&#xff0c;还能与java/python/go较较劲的岗位和技术在哪里&#xff01;同时&#xff0c;给大家整理了2021年系统全面技术学习资料。文末…

目标检测模型——One stage(YOLO v5的模型解析及应用)

1. 简介 目标检测分为Two stage和One stage,只使用一个网络同时产生候选区域并预测出物体的类别和位置&#xff0c;所以它们通常被叫做单阶段检测算法&#xff08;One stage&#xff09;。本篇文章只讲One stage模型&#xff0c;常见的模型有YOLO&#xff0c;SSD。 目标检测发…

腾讯回应QQ读取用户浏览器历史记录

腾讯QQ官方认证账号在知乎回应“QQ扫描读取所有浏览器的历史记录”表示&#xff0c;PC QQ存在读取浏览器历史用以判断用户登录安全风险的情况&#xff0c;读取的数据用于在PC QQ的本地客户端中判断是否恶意登录。所有相关数据不会上传至云端&#xff0c;不会储存&#xff0c;也…

OCR系列——总体概述

最近参加了百度Paddle的动手学OCR课程&#xff0c;特此做一个学习总结。 1. 简介 OCR&#xff08;Optical Character Recognition&#xff0c;光学字符识别&#xff09;是计算机视觉重要方向&#xff0c;传统的OCR一般面向扫描文档类对象&#xff0c;现在的OCR是指场景文字识…

STM32——系统滴答定时器

STM32——系统滴答定时器 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 一、SysTick【内核中】 【风格&#xff1a;先描述一下库对寄存器的封装&#xff0c;再举例实现某些功能】 SysTick定时器被捆绑在NVIC中&#xff0c;用于产生SysTick异常&#…

你会用while(1)还是for(;;)写循环代码?

看代码看到for(;;)&#xff0c;然后觉得为什么不写成while(1)呢&#xff0c;所以就做了下面的测试。网上有解释&#xff0c;因为while需要做一次判断&#xff0c;理论上执行会花费的时间更久&#xff0c;for(;;)只是执行了两次空语句&#xff0c;执行会更快for.c#include <s…

OCR系列——文本检测任务

1. 简介 文本检测任务是找出图像或视频中的文字位置。不同于目标检测任务&#xff0c;目标检测不仅要解决定位问题&#xff0c;还要解决目标分类问题。 目标检测和文本检测同属于“定位”问题。但是文本检测无需对目标分类&#xff0c;并且文本形状复杂多样。 当前所说的文本…

关于ORACLE 语句中,IN 超过1000个的解决方法

在ORACLE SELECT 语句中 IN 的数据如果超过 1000&#xff0c;就会出错&#xff0c;解决方法也很简单&#xff0c;以C#代码为例&#xff1a; 1、先写一个方法&#xff0c;接收2个参数 参数1&#xff1a;接收 IN里面的数据&#xff0c;如&#xff1a;a1,a2,...a2000 &#xff1b;…

9个提高代码运行效率的小技巧你知道几个?

我们写程序的目的就是使它在任何情况下都可以稳定工作。一个运行的很快但是结果错误的程序并没有任何用处。在程序开发和优化的过程中&#xff0c;我们必须考虑代码使用的方式&#xff0c;以及影响它的关键因素。通常&#xff0c;我们必须在程序的简洁性与它的运行速度之间做出…

STM32——按键

STM32——按键 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 一、GPIO工作模式 1、当I/O端口配置为输入时&#xff1a; 输出缓冲器被禁止 施密特触发输入被激活 根据输入配置(上拉&#xff0c;下拉或浮动)的不同&#xff0c;弱上拉和下拉电阻被连接 …

深度学习——模型的压缩和加速

1. 简介 随着深度学习发展&#xff0c;越来越多的模型被发现和应用&#xff0c;模型的体量也越来越大&#xff0c;出现了模型过于庞大和参数冗余的问题。同时&#xff0c;移动端对模型的需求也是越轻量越好&#xff0c;因此&#xff0c;模型压缩和加速技术应运而生。 模型压缩…