Last active
December 17, 2018 19:28
Error "java.lang.RuntimeException: Cannot initialize Visualizer engine, error: -3" while trying to execute
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 ... .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); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment