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.SeekBar;
32import android.widget.ToggleButton;
33import android.widget.CompoundButton;
34import android.widget.CompoundButton.OnCheckedChangeListener;
35import android.widget.ImageButton;
36import android.widget.ImageView;
37import java.util.HashMap;
38import java.util.Map;
39
40import android.media.audiofx.EnvironmentalReverb;
41import android.media.audiofx.AudioEffect;
42import android.media.AudioManager;
43
44public class EnvReverbTest extends Activity implements OnCheckedChangeListener, SeekBar.OnSeekBarChangeListener {
45
46    private final static String TAG = "EnvReverbTest";
47
48    private static int NUM_PARAMS = 10;
49
50    private EffectParameter[] mParameters = new EffectParameter[NUM_PARAMS];
51    private EnvironmentalReverb mReverb;
52    ToggleButton mOnOffButton;
53    ToggleButton mReleaseButton;
54    ToggleButton mAttachButton;
55    private static HashMap<Integer, EnvironmentalReverb> sInstances = new HashMap<Integer, EnvironmentalReverb>(10);
56    static SimplePlayer sPlayerController = null;
57    SeekBar mSendLevelSeekBar;
58    TextView mSendLevelDisplay;
59    static float sSendLevel = linToExp(50,100);
60    static boolean sAttached = false;
61    String mSettings = "";
62
63    public EnvReverbTest() {
64        Log.d(TAG, "contructor");
65    }
66
67    @Override
68    public void onCreate(Bundle icicle) {
69        super.onCreate(icicle);
70        Log.d(TAG, "onCreate");
71        SeekBar seekBar;
72        TextView textView;
73        ToggleButton button;
74        setContentView(R.layout.envreverbtest);
75
76        ImageView playPause = (ImageView) findViewById(R.id.playPause1);
77        ImageView stop = (ImageView) findViewById(R.id.stop1);
78        textView = (TextView) findViewById(R.id.sessionText);
79        if (sPlayerController == null) {
80            sPlayerController = new SimplePlayer(this, R.id.playPause1, playPause,
81                    R.id.stop1, stop, textView,
82                    R.raw.mp3_sample, AudioManager.STREAM_MUSIC, 0);
83        } else {
84            sPlayerController.set(this, R.id.playPause1, playPause,
85                    R.id.stop1, stop, textView,
86                    AudioManager.STREAM_MUSIC, 0);
87        }
88
89        // send level
90        mSendLevelSeekBar = (SeekBar)findViewById(R.id.sendLevelSeekBar);
91        mSendLevelDisplay = (TextView)findViewById(R.id.sendLevelValue);
92        mSendLevelSeekBar.setMax(100);
93        mSendLevelSeekBar.setOnSeekBarChangeListener(this);
94        mSendLevelSeekBar.setProgress(expToLin(sSendLevel,100));
95        sPlayerController.setAuxEffectSendLevel(sSendLevel);
96
97        mOnOffButton = (ToggleButton)findViewById(R.id.rvbOnOff);
98        mReleaseButton = (ToggleButton)findViewById(R.id.rvbReleaseButton);
99        mAttachButton = (ToggleButton)findViewById(R.id.attachButton);
100
101        getEffect(0);
102
103        if (mReverb != null) {
104            mOnOffButton.setOnCheckedChangeListener(this);
105            mReleaseButton.setOnCheckedChangeListener(this);
106            mAttachButton.setOnCheckedChangeListener(this);
107
108//            button = (ToggleButton)findViewById(R.id.rvbBypass);
109//            button.setChecked(false);
110//            button.setOnCheckedChangeListener(this);
111
112            // Room level
113            seekBar = (SeekBar)findViewById(R.id.rvbParam1SeekBar);
114            textView = (TextView)findViewById(R.id.rvbParam1Value);
115            mParameters[0] = new RoomLevelParam(mReverb, seekBar, textView);
116            seekBar.setOnSeekBarChangeListener(mParameters[0]);
117
118            // Room HF level
119            seekBar = (SeekBar)findViewById(R.id.rvbParam2SeekBar);
120            textView = (TextView)findViewById(R.id.rvbParam2Value);
121            mParameters[1] = new RoomHFLevelParam(mReverb, seekBar, textView);
122            seekBar.setOnSeekBarChangeListener(mParameters[1]);
123
124            // Decay time
125            seekBar = (SeekBar)findViewById(R.id.rvbParam3SeekBar);
126            textView = (TextView)findViewById(R.id.rvbParam3Value);
127            mParameters[2] = new DecayTimeParam(mReverb, seekBar, textView);
128            seekBar.setOnSeekBarChangeListener(mParameters[2]);
129
130            // Decay HF ratio
131            seekBar = (SeekBar)findViewById(R.id.rvbParam4SeekBar);
132            textView = (TextView)findViewById(R.id.rvbParam4Value);
133            mParameters[3] = new DecayHFRatioParam(mReverb, seekBar, textView);
134            seekBar.setOnSeekBarChangeListener(mParameters[3]);
135
136            // Reflections level
137            seekBar = (SeekBar)findViewById(R.id.rvbParam5SeekBar);
138            textView = (TextView)findViewById(R.id.rvbParam5Value);
139            mParameters[4] = new ReflectionsLevelParam(mReverb, seekBar, textView);
140            seekBar.setOnSeekBarChangeListener(mParameters[4]);
141
142            // Reflections delay
143            seekBar = (SeekBar)findViewById(R.id.rvbParam6SeekBar);
144            textView = (TextView)findViewById(R.id.rvbParam6Value);
145            mParameters[5] = new ReflectionsDelayParam(mReverb, seekBar, textView);
146            seekBar.setOnSeekBarChangeListener(mParameters[5]);
147
148            // Reverb level
149            seekBar = (SeekBar)findViewById(R.id.rvbParam7SeekBar);
150            textView = (TextView)findViewById(R.id.rvbParam7Value);
151            mParameters[6] = new ReverbLevelParam(mReverb, seekBar, textView);
152            seekBar.setOnSeekBarChangeListener(mParameters[6]);
153
154            // Reverb delay
155            seekBar = (SeekBar)findViewById(R.id.rvbParam8SeekBar);
156            textView = (TextView)findViewById(R.id.rvbParam8Value);
157            mParameters[7] = new ReverbDelayParam(mReverb, seekBar, textView);
158            seekBar.setOnSeekBarChangeListener(mParameters[7]);
159
160            // Diffusion
161            seekBar = (SeekBar)findViewById(R.id.rvbParam9SeekBar);
162            textView = (TextView)findViewById(R.id.rvbParam9Value);
163            mParameters[8] = new DiffusionParam(mReverb, seekBar, textView);
164            seekBar.setOnSeekBarChangeListener(mParameters[8]);
165
166            // Density
167            seekBar = (SeekBar)findViewById(R.id.rvbParam10SeekBar);
168            textView = (TextView)findViewById(R.id.rvbParam10Value);
169            mParameters[9] = new DensityParam(mReverb, seekBar, textView);
170            seekBar.setOnSeekBarChangeListener(mParameters[9]);
171        }
172    }
173    @Override
174    public void onResume() {
175        super.onResume();
176        Log.d(TAG, "onResume");
177    }
178
179    @Override
180    public void onPause() {
181        super.onPause();
182    }
183
184    // OnCheckedChangeListener
185    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
186        if (buttonView.getId() == R.id.rvbOnOff) {
187            if (mReverb != null) {
188                mReverb.setEnabled(isChecked);
189                Log.d(TAG,"onCheckedChanged: rvbOnOff");
190                for (int i = 0 ; i < mParameters.length; i++) {
191                    mParameters[i].updateDisplay();
192                }
193            }
194        }
195        if (buttonView.getId() == R.id.rvbReleaseButton) {
196            if (isChecked) {
197                if (mReverb == null) {
198                    getEffect(0);
199                    for (int i = 0 ; i < mParameters.length; i++) {
200                        mParameters[i].setEffect(mReverb);
201                        mParameters[i].setEnabled(true);
202                    }
203                }
204            } else {
205                if (mReverb != null) {
206                    for (int i = 0 ; i < mParameters.length; i++) {
207                        mParameters[i].setEnabled(false);
208                    }
209                    putEffect(0);
210                }
211            }
212        }
213//        if (buttonView.getId() == R.id.rvbBypass) {
214//            // REVERB_PARAM_BYPASS parametervalue is 11 in EffectEnvironmentalReverApi.h
215//            if (mReverb != null) {
216//                if (isChecked) {
217//                    mReverb.setParameter((int)11, (int)1);
218//                } else {
219//                    mReverb.setParameter((int)11, (int)0);
220//                }
221//            }
222//        }
223        if (buttonView.getId() == R.id.attachButton) {
224            if (mReverb != null) {
225                if (isChecked) {
226                    sPlayerController.attachAuxEffect(mReverb.getId());
227                    sAttached = true;
228                } else {
229                    sPlayerController.attachAuxEffect(0);
230                    sAttached = false;
231                }
232            }
233        }
234    }
235
236    // SeekBar.OnSeekBarChangeListener
237    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
238
239        if (seekBar != mSendLevelSeekBar) {
240            Log.e(TAG, "onProgressChanged called with wrong seekBar");
241            return;
242        }
243
244        sSendLevel = linToExp(progress,100);
245        if (fromTouch) {
246            sPlayerController.setAuxEffectSendLevel(sSendLevel);
247        }
248        String text = Float.toString(sSendLevel);
249        mSendLevelDisplay.setText(text);
250        if (!fromTouch) {
251            seekBar.setProgress(progress);
252        }
253    }
254
255    static float linToExp(int lin, int range) {
256        if (lin == 0) return 0;
257        return (float)Math.pow((double)10,(double)72*(lin-range)/(20*range));
258    }
259
260    static int expToLin(float exp, int range) {
261        if (exp == 0) return 0;
262        return (int)(20*range*Math.log10((double)exp)/72 + range);
263    }
264
265    public void onStartTrackingTouch(SeekBar seekBar) {
266    }
267
268    public void onStopTrackingTouch(SeekBar seekBar) {
269    }
270
271    private class EnvReverbParam extends EffectParameter {
272        private EnvironmentalReverb mReverb;
273
274        public EnvReverbParam(EnvironmentalReverb reverb, int min, int max, SeekBar seekBar, TextView textView, String unit) {
275            super (min, max, seekBar, textView, unit);
276            mReverb = reverb;
277            updateDisplay();
278        }
279
280        @Override
281        public void setParameter(Integer value) {
282        }
283
284        @Override
285        public Integer getParameter() {
286            return new Integer(0);
287        }
288
289        @Override
290        public void setEffect(Object reverb) {
291            mReverb = (EnvironmentalReverb)reverb;
292        }
293    }
294
295    private class RoomLevelParam extends EnvReverbParam {
296
297        public RoomLevelParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) {
298            super (reverb, -9600, 0, seekBar, textView, "mB");
299        }
300
301        @Override
302        public void setParameter(Integer value) {
303            if (mReverb != null) {
304                mReverb.setRoomLevel(value.shortValue());
305            }
306        }
307
308        @Override
309        public Integer getParameter() {
310            if (mReverb != null) {
311                return new Integer(mReverb.getRoomLevel());
312            }
313            return new Integer(0);
314        }
315    }
316
317    private class RoomHFLevelParam extends EnvReverbParam {
318
319        public RoomHFLevelParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) {
320            super (reverb, -4000, 0, seekBar, textView, "mB");
321        }
322
323        @Override
324        public void setParameter(Integer value) {
325            if (mReverb != null) {
326                mReverb.setRoomHFLevel(value.shortValue());
327            }
328        }
329
330        @Override
331        public Integer getParameter() {
332            if (mReverb != null) {
333                return new Integer(mReverb.getRoomHFLevel());
334            }
335            return new Integer(0);
336        }
337    }
338
339    private class DecayTimeParam extends EnvReverbParam {
340
341        public DecayTimeParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) {
342            super (reverb, 200, 4000, seekBar, textView, "ms");
343        }
344
345        @Override
346        public void setParameter(Integer value) {
347            if (mReverb != null) {
348                mReverb.setDecayTime(value.intValue());
349            }
350        }
351
352        @Override
353        public Integer getParameter() {
354            if (mReverb != null) {
355                return mReverb.getDecayTime();
356            }
357            return new Integer(0);
358        }
359    }
360
361    private class DecayHFRatioParam extends EnvReverbParam {
362
363        public DecayHFRatioParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) {
364            super (reverb, 100, 1000, seekBar, textView, "permilles");
365        }
366
367        @Override
368        public void setParameter(Integer value) {
369            if (mReverb != null) {
370                mReverb.setDecayHFRatio(value.shortValue());
371            }
372        }
373
374        @Override
375        public Integer getParameter() {
376            if (mReverb != null) {
377                return new Integer(mReverb.getDecayHFRatio());
378            }
379            return new Integer(0);
380        }
381    }
382
383    private class ReflectionsLevelParam extends EnvReverbParam {
384
385        public ReflectionsLevelParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) {
386            super (reverb, -9600, 0, seekBar, textView, "mB");
387        }
388
389        @Override
390        public void setParameter(Integer value) {
391            if (mReverb != null) {
392                mReverb.setReflectionsLevel(value.shortValue());
393            }
394        }
395
396        @Override
397        public Integer getParameter() {
398            if (mReverb != null) {
399                return new Integer(mReverb.getReflectionsLevel());
400            }
401            return new Integer(0);
402        }
403    }
404
405    private class ReflectionsDelayParam extends EnvReverbParam {
406
407        public ReflectionsDelayParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) {
408            super (reverb, 0, 65, seekBar, textView, "ms");
409        }
410
411        @Override
412        public void setParameter(Integer value) {
413            if (mReverb != null) {
414                mReverb.setReflectionsDelay(value.intValue());
415            }
416        }
417
418        @Override
419        public Integer getParameter() {
420            if (mReverb != null) {
421                return mReverb.getReflectionsDelay();
422            }
423            return new Integer(0);
424        }
425    }
426
427    private class ReverbLevelParam extends EnvReverbParam {
428
429        public ReverbLevelParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) {
430            super (reverb, -9600, 2000, seekBar, textView, "mB");
431        }
432
433        @Override
434        public void setParameter(Integer value) {
435            if (mReverb != null) {
436                mReverb.setReverbLevel(value.shortValue());
437            }
438        }
439
440        @Override
441        public Integer getParameter() {
442            if (mReverb != null) {
443                return new Integer(mReverb.getReverbLevel());
444            }
445            return new Integer(0);
446        }
447    }
448
449    private class ReverbDelayParam extends EnvReverbParam {
450
451        public ReverbDelayParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) {
452            super (reverb, 0, 65, seekBar, textView, "ms");
453        }
454
455        @Override
456        public void setParameter(Integer value) {
457            if (mReverb != null) {
458                mReverb.setReverbDelay(value.intValue());
459            }
460        }
461
462        @Override
463        public Integer getParameter() {
464            if (mReverb != null) {
465                return mReverb.getReverbDelay();
466            }
467            return new Integer(0);
468        }
469    }
470
471    private class DiffusionParam extends EnvReverbParam {
472
473        public DiffusionParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) {
474            super (reverb, 0, 1000, seekBar, textView, "permilles");
475        }
476
477        @Override
478        public void setParameter(Integer value) {
479            if (mReverb != null) {
480                mReverb.setDiffusion(value.shortValue());
481            }
482        }
483
484        @Override
485        public Integer getParameter() {
486            if (mReverb != null) {
487                return new Integer(mReverb.getDiffusion());
488            }
489            return new Integer(0);
490        }
491    }
492
493    private class DensityParam extends EnvReverbParam {
494
495        public DensityParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) {
496            super (reverb, 0, 1000, seekBar, textView, "permilles");
497        }
498
499        @Override
500        public void setParameter(Integer value) {
501            if (mReverb != null) {
502                mReverb.setDensity(value.shortValue());
503            }
504        }
505
506        @Override
507        public Integer getParameter() {
508            if (mReverb != null) {
509                return new Integer(mReverb.getDensity());
510            }
511            return new Integer(0);
512        }
513    }
514
515    private void getEffect(int session) {
516        synchronized (sInstances) {
517            if (sInstances.containsKey(session)) {
518                mReverb = sInstances.get(session);
519            } else {
520                try{
521                    mReverb = new EnvironmentalReverb(0, session);
522                } catch (IllegalArgumentException e) {
523                    Log.e(TAG,"Reverb effect not supported");
524                } catch (UnsupportedOperationException e) {
525                    Log.e(TAG,"Reverb library not loaded");
526                } catch (RuntimeException e) {
527                    Log.e(TAG,"Reverb effect not found");
528                }
529                Log.d(TAG, "new reverb: "+mReverb);
530                sInstances.put(session, mReverb);
531            }
532        }
533        mReleaseButton.setEnabled(false);
534        mOnOffButton.setEnabled(false);
535        mAttachButton.setEnabled(false);
536        if (mReverb != null) {
537            if (mSettings != "") {
538                mReverb.setProperties(new EnvironmentalReverb.Settings(mSettings));
539            }
540            mReleaseButton.setChecked(true);
541            mReleaseButton.setEnabled(true);
542            mOnOffButton.setChecked(mReverb.getEnabled());
543            mOnOffButton.setEnabled(true);
544            mAttachButton.setChecked(false);
545            mAttachButton.setEnabled(true);
546            if (sAttached) {
547                mAttachButton.setChecked(true);
548                sPlayerController.attachAuxEffect(mReverb.getId());
549            }
550        }
551    }
552
553    private void putEffect(int session) {
554        mOnOffButton.setChecked(false);
555        mOnOffButton.setEnabled(false);
556        mAttachButton.setChecked(false);
557        mAttachButton.setEnabled(false);
558        synchronized (sInstances) {
559            if (mReverb != null) {
560                mSettings = mReverb.getProperties().toString();
561                mReverb.release();
562                Log.d(TAG,"Reverb released, settings: "+mSettings);
563                mReverb = null;
564                sInstances.remove(session);
565            }
566        }
567    }
568}
569