在Android2.3中增加了对音频混响的支持,这些API包含在android.media.audiofx包中。 

  一、概述

  AudioEffect是android audio framework(android 音频框架)提供的音频效果控制的基类。开发者不能直接使用此类,应该使用它的派生类。 下面列出它的派生类。 

    Equalizer
    Virtualizer
    BassBoost
    PresetReverb
    EnvironmentalReverb

  当创建AudioEffect时,如果音频效果应用到一个具体的AudioTrack和MediaPlayer的实例,应用程序必须指定该实例的音频session ID,如果要应用Global音频输出混响的效果必须制定Session 0。

  要创建音频输出混响(音频 Session 0)要求要有 MODIFY_AUDIO_SETTINGS权限。

  如果要创建的效果在audio framework不存在,那么直接创建该效果,如果已经存在那么直接使用此效果。如果优先级高的对象要在低级别的对象使用该效果时,那么控制将转移到优先级高的对象上,否则继续停留在此对象上。在这种情况下,新的申请将被监听器通知。

  二、嵌套类

  1.AudioEffect.Descriptor:效果描述符包含在音频框架内实现某种特定的效果的信息。
  2.AudioEffect.OnControlStatusChangeListener:此接口定义了当应用程序的音频效果的控制状态改变时由AudioEffect调用的方法。

  3.AudioEffect.OnEnableStatusChangeListener:此接口定义了当应用程序的音频效果的启用状态改变时由AudioEffect调用的方法。

  三、常量

String ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION 关闭音频效果
String ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL 启动一个音频效果控制面板UI。
String ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION 打开音频效果。
int ALREADY_EXISTS 内部操作状态。
int CONTENT_TYPE_GAME 当播放内容的类型是游戏音频时EXTRA_CONTENT_TYPE的值。
int CONTENT_TYPE_MOVIE 当播放内容的类型是电影时EXTRA_CONTENT_TYPE的值。
int CONTENT_TYPE_MUSIC 当播放内容的类型是音乐时EXTRA_CONTENT_TYPE的值。
int CONTENT_TYPE_VOICE 当播放内容的类型是话音时EXTRA_CONTENT_TYPE的值。                  
String EFFECT_AUXILIARY Effect connection mode 是auxiliary
String EFFECT_INSERT Effect connection mode 是insert.
int ERROR 指示操作错误。
int ERROR_BAD_VALUE 指示由于错误的参数导致的操作失败。
int ERROR_DEAD_OBJECT 指示由于已关闭的远程对象导致的操作失败。
int ERROR_INVALID_OPERATION 指示由于错误的请求状态导致的操作失败。
int ERROR_NO_INIT 指示由于错误的对象初始化导致的操作失败。
int ERROR_NO_MEMORY 指示由于内存不足导致的操作失败。
String EXTRA_AUDIO_SESSION 包含使用效果的音频会话ID。
String EXTRA_CONTENT_TYPE 指示应用程序播放内容的类型。
String EXTRA_PACKAGE_NAME 包含调用应用程序的包名。
int SUCCESS 操作成功。

  四、公有方法

 

AudioEffect.Descriptor getDescriptor()

获取效果描述符。
boolean getEnabled()

返回效果的启用状态。
int getId()

返回效果的标识符
boolean hasControl()

检查该AudioEffect 对象是否拥有效果引擎的控制。如果有,则返回true。
static Descriptor[] queryEffects()

查询平台上的所有有效的音频效果。
void release()

释放本地AudioEffect资源。
void setControlStatusListener(AudioEffect.OnControlStatusChangeListener listener)

注册音频效果的控制状态监听器.当控制状态改变时AudioEffect发出通知。
void setEnableStatusListener(AudioEffect.OnEnableStatusChangeListener listener)

设置音频效果的启用状态监听器。当启用状态改变时AudioEffect发出通知。
int setEnabled(boolean enabled)

Enable or disable the effect.

  五、应用(此应用来自于SDK包)

  1.新建项目

  

  你或许已经发现在2.3的项目中比2.2多一个配置文件proguard.cfg,包含混淆所需的proguard脚本。

  

  2.打开AndroidManifest.xml文件

  添加权限“android.permission.RECORD_AUDIO”。

  3.可视化工具类VisualizerView.java

  

        效果图  

  4.Main.java

  

  1. package com.wjq.audiofx;
  2.  
  3. import android.app.Activity;
  4. import android.media.AudioManager;
  5. import android.media.MediaPlayer;
  6. import android.media.audiofx.Equalizer;
  7. import android.media.audiofx.Visualizer;
  8. import android.os.Bundle;
  9. import android.util.Log;
  10. import android.view.Gravity;
  11. import android.view.ViewGroup;
  12. import android.widget.LinearLayout;
  13. import android.widget.SeekBar;
  14. import android.widget.TextView;
  15.  
  16. public class Main extends Activity {
  17. private static final String TAG = "AudioFxDemo";
  18.  
  19. private static final float VISUALIZER_HEIGHT_DIP = 50f;
  20.  
  21. private MediaPlayer mMediaPlayer;
  22. private Visualizer mVisualizer;
  23. private Equalizer mEqualizer;
  24.  
  25. private LinearLayout mLinearLayout;
  26. private VisualizerView mVisualizerView;
  27. private TextView mStatusTextView;
  28.  
  29. @Override
  30. public void onCreate(Bundle icicle) {
  31. super.onCreate(icicle);
  32.  
  33. setVolumeControlStream(AudioManager.STREAM_MUSIC);
  34.  
  35. mStatusTextView = new TextView(this);
  36.  
  37. mLinearLayout = new LinearLayout(this);
  38. mLinearLayout.setOrientation(LinearLayout.VERTICAL);
  39. mLinearLayout.addView(mStatusTextView);
  40.  
  41. setContentView(mLinearLayout);
  42.  
  43. // Create the MediaPlayer
  44. mMediaPlayer = MediaPlayer.create(this, R.raw.test_cbr);
  45. Log.d(TAG, "MediaPlayer audio session ID: " + mMediaPlayer.getAudioSessionId());
  46.  
  47. setupVisualizerFxAndUI();
  48. setupEqualizerFxAndUI();
  49. // Make sure the visualizer is enabled only when you actually want to receive data, and
  50. // when it makes sense to receive data.
  51. mVisualizer.setEnabled(true);
  52.  
  53. // When the stream ends, we don't need to collect any more data. We don't do this in
  54. // setupVisualizerFxAndUI because we likely want to have more, non-Visualizer related code
  55. // in this callback.
  56. mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
  57. public void onCompletion(MediaPlayer mediaPlayer) {
  58. mVisualizer.setEnabled(false);
  59. }
  60. });
  61.  
  62. mMediaPlayer.start();
  63. mStatusTextView.setText("Playing audio...");
  64. }
  65.  
  66. private void setupEqualizerFxAndUI() {
  67. // Create the Equalizer object (an AudioEffect subclass) and attach it to our media player,
  68. // with a default priority (0).
  69. mEqualizer = new Equalizer(0, mMediaPlayer.getAudioSessionId());
  70. mEqualizer.setEnabled(true);
  71.  
  72. TextView eqTextView = new TextView(this);
  73. eqTextView.setText("Equalizer:");
  74. mLinearLayout.addView(eqTextView);
  75.  
  76. short bands = mEqualizer.getNumberOfBands();
  77.  
  78. final short minEQLevel = mEqualizer.getBandLevelRange()[0];
  79. final short maxEQLevel = mEqualizer.getBandLevelRange()[1];
  80.  
  81. for (short i = 0; i < bands; i++) {
  82. final short band = i;
  83.  
  84. TextView freqTextView = new TextView(this);
  85. freqTextView.setLayoutParams(new ViewGroup.LayoutParams(
  86. ViewGroup.LayoutParams.FILL_PARENT,
  87. ViewGroup.LayoutParams.WRAP_CONTENT));
  88. freqTextView.setGravity(Gravity.CENTER_HORIZONTAL);
  89. freqTextView.setText((mEqualizer.getCenterFreq(band) / 1000) + " Hz");
  90. mLinearLayout.addView(freqTextView);
  91.  
  92. LinearLayout row = new LinearLayout(this);
  93. row.setOrientation(LinearLayout.HORIZONTAL);
  94.  
  95. TextView minDbTextView = new TextView(this);
  96. minDbTextView.setLayoutParams(new ViewGroup.LayoutParams(
  97. ViewGroup.LayoutParams.WRAP_CONTENT,
  98. ViewGroup.LayoutParams.WRAP_CONTENT));
  99. minDbTextView.setText((minEQLevel / 100) + " dB");
  100.  
  101. TextView maxDbTextView = new TextView(this);
  102. maxDbTextView.setLayoutParams(new ViewGroup.LayoutParams(
  103. ViewGroup.LayoutParams.WRAP_CONTENT,
  104. ViewGroup.LayoutParams.WRAP_CONTENT));
  105. maxDbTextView.setText((maxEQLevel / 100) + " dB");
  106.  
  107. LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
  108. ViewGroup.LayoutParams.FILL_PARENT,
  109. ViewGroup.LayoutParams.WRAP_CONTENT);
  110. layoutParams.weight = 1;
  111. SeekBar bar = new SeekBar(this);
  112. bar.setLayoutParams(layoutParams);
  113. bar.setMax(maxEQLevel - minEQLevel);
  114. bar.setProgress(mEqualizer.getBandLevel(band));
  115.  
  116. bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
  117. public void onProgressChanged(SeekBar seekBar, int progress,
  118. boolean fromUser) {
  119. mEqualizer.setBandLevel(band, (short) (progress + minEQLevel));
  120. }
  121.  
  122. public void onStartTrackingTouch(SeekBar seekBar) {}
  123. public void onStopTrackingTouch(SeekBar seekBar) {}
  124. });
  125.  
  126. row.addView(minDbTextView);
  127. row.addView(bar);
  128. row.addView(maxDbTextView);
  129.  
  130. mLinearLayout.addView(row);
  131. }
  132. }
  133.  
  134. private void setupVisualizerFxAndUI() {
  135. // Create a VisualizerView (defined below), which will render the simplified audio
  136. // wave form to a Canvas.
  137. mVisualizerView = new VisualizerView(this);
  138. mVisualizerView.setLayoutParams(new ViewGroup.LayoutParams(
  139. ViewGroup.LayoutParams.FILL_PARENT,
  140. (int)(VISUALIZER_HEIGHT_DIP * getResources().getDisplayMetrics().density)));
  141. mLinearLayout.addView(mVisualizerView);
  142.  
  143. // Create the Visualizer object and attach it to our media player.
  144. mVisualizer = new Visualizer(mMediaPlayer.getAudioSessionId());
  145. mVisualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1]);
  146. mVisualizer.setDataCaptureListener(new Visualizer.OnDataCaptureListener() {
  147. public void onWaveFormDataCapture(Visualizer visualizer, byte[] bytes,
  148. int samplingRate) {
  149. mVisualizerView.updateVisualizer(bytes);
  150. }
  151.  
  152. public void onFftDataCapture(Visualizer visualizer, byte[] bytes, int samplingRate) {}
  153. }, Visualizer.getMaxCaptureRate() / 2, true, false);
  154. }
  155.  
  156. @Override
  157. protected void onPause() {
  158. super.onPause();
  159.  
  160. if (isFinishing() && mMediaPlayer != null) {
  161. mVisualizer.release();
  162. mEqualizer.release();
  163. mMediaPlayer.release();
  164. mMediaPlayer = null;
  165. }
  166. }
  167. }
  1. 1 package com.wjq.audiofx;
  2. 2
  3. 3 import android.content.Context;
  4. 4 import android.graphics.Canvas;
  5. 5 import android.graphics.Color;
  6. 6 import android.graphics.Paint;
  7. 7 import android.graphics.Rect;
  8. 8 import android.view.View;
  9. 9
  10. 10 public class VisualizerView extends View {
  11. 11
  12. 12 private byte[] mBytes;
  13. 13 private float[] mPoints;
  14. 14 private Rect mRect = new Rect();
  15. 15
  16. 16 private Paint mForePaint = new Paint();
  17. 17
  18. 18 public VisualizerView(Context context) {
  19. 19 super(context);
  20. 20 init();
  21. 21 }
  22. 22
  23. 23 private void init() {
  24. 24 mBytes = null;
  25. 25
  26. 26 mForePaint.setStrokeWidth(1f);
  27. 27 mForePaint.setAntiAlias(true);
  28. 28 mForePaint.setColor(Color.rgb(0, 128, 255));
  29. 29 }
  30. 30
  31. 31 public void updateVisualizer(byte[] bytes) {
  32. 32 mBytes = bytes;
  33. 33 invalidate();
  34. 34 }
  35. 35
  36. 36 @Override
  37. 37 protected void onDraw(Canvas canvas) {
  38. 38 super.onDraw(canvas);
  39. 39
  40. 40 if (mBytes == null) {
  41. 41 return;
  42. 42 }
  43. 43
  44. 44 if (mPoints == null || mPoints.length < mBytes.length * 4) {
  45. 45 mPoints = new float[mBytes.length * 4];
  46. 46 }
  47. 47
  48. 48 mRect.set(0, 0, getWidth(), getHeight());
  49. 49
  50. 50 for (int i = 0; i < mBytes.length - 1; i++) {
  51. 51 mPoints[i * 4] = mRect.width() * i / (mBytes.length - 1);
  52. 52 mPoints[i * 4 + 1] = mRect.height() / 2
  53. 53 + ((byte) (mBytes[i] + 128)) * (mRect.height() / 2) / 128;
  54. 54 mPoints[i * 4 + 2] = mRect.width() * (i + 1) / (mBytes.length - 1);
  55. 55 mPoints[i * 4 + 3] = mRect.height() / 2
  56. 56 + ((byte) (mBytes[i + 1] + 128)) * (mRect.height() / 2) / 128;
  57. 57 }
  58. 58
  59. 59 canvas.drawLines(mPoints, mForePaint);
  60. 60 }
  61. 61
  62. 62 }

Android新增API之AudioEffect中文API与应用实例的更多相关文章

  1. AudioEffect中文API

    在Android2.3中增加了对音频混响的支持,这些API包含在android.media.audiofx包中. 一.概述 AudioEffect是android audio framework(an ...

  2. android SDK下载及中文API地址

    中文API:http://wiki.eoeandroid.com/Android_API_Guides Android Dev Tools官网地址:www.androiddevtools.cn 收集整 ...

  3. Android 中文 API (40) —— RatingBar

    Android 中文 API (40) —— RatingBar 前言 本章内容是 android.widget.RatingBar,译为"评分条",版本为Android 2.2 ...

  4. Android 中文API (70) —— BluetoothDevice[蓝牙]

    前言 本章内容是  android.bluetooth.BluetoothDevice,为Android蓝牙部分的章节翻译.蓝牙设备类,代表了蓝牙通讯国足中的远端设备.版本为 Android  2.3 ...

  5. Android 中文API (69) —— BluetoothAdapter[蓝牙]

    前言 本章内容是  android.bluetooth.BluetoothAdapter,为Android蓝牙部分的章节翻译.本地蓝牙设备的适配类,所有的蓝牙操作都要通过该类完成.版本为 Androi ...

  6. Android 中文API (68) —— BluetoothClass.Service

    前言 本章内容是 android.bluetooth.BluetoothClass.Service,为Android蓝牙部分的章节翻译,版本为 Android 2.3   r1,翻译来自中山大学的&q ...

  7. Android 中文API (67) —— BluetoothClass.Device.Major

    前言 本章内容是android.bluetooth.BluetoothClass.Device.Major,为Android蓝牙部分的章节翻译,版本为Android 2.3   r1,翻译来自中山大学 ...

  8. Android 中文API (66) —— BluetoothClass.Device

    前言 本章内容是android.bluetooth.BluetoothClass.Device,为Android蓝牙部分的章节翻译,版本为Android 2.3   r1,翻译来自中山大学的" ...

  9. Android 中文API (65) —— BluetoothClass[蓝牙]

    前言 本章内容是android.bluetooth.BluetoothClass,为Android蓝牙部分的章节翻译.用于描述远端设备的类型,特点等信息,通过getBluetoothClass()方法 ...

随机推荐

  1. 通知/代理/block 三者比对

    通知 :   “一对多”,”多对一” 传值 四个步骤:  1.发送通知2.创建监听者3.接收通知4.移除监听者 使用场景:1- 很多控制器都需要知道一个事件,应该用通知:2 - 相隔多层的两个控制器之 ...

  2. 前端笔试面试中的常用知识点总结(CSS)

    1.CSS选择器的优先级!important  > 内联 > id选择器 > 类选择器 > 标签选择器多个类选择器叠加(256)之后的优先级大于一个id选择器!importan ...

  3. SqlBulkCopy的使用

    1.问题:导入大数据量到数据库,用我们普通的SqlHelper来做是每插入一条都是打开连接关闭连接,这样太慢,因此我们会想到让SqlConnection一直打开直到所有数据都插入完成再关闭连接.但是根 ...

  4. 关于UITableview刷新笔记

    今天在做项目的时候 发现调用tableview 的 reloaddata 方法的时候出现崩溃. - 具体操作是执行某个方法后将数据数组中的某条数据删除(数组中存数组)发现调用刷新方法后 程序崩溃,查看 ...

  5. Expected stackmap frame at this location

    使用eclipse,本来使用的是jdk1.7的,后来切换到jdk1.8版本就出现了这个问题,报错的Reason说的是Expected stackmap frame at this location,其 ...

  6. BZOJ 1599: [Usaco2008 Oct]笨重的石子( 枚举 )

    直接枚举 ------------------------------------------------------------------------------- #include<cst ...

  7. Servlet的学习笔记

    一.Servlet生命周期 init(ServletConfig config)  ----->初始化 service(ServletRequest req, ServletResponse r ...

  8. mysqld守护进程

    1.安装方式:安装文件:可执行的二进制文件: 源代码编译. 2.版本选择:常见版本区别:GA(一般应用,尽量使用最新版本)/RC(候选发布版本)/测试版本实版本选择主要是够用.适用.好用!不一定是最新 ...

  9. 基于visual Studio2013解决C语言竞赛题之0406数列求和

      题目 解决代码及点评 这个题目,还是考察for循环的使用 以及数列规律,该数列的特点是第n个分子 = 第n-1个分子 + 第n-2个分子,分母也是此规律 而另外一个规律是第n个分子和第n- ...

  10. pragma comment

    pragma指令简介 在编写程序的时候,我们经常要用到#pragma指令来设定编译器的状态或者是指示编译器完成一些特定的动作. 下面介绍了一下该指令的一些常用参数,希望对大家有所帮助! 一. mess ...