1/*
2 * Copyright (C) 2009 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
17package com.android.effectstest;
18
19import android.app.Activity;
20import android.content.Context;
21import android.content.Intent;
22import android.os.Bundle;
23import android.util.Log;
24import android.view.KeyEvent;
25import android.view.Menu;
26import android.view.View.OnClickListener;
27import android.view.View;
28import android.view.ViewGroup;
29import android.widget.Button;
30import android.widget.TextView;
31import android.widget.EditText;
32import android.widget.SeekBar;
33import android.widget.ToggleButton;
34import android.widget.CompoundButton;
35import android.widget.CompoundButton.OnCheckedChangeListener;
36import java.nio.ByteOrder;
37import java.nio.ByteBuffer;
38import java.util.HashMap;
39import java.util.Map;
40
41
42import android.media.audiofx.Equalizer;
43import android.media.audiofx.AudioEffect;
44
45public class EqualizerTest extends Activity implements OnCheckedChangeListener {
46
47    private final static String TAG = "EqualizerTest";
48
49    private static int NUM_BANDS = 5;
50    private static int NUM_PARAMS = NUM_BANDS + 1;
51
52    private EffectParameter[] mParameters = new EffectParameter[NUM_PARAMS];
53    private Equalizer mEqualizer;
54    ToggleButton mOnOffButton;
55    ToggleButton mReleaseButton;
56    EditText mSessionText;
57    static int sSession = 0;
58    EffectListner mEffectListener = new EffectListner();
59    private static HashMap<Integer, Equalizer> sInstances = new HashMap<Integer, Equalizer>(10);
60    String mSettings = "";
61
62    public EqualizerTest() {
63        Log.d(TAG, "contructor");
64    }
65
66    @Override
67    public void onCreate(Bundle icicle) {
68        super.onCreate(icicle);
69
70        SeekBar seekBar;
71        TextView textView;
72
73        setContentView(R.layout.equalizertest);
74
75        mSessionText = (EditText) findViewById(R.id.sessionEdit);
76        mSessionText.setOnKeyListener(mSessionKeyListener);
77
78        mSessionText.setText(Integer.toString(sSession));
79
80        mReleaseButton = (ToggleButton)findViewById(R.id.eqReleaseButton);
81        mOnOffButton = (ToggleButton)findViewById(R.id.equalizerOnOff);
82
83        getEffect(sSession);
84
85        if (mEqualizer != null) {
86            mReleaseButton.setOnCheckedChangeListener(this);
87            mOnOffButton.setOnCheckedChangeListener(this);
88
89            short[] bandLevelRange = mEqualizer.getBandLevelRange();
90            int centerFreq;
91            int []freqRange;
92
93            // Band 1 level
94            centerFreq = mEqualizer.getCenterFreq((short)0);
95            freqRange = mEqualizer.getBandFreqRange((short)0);
96            displayFreq(R.id.eqParam1Center, centerFreq);
97            displayFreq(R.id.eqParam1Min, freqRange[0]);
98            displayFreq(R.id.eqParam1Max, freqRange[1]);
99            seekBar = (SeekBar)findViewById(R.id.eqParam1SeekBar);
100            textView = (TextView)findViewById(R.id.eqParam1Value);
101            mParameters[0] = new BandLevelParam(mEqualizer, 0, bandLevelRange[0], bandLevelRange[1], seekBar, textView);
102            seekBar.setOnSeekBarChangeListener(mParameters[0]);
103
104            // Band 2 level
105            centerFreq = mEqualizer.getCenterFreq((short)1);
106            freqRange = mEqualizer.getBandFreqRange((short)1);
107            displayFreq(R.id.eqParam2Center, centerFreq);
108            displayFreq(R.id.eqParam2Min, freqRange[0]);
109            displayFreq(R.id.eqParam2Max, freqRange[1]);
110            seekBar = (SeekBar)findViewById(R.id.eqParam2SeekBar);
111            textView = (TextView)findViewById(R.id.eqParam2Value);
112            mParameters[1] = new BandLevelParam(mEqualizer, 1, bandLevelRange[0], bandLevelRange[1], seekBar, textView);
113            seekBar.setOnSeekBarChangeListener(mParameters[1]);
114
115            // Band 3 level
116            centerFreq = mEqualizer.getCenterFreq((short)2);
117            freqRange = mEqualizer.getBandFreqRange((short)2);
118            displayFreq(R.id.eqParam3Center, centerFreq);
119            displayFreq(R.id.eqParam3Min, freqRange[0]);
120            displayFreq(R.id.eqParam3Max, freqRange[1]);
121            seekBar = (SeekBar)findViewById(R.id.eqParam3SeekBar);
122            textView = (TextView)findViewById(R.id.eqParam3Value);
123            mParameters[2] = new BandLevelParam(mEqualizer, 2, bandLevelRange[0], bandLevelRange[1], seekBar, textView);
124            seekBar.setOnSeekBarChangeListener(mParameters[2]);
125
126            // Band 4 level
127            centerFreq = mEqualizer.getCenterFreq((short)3);
128            freqRange = mEqualizer.getBandFreqRange((short)3);
129            displayFreq(R.id.eqParam4Center, centerFreq);
130            displayFreq(R.id.eqParam4Min, freqRange[0]);
131            displayFreq(R.id.eqParam4Max, freqRange[1]);
132            seekBar = (SeekBar)findViewById(R.id.eqParam4SeekBar);
133            textView = (TextView)findViewById(R.id.eqParam4Value);
134            mParameters[3] = new BandLevelParam(mEqualizer, 3, bandLevelRange[0], bandLevelRange[1], seekBar, textView);
135            seekBar.setOnSeekBarChangeListener(mParameters[3]);
136
137            // Band 5 level
138            centerFreq = mEqualizer.getCenterFreq((short)4);
139            freqRange = mEqualizer.getBandFreqRange((short)4);
140            displayFreq(R.id.eqParam5Center, centerFreq);
141            displayFreq(R.id.eqParam5Min, freqRange[0]);
142            displayFreq(R.id.eqParam5Max, freqRange[1]);
143            seekBar = (SeekBar)findViewById(R.id.eqParam5SeekBar);
144            textView = (TextView)findViewById(R.id.eqParam5Value);
145            mParameters[4] = new BandLevelParam(mEqualizer, 4, bandLevelRange[0], bandLevelRange[1], seekBar, textView);
146            seekBar.setOnSeekBarChangeListener(mParameters[4]);
147
148            // Presets
149            short numPresets = mEqualizer.getNumberOfPresets();
150            seekBar = (SeekBar)findViewById(R.id.eqParam6SeekBar);
151            textView = (TextView)findViewById(R.id.eqParam6Value);
152            mParameters[5] = new PresetParam(mEqualizer, (short)0, (short)(numPresets-1), seekBar, textView);
153            seekBar.setOnSeekBarChangeListener(mParameters[5]);
154        }
155    }
156
157    @Override
158    public void onResume() {
159        super.onResume();
160    }
161
162    @Override
163    public void onPause() {
164        super.onPause();
165    }
166
167    private View.OnKeyListener mSessionKeyListener
168    = new View.OnKeyListener() {
169        public boolean onKey(View v, int keyCode, KeyEvent event) {
170            if (event.getAction() == KeyEvent.ACTION_DOWN) {
171                switch (keyCode) {
172                    case KeyEvent.KEYCODE_DPAD_CENTER:
173                    case KeyEvent.KEYCODE_ENTER:
174                        try {
175                            sSession = Integer.parseInt(mSessionText.getText().toString());
176                            getEffect(sSession);
177                            if (mEqualizer != null) {
178                                for (int i = 0 ; i < mParameters.length; i++) {
179                                    mParameters[i].setEffect(mEqualizer);
180                                    mParameters[i].setEnabled(true);
181                                }
182                            }
183                        } catch (NumberFormatException e) {
184                            Log.d(TAG, "Invalid session #: "+mSessionText.getText().toString());
185                        }
186
187                        return true;
188                }
189            }
190            return false;
191        }
192    };
193
194    // OnCheckedChangeListener
195    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
196        if (buttonView.getId() == R.id.equalizerOnOff) {
197            if (mEqualizer != null) {
198                mEqualizer.setEnabled(isChecked);
199                updateBands();
200            }
201        }
202        if (buttonView.getId() == R.id.eqReleaseButton) {
203            if (isChecked) {
204                if (mEqualizer == null) {
205                    getEffect(sSession);
206                    if (mEqualizer != null) {
207                        for (int i = 0 ; i < mParameters.length; i++) {
208                            mParameters[i].setEffect(mEqualizer);
209                            mParameters[i].setEnabled(true);
210                        }
211                    }
212                }
213            } else {
214                if (mEqualizer != null) {
215                    for (int i = 0 ; i < mParameters.length; i++) {
216                        mParameters[i].setEnabled(false);
217                    }
218                    putEffect(sSession);
219                }
220            }
221        }
222    }
223
224    protected void updateBands() {
225        for (int i = 0 ; i < NUM_BANDS; i++) {
226            mParameters[i].updateDisplay();
227        }
228    }
229
230    private void displayFreq(int viewId, int freq) {
231        TextView textView = (TextView)findViewById(viewId);
232        String text = Integer.toString(freq/1000)+" Hz";
233        textView.setText(text);
234    }
235
236    private class EqualizerParam extends EffectParameter {
237        private Equalizer mEqualizer;
238
239        public EqualizerParam(Equalizer equalizer, int min, int max, SeekBar seekBar, TextView textView, String unit) {
240            super (min, max, seekBar, textView, unit);
241
242            mEqualizer = equalizer;
243            updateDisplay();
244        }
245
246        @Override
247        public void setParameter(Integer value) {
248        }
249
250        @Override
251        public Integer getParameter() {
252            return new Integer(0);
253        }
254
255        @Override
256        public void setEffect(Object eq) {
257            mEqualizer = (Equalizer)eq;
258        }
259    }
260
261    private class BandLevelParam extends EqualizerParam {
262        private int mBand;
263
264        public BandLevelParam(Equalizer equalizer, int band, short min, short max, SeekBar seekBar, TextView textView) {
265            super (equalizer, min, max, seekBar, textView, "mB");
266
267            mBand = band;
268            mEqualizer = equalizer;
269            updateDisplay();
270        }
271
272        @Override
273        public void setParameter(Integer value) {
274            if (mEqualizer != null) {
275                mEqualizer.setBandLevel((short)mBand, value.shortValue());
276            }
277        }
278
279        @Override
280        public Integer getParameter() {
281            if (mEqualizer != null) {
282                return new Integer(mEqualizer.getBandLevel((short)mBand));
283            }
284            return new Integer(0);
285        }
286    }
287
288    private class PresetParam extends EqualizerParam {
289
290        public PresetParam(Equalizer equalizer, short min, short max, SeekBar seekBar, TextView textView) {
291            super (equalizer, min, max, seekBar, textView, "");
292
293            mEqualizer = equalizer;
294            updateDisplay();
295        }
296
297        @Override
298        public void setParameter(Integer value) {
299            if (mEqualizer != null) {
300                mEqualizer.usePreset(value.shortValue());
301            }
302        }
303
304        @Override
305        public Integer getParameter() {
306            if (mEqualizer != null) {
307                return new Integer(mEqualizer.getCurrentPreset());
308            }
309            return new Integer(0);
310        }
311
312        @Override
313        public void displayValue(int value, boolean fromTouch) {
314            String text = mEqualizer.getPresetName((short)value);
315            mValueText.setText(text);
316            if (!fromTouch) {
317                mSeekBar.setProgress(value - mMin);
318            } else {
319                updateBands();
320            }
321        }
322    }
323
324    public class EffectListner implements AudioEffect.OnEnableStatusChangeListener,
325    AudioEffect.OnControlStatusChangeListener,
326    Equalizer.OnParameterChangeListener
327   {
328        public EffectListner() {
329        }
330        public void onEnableStatusChange(AudioEffect effect, boolean enabled) {
331            Log.d(TAG,"onEnableStatusChange: "+ enabled);
332        }
333        public void onControlStatusChange(AudioEffect effect, boolean controlGranted) {
334            Log.d(TAG,"onControlStatusChange: "+ controlGranted);
335        }
336
337        public void onParameterChange(Equalizer effect, int status, int param1, int param2, int value) {
338            Log.d(TAG,"onParameterChange EQ, status: "+status+" p1: "+param1+" p2: "+param2+" v: "+value);
339        }
340
341        private int byteArrayToInt(byte[] valueBuf, int offset) {
342            ByteBuffer converter = ByteBuffer.wrap(valueBuf);
343            converter.order(ByteOrder.nativeOrder());
344            return converter.getInt(offset);
345
346        }
347        private short byteArrayToShort(byte[] valueBuf, int offset) {
348            ByteBuffer converter = ByteBuffer.wrap(valueBuf);
349            converter.order(ByteOrder.nativeOrder());
350            return converter.getShort(offset);
351
352        }
353    }
354
355    private void getEffect(int session) {
356        synchronized (sInstances) {
357            if (sInstances.containsKey(session)) {
358                mEqualizer = sInstances.get(session);
359            } else {
360                try{
361                    mEqualizer = new Equalizer(0, session);
362                } catch (IllegalArgumentException e) {
363                    Log.e(TAG,"Equalizer effect not supported");
364                } catch (UnsupportedOperationException e) {
365                    Log.e(TAG,"Equalizer library not loaded");
366                } catch (IllegalStateException e) {
367                    Log.e(TAG,"Equalizer cannot get presets");
368                } catch (RuntimeException e) {
369                    Log.e(TAG,"Equalizer effect not found");
370                }
371                sInstances.put(session, mEqualizer);
372            }
373        }
374        mReleaseButton.setEnabled(false);
375        mOnOffButton.setEnabled(false);
376        if (mEqualizer != null) {
377            if (mSettings != "") {
378                Log.d(TAG,"Equalizer settings: "+mSettings);
379                mEqualizer.setProperties(new Equalizer.Settings(mSettings));
380            }
381
382            mEqualizer.setEnableStatusListener(mEffectListener);
383            mEqualizer.setControlStatusListener(mEffectListener);
384            mEqualizer.setParameterListener(mEffectListener);
385
386            mReleaseButton.setChecked(true);
387            mReleaseButton.setEnabled(true);
388
389            mOnOffButton.setChecked(mEqualizer.getEnabled());
390            mOnOffButton.setEnabled(true);
391        }
392    }
393
394    private void putEffect(int session) {
395//        mOnOffButton.setChecked(false);
396        mOnOffButton.setEnabled(false);
397        synchronized (sInstances) {
398            if (mEqualizer != null) {
399                mSettings = mEqualizer.getProperties().toString();
400                mEqualizer.release();
401                Log.d(TAG,"Equalizer released, settings: "+mSettings);
402                mEqualizer = null;
403                sInstances.remove(session);
404            }
405        }
406    }
407}
408