Android MediaPlayer with AudioEffect: getting error (-22.0)

Well, it's just my requirement.

I have a wav file, I want to open it, add some effects and play.

I use MediaPlayer to play the file, and PresetReverb to add some effects.

This is my code.

public void playSound(){ String fullPath = MainActivity.this.filePath + "tmpaudio.wav"; final MediaPlayer player = new MediaPlayer(); player.setDataSource(this, Uri.parse(fullPath)); PresetReverb pReverb = new PresetReverb(0,player.getAudioSessionId()); pReverb.setPreset(PresetReverb.PRESET_LARGEROOM); pReverb.setEnabled(true); player.attachAuxEffect(eReverb.getId()); player.setAuxEffectSendLevel(1.0f); //prepare for playback player.prepare(); // Media prepared listener player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { public void onPrepared(MediaPlayer mp) { //play player.start(); } }); } 

When I run this code, I get logcat log (not logged by me.)

05-02 12: 02: 42.356: E / MediaPlayer (17250): error (-22.0)

But when I comment on these lines

 PresetReverb pReverb = new PresetReverb(0,player.getAudioSessionId()); pReverb.setPreset(PresetReverb.PRESET_LARGEROOM); pReverb.setEnabled(true); player.attachAuxEffect(eReverb.getId()); player.setAuxEffectSendLevel(1.0f); 

MediaPlayer successfully plays the file. So there is nothing wrong with my wav file.

Having been a little let down, I tried EnvironmentalReverb instead of PresetReverb,

 EnvironmentalReverb eReverb = new EnvironmentalReverb(1, player.getAudioSessionId()); eReverb.setDecayHFRatio((short) 1000); eReverb.setDecayTime(10000); eReverb.setDensity((short) 1000); eReverb.setDiffusion((short) 1000); eReverb.setReverbLevel((short) -1000); eReverb.setEnabled(true); player.attachAuxEffect(eReverb.getId()); player.setAuxEffectSendLevel(1.0f); 

there I also got the same error (Error (-22,0)).

So either I miss something so obvious, or there is a problem with the AudioEffect family classes (in the documentation or in the api itself). Can anyone shed some light?

EDIT: I forgot to add when I debugged the code, an error is logged when

  player.start(); 
Performed

. I removed the exception handling parts before posting the code segment above. But I'm sure no exception is caught when I executed.

EDIT AGAIN:

From this link, I realized that error -22 is PVMFErrLicenseRequiredPreviewAvailable

 /* Error due to the lack of a valid license for the content. However a preview is available. */ const PVMFStatus PVMFErrLicenseRequiredPreviewAvailable = (-22); 

I googled with PVMFErrLicenseRequiredPreviewAvailable and I got this document. And on page 87

14.10.5 Preview DRM Content Without Available Available License

The scenario variant described in Section 14.10.3 occurs when there is no valid license to fully reproduce part of the content, but there you can view it. This scenario may be a common way to initially distribute content so that users can view it before deciding to purchase a full license. In this case, the Init () method will return with the code PVMFErrLicenseRequiredPreviewAvailable, which means that a license is required for full playback, but a preview is available. To play a preview, the application must delete the current source, then add it back with the flag set in the local data source to indicate the preview mode.

Now the WAV files that I played are generated by me using the SpeechToText tool in the Android SDK itself. I do not know which license is keeping me from playing this file.

+6
source share
3 answers

Okay, I finally got into it. I re-read the documentation, played with the code, and suddenly everything worked. These are my findings in case this helps someone in the future.

In the case of PresetReverb

In the presetReverb documentation

PresetReverb is an auxiliary effect of the output mix, and should be created in the audio session 0 . For MediaPlayer or AudioTrack to be used in this effect, they must be explicit and the send level must be specified . Use the effect identifier returned by the getId () method to indicate this particular effect when attaching it to MediaPlayer or AudioTrack.

It says

 PresetReverb pReverb = new PresetReverb(0,player.getAudioSessionId()); <== error 

is not allowed. You can use the global audio 0 session to create a PresetReverb.

 PresetReverb pReverb = new PresetReverb(1,0); <== correct 

Now we can connect it using MediaPlayer or AudioTrack using

 player.attachAuxEffect(pReverb.getId()); player.setAuxEffectSendLevel(1.0f); 

My complete PresetReverb code

 PresetReverb pReverb = new PresetReverb(1,0); player.attachAuxEffect(pReverb.getId()); pReverb.setPreset(PresetReverb.PRESET_LARGEROOM); pReverb.setEnabled(true); player.setAuxEffectSendLevel(1.0f); 

Note: If you are looking for a good reverb or echo effect, it is better to use EnvironmentalReverb. I am somewhat disappointed with PresetReverb.

In the case of EnvironmentalReverb

From EnvironmentalReverb documentation

EnvironmentalReverb is an auxiliary effect of output mixing and must be created in an audio 0 session. In order for MediaPlayer or AudioTrack to be used in this effect, they must be explicit and the send level must be specified . Use the effect identifier returned by the getId () method to indicate this particular effect when attaching it to MediaPlayer or AudioTrack.

Just like PresetReverb, but when I wrote

 Log.e("DEBUG","sessionId : " + player.getAudioSessionId()); <== printed "454" EnvironmentalReverb eReverb = new EnvironmentalReverb(0,player.getAudioSessionId()); //should be error as per documentation //player.attachAuxEffect(eReverb.getId()); <== Yes this one was commented 

there was no mistake, and I get a good reverb and echo effect. So this seems like a bug in the documentation. Also, when we pass the session identifier to the player constructor (player.getAudioSessionId ()), it seems that there is no need to attach the player with an EnvironmentalReverb instance. Strange ..

For completeness, this work also worked as written in the documentation.

 EnvironmentalReverb eReverb = new EnvironmentalReverb(0,0); player.attachAuxEffect(eReverb.getId()); <== No,not comment this one 

For other children AudioEffect (Equalizer, BassBoost, Virtualizer)

These were not part of my question. But for everyone who sees this in the future.

NOTE: adding insert effects (equalizer, bass boost, virtualizer) to the global audio output using session 0 is deprecated.

see documentation

Regarding error (-22.0)

Well, to be honest, this is not an informative error message. I don’t know why the error Invalid license error occurs when we ruined the audio session. Anyway, when I corrected the audio session parameter, this error disappeared. That's all what I know.

+12
source

I have the same problem to use audio session 0, you need to use MODIFY_AUDIO_SETTINGS permission

+1
source

This line, in fact, solved one of the problems, but it still required permission.

 PresetReverb pReverb = new PresetReverb(1,0); 

So, adding the line below to your AndroidManifest.xml, the root problem was actually solved:

 <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> 

OH, also you need to configure PresetReverb and attach it to your AudioTrack so that it appears BEFORE you use AudioTrack.write () and AudioTrack.play ().

0
source

Source: https://habr.com/ru/post/914700/


All Articles