12e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen/* 22e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen * Copyright (C) 2009 The Android Open Source Project 32e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen * 42e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen * Licensed under the Apache License, Version 2.0 (the "License"); 52e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen * you may not use this file except in compliance with the License. 62e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen * You may obtain a copy of the License at 72e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen * 82e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen * http://www.apache.org/licenses/LICENSE-2.0 92e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen * 102e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen * Unless required by applicable law or agreed to in writing, software 112e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen * distributed under the License is distributed on an "AS IS" BASIS, 122e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen * See the License for the specific language governing permissions and 142e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen * limitations under the License. 152e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen */ 162e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 172e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissenpackage com.android.effectstest; 182e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 192e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissenimport android.app.Activity; 202e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissenimport android.content.Context; 212e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissenimport android.content.Intent; 222e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissenimport android.os.Bundle; 232e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissenimport android.util.Log; 242e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissenimport android.view.KeyEvent; 252e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissenimport android.view.Menu; 262e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissenimport android.view.View.OnClickListener; 272e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissenimport android.view.View; 282e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissenimport android.view.ViewGroup; 292e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissenimport android.widget.Button; 302e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissenimport android.widget.TextView; 312e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissenimport android.widget.EditText; 322e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissenimport android.widget.SeekBar; 332e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissenimport android.widget.ToggleButton; 342e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissenimport android.widget.CompoundButton; 352e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissenimport android.widget.CompoundButton.OnCheckedChangeListener; 362e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissenimport java.nio.ByteOrder; 372e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissenimport java.nio.ByteBuffer; 382e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissenimport java.util.HashMap; 392e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissenimport java.util.Map; 402e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 412e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 422e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissenimport android.media.audiofx.Equalizer; 432e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissenimport android.media.audiofx.AudioEffect; 442e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 452e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissenpublic class EqualizerTest extends Activity implements OnCheckedChangeListener { 462e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 472e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen private final static String TAG = "EqualizerTest"; 482e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 492e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen private static int NUM_BANDS = 5; 502e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen private static int NUM_PARAMS = NUM_BANDS + 1; 512e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 522e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen private EffectParameter[] mParameters = new EffectParameter[NUM_PARAMS]; 532e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen private Equalizer mEqualizer; 542e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen ToggleButton mOnOffButton; 552e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen ToggleButton mReleaseButton; 562e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen EditText mSessionText; 572e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen static int sSession = 0; 582e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen EffectListner mEffectListener = new EffectListner(); 592e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen private static HashMap<Integer, Equalizer> sInstances = new HashMap<Integer, Equalizer>(10); 602e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen String mSettings = ""; 612e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 622e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen public EqualizerTest() { 632e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen Log.d(TAG, "contructor"); 642e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 652e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 662e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen @Override 672e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen public void onCreate(Bundle icicle) { 682e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen super.onCreate(icicle); 692e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 702e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen SeekBar seekBar; 712e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen TextView textView; 722e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 732e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen setContentView(R.layout.equalizertest); 742e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 752e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mSessionText = (EditText) findViewById(R.id.sessionEdit); 762e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mSessionText.setOnKeyListener(mSessionKeyListener); 772e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 782e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mSessionText.setText(Integer.toString(sSession)); 792e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 802e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mReleaseButton = (ToggleButton)findViewById(R.id.eqReleaseButton); 812e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mOnOffButton = (ToggleButton)findViewById(R.id.equalizerOnOff); 822e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 832e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen getEffect(sSession); 842e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 852e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen if (mEqualizer != null) { 862e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mReleaseButton.setOnCheckedChangeListener(this); 872e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mOnOffButton.setOnCheckedChangeListener(this); 882e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 892e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen short[] bandLevelRange = mEqualizer.getBandLevelRange(); 902e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen int centerFreq; 912e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen int []freqRange; 922e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 932e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen // Band 1 level 942e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen centerFreq = mEqualizer.getCenterFreq((short)0); 952e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen freqRange = mEqualizer.getBandFreqRange((short)0); 962e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen displayFreq(R.id.eqParam1Center, centerFreq); 972e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen displayFreq(R.id.eqParam1Min, freqRange[0]); 982e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen displayFreq(R.id.eqParam1Max, freqRange[1]); 992e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen seekBar = (SeekBar)findViewById(R.id.eqParam1SeekBar); 1002e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen textView = (TextView)findViewById(R.id.eqParam1Value); 1012e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mParameters[0] = new BandLevelParam(mEqualizer, 0, bandLevelRange[0], bandLevelRange[1], seekBar, textView); 1022e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen seekBar.setOnSeekBarChangeListener(mParameters[0]); 1032e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 1042e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen // Band 2 level 1052e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen centerFreq = mEqualizer.getCenterFreq((short)1); 1062e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen freqRange = mEqualizer.getBandFreqRange((short)1); 1072e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen displayFreq(R.id.eqParam2Center, centerFreq); 1082e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen displayFreq(R.id.eqParam2Min, freqRange[0]); 1092e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen displayFreq(R.id.eqParam2Max, freqRange[1]); 1102e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen seekBar = (SeekBar)findViewById(R.id.eqParam2SeekBar); 1112e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen textView = (TextView)findViewById(R.id.eqParam2Value); 1122e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mParameters[1] = new BandLevelParam(mEqualizer, 1, bandLevelRange[0], bandLevelRange[1], seekBar, textView); 1132e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen seekBar.setOnSeekBarChangeListener(mParameters[1]); 1142e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 1152e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen // Band 3 level 1162e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen centerFreq = mEqualizer.getCenterFreq((short)2); 1172e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen freqRange = mEqualizer.getBandFreqRange((short)2); 1182e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen displayFreq(R.id.eqParam3Center, centerFreq); 1192e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen displayFreq(R.id.eqParam3Min, freqRange[0]); 1202e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen displayFreq(R.id.eqParam3Max, freqRange[1]); 1212e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen seekBar = (SeekBar)findViewById(R.id.eqParam3SeekBar); 1222e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen textView = (TextView)findViewById(R.id.eqParam3Value); 1232e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mParameters[2] = new BandLevelParam(mEqualizer, 2, bandLevelRange[0], bandLevelRange[1], seekBar, textView); 1242e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen seekBar.setOnSeekBarChangeListener(mParameters[2]); 1252e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 1262e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen // Band 4 level 1272e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen centerFreq = mEqualizer.getCenterFreq((short)3); 1282e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen freqRange = mEqualizer.getBandFreqRange((short)3); 1292e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen displayFreq(R.id.eqParam4Center, centerFreq); 1302e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen displayFreq(R.id.eqParam4Min, freqRange[0]); 1312e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen displayFreq(R.id.eqParam4Max, freqRange[1]); 1322e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen seekBar = (SeekBar)findViewById(R.id.eqParam4SeekBar); 1332e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen textView = (TextView)findViewById(R.id.eqParam4Value); 1342e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mParameters[3] = new BandLevelParam(mEqualizer, 3, bandLevelRange[0], bandLevelRange[1], seekBar, textView); 1352e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen seekBar.setOnSeekBarChangeListener(mParameters[3]); 1362e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 1372e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen // Band 5 level 1382e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen centerFreq = mEqualizer.getCenterFreq((short)4); 1392e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen freqRange = mEqualizer.getBandFreqRange((short)4); 1402e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen displayFreq(R.id.eqParam5Center, centerFreq); 1412e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen displayFreq(R.id.eqParam5Min, freqRange[0]); 1422e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen displayFreq(R.id.eqParam5Max, freqRange[1]); 1432e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen seekBar = (SeekBar)findViewById(R.id.eqParam5SeekBar); 1442e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen textView = (TextView)findViewById(R.id.eqParam5Value); 1452e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mParameters[4] = new BandLevelParam(mEqualizer, 4, bandLevelRange[0], bandLevelRange[1], seekBar, textView); 1462e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen seekBar.setOnSeekBarChangeListener(mParameters[4]); 1472e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 1482e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen // Presets 1492e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen short numPresets = mEqualizer.getNumberOfPresets(); 1502e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen seekBar = (SeekBar)findViewById(R.id.eqParam6SeekBar); 1512e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen textView = (TextView)findViewById(R.id.eqParam6Value); 1522e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mParameters[5] = new PresetParam(mEqualizer, (short)0, (short)(numPresets-1), seekBar, textView); 1532e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen seekBar.setOnSeekBarChangeListener(mParameters[5]); 1542e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 1552e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 1562e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 1572e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen @Override 1582e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen public void onResume() { 1592e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen super.onResume(); 1602e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 1612e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 1622e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen @Override 1632e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen public void onPause() { 1642e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen super.onPause(); 1652e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 1662e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 1672e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen private View.OnKeyListener mSessionKeyListener 1682e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen = new View.OnKeyListener() { 1692e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen public boolean onKey(View v, int keyCode, KeyEvent event) { 1702e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen if (event.getAction() == KeyEvent.ACTION_DOWN) { 1712e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen switch (keyCode) { 1722e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen case KeyEvent.KEYCODE_DPAD_CENTER: 1732e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen case KeyEvent.KEYCODE_ENTER: 1742e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen try { 1752e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen sSession = Integer.parseInt(mSessionText.getText().toString()); 1762e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen getEffect(sSession); 1772e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen if (mEqualizer != null) { 1782e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen for (int i = 0 ; i < mParameters.length; i++) { 1792e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mParameters[i].setEffect(mEqualizer); 1802e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mParameters[i].setEnabled(true); 1812e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 1822e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 1832e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } catch (NumberFormatException e) { 1842e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen Log.d(TAG, "Invalid session #: "+mSessionText.getText().toString()); 1852e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 1862e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 1872e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen return true; 1882e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 1892e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 1902e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen return false; 1912e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 1922e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen }; 1932e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 1942e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen // OnCheckedChangeListener 1952e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 1962e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen if (buttonView.getId() == R.id.equalizerOnOff) { 1972e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen if (mEqualizer != null) { 1982e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mEqualizer.setEnabled(isChecked); 1992e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen updateBands(); 2002e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 2012e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 2022e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen if (buttonView.getId() == R.id.eqReleaseButton) { 2032e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen if (isChecked) { 2042e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen if (mEqualizer == null) { 2052e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen getEffect(sSession); 2062e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen if (mEqualizer != null) { 2072e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen for (int i = 0 ; i < mParameters.length; i++) { 2082e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mParameters[i].setEffect(mEqualizer); 2092e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mParameters[i].setEnabled(true); 2102e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 2112e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 2122e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 2132e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } else { 2142e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen if (mEqualizer != null) { 2152e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen for (int i = 0 ; i < mParameters.length; i++) { 2162e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mParameters[i].setEnabled(false); 2172e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 2182e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen putEffect(sSession); 2192e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 2202e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 2212e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 2222e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 2232e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 2242e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen protected void updateBands() { 2252e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen for (int i = 0 ; i < NUM_BANDS; i++) { 2262e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mParameters[i].updateDisplay(); 2272e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 2282e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 2292e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 2302e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen private void displayFreq(int viewId, int freq) { 2312e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen TextView textView = (TextView)findViewById(viewId); 2322e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen String text = Integer.toString(freq/1000)+" Hz"; 2332e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen textView.setText(text); 2342e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 2352e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 2362e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen private class EqualizerParam extends EffectParameter { 2372e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen private Equalizer mEqualizer; 2382e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 2392e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen public EqualizerParam(Equalizer equalizer, int min, int max, SeekBar seekBar, TextView textView, String unit) { 2402e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen super (min, max, seekBar, textView, unit); 2412e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 2422e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mEqualizer = equalizer; 2432e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen updateDisplay(); 2442e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 2452e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 2462e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen @Override 2472e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen public void setParameter(Integer value) { 2482e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 2492e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 2502e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen @Override 2512e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen public Integer getParameter() { 2522e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen return new Integer(0); 2532e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 2542e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 2552e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen @Override 2562e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen public void setEffect(Object eq) { 2572e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mEqualizer = (Equalizer)eq; 2582e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 2592e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 2602e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 2612e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen private class BandLevelParam extends EqualizerParam { 2622e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen private int mBand; 2632e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 2642e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen public BandLevelParam(Equalizer equalizer, int band, short min, short max, SeekBar seekBar, TextView textView) { 2652e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen super (equalizer, min, max, seekBar, textView, "mB"); 2662e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 2672e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mBand = band; 2682e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mEqualizer = equalizer; 2692e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen updateDisplay(); 2702e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 2712e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 2722e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen @Override 2732e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen public void setParameter(Integer value) { 2742e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen if (mEqualizer != null) { 2752e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mEqualizer.setBandLevel((short)mBand, value.shortValue()); 2762e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 2772e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 2782e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 2792e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen @Override 2802e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen public Integer getParameter() { 2812e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen if (mEqualizer != null) { 2822e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen return new Integer(mEqualizer.getBandLevel((short)mBand)); 2832e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 2842e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen return new Integer(0); 2852e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 2862e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 2872e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 2882e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen private class PresetParam extends EqualizerParam { 2892e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 2902e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen public PresetParam(Equalizer equalizer, short min, short max, SeekBar seekBar, TextView textView) { 2912e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen super (equalizer, min, max, seekBar, textView, ""); 2922e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 2932e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mEqualizer = equalizer; 2942e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen updateDisplay(); 2952e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 2962e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 2972e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen @Override 2982e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen public void setParameter(Integer value) { 2992e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen if (mEqualizer != null) { 3002e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mEqualizer.usePreset(value.shortValue()); 3012e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 3022e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 3032e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 3042e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen @Override 3052e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen public Integer getParameter() { 3062e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen if (mEqualizer != null) { 3072e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen return new Integer(mEqualizer.getCurrentPreset()); 3082e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 3092e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen return new Integer(0); 3102e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 3112e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 3122e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen @Override 3132e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen public void displayValue(int value, boolean fromTouch) { 3142e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen String text = mEqualizer.getPresetName((short)value); 3152e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mValueText.setText(text); 3162e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen if (!fromTouch) { 3172e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mSeekBar.setProgress(value - mMin); 3182e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } else { 3192e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen updateBands(); 3202e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 3212e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 3222e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 3232e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 3242e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen public class EffectListner implements AudioEffect.OnEnableStatusChangeListener, 3252e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen AudioEffect.OnControlStatusChangeListener, 3262e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen Equalizer.OnParameterChangeListener 3272e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen { 3282e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen public EffectListner() { 3292e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 3302e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen public void onEnableStatusChange(AudioEffect effect, boolean enabled) { 3312e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen Log.d(TAG,"onEnableStatusChange: "+ enabled); 3322e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 3332e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen public void onControlStatusChange(AudioEffect effect, boolean controlGranted) { 3342e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen Log.d(TAG,"onControlStatusChange: "+ controlGranted); 3352e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 3362e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 3372e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen public void onParameterChange(Equalizer effect, int status, int param1, int param2, int value) { 3382e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen Log.d(TAG,"onParameterChange EQ, status: "+status+" p1: "+param1+" p2: "+param2+" v: "+value); 3392e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 3402e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 3412e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen private int byteArrayToInt(byte[] valueBuf, int offset) { 3422e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen ByteBuffer converter = ByteBuffer.wrap(valueBuf); 3432e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen converter.order(ByteOrder.nativeOrder()); 3442e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen return converter.getInt(offset); 3452e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 3462e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 3472e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen private short byteArrayToShort(byte[] valueBuf, int offset) { 3482e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen ByteBuffer converter = ByteBuffer.wrap(valueBuf); 3492e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen converter.order(ByteOrder.nativeOrder()); 3502e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen return converter.getShort(offset); 3512e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 3522e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 3532e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 3542e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 3552e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen private void getEffect(int session) { 3562e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen synchronized (sInstances) { 3572e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen if (sInstances.containsKey(session)) { 3582e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mEqualizer = sInstances.get(session); 3592e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } else { 3602e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen try{ 3612e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mEqualizer = new Equalizer(0, session); 3622e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } catch (IllegalArgumentException e) { 3632e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen Log.e(TAG,"Equalizer effect not supported"); 3642e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } catch (UnsupportedOperationException e) { 3652e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen Log.e(TAG,"Equalizer library not loaded"); 3662e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } catch (IllegalStateException e) { 3672e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen Log.e(TAG,"Equalizer cannot get presets"); 3682e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } catch (RuntimeException e) { 3692e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen Log.e(TAG,"Equalizer effect not found"); 3702e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 3712e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen sInstances.put(session, mEqualizer); 3722e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 3732e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 3742e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mReleaseButton.setEnabled(false); 3752e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mOnOffButton.setEnabled(false); 3762e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen if (mEqualizer != null) { 3772e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen if (mSettings != "") { 3782e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen Log.d(TAG,"Equalizer settings: "+mSettings); 3792e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mEqualizer.setProperties(new Equalizer.Settings(mSettings)); 3802e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 3812e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 3822e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mEqualizer.setEnableStatusListener(mEffectListener); 3832e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mEqualizer.setControlStatusListener(mEffectListener); 3842e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mEqualizer.setParameterListener(mEffectListener); 3852e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 3862e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mReleaseButton.setChecked(true); 3872e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mReleaseButton.setEnabled(true); 3882e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 3892e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mOnOffButton.setChecked(mEqualizer.getEnabled()); 3902e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mOnOffButton.setEnabled(true); 3912e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 3922e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 3932e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen 3942e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen private void putEffect(int session) { 3952e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen// mOnOffButton.setChecked(false); 3962e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mOnOffButton.setEnabled(false); 3972e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen synchronized (sInstances) { 3982e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen if (mEqualizer != null) { 3992e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mSettings = mEqualizer.getProperties().toString(); 4002e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mEqualizer.release(); 4012e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen Log.d(TAG,"Equalizer released, settings: "+mSettings); 4022e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen mEqualizer = null; 4032e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen sInstances.remove(session); 4042e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 4052e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 4062e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen } 4072e2beaaee2a427598ced5067fc59f3ae9a98cf35Marco Nelissen} 408