I wrote an app which records my voice and plays it back. For the playback part, I have used a recyclerview. Each item describes/puts a certain effect on the audio capture. For now, I just used the PresetReverb effect and played with its configurations like LargeRoom, LargeHall etc. When I click through the items, then I hear my voice with some effect on it as expected but after a while it crashes.
For the sake of brevity I want to show the ViewHolder class of the RecyclerView because that inner class listens for which item is clicked and based on that it calls the right method to put the desired effect:
public class SoundEffectAdapter extends RecyclerView.Adapter<SoundEffectAdapter.ViewHolder> {
// ...
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private CardView mCardView;
public ViewHolder(CardView v){
super(v);
v.setOnClickListener(this);
mCardView = v;
}
@Override
public void onClick(View view) {
TextView mTextView = (TextView) mCardView.findViewById(R.id.soundEffectName);
String soundEffect = mTextView.getText().toString();
//Log.d("Sound", "" + soundEffect);
switch (soundEffect){
case "LargeRoom":
Log.d("Sound", "LargeRoom is clicked");
presetReverbWithLargeRoom();
break;
case "LargeHall":
Log.d("Sound", "LargeHall is clicked");
presetReverbWithLargeHall();
break;
case "MediumHall":
Log.d("Sound", "MediumHall is clicked");
presetReverbWithMediumHall();
break;
case "MediumRoom":
Log.d("Sound", "MediumRoom is clicked");
presetReverbWithMediumRoom();
break;
case "SmallRoom":
Log.d("Sound", "SmallRoom is clicked");
presetReverbWithSmallRoom();
break;
case "EnvironmentalReverb":
Log.d("Sound", "EnvironmentalReverb is clicked");
environmentalReverb();
break;
}
}
/* wrapper for the PRESET_ENVIRONMENTALREVERB effect*/
private void environmentalReverb() {
PresetReverbMethods presetReverb = new PresetReverbMethods();
presetReverb.environmentalReverb();
}
/* wrapper for the PRESET_SMALLROOM effect*/
private void presetReverbWithSmallRoom() {
PresetReverbMethods presetReverb = new PresetReverbMethods();
presetReverb.smallRoom();
}
/* wrapper for the PRESET_MEDIUMROOM effect*/
private void presetReverbWithMediumRoom() {
PresetReverbMethods presetReverb = new PresetReverbMethods();
presetReverb.mediumRoom();
}
/* wrapper for the PRESET_MEDIUMHALL effect*/
private void presetReverbWithMediumHall() {
PresetReverbMethods presetReverb = new PresetReverbMethods();
presetReverb.mediumHall();
}
/* wrapper for the PRESET_LARGEHALL effect*/
private void presetReverbWithLargeHall() {
PresetReverbMethods presetReverb = new PresetReverbMethods();
presetReverb.largeHall();
}
/* wrapper for the PRESET_LARGEROOM effect*/
private void presetReverbWithLargeRoom() {
PresetReverbMethods presetReverb = new PresetReverbMethods();
presetReverb.largeRoom();
}
// ... OTHER METHODS OF THE ADAPTER
// .... onCreateViewHolder() etc.
}
}
Now, the methods are defined in PresetReverbMethods.java:
public class PresetReverbMethods {
public MediaPlayer mMediaPlayer;
public PresetReverbMethods() {
mMediaPlayer = new MediaPlayer();
}
public void largeRoom(){
mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.i(TAG, "onError called..." + " what: " + what + " extra: " + extra);
switch (what) {
case MediaPlayer.MEDIA_ERROR_UNKNOWN:
Log.i(TAG, "Unknown error: " + extra);
return true;
case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
Log.i(TAG, "Server died error: " + extra);
return true;
default:
Log.i(TAG, "Error not handled");
return false;
}
}
});
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
//called if
// no error listener set or
// if error listener returns false and
// when end of media source reached
Log.i(TAG, "in on completion listener");
// the player object is now in the PlaybackCompleted state.
}
});
try {
//transfers player from Idle state into initialized state
mMediaPlayer.setDataSource(FILE_NAME);
} catch (IOException e) {
Log.e(TAG, "IOException: " + e);
} catch (IllegalArgumentException e) {
Log.e(TAG, "IllegalArgumentException: " + e);
}
// asynchronously prepares the player for playback
mMediaPlayer.prepareAsync();
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
/* PresetReverbMethods with PRESET_LARGEROOM */
android.media.audiofx.PresetReverb mReverb = new android.media.audiofx.PresetReverb(0,mMediaPlayer.getAudioSessionId());
mReverb.setPreset(PresetReverb.PRESET_LARGEROOM);
mReverb.setEnabled(true);
mMediaPlayer.setAuxEffectSendLevel(1.0f);
// the media source is now ready for playback
mMediaPlayer.start();
}
});
}
public void largeHall(){
mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.i(TAG, "onError called..." + " what: " + what + " extra: " + extra);
switch (what) {
case MediaPlayer.MEDIA_ERROR_UNKNOWN:
Log.i(TAG, "Unknown error: " + extra);
return true;
case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
Log.i(TAG, "Server died error: " + extra);
return true;
default:
Log.i(TAG, "Error not handled");
return false;
}
}
});
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
//called if
// no error listener set or
// if error listener returns false and
// when end of media source reached
Log.i(TAG, "in on completion listener");
// the player object is now in the PlaybackCompleted state.
}
});
try {
//transfers player from Idle state into initialized state
mMediaPlayer.setDataSource(FILE_NAME);
} catch (IOException e) {
Log.e(TAG, "IOException: " + e);
} catch (IllegalArgumentException e) {
Log.e(TAG, "IllegalArgumentException: " + e);
}
// asynchronously prepares the player for playback
mMediaPlayer.prepareAsync();
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
/* PresetReverbMethods with PRESET_LARGEROOM */
android.media.audiofx.PresetReverb mReverb = new android.media.audiofx.PresetReverb(0,mMediaPlayer.getAudioSessionId());
mReverb.setPreset(PresetReverb.PRESET_LARGEHALL);
mReverb.setEnabled(true);
mMediaPlayer.setAuxEffectSendLevel(1.0f);
// the media source is now ready for playback
mMediaPlayer.start();
}
});
}
public void mediumHall(){
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.i(TAG, "onError called..." + " what: " + what + " extra: " + extra);
switch (what) {
case MediaPlayer.MEDIA_ERROR_UNKNOWN:
Log.i(TAG, "Unknown error: " + extra);
return true;
case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
Log.i(TAG, "Server died error: " + extra);
return true;
default:
Log.i(TAG, "Error not handled");
return false;
}
}
});
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
//called if
// no error listener set or
// if error listener returns false and
// when end of media source reached
Log.i(TAG, "in on completion listener");
// the player object is now in the PlaybackCompleted state.
}
});
try {
//transfers player from Idle state into initialized state
mMediaPlayer.setDataSource(FILE_NAME);
} catch (IOException e) {
Log.e(TAG, "IOException: " + e);
} catch (IllegalArgumentException e) {
Log.e(TAG, "IllegalArgumentException: " + e);
}
// asynchronously prepares the player for playback
mMediaPlayer.prepareAsync();
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
/* PresetReverbMethods with PRESET_LARGEROOM */
android.media.audiofx.PresetReverb mReverb = new android.media.audiofx.PresetReverb(0,mMediaPlayer.getAudioSessionId());
mReverb.setPreset(PresetReverb.PRESET_MEDIUMHALL);
mReverb.setEnabled(true);
mMediaPlayer.setAuxEffectSendLevel(1.0f);
// the media source is now ready for playback
mMediaPlayer.start();
}
});
}
public void mediumRoom() {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.i(TAG, "onError called..." + " what: " + what + " extra: " + extra);
switch (what) {
case MediaPlayer.MEDIA_ERROR_UNKNOWN:
Log.i(TAG, "Unknown error: " + extra);
return true;
case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
Log.i(TAG, "Server died error: " + extra);
return true;
default:
Log.i(TAG, "Error not handled");
return false;
}
}
});
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
//called if
// no error listener set or
// if error listener returns false and
// when end of media source reached
Log.i(TAG, "in on completion listener");
// the player object is now in the PlaybackCompleted state.
}
});
try {
//transfers player from Idle state into initialized state
mMediaPlayer.setDataSource(FILE_NAME);
} catch (IOException e) {
Log.e(TAG, "IOException: " + e);
} catch (IllegalArgumentException e) {
Log.e(TAG, "IllegalArgumentException: " + e);
}
// asynchronously prepares the player for playback
mMediaPlayer.prepareAsync();
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
/* PresetReverbMethods with PRESET_LARGEROOM */
android.media.audiofx.PresetReverb mReverb = new android.media.audiofx.PresetReverb(0,mMediaPlayer.getAudioSessionId());
mReverb.setPreset(PresetReverb.PRESET_MEDIUMROOM);
mReverb.setEnabled(true);
mMediaPlayer.setAuxEffectSendLevel(1.0f);
// the media source is now ready for playback
mMediaPlayer.start();
}
});
}
public void smallRoom() {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.i(TAG, "onError called..." + " what: " + what + " extra: " + extra);
switch (what) {
case MediaPlayer.MEDIA_ERROR_UNKNOWN:
Log.i(TAG, "Unknown error: " + extra);
return true;
case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
Log.i(TAG, "Server died error: " + extra);
return true;
default:
Log.i(TAG, "Error not handled");
return false;
}
}
});
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
//called if
// no error listener set or
// if error listener returns false and
// when end of media source reached
Log.i(TAG, "in on completion listener");
// the player object is now in the PlaybackCompleted state.
}
});
try {
//transfers player from Idle state into initialized state
mMediaPlayer.setDataSource(FILE_NAME);
} catch (IOException e) {
Log.e(TAG, "IOException: " + e);
} catch (IllegalArgumentException e) {
Log.e(TAG, "IllegalArgumentException: " + e);
}
// asynchronously prepares the player for playback
mMediaPlayer.prepareAsync();
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
android.media.audiofx.PresetReverb mReverb = new android.media.audiofx.PresetReverb(0,mMediaPlayer.getAudioSessionId());
mReverb.setPreset(PresetReverb.PRESET_SMALLROOM);
mReverb.setEnabled(true);
mMediaPlayer.setAuxEffectSendLevel(1.0f);
mMediaPlayer.start();
}
});
}
public void environmentalReverb(){
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.i(TAG, "onError called..." + " what: " + what + " extra: " + extra);
switch (what) {
case MediaPlayer.MEDIA_ERROR_UNKNOWN:
Log.i(TAG, "Unknown error: " + extra);
return true;
case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
Log.i(TAG, "Server died error: " + extra);
return true;
default:
Log.i(TAG, "Error not handled");
return false;
}
}
});
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
Log.i(TAG, "in on completion listener");
}
});
try {
mMediaPlayer.setDataSource(FILE_NAME);
} catch (IOException e) {
Log.e(TAG, "IOException: " + e);
} catch (IllegalArgumentException e) {
Log.e(TAG, "IllegalArgumentException: " + e);
} catch (RuntimeException e){
Log.e(TAG, "RuntimeException: " + e.getMessage() );
}
// asynchronously prepares the player for playback
mMediaPlayer.prepareAsync();
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
EnvironmentalReverb environmentalReverb = new EnvironmentalReverb(0, mMediaPlayer.getAudioSessionId());
environmentalReverb.setRoomLevel((short) -1000);
environmentalReverb.setRoomHFLevel((short) -500);
environmentalReverb.setDecayTime(3920);
environmentalReverb.setDecayHFRatio((short) 700);
environmentalReverb.setReflectionsLevel((short) -1230);
environmentalReverb.setReflectionsDelay(20);
environmentalReverb.setReverbLevel((short) -2);
environmentalReverb.setReverbDelay(29);
environmentalReverb.setDiffusion((short) 1000);
environmentalReverb.setDensity((short) 1000);
environmentalReverb.setEnabled(true);
mMediaPlayer.start();
}
});
}
}
When I start the app, everything is fine. But after testing the effects on the audio I made, it crashes with the following error message:
04-23 16:25:24.999 21821-21821/com.celik.abdullah.presetreverb
E/AudioEffect: set(): AudioFlinger could not create effect, status:
-38 04-23 16:25:24.999 21821-21821/com.celik.abdullah.presetreverb E/AudioEffects-JNI: Error setting AudioEffect 04-23 16:25:24.999
21821-21821/com.celik.abdullah.presetreverb E/AudioEffect-JAVA: Error
code -19 when initializing AudioEffect. 04-23 16:25:25.000
21821-21821/com.celik.abdullah.presetreverb D/AndroidRuntime: Shutting
down VM 04-23 16:25:25.005 21821-21821/com.celik.abdullah.presetreverb
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.celik.abdullah.presetreverb, PID: 21821
java.lang.RuntimeException: Cannot initialize effect engine for type: 47382d60-ddd8-11db-bf3a-0002a5d5c51b Error: -19
at android.media.audiofx.AudioEffect.<init>(AudioEffect.java:425)
at android.media.audiofx.PresetReverb.<init>(PresetReverb.java:128)
at com.celik.abdullah.presetreverb.PresetReverbMethods$15.onPrepared(PresetReverbMethods.java:347)
at android.media.MediaPlayer$EventHandler.handleMessage(MediaPlayer.java:3824)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386)
Here, the GIF I have made to visualize the whole problem better(one can not see it, but I click on each of the recyclerview items until the app crashes):
Why is this happening? What do I need to do better? Thanks in advance for your effort.