`
lxf_2011
  • 浏览: 60649 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Android Audio System线性音量和对数音量的转换

阅读更多

Android的音频系统的代码中,应用程序对每个音频流的音量做出调整后,最终会转换为一个系数K,所有的音频数据在输出到硬件之前,都要乘以系数K,只要应用程序发出调整音量的调用,中间层的Audio System就会重新计算系数K的值。对应用程序来说,音量控制通常都是按照线性进行调整的,比如对于具有15级音量的音频流来说,我们预期每级的音量变化都是相当的,也就是说:从第5级调到第6级,和从第7级调到第8级,我们期望人耳可以感觉到同样大小的音量变化。但是,在Android的代码中,我们看到了计算系数K的公式,它相当奇怪,代码位于frameworks/base/media/libmedia/audiosystem.cpp中:

/*****************************************************************************************************/
声明:本博内容均由http://blog.csdn.net/droidphone原创,转载请注明出处,谢谢!
/*****************************************************************************************************/

  1. // convert volume steps to natural log scale  
  2.   
  3. // change this value to change volume scaling  
  4. static const float dBPerStep = 0.50f;  
  5. // shouldn't need to touch these  
  6. static const float dBConvert = -dBPerStep * 2.302585093f / 20.0f;  
  7. static const float dBConvertInverse = 1.0f / dBConvert;  
  8.   
  9. float AudioSystem::linearToLog(int volume)  
  10. {  
  11.     // float v = volume ? exp(float(100 - volume) * dBConvert) : 0;  
  12.     // LOGD("linearToLog(%d)=%f", volume, v);  
  13.     // return v;  
  14.     return volume ? exp(float(100 - volume) * dBConvert) : 0;  
  15. }  
  16.   
  17. int AudioSystem::logToLinear(float volume)  
  18. {  
  19.     // int v = volume ? 100 - int(dBConvertInverse * log(volume) + 0.5) : 0;  
  20.     // LOGD("logTolinear(%d)=%f", v, volume);  
  21.     // return v;  
  22.     return volume ? 100 - int(dBConvertInverse * log(volume) + 0.5) : 0;  
  23. }  

 

要理解上面代码中的公式,我们先要了解人耳的声心理学模型。根据人耳的声心理学的研究,人耳对声音大小的感知程度并不是线性的,而是呈对数关系。对数形式的单位是dB,在音频领域,通常我们会定义一个标准电平V0,那么电平X的转换公式是:

dB=20log(X/V0);

例如:我们给喇叭输出满负荷最大音量时的电平是1V,如果有15级音量,如果按线性进行调整,1/15 = 66.6mV,我们就得到每级音量的调整量是:

66.6mV,133.2mV,200mV,......,866.8mV,933.4mV,1000mV;

如果按照这个步长进行调整,人耳感觉到的音量变化就不是连续的。

另一种方式是按对数进行调整,在数字音频领域,通常0dB代表最大音量,0dB意味着不对数据进行任何的变换处理,输出等于输入,所以20log(V0/V0)=20log(1)=0dB。这意味着最大音量以下的dB值为一个负数,现在我们把1V认为是0dB,最低音量是-28dB,那么对应15级音量的dB值就是:

 

-28dB,-26dB,-24dB,......,-4dB,-2dB,0dB;

对应的电平值是( 使用公式Vx=10^(dB/20)*V0 ):

 

 

39mV,50mV,63mV,......,630mV,794mV,1000mV;

 

                                      线性音量和对数音量的调整曲线

回到Android的代码中,它也使用了对数的调节方式,它先是定义了每次调节音量的步长值为0.5dB:

static const float dBPerStep = 0.50f;

然后他定义了一个计算用的中间常数:

 

static const float dBConvert = -dBPerStep * 2.302585093f / 20.0f;

这个一开始有点难于理解,尤其是奇怪的系数:2.302585093。所有这些定义都是为了得到用于与音频数据相乘的系数K,Android中有多种音频流,每种音频流的默认音量调节步数都不一样,有的是7步,有的是5步,有的是15步,为了便于计算的统一,计算前都会先把相应的步数映射为0-100步之间,因为步长已经定义为0.5dB,所以各级音量对应的dB数如下:

 

 

音量级别 0 1 2 3 ...... 97 98 99 100
dB数 mute -49.5dB -49dB -48.5dB ...... -1.5dB 1.0dB 0.5dB 0dB

 

 

 

 

很显然,知道了音量为哪个步数级别后,相应的dB值也会知道,那么我们要做的就是把dB值转换为系数K值,K值实际上就是公式dB=20log(X/V0)中的比值:X/V0,根据此公式反推,音量级别为volume对应的K值:

(1)          dB = -dBPerStep * ( 100 - volume );

又因为:

(2)          dB/20 = log(Vx/V0) = log(K);

把(1)式代入(2)式:

(3)          -dBPerStep * ( 100 - volume ) / 20 = log(K);

为了得到K,两边取以10为底的指数:

(4)           10 ^ ( -dBPerStep * ( 100 - volume ) / 20 ) = 10 ^ ( log(K) );

(5)            K = 10 ^ ( log(K) ) = 10 ^ ( -dBPerStep * ( 100 - volume ) / 20 ) ;

(6)             K = 10 ^ ( dBConvert * ( 100 - volume ) ) ;      // 令:dBConvert = -dBPerStep  / 20;

使用(6)式即可得到系数K,需要计算以10为底的幂,可是这与Android使用的计算公式有些差异,Andrioid使用的公式是:

(7)            exp(float(100 - volume) * dBConvert);

这是因为它没有使用以10为底的幂运算,而是使用以自然常数e为底的幂运算,因为:

(8)           ln( 10)  = 2.302585093;

我们把dBConvert 重新定义为-dBPerStep * 2.302585093/ 20后,式子(6)和式子(7)实际上是完全等价的。也就是说:

(9)           e^2.302585093 = e^ln(10) = 10;

这下终于知道2.302585093这个奇怪数字的来历啦!!从代码的注释中,我们可以知道,只要改变dBPerStep的大小,就可以决定系统的最小音量了:

最小音量 = -99 * dBPerStep;默认情况下是-49.5dB,K值为:0.00334965439;

至于最大软件数字音量,就是0dB,不能改变,要改就修改底层的音频驱动的硬件音量吧!!

 

 

转自:http://blog.csdn.net/droidphone/article/details/7477350

分享到:
评论

相关推荐

    Android AudioRecord和MediaRecorder录音并实现了实时获取音量大小

    本文将深入探讨如何使用`AudioRecord`和`MediaRecorder`类进行录音,并实现实时获取音量大小的功能。 首先,`AudioRecord`是Android提供的一个低级API,允许开发者直接访问音频硬件来录制声音。它提供了高度的...

    android audio system

    Android音频系统是Android操作系统的一个核心组成部分,负责处理设备上的所有音频功能,包括播放、录制、音量控制、音频格式转换等。它通过一系列的服务和API来实现这些功能,这些服务和API可以被应用程序调用来完成...

    Android 获取麦克风的音量(分贝)

    总结一下,Android获取麦克风音量并转化为分贝值,需要使用`MediaRecorder`类来获取音频样本,然后通过计算RMS值并转换为分贝。同时,别忘了处理权限问题和优化性能。在开发过程中,可以参考ATest项目中的代码进行...

    Android 各种音量的获取

    - **AudioManager**:这是Android提供的用于管理音频流的类,开发者可以通过它来控制和获取系统中的音量。 - **Stream Types**:Android中的音频流被分为不同的类型,每种类型对应不同的应用场景,如通话、铃声、...

    android录音实时监控音量大小

    在Android平台上,录音功能是应用程序开发中的常见需求。实时监控音量大小并将其动态展示在界面上,不仅可以...当然,实际应用可能需要根据具体需求进行更复杂的调整和优化,例如添加音量平滑处理、音量阈值判断等。

    android java 自定义音量键seekbar控制系统的媒体音量和通话音量,可自动实现切换

    5. **权限申请**:为了能够访问和修改系统音量,需要在AndroidManifest.xml中添加必要的权限,如`<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />`。 6. **生命周期管理**:...

    android设置系统音量、媒体音量Demo

    在Android平台上,调整系统音量和媒体音量是常见的需求,尤其对于开发音频播放或通信类应用至关重要。本文将深入探讨如何在Android中实现这一功能,以"android设置系统音量、媒体音量Demo"为例,我们将分析源码并...

    android音量(自定义音量)

    AudioManager 类位于 android.Media 包中,该类提供访问控制音量和钤声模式的操作。通过 AudioManager,可以获取当前音量大小、最大音量大小、设置音量大小、获取当前音频模式、获取当前铃声模式等。 二、...

    Android实现手机音量最大值限制

    Android有多个音量流(Stream),如媒体音量、闹钟音量、铃声音量等,每个流有自己的独立调节和限制。开发者通常需要使用AudioManager类来操作这些音量流。 1. **AudioManager的使用**: - `getStreamMaxVolume...

    CoreAudio获取系统的音量状态

    在Windows平台上,通过.NET程序集,开发者也可以利用CoreAudio API来实现对系统的音量状态的获取和设置。在这个项目中,我们看到一个基于Visual Studio 2015的Windows Forms应用程序——"WindowsFormsApplication1...

    Android自定义(四)音量控制器的实现

    综上所述,创建一个自定义的Android音量控制器涉及到对系统音频管理的深入理解,自定义View的创建和样式设计,以及事件处理和权限管理。通过以上步骤,我们可以构建出一个功能强大且具有个性化风格的音量控制组件,...

    WINDOWS CORE AUDIO APIS的音量、回调事件演示

    本程序是验证CORE AUDIO APIS功能用的。 Main Valume可以将文本框中的数据设置为喇叭主音量。 Listbox Clear可以清空Listbox中内容。 CaptureCaps可以显示目前录音设备的性能。 该程序还可以响应windows系统音频调节...

    Android audio知识总结.pdf

    本文将深入探讨Android音频框架,特别是AudioTrack、AudioRecord、AudioSystem、AudioPolicyService、AudioFlinger以及Audio HAL,并讨论它们在音视频处理中的作用。 1. AudioTrack: AudioTrack是Android应用程序...

    android音量控制

    在Android操作系统中,音量控制是一项关键功能,它允许用户根据个人喜好和环境需求调整不同场景下的音量级别。在Android设备上,音量控制主要分为五个不同的类别:系统音量、通话音量、铃声音量、媒体音量以及提示...

    Android项目仿ios音量调节的效果.rar

    在Android开发中,有时我们希望实现与iOS类似的音量调节界面和体验,以提供用户更加一致的操作感受。这个"Android项目仿ios音量调节的效果"压缩包文件包含了一个示例项目,展示了如何在Android上模仿iOS的音量控制UI...

    android获取音量分贝值

    在Android平台上,获取音量分贝值涉及到音频输入、音频处理和传感器的使用。下面将详细解释这个过程,以及如何实现这一功能。 首先,我们需要理解音量分贝(dB)是一个表示声音强度的单位,它基于人耳对声音感知的...

    android_audio_HAL.rar_android_android audio_android audio HAL_an

    在Android系统中,Audio HAL(Hardware Abstraction Layer)是操作系统与硬件之间的重要接口,它负责处理音频输入和输出的低级操作。这篇关于"android_audio_HAL"的详细文档,主要涵盖了Android音频HAL的移植和Audio...

    Android Audio相关流程时序图

    Android 11 Audio相关流程时序图,需要使用EA画图工具打开。包含Audio中音量获取/设置、焦点申请/放弃、属性设置等相关流程,从APP层到Hal层。详细讲解相关文章参考:...

    android 音量控制

    - Android系统将音量分为多个通道,包括媒体(Media)、通话(Voice Call)、闹钟(Alarm)、通知(Notification)和系统(System)。每个通道都有独立的音量级别,用户可以通过系统设置或物理音量键进行调整。 2....

    android设置系统亮度、音量

    在Android操作系统中,控制设备的亮度、音量以及开关功能如GPS和WiFi是常见的操作,这对于用户来说至关重要,因为它们直接影响到设备的使用体验。本文将深入探讨如何在Android平台上实现这些功能。 首先,让我们来...

Global site tag (gtag.js) - Google Analytics