Android Equalizer with Exo Player

A Brief and Simple implementation of the Android Equalizer library


Disclaimer: This tutorial is in no way the best implementation, this might not suit your use-case. You may also find similar implementations or code snippets.


Assumption: You have created a project in android studio and configured the Exo Player to your specific requirements.

Step 1: Attaching the Equalizer to ExoPlayer

Now, For equalizer to work, it needs the Session ID (process session id) of the media you are currently using. In Exo Player, You’ll need to implement a new AudioRendererEventListener

Example PlayerActivity.java this is the only thing you will need to

Equalizer mEqualizer;
player.setAudioDebugListener(new AudioRendererEventListener() {

@Override
public void onAudioSessionId(int audioSessionId) {
mEqualizer = new Equalizer(1000, audioSessionId);
mEqualizer.setEnabled(true);
//That's it, this will initialize the Equalizer and set it to the //default preset

int current = properties.preferences.getInt("position", 0);
if (current == 0) {
for (short seek_id = 0; seek_id < mEqualizer.getNumberOfBands(); seek_id++) {
int progressBar = properties.preferences.getInt("seek_" + seek_id, 1500);
short equalizerBandIndex = (short) (seek_id);
final short lowerEqualizerBandLevel = mEqualizer.getBandLevelRange()[0];
Log.i("seek_" + seek_id, ":" + progressBar);
if (progressBar != 1500) {
mEqualizer.setBandLevel(equalizerBandIndex,
(short) (progressBar + lowerEqualizerBandLevel));
} else {
/*First time default 1500Hz*/
mEqualizer.setBandLevel(equalizerBandIndex,
(short) (progressBar + lowerEqualizerBandLevel));
}
}
} else {
mEqualizer.usePreset((short) (current - 1));
}
    }
});

This will get you started up and there will be other Listeners attached to the exoplayer as well.

Step 2: Creating a EqualizerActivity

So What I did was, I Created a EqualizerActivity and a PlayerActivity. I attached the session id of the app to initialize the Equalizer library and then stored the selected preset in the shared preferences, you can do the same with bands, but I only recommend it, in case you are allowing the user to create a custom preset.

You can initialize the Equalizer in EqualizerActivity.java OnCreate function

//in On Create
mEqualizer = new Equalizer(0, getTaskId());
mEqualizer.setEnabled(true);
// setup FX
mLinearLayout = (LinearLayout) findViewById(R.id.linearLayoutEqual);
mLinearLayout.setPadding(0, 0, 0, 20);

// get number frequency bands supported by the equalizer engine
short numberFrequencyBands = mEqualizer.getNumberOfBands();

// get the level ranges to be used in setting the band level
// get lower limit of the range in milliBels
final short lowerEqualizerBandLevel = mEqualizer.getBandLevelRange()[0];
// get the upper limit of the range in millibels
final short upperEqualizerBandLevel = mEqualizer.getBandLevelRange()[1];

Step 3: Setup UI of Equalizer

Now, Loop through all the bands and setup their UI, You can create the UI in Layouts folder and then populate it, or just simply, Popuate the FrameLayout like I did.

for (short i = 0; i < numberFrequencyBands; i++) {
final short equalizerBandIndex = i;

// frequency header for each seekBar
TextView frequencyHeaderTextview = new TextView(this);
frequencyHeaderTextview.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
frequencyHeaderTextview.setGravity(Gravity.CENTER_HORIZONTAL);
frequencyHeaderTextview
.setText((mEqualizer.getCenterFreq(equalizerBandIndex) / 1000) + " Hz");
mLinearLayout.addView(frequencyHeaderTextview);

// set up linear layout to contain each seekBar
LinearLayout seekBarRowLayout = new LinearLayout(this);
seekBarRowLayout.setOrientation(LinearLayout.HORIZONTAL);

// set up lower level textview for this seekBar
TextView lowerEqualizerBandLevelTextview = new TextView(this);
lowerEqualizerBandLevelTextview.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
lowerEqualizerBandLevelTextview.setText((lowerEqualizerBandLevel / 100) + " dB");
lowerEqualizerBandLevelTextview.setRotation(90);
// set up upper level textview for this seekBar
TextView upperEqualizerBandLevelTextview = new TextView(this);
upperEqualizerBandLevelTextview.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
upperEqualizerBandLevelTextview.setText((upperEqualizerBandLevel / 100) + " dB");
upperEqualizerBandLevelTextview.setRotation(90);


// ********** the seekBar **************
// set the layout parameters for the seekbar
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT - 60,
120);
layoutParams.weight = 1;

// create a new seekBar
SeekBar seekBar = new SeekBar(this);
// give the seekBar an ID
seekBar.setId(i);
ColorDrawable seekbg;
seekbg = new ColorDrawable(Color.parseColor(realThemeColor));
seekbg.setAlpha(90);
// seekBar.setBackground(new ColorDrawable(Color.rgb(201, 224, 203)));
seekBar.setBackground(seekbg);
seekBar.setPadding(35, 15, 35, 15);

seekBar.setLayoutParams(layoutParams);
seekBar.setMax(upperEqualizerBandLevel - lowerEqualizerBandLevel);
// set the progress for this seekBar
final int seek_id = i;
int progressBar = properties.preferences.getInt("seek_" + seek_id, 1500);
// Log.i("storedOld_seek_"+seek_id,":"+ progressBar);
if (progressBar != 1500) {
seekBar.setProgress(progressBar);
mEqualizer.setBandLevel(equalizerBandIndex,
(short) (progressBar + lowerEqualizerBandLevel));
} else {
seekBar.setProgress(mEqualizer.getBandLevel(equalizerBandIndex));
mEqualizer.setBandLevel(equalizerBandIndex,
(short) (progressBar + lowerEqualizerBandLevel));
}
// change progress as its changed by moving the sliders
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
mEqualizer.setBandLevel(equalizerBandIndex,
(short) (progress + lowerEqualizerBandLevel));

}

public void onStartTrackingTouch(SeekBar seekBar) {
//not used
}

public void onStopTrackingTouch(SeekBar seekBar) {
//not used
properties.edit_preferences.putInt("seek_" + seek_id, seekBar.getProgress()).commit();
properties.edit_preferences.putInt("position", 0).commit();
}
});

IconDrawable equalizer = new IconDrawable(this, FontAwesomeIcons.fa_minus_square).colorRes(R.color.colorAccent);
equalizer.actionBarSize();
seekBar.setThumb(equalizer);
seekBar.setProgressDrawable(new ColorDrawable(Color.rgb(56, 60, 62)));
// seekbar row layout settings. The layout is rotated at 270 so left=>bottom, Right=>top and so on
LinearLayout.LayoutParams seekBarLayout = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
);
seekBarLayout.weight = 1;
seekBarLayout.setMargins(5, 0, 5, 0);
seekBarRowLayout.setLayoutParams(seekBarLayout);

// add the lower and upper band level textviews and the seekBar to the row layout
seekBarRowLayout.addView(lowerEqualizerBandLevelTextview);
seekBarRowLayout.addView(seekBar);
seekBarRowLayout.addView(upperEqualizerBandLevelTextview);

mLinearLayout.addView(seekBarRowLayout);

// show the spinner
equalizeSound();
}
mLinearLayout.setRotation(270);
UI output of the code above

Summary: I populated the equalizer and stored it it’s preset in shared Preferences, if it was a custom preset, I stored the band levels in shared preferences and then retrieved them in the Player activity. The same can be done with mediaplayer, just go through the documentation to see what function would return it’s AudioSessionID