zoukankan      html  css  js  c++  java
  • Android新增API之AudioEffect中文API与应用实例

    在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

      

    package com.wjq.audiofx;
    
    import android.app.Activity;
    import android.media.AudioManager;
    import android.media.MediaPlayer;
    import android.media.audiofx.Equalizer;
    import android.media.audiofx.Visualizer;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.Gravity;
    import android.view.ViewGroup;
    import android.widget.LinearLayout;
    import android.widget.SeekBar;
    import android.widget.TextView;
    
    public class Main extends Activity {
         private static final String TAG = "AudioFxDemo";
    
            private static final float VISUALIZER_HEIGHT_DIP = 50f;
    
            private MediaPlayer mMediaPlayer;
            private Visualizer mVisualizer;
            private Equalizer mEqualizer;
    
            private LinearLayout mLinearLayout;
            private VisualizerView mVisualizerView;
            private TextView mStatusTextView;
    
            @Override
            public void onCreate(Bundle icicle) {
                super.onCreate(icicle);
    
                setVolumeControlStream(AudioManager.STREAM_MUSIC);
    
                mStatusTextView = new TextView(this);
    
                mLinearLayout = new LinearLayout(this);
                mLinearLayout.setOrientation(LinearLayout.VERTICAL);
                mLinearLayout.addView(mStatusTextView);
    
                setContentView(mLinearLayout);
    
                // Create the MediaPlayer
                mMediaPlayer = MediaPlayer.create(this, R.raw.test_cbr);
                Log.d(TAG, "MediaPlayer audio session ID: " + mMediaPlayer.getAudioSessionId());
    
                setupVisualizerFxAndUI();
                setupEqualizerFxAndUI();
        // Make sure the visualizer is enabled only when you actually want to receive data, and
        // when it makes sense to receive data.
        mVisualizer.setEnabled(true);
    
        // When the stream ends, we don't need to collect any more data. We don't do this in
        // setupVisualizerFxAndUI because we likely want to have more, non-Visualizer related code
        // in this callback.
        mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            public void onCompletion(MediaPlayer mediaPlayer) {
                mVisualizer.setEnabled(false);
            }
        });
    
        mMediaPlayer.start();
        mStatusTextView.setText("Playing audio...");
    }
    
    private void setupEqualizerFxAndUI() {
        // Create the Equalizer object (an AudioEffect subclass) and attach it to our media player,
        // with a default priority (0).
        mEqualizer = new Equalizer(0, mMediaPlayer.getAudioSessionId());
        mEqualizer.setEnabled(true);
    
        TextView eqTextView = new TextView(this);
        eqTextView.setText("Equalizer:");
        mLinearLayout.addView(eqTextView);
    
        short bands = mEqualizer.getNumberOfBands();
    
        final short minEQLevel = mEqualizer.getBandLevelRange()[0];
        final short maxEQLevel = mEqualizer.getBandLevelRange()[1];
    
        for (short i = 0; i < bands; i++) {
            final short band = i;
    
            TextView freqTextView = new TextView(this);
            freqTextView.setLayoutParams(new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.FILL_PARENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT));
            freqTextView.setGravity(Gravity.CENTER_HORIZONTAL);
            freqTextView.setText((mEqualizer.getCenterFreq(band) / 1000) + " Hz");
            mLinearLayout.addView(freqTextView);
    
            LinearLayout row = new LinearLayout(this);
            row.setOrientation(LinearLayout.HORIZONTAL);
    
            TextView minDbTextView = new TextView(this);
            minDbTextView.setLayoutParams(new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.WRAP_CONTENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT));
            minDbTextView.setText((minEQLevel / 100) + " dB");
    
            TextView maxDbTextView = new TextView(this);
            maxDbTextView.setLayoutParams(new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.WRAP_CONTENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT));
            maxDbTextView.setText((maxEQLevel / 100) + " dB");
    
            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
                    ViewGroup.LayoutParams.FILL_PARENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT);
            layoutParams.weight = 1;
            SeekBar bar = new SeekBar(this);
            bar.setLayoutParams(layoutParams);
            bar.setMax(maxEQLevel - minEQLevel);
            bar.setProgress(mEqualizer.getBandLevel(band));
    
            bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
                public void onProgressChanged(SeekBar seekBar, int progress,
                        boolean fromUser) {
                    mEqualizer.setBandLevel(band, (short) (progress + minEQLevel));
                }
    
                public void onStartTrackingTouch(SeekBar seekBar) {}
                public void onStopTrackingTouch(SeekBar seekBar) {}
            });
    
            row.addView(minDbTextView);
            row.addView(bar);
            row.addView(maxDbTextView);
    
            mLinearLayout.addView(row);
        }
    }
    
    private void setupVisualizerFxAndUI() {
        // Create a VisualizerView (defined below), which will render the simplified audio
        // wave form to a Canvas.
        mVisualizerView = new VisualizerView(this);
        mVisualizerView.setLayoutParams(new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.FILL_PARENT,
                (int)(VISUALIZER_HEIGHT_DIP * getResources().getDisplayMetrics().density)));
        mLinearLayout.addView(mVisualizerView);
    
        // Create the Visualizer object and attach it to our media player.
        mVisualizer = new Visualizer(mMediaPlayer.getAudioSessionId());
        mVisualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1]);
        mVisualizer.setDataCaptureListener(new Visualizer.OnDataCaptureListener() {
            public void onWaveFormDataCapture(Visualizer visualizer, byte[] bytes,
                    int samplingRate) {
                mVisualizerView.updateVisualizer(bytes);
            }
    
            public void onFftDataCapture(Visualizer visualizer, byte[] bytes, int samplingRate) {}
        }, Visualizer.getMaxCaptureRate() / 2, true, false);
    }
    
    @Override
    protected void onPause() {
        super.onPause();
    
        if (isFinishing() && mMediaPlayer != null) {
            mVisualizer.release();
            mEqualizer.release();
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
    }
    }
     1 package com.wjq.audiofx;
     2 
     3 import android.content.Context;
     4 import android.graphics.Canvas;
     5 import android.graphics.Color;
     6 import android.graphics.Paint;
     7 import android.graphics.Rect;
     8 import android.view.View;
     9 
    10 public class VisualizerView extends View {
    11 
    12        private byte[] mBytes;
    13         private float[] mPoints;
    14         private Rect mRect = new Rect();
    15 
    16         private Paint mForePaint = new Paint();
    17 
    18         public VisualizerView(Context context) {
    19             super(context);
    20             init();
    21         }
    22 
    23         private void init() {
    24             mBytes = null;
    25 
    26             mForePaint.setStrokeWidth(1f);
    27             mForePaint.setAntiAlias(true);
    28             mForePaint.setColor(Color.rgb(0, 128, 255));
    29         }
    30 
    31         public void updateVisualizer(byte[] bytes) {
    32             mBytes = bytes;
    33             invalidate();
    34         }
    35 
    36         @Override
    37         protected void onDraw(Canvas canvas) {
    38             super.onDraw(canvas);
    39 
    40             if (mBytes == null) {
    41                 return;
    42             }
    43 
    44             if (mPoints == null || mPoints.length < mBytes.length * 4) {
    45                 mPoints = new float[mBytes.length * 4];
    46             }
    47 
    48             mRect.set(0, 0, getWidth(), getHeight());
    49 
    50             for (int i = 0; i < mBytes.length - 1; i++) {
    51                 mPoints[i * 4] = mRect.width() * i / (mBytes.length - 1);
    52                 mPoints[i * 4 + 1] = mRect.height() / 2
    53                         + ((byte) (mBytes[i] + 128)) * (mRect.height() / 2) / 128;
    54                 mPoints[i * 4 + 2] = mRect.width() * (i + 1) / (mBytes.length - 1);
    55                 mPoints[i * 4 + 3] = mRect.height() / 2
    56                         + ((byte) (mBytes[i + 1] + 128)) * (mRect.height() / 2) / 128;
    57             }
    58 
    59             canvas.drawLines(mPoints, mForePaint);
    60         }
    61 
    62 }
  • 相关阅读:
    java核心学习(二十七) 多线程---线程相关类
    java核心学习(二十六) 多线程---线程池
    java核心学习(二十五) 多线程---线程组和未处理的异常
    java核心学习(二十四) 多线程---线程通信
    java核心学习(二十三) 多线程---线程同步
    java核心学习(二十二) 多线程---线程控制
    模线性方程 poj2115
    求两个圆的重合面积+二分 hdu3264
    求多边形面积 HDU2036
    判断两直线是否相交 hdu1086
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/4876531.html
Copyright © 2011-2022 走看看