数字MIC(es7202 PDM协议)MIC录音声音较小

article/2025/9/29 15:28:42

问题:我司有个项目,android 11 rk3566 的项目,该项目带audio 模块,项目MIC 使用的es7202(ADC),该芯片是一个编码芯片,没有解码功能,该模块的录音的增益已经调到最大,但录入的MIC音量还是很小,硬件也没有解决的办法,该数字MIC 利用的是PDM 协议,而PDM数字信号较为复杂。PDM信号在我的其它文章中有介绍。

rk3566 android11 配置声卡(es7202 ADC)_android不会飞的博客-CSDN博客_android 声卡

分析:MIC给到CPU为ES7202输出数字MIC信号,请确认CPU内对数字MIC信号的放大处理是否有?理论上是有的,CPU PDM 数据信号默认为可接受低幅值输入,而PDM 信号在CPU 中的处理是相对复杂的。基于PDM接口的应用降低了发送设备的复杂性,由于作为接收设备的CODEC内部集成抽取滤波器,因此系统整体复杂度大大降低。而PDM则使用远高于PCM采样率的时钟采样调制模拟分量,只有1位输出,要么为0,要么为1。因此通过PDM方式表示的数字音频也被称为Oversampled 1-bit Audio。相比PDM一连串的0和1,PCM的量化结果更为直观简单。以PDM方式作为模数转换的接收端,需要用到抽取滤波器(Decimation Filter),将密密麻麻的0和1代表的密度分量转换为幅值分量,而PCM方式得到的已经是幅值分量了。

解决方向:由于我们的es7202 MIC 增益已经调增到最大,但还是没有好的效果,无法实现增大MIC录音的效果。直接去处理PDM数据信号,由于 DATA MIC录入的数据,而PDM的数据复杂度较高我们不好去处理相关的数据,所以我们采用第三种,就是在tinyalsa 中处理,上层android应用在调用底层驱动时,是同过HAL层来调用底层驱动,通过驱动硬件工作,而在HAL层中的处理会调用,由于我们使用的是audio ALSA 架构,上层调用驱动会经过相关的pcm处理函数,相信使用过tinycap ,tinyplay 可能比较了解,如果不太了解的话,可以去看一下相关的源码,在我们调试过程中时,用的比较多相关命令,继续分析...... 而我们音频采样,PCM流是什么样的呢,如果是单声道,那每个采样的数据,这里我们就把数据看成一个个整型数据,它是一连串的,每个整数占据2个字节(16-bit),9个采样也就是18字节的数据。每个采样的整数大小最小为 -32768,最大为 32768(注意:这里的数据类型是short 类型的) 。根据采样数据的位置和值画一个图的话,就会得到像播放器上那样的波浪形图。而立体声,其实就是双通道采样的,其数据也看成一串数据的话,它其实就是左右声道的数据交叉存放,每一个frame是一个16-bit的采样点。所以我们可以在alsa调用底层驱动时,获取到的PCM原始数据进行处理操作,而我们所要做的操作就是将它放大。而这就解决了我们的问题,其原理就是将MIC 录入的PCM原始数据看成一个正弦波,而我们要做的就是将该正弦波的振幅放大,这就相当于增加了PCM数据的音量了,只需要将每一个采样的数据乘以一个系数就行了。

首先我们先来看一下HAL层的调用函数代码:

static int get_next_buffer(struct resampler_buffer_provider *buffer_provider,struct resampler_buffer* buffer)
{struct stream_in *in;size_t i,size;if (buffer_provider == NULL || buffer == NULL)return -EINVAL;in = (struct stream_in *)((char *)buffer_provider -offsetof(struct stream_in, buf_provider));if (in->pcm == NULL) {buffer->raw = NULL;buffer->frame_count = 0;in->read_status = -ENODEV;return -ENODEV;}if (in->frames_in == 0) {size = pcm_frames_to_bytes(in->pcm,pcm_get_buffer_size(in->pcm)in->read_status = pcm_read(in->pcm,//这里就调用了pcm_read,来起一个过度作用,其实是使用了tinyalsa,来获取原始pcm数据,(void*)in->buffer,中装入了PCM 原始数据。(void*)in->buffer,pcm_frames_to_bytes(in->pcm, in->config->period_size));if (in->read_status != 0) {ALOGE("get_next_buffer() pcm_read error %d", in->read_status);buffer->raw = NULL;buffer->frame_count = 0;return in->read_status;}//fwrite(in->buffer,pcm_frames_to_bytes(in->pcm,pcm_get_buffer_size(in->pcm)),1,in_debug);in->frames_in = in->config->period_size;/* Do stereo to mono conversion in place by discarding right channel */if ((in->channel_mask == AUDIO_CHANNEL_IN_MONO)&&(in->config->channels == 2)) {//ALOGE("channel_mask = AUDIO_CHANNEL_IN_MONO");for (i = 0; i < in->frames_in; i++)in->buffer[i] = in->buffer[i * 2];}}//ALOGV("pcm_frames_to_bytes(in->pcm,pcm_get_buffer_size(in->pcm)):%d",size);buffer->frame_count = (buffer->frame_count > in->frames_in) ?in->frames_in : buffer->frame_count;buffer->i16 = in->buffer +(in->config->period_size - in->frames_in) *audio_channel_count_from_in_mask(in->channel_mask);return in->read_status;}

再来看一下tinyalsa,中的代码,我这里主要给的是输入流的相关代码,即录音时,而播放流与其相反。

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);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)) {//用户层通过ioctl的方式来调用kernel,//读出入初始化数据,即录音。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 (pcm->config.channels == 2) {if (channalFlags == -1 ) {if (startCheckCount < SAMPLECOUNT) {startCheckCount += count;} else {channalFlags = channel_check(data,count / 2);}}channel_fixed(data,count / 2, channalFlags);}return 0;}
}

kernel层的实现,在内核中发起系统调用,执行本应用户空间发起的fops函数集。

kernel 内核版本,4.19.172

PCM逻辑设备文件操作函数集:snd_pcm_f_ops[]
PCM逻辑设备文件操作函数集对于Playback和Capture是分开定义的,该操作函数集如下:const struct file_operations snd_pcm_f_ops[2] = {{.owner =                THIS_MODULE,.write =                snd_pcm_write,//用于单通道音频信号写.write_iter =           snd_pcm_writev, .open =                 snd_pcm_playback_open,.release =              snd_pcm_release,.llseek =               no_llseek,.poll =                 snd_pcm_poll,.unlocked_ioctl =       snd_pcm_ioctl,//用于多通道音频信号写.compat_ioctl =         snd_pcm_ioctl_compat,.mmap =                 snd_pcm_mmap,.fasync =               snd_pcm_fasync,.get_unmapped_area =    snd_pcm_get_unmapped_area,},{.owner =                THIS_MODULE,.read =                 snd_pcm_read,//用于单通道音频信号读.read_iter =            snd_pcm_readv,.open =                 snd_pcm_capture_open,.release =              snd_pcm_release,.llseek =               no_llseek,.poll =                 snd_pcm_poll,.unlocked_ioctl =       snd_pcm_ioctl,//用于多通道音频信号读.compat_ioctl =         snd_pcm_ioctl_compat,.mmap =                 snd_pcm_mmap,.fasync =               snd_pcm_fasync,.get_unmapped_area =    snd_pcm_get_unmapped_area,}
};

 

        先来看一下我们es7202 的硬件电路图,以及框架图与相关的调节增益的相关寄存器。

es7202 内部框架图:

es7202外围电路,相对较少:

 

es7202内部调制MIC 增益的寄存器: 

 

        所以从整体来说,使用数字MIC来讲,整体的优势还是比较明显的,外围电路比较少,录入的MIC数据同CLK 的采集混入PDM DATA 通过PDM数据接口直接送入CPU内部,进行处理。 

下面给到修改的patch,目录在external/tinyalsa/pcm.c

diff --git a/pcm.c b/pcm.c
index 0b97bbc..01d777e 100644
--- a/pcm.c
+++ b/pcm.c
@@ -635,13 +635,36 @@ void channel_fixed(void *data, unsigned len, int chFlag)return;}+static short out_vol = 4.0;//扩大音量倍数
+static void volume_process(const void *buffer, size_t length, short volume) {
+
+short * buffer_end = (short*)buffer + length/2;
+       short * pcmData = (short *)buffer;
+          int i = 0;
+       int pcmval;
+
+       while (pcmData < buffer_end) {
+               pcmval = (short)*pcmData * volume;
+                if (pcmval < 32768 && pcmval > -32768) {
+                        *pcmData = pcmval;
+                } else if (pcmval > 32767) {
+                        *pcmData = 32767; //限制最大幅度
+                } else if (pcmval < -32767) {
+                        *pcmData = -32767;//限制最小幅度
+                }
+                
+            ++pcmData;
+           i++;
+       }
+}
+int pcm_read(struct pcm *pcm, void *data, unsigned int count){struct snd_xferi x;if (!(pcm->flags & PCM_IN))return -EINVAL;
-
+       memset(data, 0, count);x.buf = data;x.frames = count / (pcm->config.channels *pcm_format_to_bits(pcm->config.format) / 8);
@@ -676,6 +699,7 @@ int pcm_read(struct pcm *pcm, void *data, unsigned int count)channel_fixed(data,count / 2, channalFlags);}+       volume_process(x.buf, count , out_vol);return 0;}}

 理论上来说,该patch也可解决其它codec引起的输入MIC录入音量较小的问题。


http://chatgpt.dhexx.cn/article/MhNMknNt.shtml

相关文章

麦克风MIC 工作原理以及灵敏度调整

1、先看MIC电路连接 这是个差分输入的例子&#xff0c;MICP2和MICN2是一对差分信号&#xff0c;经过C156的滤波&#xff0c;输入到MIC两端 MIC两引脚分别是到地和供电&#xff0c;上图的R177参数就关系到MIC输入的灵敏度 2、电阻R177影响灵敏度分析 MICBIAS是提供MIC的偏置电压…

WO Mic -免费话筒

原文&#xff1a;https://wolicheng.com/womic/ WO Mic -免费话筒 一、特点 WO Mic 可以把你的手机变成电脑的麦克风。您无需支付一分钱即可购买任何小工具。如果您选择无线传输&#xff0c;它就是移动的。数以百万计的人安装了它&#xff0c;并且每天都在使用它进行通话、录…

麦克风测试指标术语

麦克风测试指标术语 1. dB 2. 谐波 3. THD 4. 灵敏度 5. 频率响应 6. 本底噪音 7. 持续中。。。 1&#xff0c;dB 多数的麦克风技术指标里最基础的就是dB 的单位。分贝是一个相对数&#xff0c;等同于人耳在声音的压力下感到的变化曲线。此外&#xff0c;分贝的变化是很…

浅析硬件“好声音”:麦克风技术指标及选型指南

如今大多数IoT类设备都具有语音唤醒和声控的功能&#xff0c;如天猫精灵、百度音箱等。 这类设备中都集成了麦克风和喇叭等电声器件&#xff0c;其中麦克风用于识别用户的声音&#xff0c;喇叭用于播放设备对用户指令的反应。麦克风的性能是影响语音唤醒率高低的重要因数&…

麦克风概述

麦克风可以将声音的变化通过特定的机制转换为电压或者电流的变化&#xff0c;再交给电路系统进行处理。声音的强度&#xff0c;通过声压表示&#xff0c;对应电压或电流的幅值&#xff1b;声音变化的快慢&#xff0c;则对应电信号的频率。 声压级和距离的关系&#xff1a;其中…

硬件参数 调整 麦克风MIC灵敏度 原理

1、先看MIC电路连接 这是个差分输入的例子&#xff0c;MICP2和MICN2是一对差分信号&#xff0c;经过C156的滤波&#xff0c;输入到MIC两端 MIC两引脚分别是到地和供电&#xff0c;上图的R177参数就关系到MIC输入的灵敏度 2、电阻R177影响灵敏度分析 MICBIAS是提供MIC的偏置电…

浏览器检测麦克风音量

开发直播类的Web应用时在开播前通常需要检测设备是否正常&#xff0c;本文就来介绍一下如果如何做麦克风音量的可视化。 AudioWorklet出现的背景 做这个功能需要用到 Chrome 的 AudioWorklet。 Web Audio API 中的音频处理运行在一个单独的线程&#xff0c;这样才会比较流畅。…

最大信息系数(MIC)

童鞋们觉得文章不错&#xff0c;就麻烦点一下下面人工智能的教程链接吧&#xff0c;然后随便翻阅一下 https://www.captainbed.net/qtlyx MIC&#xff08;Maximal information coefficient&#xff09;一个很神奇的东西&#xff0c;源自于2011年发在sicence上的一个论文。 学…

麦克风基础参数

麦克风由Microphone读音翻译的&#xff0c;正确的翻译为微音器&#xff0c;或者称拾音器&#xff0c;传声器。我们的咪芯其实就是一只麦克风&#xff0c;只不过属于半成品。给它加网罩&#xff0c;手柄&#xff0c;开关&#xff0c;导线就成了一支完整的麦克风了。 我们生产的…

mic的灵敏度和声音的大小

今天查看麦克风的一些资料&#xff0c;发现这个博客写得很好&#xff0c;不知道这样转载是否可以。 mic的灵敏度和声音的大小 我对于mic的灵敏度一直无法说出其准确定义的表述。我看过mic的sepc上面都是标注的负的多少dB&#xff0c;比如-42dB。所以我一直认为-30dB的mic的灵…

MIC(最大信息系数)

MIC 我在论文使用MIC来衡量两个基因之间的关联程度&#xff0c;线性或非线性关系&#xff0c;相较于Mutual Information&#xff08;MI&#xff09;互信息而言有更高的准确度巴拉巴拉的&#xff0c;按作者的话说总之比其他的方式好。 原文参照&#xff1a; Detecting Novel As…

MIC相关基础知识

一、mic及声音的指标&#xff1a; &#xff08;1&#xff09;声音的分贝&#xff08;dB&#xff09; 分贝 Decibel 分贝&#xff08;dB&#xff09;是一个对数单位&#xff08;logarithmic unit&#xff09;, 它和很多常见的单位如“米”&#xff0c;“秒”或者“千克”等物理单…

MIC - 最大信息系数

MIC 文章目录 MIC前言MIC介绍MIC库Python实例MIC缺陷参考文章 前言 皮尔逊相关系数即我们通常说的(线性)相关系数&#xff0c;是用来反映两个变量线性相关程度的统计量&#xff0c;变化范围为-1到1。 系数的值为1意味着X和Y可以很好的由直线方程来进行描述&#xff0c;所有的…

MIC:最大信息系数

目录 1. 概念 1.1 MIC 1.2 互信息 2. MIC的优点 3. 算法原理 3.1 MIC公式原理 3.2 MIC计算步骤 &#xff08;1&#xff09;计算最大互信息值 &#xff08;2&#xff09;对最大的互信息值进行归一化 &#xff08;3&#xff09;选择不同尺度下互信息的最大值作为MIC值…

MIC 的指标解读

MIC 的指标解读 1.Sensitivity 灵敏度 麦克风是支持以声压信号为输入&#xff0c;最后转换为电信号的传感器。sensitivity是microphone 能够capture的最小声压信号&#xff0c;声压信号的单位为dBSPL.sensitivity 是ratio &#xff0c;是模拟输出电压或者数字输出值对于输入的…

MIC一般参数指标

SNR>68dB&#xff0c; 灵敏度>-34dB&#xff0c;频响范围&#xff1a;/-3dB &#xff08;300Hz-3kHz&#xff09;&#xff1b;失真度&#xff1a;<3% 麦克风的灵敏度高好还是低&#xff0c;要根据你使用的条件来选择。如果声源离麦克风较远&#xff0c;需用灵敏度高的…

Maximal Information Coefficient (MIC)最大互信息系数

MIC 我在论文使用MIC来衡量两个基因之间的关联程度&#xff0c;线性或非线性关系&#xff0c;相较于Mutual Information&#xff08;MI&#xff09;互信息而言有更高的准确度巴拉巴拉的&#xff0c;按作者的话说总之比其他的方式好。 原文参照&#xff1a; Detecting Novel A…

R+树

考虑R树的性能&#xff0c;其中覆盖(coverage)和重叠(overlap)两个概念很重要&#xff0c;因为R树查询是根据给定区域与当前MBR是否有交叉来判断, 因此覆盖和重叠都应当尽量小 覆盖小即MBR要小&#xff0c;最好刚好包围其中的数据点 (对于叶节点)或子MBR (对于非叶节点) 重叠…

R树及其应用场景

地理围栏&#xff08;Geo-fencing&#xff09;是LBS的一种应用&#xff0c;就是用一个虚拟的栅栏围出一个虚拟地理边界&#xff0c;当手机进入、离开某个特定地理区域&#xff0c;或在该区域内活动时&#xff0c;手机可以接收自动通知和警告。如下图所示&#xff0c;假设地图上…

R树与空间索引

B树或者B树可以非常好的处理一维空间存储的问题。B树是一棵平衡树&#xff0c;它是把一维直线分为若干段线段&#xff0c;当我们查找满足某个要求的点的时候&#xff0c;只要去查找它所属的线段即可。依我看来&#xff0c;这种思想其实就是先找一个大的空间&#xff0c;再逐步缩…