diff options
Diffstat (limited to 'media/tests/EffectsTest/src/com')
9 files changed, 2587 insertions, 0 deletions
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/BassBoostTest.java b/media/tests/EffectsTest/src/com/android/effectstest/BassBoostTest.java new file mode 100755 index 0000000..1a10d64 --- /dev/null +++ b/media/tests/EffectsTest/src/com/android/effectstest/BassBoostTest.java @@ -0,0 +1,276 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.effectstest; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.View.OnClickListener; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; +import android.widget.EditText; +import android.widget.SeekBar; +import android.widget.ToggleButton; +import android.widget.CompoundButton; +import android.widget.CompoundButton.OnCheckedChangeListener; +import java.nio.ByteOrder; +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; + +import android.media.audiofx.BassBoost; +import android.media.audiofx.AudioEffect; + +public class BassBoostTest extends Activity implements OnCheckedChangeListener { + + private final static String TAG = "BassBoostTest"; + + private static int NUM_PARAMS = 1; + + private EffectParameter mStrength; + private BassBoost mBassBoost = null; + ToggleButton mOnOffButton; + ToggleButton mReleaseButton; + EditText mSessionText; + static int sSession = 0; + EffectListner mEffectListener = new EffectListner(); + private static HashMap<Integer, BassBoost> sInstances = new HashMap<Integer, BassBoost>(10); + String mSettings = ""; + + public BassBoostTest() { + Log.d(TAG, "contructor"); + } + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + SeekBar seekBar; + TextView textView; + + setContentView(R.layout.bassboosttest); + + mSessionText = (EditText) findViewById(R.id.sessionEdit); + mSessionText.setOnKeyListener(mSessionKeyListener); + + mSessionText.setText(Integer.toString(sSession)); + + mReleaseButton = (ToggleButton)findViewById(R.id.bbReleaseButton); + mOnOffButton = (ToggleButton)findViewById(R.id.bassboostOnOff); + + getEffect(sSession); + + if (mBassBoost != null) { + mReleaseButton.setOnCheckedChangeListener(this); + mOnOffButton.setOnCheckedChangeListener(this); + + textView = (TextView)findViewById(R.id.bbStrengthMin); + textView.setText("0"); + textView = (TextView)findViewById(R.id.bbStrengthMax); + textView.setText("1000"); + seekBar = (SeekBar)findViewById(R.id.bbStrengthSeekBar); + textView = (TextView)findViewById(R.id.bbStrengthValue); + mStrength = new BassBoostParam(mBassBoost, 0, 1000, seekBar, textView); + seekBar.setOnSeekBarChangeListener(mStrength); + mStrength.setEnabled(mBassBoost.getStrengthSupported()); + } + } + + @Override + public void onResume() { + super.onResume(); + } + + @Override + public void onPause() { + super.onPause(); + } + + private View.OnKeyListener mSessionKeyListener + = new View.OnKeyListener() { + public boolean onKey(View v, int keyCode, KeyEvent event) { + Log.d(TAG, "onKey() keyCode: "+keyCode+" event.getAction(): "+event.getAction()); + if (event.getAction() == KeyEvent.ACTION_DOWN) { + switch (keyCode) { + case KeyEvent.KEYCODE_DPAD_CENTER: + case KeyEvent.KEYCODE_ENTER: + try { + sSession = Integer.parseInt(mSessionText.getText().toString()); + getEffect(sSession); + if (mBassBoost != null) { + mStrength.setEffect(mBassBoost); + mStrength.setEnabled(mBassBoost.getStrengthSupported()); + } + } catch (NumberFormatException e) { + Log.d(TAG, "Invalid session #: "+mSessionText.getText().toString()); + } + return true; + } + } + return false; + } + }; + + // OnCheckedChangeListener + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (buttonView.getId() == R.id.bassboostOnOff) { + if (mBassBoost != null) { + mBassBoost.setEnabled(isChecked); + mStrength.updateDisplay(); + } + } + if (buttonView.getId() == R.id.bbReleaseButton) { + if (isChecked) { + if (mBassBoost == null) { + getEffect(sSession); + if (mBassBoost != null) { + mStrength.setEffect(mBassBoost); + mStrength.setEnabled(mBassBoost.getStrengthSupported()); + } + } + } else { + if (mBassBoost != null) { + mStrength.setEnabled(false); + putEffect(sSession); + } + } + } + } + + private class BassBoostParam extends EffectParameter { + private BassBoost mBassBoost; + + public BassBoostParam(BassBoost bassboost, int min, int max, SeekBar seekBar, TextView textView) { + super (min, max, seekBar, textView, "o/oo"); + + mBassBoost = bassboost; + updateDisplay(); + } + + @Override + public void setParameter(Integer value) { + if (mBassBoost != null) { + mBassBoost.setStrength(value.shortValue()); + } + } + + @Override + public Integer getParameter() { + if (mBassBoost != null) { + return new Integer(mBassBoost.getRoundedStrength()); + } + return new Integer(0); + } + + @Override + public void setEffect(Object effect) { + mBassBoost = (BassBoost)effect; + } + } + + public class EffectListner implements AudioEffect.OnEnableStatusChangeListener, + AudioEffect.OnControlStatusChangeListener, AudioEffect.OnParameterChangeListener + { + public EffectListner() { + } + public void onEnableStatusChange(AudioEffect effect, boolean enabled) { + Log.d(TAG,"onEnableStatusChange: "+ enabled); + } + public void onControlStatusChange(AudioEffect effect, boolean controlGranted) { + Log.d(TAG,"onControlStatusChange: "+ controlGranted); + } + public void onParameterChange(AudioEffect effect, int status, byte[] param, byte[] value) { + int p = byteArrayToInt(param, 0); + short v = byteArrayToShort(value, 0); + + Log.d(TAG,"onParameterChange, status: "+status+" p: "+p+" v: "+v); + } + + private int byteArrayToInt(byte[] valueBuf, int offset) { + ByteBuffer converter = ByteBuffer.wrap(valueBuf); + converter.order(ByteOrder.nativeOrder()); + return converter.getInt(offset); + + } + private short byteArrayToShort(byte[] valueBuf, int offset) { + ByteBuffer converter = ByteBuffer.wrap(valueBuf); + converter.order(ByteOrder.nativeOrder()); + return converter.getShort(offset); + + } + + } + + private void getEffect(int session) { + synchronized (sInstances) { + if (sInstances.containsKey(session)) { + mBassBoost = sInstances.get(session); + } else { + try{ + mBassBoost = new BassBoost(0, session); + } catch (IllegalArgumentException e) { + Log.e(TAG,"BassBoost effect not supported"); + } catch (IllegalStateException e) { + Log.e(TAG,"BassBoost cannot get strength supported"); + } catch (UnsupportedOperationException e) { + Log.e(TAG,"BassBoost library not loaded"); + } catch (RuntimeException e) { + Log.e(TAG,"BassBoost effect not found"); + } + sInstances.put(session, mBassBoost); + } + mReleaseButton.setEnabled(false); + mOnOffButton.setEnabled(false); + + if (mBassBoost != null) { + if (mSettings != "") { + mBassBoost.setProperties(new BassBoost.Settings(mSettings)); + } + mBassBoost.setEnableStatusListener(mEffectListener); + mBassBoost.setControlStatusListener(mEffectListener); + mBassBoost.setParameterListener(mEffectListener); + + mReleaseButton.setChecked(true); + mReleaseButton.setEnabled(true); + + mOnOffButton.setChecked(mBassBoost.getEnabled()); + mOnOffButton.setEnabled(true); + } + } + } + + private void putEffect(int session) { + mOnOffButton.setChecked(false); + mOnOffButton.setEnabled(false); + synchronized (sInstances) { + if (mBassBoost != null) { + mSettings = mBassBoost.getProperties().toString(); + mBassBoost.release(); + Log.d(TAG,"BassBoost released"); + mBassBoost = null; + sInstances.remove(session); + } + } + } + +} diff --git a/media/tests/EffectsTest/src/com/android/effectstest/EffectParameter.java b/media/tests/EffectsTest/src/com/android/effectstest/EffectParameter.java new file mode 100755 index 0000000..95077e7 --- /dev/null +++ b/media/tests/EffectsTest/src/com/android/effectstest/EffectParameter.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.effectstest; + +import android.os.Bundle; +import android.util.Log; +import android.widget.TextView; +import android.widget.SeekBar; + + +abstract class EffectParameter implements SeekBar.OnSeekBarChangeListener { + + private final static String TAG = "EffectParameter"; + + protected int mMin; + protected int mMax; + protected String mUnit; + protected SeekBar mSeekBar; + protected TextView mValueText; + + public EffectParameter (int min, int max, SeekBar seekBar, TextView textView, String unit) { + mMin = min; + mMax = max; + mSeekBar = seekBar; + mValueText = textView; + mUnit = unit; + byte[] paramBuf = new byte[4]; + + mSeekBar.setMax(max-min); + } + + public void displayValue(int value, boolean fromTouch) { + String text = Integer.toString(value)+" "+mUnit; + mValueText.setText(text); + if (!fromTouch) { + mSeekBar.setProgress(value - mMin); + } + } + + public void updateDisplay() { + displayValue(getParameter(), false); + } + + public abstract void setParameter(Integer value); + + public abstract Integer getParameter(); + + public abstract void setEffect(Object effect); + + // SeekBar.OnSeekBarChangeListener + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) { + + if (seekBar != mSeekBar) { + Log.e(TAG, "onProgressChanged called with wrong seekBar"); + return; + } + + int value = progress + mMin; + if (fromTouch) { + setParameter(value); + } + + displayValue(getParameter(), fromTouch); + } + + public void onStartTrackingTouch(SeekBar seekBar) { + } + + public void onStopTrackingTouch(SeekBar seekBar) { + } + + public void setEnabled(boolean e) { + mSeekBar.setEnabled(e); + } +} diff --git a/media/tests/EffectsTest/src/com/android/effectstest/EffectsTest.java b/media/tests/EffectsTest/src/com/android/effectstest/EffectsTest.java new file mode 100755 index 0000000..6612766 --- /dev/null +++ b/media/tests/EffectsTest/src/com/android/effectstest/EffectsTest.java @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.effectstest; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.View.OnClickListener; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; +import android.widget.ListView; +import android.widget.BaseAdapter; +import android.widget.LinearLayout; +import android.media.audiofx.AudioEffect; +import java.util.UUID; + +public class EffectsTest extends Activity { + + private final static String TAG = "EffectsTest"; + + + public EffectsTest() { + Log.d(TAG, "contructor"); + } + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + setContentView(R.layout.effectstest); + + Button button = (Button) findViewById(R.id.env_reverb_actvity); + button.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + startActivity(new Intent(EffectsTest.this, EnvReverbTest.class)); + } + }); + + button = (Button) findViewById(R.id.preset_reverb_actvity); + button.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + startActivity(new Intent(EffectsTest.this, PresetReverbTest.class)); + } + }); + + button = (Button) findViewById(R.id.equalizer_actvity); + button.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + startActivity(new Intent(EffectsTest.this, EqualizerTest.class)); + } + }); + + button = (Button) findViewById(R.id.virtualizer_actvity); + button.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + startActivity(new Intent(EffectsTest.this, VirtualizerTest.class)); + } + }); + + button = (Button) findViewById(R.id.bassboost_actvity); + button.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + startActivity(new Intent(EffectsTest.this, BassBoostTest.class)); + } + }); + + button = (Button) findViewById(R.id.visualizer_actvity); + button.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + startActivity(new Intent(EffectsTest.this, VisualizerTest.class)); + } + }); + + AudioEffect.Descriptor[] descriptors = AudioEffect.queryEffects(); + + ListView list = (ListView) findViewById(R.id.effect_list); + list.setAdapter(new EffectListAdapter(this, descriptors)); + + } + + private class EffectListAdapter extends BaseAdapter { + + private Context mContext; + + AudioEffect.Descriptor[] mDescriptors; + + public EffectListAdapter(Context context, AudioEffect.Descriptor[] descriptors) { + Log.d(TAG, "EffectListAdapter contructor"); + mContext = context; + mDescriptors = descriptors; + for (int i = 0; i < mDescriptors.length; i++) { + Log.d(TAG, "Effect: "+i+" name: "+ mDescriptors[i].name); + } + } + + public int getCount() { + Log.d(TAG, "EffectListAdapter getCount(): "+mDescriptors.length); + return mDescriptors.length; + } + + public Object getItem(int position) { + Log.d(TAG, "EffectListAdapter getItem() at: "+position+" name: " + +mDescriptors[position].name); + return mDescriptors[position]; + } + + public long getItemId(int position) { + return position; + } + + public View getView(int position, View convertView, ViewGroup parent) { + EffectView ev; + if (convertView == null) { + Log.d(TAG, "getView() new EffectView position: " + position); + ev = new EffectView(mContext, mDescriptors); + } else { + Log.d(TAG, "getView() convertView position: " + position); + ev = new EffectView(mContext, mDescriptors); + //ev = (EffectView) convertView; + } + ev.set(position); + return ev; + } + } + + private class EffectView extends LinearLayout { + private Context mContext; + AudioEffect.Descriptor[] mDescriptors; + + public EffectView(Context context, AudioEffect.Descriptor[] descriptors) { + super(context); + + mContext = context; + mDescriptors = descriptors; + this.setOrientation(VERTICAL); + } + + public void set(int position) { + TextView tv = new TextView(mContext); + tv.setText("Effect "+ position); + addView(tv, new LinearLayout.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); + tv = new TextView(mContext); + tv.setText(" type: "+ mDescriptors[position].type.toString()); + addView(tv, new LinearLayout.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); + tv = new TextView(mContext); + tv.setText(" uuid: "+ mDescriptors[position].uuid.toString()); + addView(tv, new LinearLayout.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); + tv = new TextView(mContext); + tv.setText(" name: "+ mDescriptors[position].name); + addView(tv, new LinearLayout.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); + tv = new TextView(mContext); + tv.setText(" vendor: "+ mDescriptors[position].implementor); + addView(tv, new LinearLayout.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); + tv = new TextView(mContext); + tv.setText(" mode: "+ mDescriptors[position].connectMode); + addView(tv, new LinearLayout.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); + } + } + +} diff --git a/media/tests/EffectsTest/src/com/android/effectstest/EnvReverbTest.java b/media/tests/EffectsTest/src/com/android/effectstest/EnvReverbTest.java new file mode 100755 index 0000000..594e844 --- /dev/null +++ b/media/tests/EffectsTest/src/com/android/effectstest/EnvReverbTest.java @@ -0,0 +1,568 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.effectstest; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.View.OnClickListener; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; +import android.widget.SeekBar; +import android.widget.ToggleButton; +import android.widget.CompoundButton; +import android.widget.CompoundButton.OnCheckedChangeListener; +import android.widget.ImageButton; +import android.widget.ImageView; +import java.util.HashMap; +import java.util.Map; + +import android.media.audiofx.EnvironmentalReverb; +import android.media.audiofx.AudioEffect; +import android.media.AudioManager; + +public class EnvReverbTest extends Activity implements OnCheckedChangeListener, SeekBar.OnSeekBarChangeListener { + + private final static String TAG = "EnvReverbTest"; + + private static int NUM_PARAMS = 10; + + private EffectParameter[] mParameters = new EffectParameter[NUM_PARAMS]; + private EnvironmentalReverb mReverb; + ToggleButton mOnOffButton; + ToggleButton mReleaseButton; + ToggleButton mAttachButton; + private static HashMap<Integer, EnvironmentalReverb> sInstances = new HashMap<Integer, EnvironmentalReverb>(10); + static SimplePlayer sPlayerController = null; + SeekBar mSendLevelSeekBar; + TextView mSendLevelDisplay; + static float sSendLevel = linToExp(50,100); + static boolean sAttached = false; + String mSettings = ""; + + public EnvReverbTest() { + Log.d(TAG, "contructor"); + } + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + Log.d(TAG, "onCreate"); + SeekBar seekBar; + TextView textView; + ToggleButton button; + setContentView(R.layout.envreverbtest); + + ImageView playPause = (ImageView) findViewById(R.id.playPause1); + ImageView stop = (ImageView) findViewById(R.id.stop1); + textView = (TextView) findViewById(R.id.sessionText); + if (sPlayerController == null) { + sPlayerController = new SimplePlayer(this, R.id.playPause1, playPause, + R.id.stop1, stop, textView, + R.raw.mp3_sample, AudioManager.STREAM_MUSIC, 0); + } else { + sPlayerController.set(this, R.id.playPause1, playPause, + R.id.stop1, stop, textView, + AudioManager.STREAM_MUSIC, 0); + } + + // send level + mSendLevelSeekBar = (SeekBar)findViewById(R.id.sendLevelSeekBar); + mSendLevelDisplay = (TextView)findViewById(R.id.sendLevelValue); + mSendLevelSeekBar.setMax(100); + mSendLevelSeekBar.setOnSeekBarChangeListener(this); + mSendLevelSeekBar.setProgress(expToLin(sSendLevel,100)); + sPlayerController.setAuxEffectSendLevel(sSendLevel); + + mOnOffButton = (ToggleButton)findViewById(R.id.rvbOnOff); + mReleaseButton = (ToggleButton)findViewById(R.id.rvbReleaseButton); + mAttachButton = (ToggleButton)findViewById(R.id.attachButton); + + getEffect(0); + + if (mReverb != null) { + mOnOffButton.setOnCheckedChangeListener(this); + mReleaseButton.setOnCheckedChangeListener(this); + mAttachButton.setOnCheckedChangeListener(this); + +// button = (ToggleButton)findViewById(R.id.rvbBypass); +// button.setChecked(false); +// button.setOnCheckedChangeListener(this); + + // Room level + seekBar = (SeekBar)findViewById(R.id.rvbParam1SeekBar); + textView = (TextView)findViewById(R.id.rvbParam1Value); + mParameters[0] = new RoomLevelParam(mReverb, seekBar, textView); + seekBar.setOnSeekBarChangeListener(mParameters[0]); + + // Room HF level + seekBar = (SeekBar)findViewById(R.id.rvbParam2SeekBar); + textView = (TextView)findViewById(R.id.rvbParam2Value); + mParameters[1] = new RoomHFLevelParam(mReverb, seekBar, textView); + seekBar.setOnSeekBarChangeListener(mParameters[1]); + + // Decay time + seekBar = (SeekBar)findViewById(R.id.rvbParam3SeekBar); + textView = (TextView)findViewById(R.id.rvbParam3Value); + mParameters[2] = new DecayTimeParam(mReverb, seekBar, textView); + seekBar.setOnSeekBarChangeListener(mParameters[2]); + + // Decay HF ratio + seekBar = (SeekBar)findViewById(R.id.rvbParam4SeekBar); + textView = (TextView)findViewById(R.id.rvbParam4Value); + mParameters[3] = new DecayHFRatioParam(mReverb, seekBar, textView); + seekBar.setOnSeekBarChangeListener(mParameters[3]); + + // Reflections level + seekBar = (SeekBar)findViewById(R.id.rvbParam5SeekBar); + textView = (TextView)findViewById(R.id.rvbParam5Value); + mParameters[4] = new ReflectionsLevelParam(mReverb, seekBar, textView); + seekBar.setOnSeekBarChangeListener(mParameters[4]); + + // Reflections delay + seekBar = (SeekBar)findViewById(R.id.rvbParam6SeekBar); + textView = (TextView)findViewById(R.id.rvbParam6Value); + mParameters[5] = new ReflectionsDelayParam(mReverb, seekBar, textView); + seekBar.setOnSeekBarChangeListener(mParameters[5]); + + // Reverb level + seekBar = (SeekBar)findViewById(R.id.rvbParam7SeekBar); + textView = (TextView)findViewById(R.id.rvbParam7Value); + mParameters[6] = new ReverbLevelParam(mReverb, seekBar, textView); + seekBar.setOnSeekBarChangeListener(mParameters[6]); + + // Reverb delay + seekBar = (SeekBar)findViewById(R.id.rvbParam8SeekBar); + textView = (TextView)findViewById(R.id.rvbParam8Value); + mParameters[7] = new ReverbDelayParam(mReverb, seekBar, textView); + seekBar.setOnSeekBarChangeListener(mParameters[7]); + + // Diffusion + seekBar = (SeekBar)findViewById(R.id.rvbParam9SeekBar); + textView = (TextView)findViewById(R.id.rvbParam9Value); + mParameters[8] = new DiffusionParam(mReverb, seekBar, textView); + seekBar.setOnSeekBarChangeListener(mParameters[8]); + + // Density + seekBar = (SeekBar)findViewById(R.id.rvbParam10SeekBar); + textView = (TextView)findViewById(R.id.rvbParam10Value); + mParameters[9] = new DensityParam(mReverb, seekBar, textView); + seekBar.setOnSeekBarChangeListener(mParameters[9]); + } + } + @Override + public void onResume() { + super.onResume(); + Log.d(TAG, "onResume"); + } + + @Override + public void onPause() { + super.onPause(); + } + + // OnCheckedChangeListener + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (buttonView.getId() == R.id.rvbOnOff) { + if (mReverb != null) { + mReverb.setEnabled(isChecked); + Log.d(TAG,"onCheckedChanged: rvbOnOff"); + for (int i = 0 ; i < mParameters.length; i++) { + mParameters[i].updateDisplay(); + } + } + } + if (buttonView.getId() == R.id.rvbReleaseButton) { + if (isChecked) { + if (mReverb == null) { + getEffect(0); + for (int i = 0 ; i < mParameters.length; i++) { + mParameters[i].setEffect(mReverb); + mParameters[i].setEnabled(true); + } + } + } else { + if (mReverb != null) { + for (int i = 0 ; i < mParameters.length; i++) { + mParameters[i].setEnabled(false); + } + putEffect(0); + } + } + } +// if (buttonView.getId() == R.id.rvbBypass) { +// // REVERB_PARAM_BYPASS parametervalue is 11 in EffectEnvironmentalReverApi.h +// if (mReverb != null) { +// if (isChecked) { +// mReverb.setParameter((int)11, (int)1); +// } else { +// mReverb.setParameter((int)11, (int)0); +// } +// } +// } + if (buttonView.getId() == R.id.attachButton) { + if (mReverb != null) { + if (isChecked) { + sPlayerController.attachAuxEffect(mReverb.getId()); + sAttached = true; + } else { + sPlayerController.attachAuxEffect(0); + sAttached = false; + } + } + } + } + + // SeekBar.OnSeekBarChangeListener + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) { + + if (seekBar != mSendLevelSeekBar) { + Log.e(TAG, "onProgressChanged called with wrong seekBar"); + return; + } + + sSendLevel = linToExp(progress,100); + if (fromTouch) { + sPlayerController.setAuxEffectSendLevel(sSendLevel); + } + String text = Float.toString(sSendLevel); + mSendLevelDisplay.setText(text); + if (!fromTouch) { + seekBar.setProgress(progress); + } + } + + static float linToExp(int lin, int range) { + if (lin == 0) return 0; + return (float)Math.pow((double)10,(double)72*(lin-range)/(20*range)); + } + + static int expToLin(float exp, int range) { + if (exp == 0) return 0; + return (int)(20*range*Math.log10((double)exp)/72 + range); + } + + public void onStartTrackingTouch(SeekBar seekBar) { + } + + public void onStopTrackingTouch(SeekBar seekBar) { + } + + private class EnvReverbParam extends EffectParameter { + private EnvironmentalReverb mReverb; + + public EnvReverbParam(EnvironmentalReverb reverb, int min, int max, SeekBar seekBar, TextView textView, String unit) { + super (min, max, seekBar, textView, unit); + mReverb = reverb; + updateDisplay(); + } + + @Override + public void setParameter(Integer value) { + } + + @Override + public Integer getParameter() { + return new Integer(0); + } + + @Override + public void setEffect(Object reverb) { + mReverb = (EnvironmentalReverb)reverb; + } + } + + private class RoomLevelParam extends EnvReverbParam { + + public RoomLevelParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) { + super (reverb, -9600, 0, seekBar, textView, "mB"); + } + + @Override + public void setParameter(Integer value) { + if (mReverb != null) { + mReverb.setRoomLevel(value.shortValue()); + } + } + + @Override + public Integer getParameter() { + if (mReverb != null) { + return new Integer(mReverb.getRoomLevel()); + } + return new Integer(0); + } + } + + private class RoomHFLevelParam extends EnvReverbParam { + + public RoomHFLevelParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) { + super (reverb, -4000, 0, seekBar, textView, "mB"); + } + + @Override + public void setParameter(Integer value) { + if (mReverb != null) { + mReverb.setRoomHFLevel(value.shortValue()); + } + } + + @Override + public Integer getParameter() { + if (mReverb != null) { + return new Integer(mReverb.getRoomHFLevel()); + } + return new Integer(0); + } + } + + private class DecayTimeParam extends EnvReverbParam { + + public DecayTimeParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) { + super (reverb, 200, 4000, seekBar, textView, "ms"); + } + + @Override + public void setParameter(Integer value) { + if (mReverb != null) { + mReverb.setDecayTime(value.intValue()); + } + } + + @Override + public Integer getParameter() { + if (mReverb != null) { + return mReverb.getDecayTime(); + } + return new Integer(0); + } + } + + private class DecayHFRatioParam extends EnvReverbParam { + + public DecayHFRatioParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) { + super (reverb, 100, 1000, seekBar, textView, "permilles"); + } + + @Override + public void setParameter(Integer value) { + if (mReverb != null) { + mReverb.setDecayHFRatio(value.shortValue()); + } + } + + @Override + public Integer getParameter() { + if (mReverb != null) { + return new Integer(mReverb.getDecayHFRatio()); + } + return new Integer(0); + } + } + + private class ReflectionsLevelParam extends EnvReverbParam { + + public ReflectionsLevelParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) { + super (reverb, -9600, 0, seekBar, textView, "mB"); + } + + @Override + public void setParameter(Integer value) { + if (mReverb != null) { + mReverb.setReflectionsLevel(value.shortValue()); + } + } + + @Override + public Integer getParameter() { + if (mReverb != null) { + return new Integer(mReverb.getReflectionsLevel()); + } + return new Integer(0); + } + } + + private class ReflectionsDelayParam extends EnvReverbParam { + + public ReflectionsDelayParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) { + super (reverb, 0, 65, seekBar, textView, "ms"); + } + + @Override + public void setParameter(Integer value) { + if (mReverb != null) { + mReverb.setReflectionsDelay(value.intValue()); + } + } + + @Override + public Integer getParameter() { + if (mReverb != null) { + return mReverb.getReflectionsDelay(); + } + return new Integer(0); + } + } + + private class ReverbLevelParam extends EnvReverbParam { + + public ReverbLevelParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) { + super (reverb, -9600, 2000, seekBar, textView, "mB"); + } + + @Override + public void setParameter(Integer value) { + if (mReverb != null) { + mReverb.setReverbLevel(value.shortValue()); + } + } + + @Override + public Integer getParameter() { + if (mReverb != null) { + return new Integer(mReverb.getReverbLevel()); + } + return new Integer(0); + } + } + + private class ReverbDelayParam extends EnvReverbParam { + + public ReverbDelayParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) { + super (reverb, 0, 65, seekBar, textView, "ms"); + } + + @Override + public void setParameter(Integer value) { + if (mReverb != null) { + mReverb.setReverbDelay(value.intValue()); + } + } + + @Override + public Integer getParameter() { + if (mReverb != null) { + return mReverb.getReverbDelay(); + } + return new Integer(0); + } + } + + private class DiffusionParam extends EnvReverbParam { + + public DiffusionParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) { + super (reverb, 0, 1000, seekBar, textView, "permilles"); + } + + @Override + public void setParameter(Integer value) { + if (mReverb != null) { + mReverb.setDiffusion(value.shortValue()); + } + } + + @Override + public Integer getParameter() { + if (mReverb != null) { + return new Integer(mReverb.getDiffusion()); + } + return new Integer(0); + } + } + + private class DensityParam extends EnvReverbParam { + + public DensityParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) { + super (reverb, 0, 1000, seekBar, textView, "permilles"); + } + + @Override + public void setParameter(Integer value) { + if (mReverb != null) { + mReverb.setDensity(value.shortValue()); + } + } + + @Override + public Integer getParameter() { + if (mReverb != null) { + return new Integer(mReverb.getDensity()); + } + return new Integer(0); + } + } + + private void getEffect(int session) { + synchronized (sInstances) { + if (sInstances.containsKey(session)) { + mReverb = sInstances.get(session); + } else { + try{ + mReverb = new EnvironmentalReverb(0, session); + } catch (IllegalArgumentException e) { + Log.e(TAG,"Reverb effect not supported"); + } catch (UnsupportedOperationException e) { + Log.e(TAG,"Reverb library not loaded"); + } catch (RuntimeException e) { + Log.e(TAG,"Reverb effect not found"); + } + Log.d(TAG, "new reverb: "+mReverb); + sInstances.put(session, mReverb); + } + } + mReleaseButton.setEnabled(false); + mOnOffButton.setEnabled(false); + mAttachButton.setEnabled(false); + if (mReverb != null) { + if (mSettings != "") { + mReverb.setProperties(new EnvironmentalReverb.Settings(mSettings)); + } + mReleaseButton.setChecked(true); + mReleaseButton.setEnabled(true); + mOnOffButton.setChecked(mReverb.getEnabled()); + mOnOffButton.setEnabled(true); + mAttachButton.setChecked(false); + mAttachButton.setEnabled(true); + if (sAttached) { + mAttachButton.setChecked(true); + sPlayerController.attachAuxEffect(mReverb.getId()); + } + } + } + + private void putEffect(int session) { + mOnOffButton.setChecked(false); + mOnOffButton.setEnabled(false); + mAttachButton.setChecked(false); + mAttachButton.setEnabled(false); + synchronized (sInstances) { + if (mReverb != null) { + mSettings = mReverb.getProperties().toString(); + mReverb.release(); + Log.d(TAG,"Reverb released, settings: "+mSettings); + mReverb = null; + sInstances.remove(session); + } + } + } +} diff --git a/media/tests/EffectsTest/src/com/android/effectstest/EqualizerTest.java b/media/tests/EffectsTest/src/com/android/effectstest/EqualizerTest.java new file mode 100755 index 0000000..f30a26f --- /dev/null +++ b/media/tests/EffectsTest/src/com/android/effectstest/EqualizerTest.java @@ -0,0 +1,407 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.effectstest; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.View.OnClickListener; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; +import android.widget.EditText; +import android.widget.SeekBar; +import android.widget.ToggleButton; +import android.widget.CompoundButton; +import android.widget.CompoundButton.OnCheckedChangeListener; +import java.nio.ByteOrder; +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; + + +import android.media.audiofx.Equalizer; +import android.media.audiofx.AudioEffect; + +public class EqualizerTest extends Activity implements OnCheckedChangeListener { + + private final static String TAG = "EqualizerTest"; + + private static int NUM_BANDS = 5; + private static int NUM_PARAMS = NUM_BANDS + 1; + + private EffectParameter[] mParameters = new EffectParameter[NUM_PARAMS]; + private Equalizer mEqualizer; + ToggleButton mOnOffButton; + ToggleButton mReleaseButton; + EditText mSessionText; + static int sSession = 0; + EffectListner mEffectListener = new EffectListner(); + private static HashMap<Integer, Equalizer> sInstances = new HashMap<Integer, Equalizer>(10); + String mSettings = ""; + + public EqualizerTest() { + Log.d(TAG, "contructor"); + } + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + SeekBar seekBar; + TextView textView; + + setContentView(R.layout.equalizertest); + + mSessionText = (EditText) findViewById(R.id.sessionEdit); + mSessionText.setOnKeyListener(mSessionKeyListener); + + mSessionText.setText(Integer.toString(sSession)); + + mReleaseButton = (ToggleButton)findViewById(R.id.eqReleaseButton); + mOnOffButton = (ToggleButton)findViewById(R.id.equalizerOnOff); + + getEffect(sSession); + + if (mEqualizer != null) { + mReleaseButton.setOnCheckedChangeListener(this); + mOnOffButton.setOnCheckedChangeListener(this); + + short[] bandLevelRange = mEqualizer.getBandLevelRange(); + int centerFreq; + int []freqRange; + + // Band 1 level + centerFreq = mEqualizer.getCenterFreq((short)0); + freqRange = mEqualizer.getBandFreqRange((short)0); + displayFreq(R.id.eqParam1Center, centerFreq); + displayFreq(R.id.eqParam1Min, freqRange[0]); + displayFreq(R.id.eqParam1Max, freqRange[1]); + seekBar = (SeekBar)findViewById(R.id.eqParam1SeekBar); + textView = (TextView)findViewById(R.id.eqParam1Value); + mParameters[0] = new BandLevelParam(mEqualizer, 0, bandLevelRange[0], bandLevelRange[1], seekBar, textView); + seekBar.setOnSeekBarChangeListener(mParameters[0]); + + // Band 2 level + centerFreq = mEqualizer.getCenterFreq((short)1); + freqRange = mEqualizer.getBandFreqRange((short)1); + displayFreq(R.id.eqParam2Center, centerFreq); + displayFreq(R.id.eqParam2Min, freqRange[0]); + displayFreq(R.id.eqParam2Max, freqRange[1]); + seekBar = (SeekBar)findViewById(R.id.eqParam2SeekBar); + textView = (TextView)findViewById(R.id.eqParam2Value); + mParameters[1] = new BandLevelParam(mEqualizer, 1, bandLevelRange[0], bandLevelRange[1], seekBar, textView); + seekBar.setOnSeekBarChangeListener(mParameters[1]); + + // Band 3 level + centerFreq = mEqualizer.getCenterFreq((short)2); + freqRange = mEqualizer.getBandFreqRange((short)2); + displayFreq(R.id.eqParam3Center, centerFreq); + displayFreq(R.id.eqParam3Min, freqRange[0]); + displayFreq(R.id.eqParam3Max, freqRange[1]); + seekBar = (SeekBar)findViewById(R.id.eqParam3SeekBar); + textView = (TextView)findViewById(R.id.eqParam3Value); + mParameters[2] = new BandLevelParam(mEqualizer, 2, bandLevelRange[0], bandLevelRange[1], seekBar, textView); + seekBar.setOnSeekBarChangeListener(mParameters[2]); + + // Band 4 level + centerFreq = mEqualizer.getCenterFreq((short)3); + freqRange = mEqualizer.getBandFreqRange((short)3); + displayFreq(R.id.eqParam4Center, centerFreq); + displayFreq(R.id.eqParam4Min, freqRange[0]); + displayFreq(R.id.eqParam4Max, freqRange[1]); + seekBar = (SeekBar)findViewById(R.id.eqParam4SeekBar); + textView = (TextView)findViewById(R.id.eqParam4Value); + mParameters[3] = new BandLevelParam(mEqualizer, 3, bandLevelRange[0], bandLevelRange[1], seekBar, textView); + seekBar.setOnSeekBarChangeListener(mParameters[3]); + + // Band 5 level + centerFreq = mEqualizer.getCenterFreq((short)4); + freqRange = mEqualizer.getBandFreqRange((short)4); + displayFreq(R.id.eqParam5Center, centerFreq); + displayFreq(R.id.eqParam5Min, freqRange[0]); + displayFreq(R.id.eqParam5Max, freqRange[1]); + seekBar = (SeekBar)findViewById(R.id.eqParam5SeekBar); + textView = (TextView)findViewById(R.id.eqParam5Value); + mParameters[4] = new BandLevelParam(mEqualizer, 4, bandLevelRange[0], bandLevelRange[1], seekBar, textView); + seekBar.setOnSeekBarChangeListener(mParameters[4]); + + // Presets + short numPresets = mEqualizer.getNumberOfPresets(); + seekBar = (SeekBar)findViewById(R.id.eqParam6SeekBar); + textView = (TextView)findViewById(R.id.eqParam6Value); + mParameters[5] = new PresetParam(mEqualizer, (short)0, (short)(numPresets-1), seekBar, textView); + seekBar.setOnSeekBarChangeListener(mParameters[5]); + } + } + + @Override + public void onResume() { + super.onResume(); + } + + @Override + public void onPause() { + super.onPause(); + } + + private View.OnKeyListener mSessionKeyListener + = new View.OnKeyListener() { + public boolean onKey(View v, int keyCode, KeyEvent event) { + if (event.getAction() == KeyEvent.ACTION_DOWN) { + switch (keyCode) { + case KeyEvent.KEYCODE_DPAD_CENTER: + case KeyEvent.KEYCODE_ENTER: + try { + sSession = Integer.parseInt(mSessionText.getText().toString()); + getEffect(sSession); + if (mEqualizer != null) { + for (int i = 0 ; i < mParameters.length; i++) { + mParameters[i].setEffect(mEqualizer); + mParameters[i].setEnabled(true); + } + } + } catch (NumberFormatException e) { + Log.d(TAG, "Invalid session #: "+mSessionText.getText().toString()); + } + + return true; + } + } + return false; + } + }; + + // OnCheckedChangeListener + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (buttonView.getId() == R.id.equalizerOnOff) { + if (mEqualizer != null) { + mEqualizer.setEnabled(isChecked); + updateBands(); + } + } + if (buttonView.getId() == R.id.eqReleaseButton) { + if (isChecked) { + if (mEqualizer == null) { + getEffect(sSession); + if (mEqualizer != null) { + for (int i = 0 ; i < mParameters.length; i++) { + mParameters[i].setEffect(mEqualizer); + mParameters[i].setEnabled(true); + } + } + } + } else { + if (mEqualizer != null) { + for (int i = 0 ; i < mParameters.length; i++) { + mParameters[i].setEnabled(false); + } + putEffect(sSession); + } + } + } + } + + protected void updateBands() { + for (int i = 0 ; i < NUM_BANDS; i++) { + mParameters[i].updateDisplay(); + } + } + + private void displayFreq(int viewId, int freq) { + TextView textView = (TextView)findViewById(viewId); + String text = Integer.toString(freq/1000)+" Hz"; + textView.setText(text); + } + + private class EqualizerParam extends EffectParameter { + private Equalizer mEqualizer; + + public EqualizerParam(Equalizer equalizer, int min, int max, SeekBar seekBar, TextView textView, String unit) { + super (min, max, seekBar, textView, unit); + + mEqualizer = equalizer; + updateDisplay(); + } + + @Override + public void setParameter(Integer value) { + } + + @Override + public Integer getParameter() { + return new Integer(0); + } + + @Override + public void setEffect(Object eq) { + mEqualizer = (Equalizer)eq; + } + } + + private class BandLevelParam extends EqualizerParam { + private int mBand; + + public BandLevelParam(Equalizer equalizer, int band, short min, short max, SeekBar seekBar, TextView textView) { + super (equalizer, min, max, seekBar, textView, "mB"); + + mBand = band; + mEqualizer = equalizer; + updateDisplay(); + } + + @Override + public void setParameter(Integer value) { + if (mEqualizer != null) { + mEqualizer.setBandLevel((short)mBand, value.shortValue()); + } + } + + @Override + public Integer getParameter() { + if (mEqualizer != null) { + return new Integer(mEqualizer.getBandLevel((short)mBand)); + } + return new Integer(0); + } + } + + private class PresetParam extends EqualizerParam { + + public PresetParam(Equalizer equalizer, short min, short max, SeekBar seekBar, TextView textView) { + super (equalizer, min, max, seekBar, textView, ""); + + mEqualizer = equalizer; + updateDisplay(); + } + + @Override + public void setParameter(Integer value) { + if (mEqualizer != null) { + mEqualizer.usePreset(value.shortValue()); + } + } + + @Override + public Integer getParameter() { + if (mEqualizer != null) { + return new Integer(mEqualizer.getCurrentPreset()); + } + return new Integer(0); + } + + @Override + public void displayValue(int value, boolean fromTouch) { + String text = mEqualizer.getPresetName((short)value); + mValueText.setText(text); + if (!fromTouch) { + mSeekBar.setProgress(value - mMin); + } else { + updateBands(); + } + } + } + + public class EffectListner implements AudioEffect.OnEnableStatusChangeListener, + AudioEffect.OnControlStatusChangeListener, + Equalizer.OnParameterChangeListener + { + public EffectListner() { + } + public void onEnableStatusChange(AudioEffect effect, boolean enabled) { + Log.d(TAG,"onEnableStatusChange: "+ enabled); + } + public void onControlStatusChange(AudioEffect effect, boolean controlGranted) { + Log.d(TAG,"onControlStatusChange: "+ controlGranted); + } + + public void onParameterChange(Equalizer effect, int status, int param1, int param2, int value) { + Log.d(TAG,"onParameterChange EQ, status: "+status+" p1: "+param1+" p2: "+param2+" v: "+value); + } + + private int byteArrayToInt(byte[] valueBuf, int offset) { + ByteBuffer converter = ByteBuffer.wrap(valueBuf); + converter.order(ByteOrder.nativeOrder()); + return converter.getInt(offset); + + } + private short byteArrayToShort(byte[] valueBuf, int offset) { + ByteBuffer converter = ByteBuffer.wrap(valueBuf); + converter.order(ByteOrder.nativeOrder()); + return converter.getShort(offset); + + } + } + + private void getEffect(int session) { + synchronized (sInstances) { + if (sInstances.containsKey(session)) { + mEqualizer = sInstances.get(session); + } else { + try{ + mEqualizer = new Equalizer(0, session); + } catch (IllegalArgumentException e) { + Log.e(TAG,"Equalizer effect not supported"); + } catch (UnsupportedOperationException e) { + Log.e(TAG,"Equalizer library not loaded"); + } catch (IllegalStateException e) { + Log.e(TAG,"Equalizer cannot get presets"); + } catch (RuntimeException e) { + Log.e(TAG,"Equalizer effect not found"); + } + sInstances.put(session, mEqualizer); + } + } + mReleaseButton.setEnabled(false); + mOnOffButton.setEnabled(false); + if (mEqualizer != null) { + if (mSettings != "") { + Log.d(TAG,"Equalizer settings: "+mSettings); + mEqualizer.setProperties(new Equalizer.Settings(mSettings)); + } + + mEqualizer.setEnableStatusListener(mEffectListener); + mEqualizer.setControlStatusListener(mEffectListener); + mEqualizer.setParameterListener(mEffectListener); + + mReleaseButton.setChecked(true); + mReleaseButton.setEnabled(true); + + mOnOffButton.setChecked(mEqualizer.getEnabled()); + mOnOffButton.setEnabled(true); + } + } + + private void putEffect(int session) { +// mOnOffButton.setChecked(false); + mOnOffButton.setEnabled(false); + synchronized (sInstances) { + if (mEqualizer != null) { + mSettings = mEqualizer.getProperties().toString(); + mEqualizer.release(); + Log.d(TAG,"Equalizer released, settings: "+mSettings); + mEqualizer = null; + sInstances.remove(session); + } + } + } +} diff --git a/media/tests/EffectsTest/src/com/android/effectstest/PresetReverbTest.java b/media/tests/EffectsTest/src/com/android/effectstest/PresetReverbTest.java new file mode 100755 index 0000000..91d7948 --- /dev/null +++ b/media/tests/EffectsTest/src/com/android/effectstest/PresetReverbTest.java @@ -0,0 +1,298 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.effectstest; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.View.OnClickListener; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; +import android.widget.EditText; +import android.widget.SeekBar; +import android.widget.ToggleButton; +import android.widget.CompoundButton; +import android.widget.CompoundButton.OnCheckedChangeListener; +import java.nio.ByteOrder; +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; + +import android.media.audiofx.PresetReverb; +import android.media.audiofx.AudioEffect; + +public class PresetReverbTest extends Activity implements OnCheckedChangeListener { + + private final static String TAG = "PresetReverbTest"; + + private static int NUM_PARAMS = 1; + + private EffectParameter[] mParameters = new EffectParameter[NUM_PARAMS]; + private PresetReverb mPresetReverb; + ToggleButton mOnOffButton; + ToggleButton mReleaseButton; + EditText mSessionText; + static int sSession = 0; + EffectListner mEffectListener = new EffectListner(); + private static HashMap<Integer, PresetReverb> sInstances = new HashMap<Integer, PresetReverb>(10); + String mSettings = ""; + + public PresetReverbTest() { + Log.d(TAG, "contructor"); + } + + private static String[] sPresetNames = { + "NONE", //PresetReverb.PRESET_NONE + "SMALLROOM", //PresetReverb.PRESET_SMALLROOM + "MEDIUMROOM", //PresetReverb.PRESET_MEDIUMROOM + "LARGEROOM", //PresetReverb.PRESET_LARGEROOM + "MEDIUMHALL", //PresetReverb.PRESET_MEDIUMHALL + "LARGEHALL", //PresetReverb.PRESET_LARGEHALL + "PLATE", //PresetReverb.PRESET_PLATE + }; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + setContentView(R.layout.presetreverbtest); + + mSessionText = (EditText) findViewById(R.id.sessionEdit); + mSessionText.setOnKeyListener(mSessionKeyListener); + + mSessionText.setText(Integer.toString(sSession)); + + mReleaseButton = (ToggleButton)findViewById(R.id.presetrvbReleaseButton); + mOnOffButton = (ToggleButton)findViewById(R.id.presetrvbOnOff); + + getEffect(sSession); + + if (mPresetReverb != null) { + mReleaseButton.setOnCheckedChangeListener(this); + mOnOffButton.setOnCheckedChangeListener(this); + // Presets + SeekBar seekBar = (SeekBar)findViewById(R.id.presetrvbParam1SeekBar); + TextView textView = (TextView)findViewById(R.id.presetrvbParam1Value); + mParameters[0] = new PresetParam(mPresetReverb, (short)0, (short)(sPresetNames.length - 1), seekBar, textView); + seekBar.setOnSeekBarChangeListener(mParameters[0]); + } + } + + @Override + public void onResume() { + super.onResume(); + } + + @Override + public void onPause() { + super.onPause(); + } + + private View.OnKeyListener mSessionKeyListener + = new View.OnKeyListener() { + public boolean onKey(View v, int keyCode, KeyEvent event) { + if (event.getAction() == KeyEvent.ACTION_DOWN) { + switch (keyCode) { + case KeyEvent.KEYCODE_DPAD_CENTER: + case KeyEvent.KEYCODE_ENTER: + try { + sSession = Integer.parseInt(mSessionText.getText().toString()); + getEffect(sSession); + if (mPresetReverb != null) { + for (int i = 0 ; i < mParameters.length; i++) { + mParameters[i].setEffect(mPresetReverb); + mParameters[i].setEnabled(true); + mParameters[i].updateDisplay(); + } + } + } catch (NumberFormatException e) { + Log.d(TAG, "Invalid session #: "+mSessionText.getText().toString()); + } + + return true; + } + } + return false; + } + }; + + // OnCheckedChangeListener + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (buttonView.getId() == R.id.presetrvbOnOff) { + if (mPresetReverb != null) { + mPresetReverb.setEnabled(isChecked); + updateParams(); + } + } + if (buttonView.getId() == R.id.presetrvbReleaseButton) { + if (isChecked) { + if (mPresetReverb == null) { + getEffect(sSession); + if (mPresetReverb != null) { + for (int i = 0 ; i < mParameters.length; i++) { + mParameters[i].setEffect(mPresetReverb); + mParameters[i].setEnabled(true); + mParameters[i].updateDisplay(); + } + } + } + } else { + if (mPresetReverb != null) { + for (int i = 0 ; i < mParameters.length; i++) { + mParameters[i].setEnabled(false); + } + putEffect(sSession); + } + } + } + } + + private class PresetParam extends EffectParameter { + private PresetReverb mPresetReverb; + + public PresetParam(PresetReverb presetrvb, short min, short max, SeekBar seekBar, TextView textView) { + super (min, max, seekBar, textView, ""); + + mPresetReverb = presetrvb; + updateDisplay(); + } + + @Override + public void setParameter(Integer value) { + if (mPresetReverb != null) { + mPresetReverb.setPreset(value.shortValue()); + } + } + + @Override + public Integer getParameter() { + if (mPresetReverb != null) { + return new Integer(mPresetReverb.getPreset()); + } + return new Integer(0); + } + + @Override + public void displayValue(int value, boolean fromTouch) { + mValueText.setText(sPresetNames[value]); + if (!fromTouch) { + mSeekBar.setProgress(value - mMin); + } else { + updateParams(); + } + } + + @Override + public void setEffect(Object presetrvb) { + mPresetReverb = (PresetReverb)presetrvb; + } + + } + + protected void updateParams() { + for (int i = 0 ; i < mParameters.length; i++) { + mParameters[i].updateDisplay(); + } + } + + public class EffectListner implements AudioEffect.OnEnableStatusChangeListener, + AudioEffect.OnControlStatusChangeListener, + PresetReverb.OnParameterChangeListener + { + public EffectListner() { + } + public void onEnableStatusChange(AudioEffect effect, boolean enabled) { + Log.d(TAG,"onEnableStatusChange: "+ enabled); + } + public void onControlStatusChange(AudioEffect effect, boolean controlGranted) { + Log.d(TAG,"onControlStatusChange: "+ controlGranted); + } + + public void onParameterChange(PresetReverb effect, int status, int param, short value) { + Log.d(TAG,"onParameterChange, status: "+status+" p: "+param+" v: "+value); + } + + private int byteArrayToInt(byte[] valueBuf, int offset) { + ByteBuffer converter = ByteBuffer.wrap(valueBuf); + converter.order(ByteOrder.nativeOrder()); + return converter.getInt(offset); + + } + private short byteArrayToShort(byte[] valueBuf, int offset) { + ByteBuffer converter = ByteBuffer.wrap(valueBuf); + converter.order(ByteOrder.nativeOrder()); + return converter.getShort(offset); + + } + } + + private void getEffect(int session) { + synchronized (sInstances) { + if (sInstances.containsKey(session)) { + mPresetReverb = sInstances.get(session); + } else { + try{ + mPresetReverb = new PresetReverb(0, session); + } catch (IllegalArgumentException e) { + Log.e(TAG,"PresetReverb effect not supported"); + } catch (UnsupportedOperationException e) { + Log.e(TAG,"PresetReverb library not loaded"); + } catch (RuntimeException e) { + Log.e(TAG,"PresetReverb effect not found"); + } + sInstances.put(session, mPresetReverb); + } + } + mReleaseButton.setEnabled(false); + mOnOffButton.setEnabled(false); + + if (mPresetReverb != null) { + if (mSettings != "") { + mPresetReverb.setProperties(new PresetReverb.Settings(mSettings)); + } + mPresetReverb.setEnableStatusListener(mEffectListener); + mPresetReverb.setControlStatusListener(mEffectListener); + mPresetReverb.setParameterListener(mEffectListener); + + mReleaseButton.setChecked(true); + mReleaseButton.setEnabled(true); + + mOnOffButton.setChecked(mPresetReverb.getEnabled()); + mOnOffButton.setEnabled(true); + } + } + + private void putEffect(int session) { + mOnOffButton.setChecked(false); + mOnOffButton.setEnabled(false); + synchronized (sInstances) { + if (mPresetReverb != null) { + mSettings = mPresetReverb.getProperties().toString(); + mPresetReverb.release(); + Log.d(TAG,"PresetReverb released"); + mPresetReverb = null; + sInstances.remove(session); + } + } + } +} diff --git a/media/tests/EffectsTest/src/com/android/effectstest/SimplePlayer.java b/media/tests/EffectsTest/src/com/android/effectstest/SimplePlayer.java new file mode 100644 index 0000000..119a604 --- /dev/null +++ b/media/tests/EffectsTest/src/com/android/effectstest/SimplePlayer.java @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.effectstest; + +import android.content.Context; +import android.content.res.AssetFileDescriptor; +import android.os.Bundle; +import android.util.Log; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.View.OnClickListener; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; +import android.widget.EditText; +import android.widget.SeekBar; +import android.widget.ToggleButton; +import android.widget.CompoundButton; +import android.widget.CompoundButton.OnCheckedChangeListener; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.media.AudioManager; +import android.media.MediaPlayer; +import java.nio.ByteOrder; +import java.nio.ByteBuffer; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class SimplePlayer implements OnClickListener { + + private final static String TAG = "SimplePlayer"; + + int mPlayPauseButtonId; + int mStopButtonId; + Context mContext; + ImageView mPlayPauseButton; + int mPlayImageResource; + int mPauseImageResource; + String mFileName; + int mFileResId; + MediaPlayer mMediaPlayer; + int mStreamType; + int mSession; + float mSendLevel = (float)0.5; + int mEffectId = 0; + TextView mSessionText; + + SimplePlayer(Context context, int playPausebuttonId, ImageView playPausebutton, + int stopButtonId, ImageView stopButton, TextView sessionText, String fileName, int stream, int session) + { + set(context, playPausebuttonId, playPausebutton, stopButtonId, stopButton, sessionText, stream, session); + mFileName = fileName; + } + + SimplePlayer(Context context, int playPausebuttonId, ImageView playPausebutton, + int stopButtonId, ImageView stopButton, TextView sessionText, int fileResId, int stream, int session) { + set(context, playPausebuttonId, playPausebutton, stopButtonId, stopButton, sessionText, stream, session); + mFileResId = fileResId; + mFileName = ""; + } + + public void set(Context context, int playPausebuttonId, ImageView playPausebutton, + int stopButtonId, ImageView stopButton, TextView sessionText, int stream, int session) { + mContext = context; + mPlayPauseButtonId = playPausebuttonId; + mStopButtonId = stopButtonId; + mPlayPauseButton = (ImageButton) playPausebutton; + ImageButton stop = (ImageButton) stopButton; + + mPlayPauseButton.setOnClickListener(this); + mPlayPauseButton.requestFocus(); + stop.setOnClickListener(this); + + mPlayImageResource = android.R.drawable.ic_media_play; + mPauseImageResource = android.R.drawable.ic_media_pause; + mStreamType = stream; + mSession = session; + mSessionText = sessionText; + } + + + public void onClick(View v) { + if (v.getId() == mPlayPauseButtonId) { + playOrPause(); + } else if (v.getId() == mStopButtonId) { + stop(); + } + } + + public void playOrPause() { + if (mMediaPlayer == null || !mMediaPlayer.isPlaying()){ + if (mMediaPlayer == null) { + try { + mMediaPlayer = new MediaPlayer(); + if (mSession != 0) { + mMediaPlayer.setAudioSessionId(mSession); + Log.d(TAG, "mMediaPlayer.setAudioSessionId(): "+ mSession); + } + + if (mFileName.equals("")) { + Log.d(TAG, "Playing from resource"); + AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(mFileResId); + mMediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength()); + afd.close(); + } else { + Log.d(TAG, "Playing file: "+mFileName); + mMediaPlayer.setDataSource(mFileName); + } + mMediaPlayer.setAudioStreamType(mStreamType); + mMediaPlayer.prepare(); + mMediaPlayer.setLooping(true); + } catch (IOException ex) { + Log.e(TAG, "mMediaPlayercreate failed:", ex); + mMediaPlayer = null; + } catch (IllegalArgumentException ex) { + Log.e(TAG, "mMediaPlayercreate failed:", ex); + mMediaPlayer = null; + } catch (SecurityException ex) { + Log.e(TAG, "mMediaPlayercreate failed:", ex); + mMediaPlayer = null; + } + + if (mMediaPlayer != null) { + mMediaPlayer.setAuxEffectSendLevel(mSendLevel); + mMediaPlayer.attachAuxEffect(mEffectId); + mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { + public void onCompletion(MediaPlayer mp) { + updatePlayPauseButton(); + } + }); + mSessionText.setText("Session: "+Integer.toString(mMediaPlayer.getAudioSessionId())); + } + } + if (mMediaPlayer != null) { + mMediaPlayer.start(); + } + } else { + mMediaPlayer.pause(); + } + updatePlayPauseButton(); + } + + public void stop() { + if (mMediaPlayer != null) { + mMediaPlayer.stop(); + mMediaPlayer.release(); + mMediaPlayer = null; + } + updatePlayPauseButton(); + } + + public boolean isPlaying() { + if (mMediaPlayer != null) { + return mMediaPlayer.isPlaying(); + } else { + return false; + } + } + + public void updatePlayPauseButton() { + mPlayPauseButton.setImageResource(isPlaying() ? mPauseImageResource : mPlayImageResource); + } + + public void attachAuxEffect(int effectId) { + mEffectId = effectId; + if (mMediaPlayer != null) { + Log.d(TAG,"attach effect: "+effectId); + mMediaPlayer.attachAuxEffect(effectId); + } + } + public void setAuxEffectSendLevel(float level) { + mSendLevel = level; + if (mMediaPlayer != null) { + mMediaPlayer.setAuxEffectSendLevel(level); + } + } + + public void setContext(Context context) { + mContext = context; + } +} diff --git a/media/tests/EffectsTest/src/com/android/effectstest/VirtualizerTest.java b/media/tests/EffectsTest/src/com/android/effectstest/VirtualizerTest.java new file mode 100755 index 0000000..bb32e6f --- /dev/null +++ b/media/tests/EffectsTest/src/com/android/effectstest/VirtualizerTest.java @@ -0,0 +1,271 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.effectstest; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.View.OnClickListener; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; +import android.widget.EditText; +import android.widget.SeekBar; +import android.widget.ToggleButton; +import android.widget.CompoundButton; +import android.widget.CompoundButton.OnCheckedChangeListener; +import java.nio.ByteOrder; +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; + +import android.media.audiofx.Virtualizer; +import android.media.audiofx.AudioEffect; + +public class VirtualizerTest extends Activity implements OnCheckedChangeListener { + + private final static String TAG = "VirtualizerTest"; + + private static int NUM_PARAMS = 1; + + private EffectParameter mStrength; + private Virtualizer mVirtualizer; + ToggleButton mOnOffButton; + ToggleButton mReleaseButton; + EditText mSessionText; + static int sSession = 0; + EffectListner mEffectListener = new EffectListner(); + private static HashMap<Integer, Virtualizer> sInstances = new HashMap<Integer, Virtualizer>(10); + String mSettings = ""; + + public VirtualizerTest() { + Log.d(TAG, "contructor"); + } + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + SeekBar seekBar; + TextView textView; + + setContentView(R.layout.virtualizertest); + + mSessionText = (EditText) findViewById(R.id.sessionEdit); + mSessionText.setOnKeyListener(mSessionKeyListener); + mSessionText.setText(Integer.toString(sSession)); + + mReleaseButton = (ToggleButton)findViewById(R.id.virtReleaseButton); + mOnOffButton = (ToggleButton)findViewById(R.id.virtualizerOnOff); + + getEffect(sSession); + + if (mVirtualizer != null) { + mReleaseButton.setOnCheckedChangeListener(this); + mOnOffButton.setOnCheckedChangeListener(this); + textView = (TextView)findViewById(R.id.virtStrengthMin); + textView.setText("0"); + textView = (TextView)findViewById(R.id.virtStrengthMax); + textView.setText("1000"); + seekBar = (SeekBar)findViewById(R.id.virtStrengthSeekBar); + textView = (TextView)findViewById(R.id.virtStrengthValue); + mStrength = new VirtualizerParam(mVirtualizer, 0, 1000, seekBar, textView); + seekBar.setOnSeekBarChangeListener(mStrength); + mStrength.setEnabled(mVirtualizer.getStrengthSupported()); + } + } + + @Override + public void onResume() { + super.onResume(); + } + + @Override + public void onPause() { + super.onPause(); + } + + private View.OnKeyListener mSessionKeyListener + = new View.OnKeyListener() { + public boolean onKey(View v, int keyCode, KeyEvent event) { + if (event.getAction() == KeyEvent.ACTION_DOWN) { + switch (keyCode) { + case KeyEvent.KEYCODE_DPAD_CENTER: + case KeyEvent.KEYCODE_ENTER: + try { + sSession = Integer.parseInt(mSessionText.getText().toString()); + getEffect(sSession); + if (mVirtualizer != null) { + mStrength.setEffect(mVirtualizer); + mStrength.setEnabled(mVirtualizer.getStrengthSupported()); + } + } catch (NumberFormatException e) { + Log.d(TAG, "Invalid session #: "+mSessionText.getText().toString()); + } + return true; + } + } + return false; + } + }; + + // OnCheckedChangeListener + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (buttonView.getId() == R.id.virtualizerOnOff) { + if (mVirtualizer != null) { + mVirtualizer.setEnabled(isChecked); + mStrength.updateDisplay(); + } + } + if (buttonView.getId() == R.id.virtReleaseButton) { + if (isChecked) { + if (mVirtualizer == null) { + getEffect(sSession); + if (mVirtualizer != null) { + mStrength.setEffect(mVirtualizer); + mStrength.setEnabled(mVirtualizer.getStrengthSupported()); + } + } + } else { + if (mVirtualizer != null) { + mStrength.setEnabled(false); + putEffect(sSession); + } + } + } + } + + private class VirtualizerParam extends EffectParameter { + private Virtualizer mVirtualizer; + + public VirtualizerParam(Virtualizer virtualizer, int min, int max, SeekBar seekBar, TextView textView) { + super (min, max, seekBar, textView, "o/oo"); + + mVirtualizer = virtualizer; + updateDisplay(); + } + + @Override + public void setParameter(Integer value) { + if (mVirtualizer != null) { + mVirtualizer.setStrength(value.shortValue()); + } + } + + @Override + public Integer getParameter() { + if (mVirtualizer != null) { + return new Integer(mVirtualizer.getRoundedStrength()); + } + return new Integer(0); + } + + @Override + public void setEffect(Object effect) { + mVirtualizer = (Virtualizer)effect; + } + } + + public class EffectListner implements AudioEffect.OnEnableStatusChangeListener, + AudioEffect.OnControlStatusChangeListener, AudioEffect.OnParameterChangeListener + { + public EffectListner() { + } + public void onEnableStatusChange(AudioEffect effect, boolean enabled) { + Log.d(TAG,"onEnableStatusChange: "+ enabled); + } + public void onControlStatusChange(AudioEffect effect, boolean controlGranted) { + Log.d(TAG,"onControlStatusChange: "+ controlGranted); + } + public void onParameterChange(AudioEffect effect, int status, byte[] param, byte[] value) { + int p = byteArrayToInt(param, 0); + short v = byteArrayToShort(value, 0); + + Log.d(TAG,"onParameterChange, status: "+status+" p: "+p+" v: "+v); + } + + private int byteArrayToInt(byte[] valueBuf, int offset) { + ByteBuffer converter = ByteBuffer.wrap(valueBuf); + converter.order(ByteOrder.nativeOrder()); + return converter.getInt(offset); + + } + private short byteArrayToShort(byte[] valueBuf, int offset) { + ByteBuffer converter = ByteBuffer.wrap(valueBuf); + converter.order(ByteOrder.nativeOrder()); + return converter.getShort(offset); + + } + } + + private void getEffect(int session) { + synchronized (sInstances) { + if (sInstances.containsKey(session)) { + mVirtualizer = sInstances.get(session); + } else { + try{ + mVirtualizer = new Virtualizer(0, session); + } catch (IllegalArgumentException e) { + Log.e(TAG,"Virtualizer effect not supported"); + } catch (IllegalStateException e) { + Log.e(TAG,"Virtualizer cannot get strength supported"); + } catch (UnsupportedOperationException e) { + Log.e(TAG,"Virtualizer library not loaded"); + } catch (RuntimeException e) { + Log.e(TAG,"Virtualizer effect not found"); + } + sInstances.put(session, mVirtualizer); + } + } + mReleaseButton.setEnabled(false); + mOnOffButton.setEnabled(false); + + if (mVirtualizer != null) { + if (mSettings != "") { + mVirtualizer.setProperties(new Virtualizer.Settings(mSettings)); + } + mVirtualizer.setEnableStatusListener(mEffectListener); + mVirtualizer.setControlStatusListener(mEffectListener); + mVirtualizer.setParameterListener(mEffectListener); + + mReleaseButton.setChecked(true); + mReleaseButton.setEnabled(true); + + mOnOffButton.setChecked(mVirtualizer.getEnabled()); + mOnOffButton.setEnabled(true); + } + } + + private void putEffect(int session) { + mOnOffButton.setChecked(false); + mOnOffButton.setEnabled(false); + synchronized (sInstances) { + if (mVirtualizer != null) { + mSettings = mVirtualizer.getProperties().toString(); + mVirtualizer.release(); + Log.d(TAG,"Virtualizer released"); + mVirtualizer = null; + sInstances.remove(session); + } + } + } +} diff --git a/media/tests/EffectsTest/src/com/android/effectstest/VisualizerTest.java b/media/tests/EffectsTest/src/com/android/effectstest/VisualizerTest.java new file mode 100755 index 0000000..60583e0 --- /dev/null +++ b/media/tests/EffectsTest/src/com/android/effectstest/VisualizerTest.java @@ -0,0 +1,296 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.effectstest; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.media.audiofx.Visualizer; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.util.Log; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.CompoundButton; +import android.widget.CompoundButton.OnCheckedChangeListener; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.ToggleButton; +import android.widget.SeekBar; + +import java.nio.ByteOrder; +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; + +public class VisualizerTest extends Activity implements OnCheckedChangeListener { + + private final static String TAG = "Visualizer Test"; + + private Visualizer mVisualizer; + ToggleButton mOnOffButton; + ToggleButton mReleaseButton; + boolean mEnabled; + EditText mSessionText; + static int sSession = 0; + int mCaptureSize; + ToggleButton mCallbackButton; + boolean mCallbackOn; + VisualizerListener mVisualizerListener; + private static HashMap<Integer, Visualizer> sInstances = new HashMap<Integer, Visualizer>(10); + private VisualizerTestHandler mVisualizerTestHandler = null; + + public VisualizerTest() { + Log.d(TAG, "contructor"); + } + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + TextView textView; + + setContentView(R.layout.visualizertest); + + mSessionText = (EditText) findViewById(R.id.sessionEdit); + mSessionText.setOnKeyListener(mSessionKeyListener); + mSessionText.setText(Integer.toString(sSession)); + + mReleaseButton = (ToggleButton)findViewById(R.id.visuReleaseButton); + mOnOffButton = (ToggleButton)findViewById(R.id.visualizerOnOff); + mCallbackButton = (ToggleButton)findViewById(R.id.visuCallbackOnOff); + mCallbackOn = false; + mCallbackButton.setChecked(mCallbackOn); + + mVisualizerTestHandler = new VisualizerTestHandler(); + mVisualizerListener = new VisualizerListener(); + + getEffect(sSession); + + if (mVisualizer != null) { + mReleaseButton.setOnCheckedChangeListener(this); + mOnOffButton.setOnCheckedChangeListener(this); + mCallbackButton.setOnCheckedChangeListener(this); + } + } + + private static final int MSG_START_CAPTURE = 0; + private static final int MSG_STOP_CAPTURE = 1; + private static final int MSG_NEW_CAPTURE = 2; + private static final int CAPTURE_PERIOD_MS = 100; + + private class VisualizerTestHandler extends Handler { + boolean mActive = false; + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_START_CAPTURE: + if (!mActive) { + Log.d(TAG, "Start capture"); + mActive = true; + sendMessageDelayed(obtainMessage(MSG_NEW_CAPTURE, 0, 0, null), CAPTURE_PERIOD_MS); + } + break; + case MSG_STOP_CAPTURE: + if (mActive) { + Log.d(TAG, "Stop capture"); + mActive = false; + } + break; + case MSG_NEW_CAPTURE: + if (mActive && mVisualizer != null) { + if (mCaptureSize > 0) { + byte[] data = new byte[mCaptureSize]; + if (mVisualizer.getWaveForm(data) == Visualizer.SUCCESS) { + int len = data.length < mCaptureSize ? data.length : mCaptureSize; + displayVal(R.id.waveformMin, data[0]); + displayVal(R.id.waveformMax, data[len-1]); + displayVal(R.id.waveformCenter, data[len/2]); + }; + if (mVisualizer.getFft(data) == Visualizer.SUCCESS) { + int len = data.length < mCaptureSize ? data.length : mCaptureSize; + displayVal(R.id.fftMin, data[0]); + displayVal(R.id.fftMax, data[len-1]); + displayVal(R.id.fftCenter, data[len/2]); + }; + } + sendMessageDelayed(obtainMessage(MSG_NEW_CAPTURE, 0, 0, null), CAPTURE_PERIOD_MS); + } + break; + } + } + } + + private class VisualizerListener implements Visualizer.OnDataCaptureListener { + + public VisualizerListener() { + } + public void onWaveFormDataCapture(Visualizer visualizer, byte[] waveform, int samplingRate) { + if (visualizer == mVisualizer) { + if (waveform.length > 0) { + Log.d(TAG, "onWaveFormDataCapture(): "+waveform[0]+" smp rate: "+samplingRate/1000); + displayVal(R.id.waveformMin, waveform[0]); + displayVal(R.id.waveformMax, waveform[waveform.length - 1]); + displayVal(R.id.waveformCenter, waveform[waveform.length/2]); + } + } + } + public void onFftDataCapture(Visualizer visualizer, byte[] fft, int samplingRate) { + if (visualizer == mVisualizer) { + if (fft.length > 0) { + Log.d(TAG, "onFftDataCapture(): "+fft[0]); + displayVal(R.id.fftMin, fft[0]); + displayVal(R.id.fftMax, fft[fft.length - 1]); + displayVal(R.id.fftCenter, fft[fft.length/2]); + } + } + } + } + + @Override + public void onResume() { + super.onResume(); + } + + @Override + public void onPause() { + super.onPause(); + } + + private View.OnKeyListener mSessionKeyListener + = new View.OnKeyListener() { + public boolean onKey(View v, int keyCode, KeyEvent event) { + if (event.getAction() == KeyEvent.ACTION_DOWN) { + switch (keyCode) { + case KeyEvent.KEYCODE_DPAD_CENTER: + case KeyEvent.KEYCODE_ENTER: + try { + sSession = Integer.parseInt(mSessionText.getText().toString()); + getEffect(sSession); + } catch (NumberFormatException e) { + Log.d(TAG, "Invalid session #: "+mSessionText.getText().toString()); + } + + return true; + } + } + return false; + } + }; + + // OnCheckedChangeListener + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (buttonView.getId() == R.id.visualizerOnOff) { + if (mVisualizer != null) { + mEnabled = isChecked; + mCallbackButton.setEnabled(!mEnabled); + if (mCallbackOn && mEnabled) { + mVisualizer.setDataCaptureListener(mVisualizerListener, + 10000, + true, + true); + } + mVisualizer.setEnabled(mEnabled); + if (mCallbackOn) { + if (!mEnabled) { + mVisualizer.setDataCaptureListener(null, + 10000, + false, + false); + } + } else { + int msg = isChecked ? MSG_START_CAPTURE : MSG_STOP_CAPTURE; + mVisualizerTestHandler.sendMessage( + mVisualizerTestHandler.obtainMessage(msg, 0, 0, null)); + } + } + } + if (buttonView.getId() == R.id.visuReleaseButton) { + if (isChecked) { + if (mVisualizer == null) { + getEffect(sSession); + } + } else { + if (mVisualizer != null) { + putEffect(sSession); + } + } + } + if (buttonView.getId() == R.id.visuCallbackOnOff) { + mCallbackOn = isChecked; + } + } + + private void displayVal(int viewId, int val) { + TextView textView = (TextView)findViewById(viewId); + String text = Integer.toString(val); + textView.setText(text); + } + + + private void getEffect(int session) { + synchronized (sInstances) { + if (sInstances.containsKey(session)) { + mVisualizer = sInstances.get(session); + } else { + try{ + mVisualizer = new Visualizer(session); + } catch (UnsupportedOperationException e) { + Log.e(TAG,"Visualizer library not loaded"); + throw (new RuntimeException("Cannot initialize effect")); + } catch (RuntimeException e) { + throw e; + } + sInstances.put(session, mVisualizer); + } + } + mReleaseButton.setEnabled(false); + mOnOffButton.setEnabled(false); + if (mVisualizer != null) { + mCaptureSize = mVisualizer.getCaptureSize(); + + mReleaseButton.setChecked(true); + mReleaseButton.setEnabled(true); + + mEnabled = mVisualizer.getEnabled(); + mOnOffButton.setChecked(mEnabled); + mOnOffButton.setEnabled(true); + + mCallbackButton.setEnabled(!mEnabled); + } + } + + private void putEffect(int session) { + mOnOffButton.setChecked(false); + mOnOffButton.setEnabled(false); + synchronized (sInstances) { + if (mVisualizer != null) { + mVisualizer.release(); + Log.d(TAG,"Visualizer released"); + mVisualizer = null; + sInstances.remove(session); + } + } + } + +} |