Home | History | Annotate | Download | only in media
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.example.android.apis.media;
     18 
     19 import com.example.android.apis.R;
     20 
     21 import android.app.Activity;
     22 import android.content.Context;
     23 import android.content.res.AssetFileDescriptor;
     24 import android.graphics.Canvas;
     25 import android.graphics.Color;
     26 import android.graphics.Paint;
     27 import android.graphics.Rect;
     28 import android.media.AudioManager;
     29 import android.media.MediaPlayer;
     30 import android.media.audiofx.Equalizer;
     31 import android.media.audiofx.Visualizer;
     32 import android.net.Uri;
     33 import android.os.Bundle;
     34 import android.util.Log;
     35 import android.view.Gravity;
     36 import android.view.View;
     37 import android.view.ViewGroup;
     38 import android.widget.LinearLayout;
     39 import android.widget.SeekBar;
     40 import android.widget.TextView;
     41 
     42 import java.io.IOException;
     43 
     44 public class AudioFxDemo extends Activity {
     45     private static final String TAG = "AudioFxDemo";
     46 
     47     private static final float VISUALIZER_HEIGHT_DIP = 50f;
     48 
     49     private MediaPlayer mMediaPlayer;
     50     private Visualizer mVisualizer;
     51     private Equalizer mEqualizer;
     52 
     53     private LinearLayout mLinearLayout;
     54     private VisualizerView mVisualizerView;
     55     private TextView mStatusTextView;
     56 
     57     @Override
     58     public void onCreate(Bundle icicle) {
     59         super.onCreate(icicle);
     60 
     61         setVolumeControlStream(AudioManager.STREAM_MUSIC);
     62 
     63         mStatusTextView = new TextView(this);
     64 
     65         mLinearLayout = new LinearLayout(this);
     66         mLinearLayout.setOrientation(LinearLayout.VERTICAL);
     67         mLinearLayout.addView(mStatusTextView);
     68 
     69         setContentView(mLinearLayout);
     70 
     71         // Create the MediaPlayer
     72         mMediaPlayer = MediaPlayer.create(this, R.raw.test_cbr);
     73         Log.d(TAG, "MediaPlayer audio session ID: " + mMediaPlayer.getAudioSessionId());
     74 
     75         setupVisualizerFxAndUI();
     76         setupEqualizerFxAndUI();
     77 
     78         // Make sure the visualizer is enabled only when you actually want to receive data, and
     79         // when it makes sense to receive data.
     80         mVisualizer.setEnabled(true);
     81 
     82         // When the stream ends, we don't need to collect any more data. We don't do this in
     83         // setupVisualizerFxAndUI because we likely want to have more, non-Visualizer related code
     84         // in this callback.
     85         mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
     86             public void onCompletion(MediaPlayer mediaPlayer) {
     87                 mVisualizer.setEnabled(false);
     88             }
     89         });
     90 
     91         mMediaPlayer.start();
     92         mStatusTextView.setText("Playing audio...");
     93     }
     94 
     95     private void setupEqualizerFxAndUI() {
     96         // Create the Equalizer object (an AudioEffect subclass) and attach it to our media player,
     97         // with a default priority (0).
     98         mEqualizer = new Equalizer(0, mMediaPlayer.getAudioSessionId());
     99         mEqualizer.setEnabled(true);
    100 
    101         TextView eqTextView = new TextView(this);
    102         eqTextView.setText("Equalizer:");
    103         mLinearLayout.addView(eqTextView);
    104 
    105         short bands = mEqualizer.getNumberOfBands();
    106 
    107         final short minEQLevel = mEqualizer.getBandLevelRange()[0];
    108         final short maxEQLevel = mEqualizer.getBandLevelRange()[1];
    109 
    110         for (short i = 0; i < bands; i++) {
    111             final short band = i;
    112 
    113             TextView freqTextView = new TextView(this);
    114             freqTextView.setLayoutParams(new ViewGroup.LayoutParams(
    115                     ViewGroup.LayoutParams.FILL_PARENT,
    116                     ViewGroup.LayoutParams.WRAP_CONTENT));
    117             freqTextView.setGravity(Gravity.CENTER_HORIZONTAL);
    118             freqTextView.setText((mEqualizer.getCenterFreq(band) / 1000) + " Hz");
    119             mLinearLayout.addView(freqTextView);
    120 
    121             LinearLayout row = new LinearLayout(this);
    122             row.setOrientation(LinearLayout.HORIZONTAL);
    123 
    124             TextView minDbTextView = new TextView(this);
    125             minDbTextView.setLayoutParams(new ViewGroup.LayoutParams(
    126                     ViewGroup.LayoutParams.WRAP_CONTENT,
    127                     ViewGroup.LayoutParams.WRAP_CONTENT));
    128             minDbTextView.setText((minEQLevel / 100) + " dB");
    129 
    130             TextView maxDbTextView = new TextView(this);
    131             maxDbTextView.setLayoutParams(new ViewGroup.LayoutParams(
    132                     ViewGroup.LayoutParams.WRAP_CONTENT,
    133                     ViewGroup.LayoutParams.WRAP_CONTENT));
    134             maxDbTextView.setText((maxEQLevel / 100) + " dB");
    135 
    136             LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
    137                     ViewGroup.LayoutParams.FILL_PARENT,
    138                     ViewGroup.LayoutParams.WRAP_CONTENT);
    139             layoutParams.weight = 1;
    140             SeekBar bar = new SeekBar(this);
    141             bar.setLayoutParams(layoutParams);
    142             bar.setMax(maxEQLevel - minEQLevel);
    143             bar.setProgress(mEqualizer.getBandLevel(band));
    144 
    145             bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
    146                 public void onProgressChanged(SeekBar seekBar, int progress,
    147                         boolean fromUser) {
    148                     mEqualizer.setBandLevel(band, (short) (progress + minEQLevel));
    149                 }
    150 
    151                 public void onStartTrackingTouch(SeekBar seekBar) {}
    152                 public void onStopTrackingTouch(SeekBar seekBar) {}
    153             });
    154 
    155             row.addView(minDbTextView);
    156             row.addView(bar);
    157             row.addView(maxDbTextView);
    158 
    159             mLinearLayout.addView(row);
    160         }
    161     }
    162 
    163     private void setupVisualizerFxAndUI() {
    164         // Create a VisualizerView (defined below), which will render the simplified audio
    165         // wave form to a Canvas.
    166         mVisualizerView = new VisualizerView(this);
    167         mVisualizerView.setLayoutParams(new ViewGroup.LayoutParams(
    168                 ViewGroup.LayoutParams.FILL_PARENT,
    169                 (int)(VISUALIZER_HEIGHT_DIP * getResources().getDisplayMetrics().density)));
    170         mLinearLayout.addView(mVisualizerView);
    171 
    172         // Create the Visualizer object and attach it to our media player.
    173         mVisualizer = new Visualizer(mMediaPlayer.getAudioSessionId());
    174         mVisualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1]);
    175         mVisualizer.setDataCaptureListener(new Visualizer.OnDataCaptureListener() {
    176             public void onWaveFormDataCapture(Visualizer visualizer, byte[] bytes,
    177                     int samplingRate) {
    178                 mVisualizerView.updateVisualizer(bytes);
    179             }
    180 
    181             public void onFftDataCapture(Visualizer visualizer, byte[] bytes, int samplingRate) {}
    182         }, Visualizer.getMaxCaptureRate() / 2, true, false);
    183     }
    184 
    185     @Override
    186     protected void onPause() {
    187         super.onPause();
    188 
    189         if (isFinishing() && mMediaPlayer != null) {
    190             mVisualizer.release();
    191             mEqualizer.release();
    192             mMediaPlayer.release();
    193             mMediaPlayer = null;
    194         }
    195     }
    196 }
    197 
    198 /**
    199  * A simple class that draws waveform data received from a
    200  * {@link Visualizer.OnDataCaptureListener#onWaveFormDataCapture }
    201  */
    202 class VisualizerView extends View {
    203     private byte[] mBytes;
    204     private float[] mPoints;
    205     private Rect mRect = new Rect();
    206 
    207     private Paint mForePaint = new Paint();
    208 
    209     public VisualizerView(Context context) {
    210         super(context);
    211         init();
    212     }
    213 
    214     private void init() {
    215         mBytes = null;
    216 
    217         mForePaint.setStrokeWidth(1f);
    218         mForePaint.setAntiAlias(true);
    219         mForePaint.setColor(Color.rgb(0, 128, 255));
    220     }
    221 
    222     public void updateVisualizer(byte[] bytes) {
    223         mBytes = bytes;
    224         invalidate();
    225     }
    226 
    227     @Override
    228     protected void onDraw(Canvas canvas) {
    229         super.onDraw(canvas);
    230 
    231         if (mBytes == null) {
    232             return;
    233         }
    234 
    235         if (mPoints == null || mPoints.length < mBytes.length * 4) {
    236             mPoints = new float[mBytes.length * 4];
    237         }
    238 
    239         mRect.set(0, 0, getWidth(), getHeight());
    240 
    241         for (int i = 0; i < mBytes.length - 1; i++) {
    242             mPoints[i * 4] = mRect.width() * i / (mBytes.length - 1);
    243             mPoints[i * 4 + 1] = mRect.height() / 2
    244                     + ((byte) (mBytes[i] + 128)) * (mRect.height() / 2) / 128;
    245             mPoints[i * 4 + 2] = mRect.width() * (i + 1) / (mBytes.length - 1);
    246             mPoints[i * 4 + 3] = mRect.height() / 2
    247                     + ((byte) (mBytes[i + 1] + 128)) * (mRect.height() / 2) / 128;
    248         }
    249 
    250         canvas.drawLines(mPoints, mForePaint);
    251     }
    252 }
    253