Skip to content

Instantly share code, notes, and snippets.

@graffiti75
Last active December 17, 2018 19:28

Revisions

  1. graffiti75 revised this gist Dec 17, 2018. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion AudioFxDemo.java
    Original file line number Diff line number Diff line change
    @@ -26,7 +26,7 @@

    import java.util.List;

    import br.cericatto.audioeffects.R;
    import ... .audioeffects.R;

    public class AudioFxDemo extends AppCompatActivity {
    private static final String TAG = AudioFxDemo.class.getSimpleName();
  2. graffiti75 created this gist Dec 17, 2018.
    241 changes: 241 additions & 0 deletions AudioFxDemo.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,241 @@
    import android.Manifest;
    import android.support.v7.app.AppCompatActivity;
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Rect;
    import android.media.AudioManager;
    import android.media.MediaPlayer;
    import android.media.audiofx.Equalizer;
    import android.media.audiofx.Visualizer;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.Gravity;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.LinearLayout;
    import android.widget.SeekBar;
    import android.widget.TextView;

    import com.karumi.dexter.Dexter;
    import com.karumi.dexter.MultiplePermissionsReport;
    import com.karumi.dexter.PermissionToken;
    import com.karumi.dexter.listener.PermissionRequest;
    import com.karumi.dexter.listener.multi.MultiplePermissionsListener;

    import java.util.List;

    import br.cericatto.audioeffects.R;

    public class AudioFxDemo extends AppCompatActivity {
    private static final String TAG = AudioFxDemo.class.getSimpleName();

    private static final float VISUALIZER_HEIGHT_DIP = 50f;

    private MediaPlayer mMediaPlayer;
    private Visualizer mVisualizer;
    private Equalizer mEqualizer;

    private LinearLayout mLinearLayout;
    private CustomVisualizerView mVisualizerView;
    private TextView mStatusTextView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setVolumeControlStream(AudioManager.STREAM_MUSIC);

    mStatusTextView = new TextView(this);

    mLinearLayout = new LinearLayout(this);
    mLinearLayout.setOrientation(LinearLayout.VERTICAL);
    mLinearLayout.addView(mStatusTextView);

    setContentView(mLinearLayout);
    // checkAudioPermissions();

    // Create the MediaPlayer
    mMediaPlayer = MediaPlayer.create(this, R.raw.a);
    Log.d(TAG, "MediaPlayer audio session ID: " + mMediaPlayer.getAudioSessionId());

    setupVisualizerFxAndUI();
    setupEqualizerFxAndUI();

    // Make sure the visualizer is enabled only when you actually want to receive data, and
    // when it makes sense to receive data.
    mVisualizer.setEnabled(true);

    // When the stream ends, we don't need to collect any more data. We don't do this in
    // setupVisualizerFxAndUI because we likely want to have more, non-Visualizer related code
    // in this callback.
    mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
    public void onCompletion(MediaPlayer mediaPlayer) {
    mVisualizer.setEnabled(false);
    }
    });

    mMediaPlayer.start();
    mStatusTextView.setText("Playing audio...");
    }

    private void checkAudioPermissions() {
    Dexter.withActivity(this)
    .withPermissions(Manifest.permission.MODIFY_AUDIO_SETTINGS, Manifest.permission.RECORD_AUDIO)
    .withListener(new MultiplePermissionsListener() {
    @Override public void onPermissionsChecked(MultiplePermissionsReport report) {
    if (report.isAnyPermissionPermanentlyDenied()) {
    finish();
    }
    }
    @Override public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {
    token.continuePermissionRequest();
    }
    }).check();
    }

    private void setupEqualizerFxAndUI() {
    // Create the Equalizer object (an AudioEffect subclass) and attach it to our media player,
    // with a default priority (0).
    mEqualizer = new Equalizer(0, mMediaPlayer.getAudioSessionId());
    mEqualizer.setEnabled(true);

    TextView eqTextView = new TextView(this);
    eqTextView.setText("Equalizer:");
    mLinearLayout.addView(eqTextView);

    short bands = mEqualizer.getNumberOfBands();

    final short minEQLevel = mEqualizer.getBandLevelRange()[0];
    final short maxEQLevel = mEqualizer.getBandLevelRange()[1];

    for (short i = 0; i < bands; i++) {
    final short band = i;

    TextView freqTextView = new TextView(this);
    freqTextView.setLayoutParams(new ViewGroup.LayoutParams(
    ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
    freqTextView.setGravity(Gravity.CENTER_HORIZONTAL);
    freqTextView.setText((mEqualizer.getCenterFreq(band) / 1000) + " Hz");
    mLinearLayout.addView(freqTextView);

    LinearLayout row = new LinearLayout(this);
    row.setOrientation(LinearLayout.HORIZONTAL);

    TextView minDbTextView = new TextView(this);
    minDbTextView.setLayoutParams(new ViewGroup.LayoutParams(
    ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
    minDbTextView.setText((minEQLevel / 100) + " dB");

    TextView maxDbTextView = new TextView(this);
    maxDbTextView.setLayoutParams(new ViewGroup.LayoutParams(
    ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
    maxDbTextView.setText((maxEQLevel / 100) + " dB");

    LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
    ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    layoutParams.weight = 1;
    SeekBar bar = new SeekBar(this);
    bar.setLayoutParams(layoutParams);
    bar.setMax(maxEQLevel - minEQLevel);
    bar.setProgress(mEqualizer.getBandLevel(band));
    bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
    mEqualizer.setBandLevel(band, (short) (progress + minEQLevel));
    }

    public void onStartTrackingTouch(SeekBar seekBar) {}
    public void onStopTrackingTouch(SeekBar seekBar) {}
    });

    row.addView(minDbTextView);
    row.addView(bar);
    row.addView(maxDbTextView);
    mLinearLayout.addView(row);
    }
    }

    private void setupVisualizerFxAndUI() {
    // Create a VisualizerView (defined below), which will render the simplified audio
    // wave form to a Canvas.
    mVisualizerView = new CustomVisualizerView(this);
    mVisualizerView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
    (int)(VISUALIZER_HEIGHT_DIP * getResources().getDisplayMetrics().density)));
    mLinearLayout.addView(mVisualizerView);

    // Create the Visualizer object and attach it to our media player.
    mVisualizer = new Visualizer(mMediaPlayer.getAudioSessionId());
    mVisualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1]);
    mVisualizer.setDataCaptureListener(new Visualizer.OnDataCaptureListener() {
    public void onWaveFormDataCapture(Visualizer visualizer, byte[] bytes, int samplingRate) {
    mVisualizerView.updateVisualizer(bytes);
    }

    public void onFftDataCapture(Visualizer visualizer, byte[] bytes, int samplingRate) {}
    }, Visualizer.getMaxCaptureRate() / 2, true, false);
    }

    @Override
    protected void onPause() {
    super.onPause();
    if (isFinishing() && mMediaPlayer != null) {
    mVisualizer.release();
    mEqualizer.release();
    mMediaPlayer.release();
    mMediaPlayer = null;
    }
    }
    }

    /**
    * A simple class that draws waveform data received from a
    * {@link Visualizer.OnDataCaptureListener#onWaveFormDataCapture }
    */
    class CustomVisualizerView extends View {
    private byte[] mBytes;
    private float[] mPoints;
    private Rect mRect = new Rect();

    private Paint mForePaint = new Paint();

    public CustomVisualizerView(Context context) {
    super(context);
    init();
    }

    private void init() {
    mBytes = null;
    mForePaint.setStrokeWidth(1f);
    mForePaint.setAntiAlias(true);
    mForePaint.setColor(Color.rgb(0, 128, 255));
    }

    public void updateVisualizer(byte[] bytes) {
    mBytes = bytes;
    invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    if (mBytes == null) {
    return;
    }

    if (mPoints == null || mPoints.length < mBytes.length * 4) {
    mPoints = new float[mBytes.length * 4];
    }

    mRect.set(0, 0, getWidth(), getHeight());
    for (int i = 0; i < mBytes.length - 1; i++) {
    mPoints[i * 4] = mRect.width() * i / (mBytes.length - 1);
    mPoints[i * 4 + 1] = mRect.height() / 2
    + ((byte) (mBytes[i] + 128)) * (mRect.height() / 2) / 128;
    mPoints[i * 4 + 2] = mRect.width() * (i + 1) / (mBytes.length - 1);
    mPoints[i * 4 + 3] = mRect.height() / 2
    + ((byte) (mBytes[i + 1] + 128)) * (mRect.height() / 2) / 128;
    }
    canvas.drawLines(mPoints, mForePaint);
    }
    }