问题
Well, simply this is my requirement..
I have a WAV file, I want to open it, add some effects, and play.
I am using MediaPlayer to play 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 am getting a log in logcat(Not logged by me.)
05-02 12:02:42.356: E/MediaPlayer(17250): Error (-22,0)
But when I comment 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 is playing the file successfully. So nothing wrong with my WAV file.
Being somewhat 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 also I got the same error (Error (-22,0)).
So either I am missing something so obvious, or there is some problem with AudioEffect family classes (in documentation or api itself). Can anyone shed some light?
EDIT : I forgot to add, when I debugged the code the error is logged when
player.start();
is executed. I have removed exception handling parts before posting the code segment above. But I am positive, no exception is caught when I executed.
EDIT AGAIN :
From this link I came to understand 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 of DRM Content without a Valid License Available
A variation on the scenario covered in Section 14.10.3 is the case where there is no valid license for full playback of a piece of content, but there it can be previewed. This scenario might be a common way of initially distributing content so that consumers can preview it before deciding to purchase a full license. In this case the Init() method will return with the code PVMFErrLicenseRequiredPreviewAvailable, which indicates that a license is required for full playback but a preview is available. In order to play the preview, the application must remove the current source then add it back with a flag set on the local data source to indicate preview mode.
Now the WAV files I played is generated by me using SpeechToText tool in android SDK itself. I don't know what license holding me from playing this file.
回答1:
Well, I got it working at last. I reread the documentation, played with the code and suddenly everything worked. These are my findings in case it helps anyone in future.
In the case of PresetReverb
In presetReverb documentation
The PresetReverb is an output mix auxiliary effect and should be created on Audio session 0. In order for a MediaPlayer or AudioTrack to be fed into this effect, they must be explicitely attached to it and a send level must be specified. Use the effect ID returned by getId() method to designate this particular effect when attaching it to the MediaPlayer or AudioTrack.
That says
PresetReverb pReverb = new PresetReverb(0,player.getAudioSessionId()); <== error
is not allowed. You can only use global audio session 0 to construct PresetReverb.
PresetReverb pReverb = new PresetReverb(1,0); <== correct
Now we can attach it with MediaPlayer or AudioTrack using
player.attachAuxEffect(pReverb.getId());
player.setAuxEffectSendLevel(1.0f);
My full PresetReverb code is
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 good reverb effect or echo, better use EnvironmentalReverb. I am somewhat disappointed with the performance of PresetReverb.
In the case of EnvironmentalReverb
From the documentation of EnvironmentalReverb
The EnvironmentalReverb is an output mix auxiliary effect and should be created on Audio session 0. In order for a MediaPlayer or AudioTrack to be fed into this effect, they must be explicitely attached to it and a send level must be specified. Use the effect ID returned by getId() method to designate this particular effect when attaching it to the MediaPlayer or AudioTrack.
Exactly 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 error and I get good reverb effect and echo. So It seems like a bug in documentation. Also when we pass session id of player to the constructor(player.getAudioSessionId()), there seems to be no need to attach player with EnvironmentalReverb instance. Strange..
For sake of completeness this one also worked just as documentation says.
EnvironmentalReverb eReverb
= new EnvironmentalReverb(0,0);
player.attachAuxEffect(eReverb.getId()); <== No,not comment this one
For other AudioEffect childrens (Equalizer, BassBoost, Virtualizer)
These ones were not the part of my question. But for everyone who sees this in the future..
NOTE: attaching insert effects (equalizer, bass boost, virtualizer) to the global audio output mix by use of session 0 is deprecated.
see documentation
Regarding Error (-22,0)
Well, fair to say it was not an informative error message. I don't know why an Invalid license error comes up when we mess up audio session. Anyway when I corrected the audio session parameter this error vanished. Thats all I know.
回答2:
I got the same issue, to use the audio session 0 you have to use the permission MODIFY_AUDIO_SETTINGS
回答3:
This line in essence, solved one of the problems, but it still required permissions.
PresetReverb pReverb = new PresetReverb(1,0);
So adding the line below to your AndroidManifest.xml actually solved the root problem:
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
OH, also, you need to set up PresetReverb and attach it to your AudioTrack to occur BEFORE you do the AudioTrack.write() and AudioTrack.play().
来源:https://stackoverflow.com/questions/10409122/android-mediaplayer-with-audioeffect-getting-error-22-0