简体   繁体   English

带有AudioEffect的Android MediaPlayer:出错(-22,0)

[英]Android MediaPlayer with AudioEffect : Getting Error (-22,0)

Well, simply this is my requirement.. 嗯,这只是我的要求..

I have a WAV file, I want to open it, add some effects, and play. 我有一个WAV文件,我想打开它,添加一些效果,然后播放。

I am using MediaPlayer to play file, and PresetReverb to add some effects. 我使用MediaPlayer播放文件,而PresetReverb则添加一些效果。

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.) 当我运行此代码时,我正在登录logcat(我没有记录。)

05-02 12:02:42.356: E/MediaPlayer(17250): Error (-22,0) 05-02 12:02:42.356:E / MediaPlayer(17250):错误(-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. MediaPlayer正在成功播放该文件。 So nothing wrong with my WAV file. 所以我的WAV文件没有错。

Being somewhat let down, I tried EnvironmentalReverb , instead of PresetReverb, 有点失望,我尝试了EnvironmentalReverb ,而不是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)). 我也得到了同样的错误(错误(-22,0))。

So either I am missing something so obvious, or there is some problem with AudioEffect family classes (in documentation or api itself). 所以要么我缺少一些如此明显的东西,要么AudioEffect系列类存在一些问题(在文档或api本身)。 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 这个链接我开始明白错误-22是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. 我用PVMFErrLicenseRequiredPreviewAvailable搜索了,我得到了这个文件。 And on page 87 并在第87页

14.10.5 Preview of DRM Content without a Valid License Available 14.10.5在没有有效许可证的情况下预览DRM内容

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. 第14.10.3节中介绍的场景的变体是没有有效许可证来完整播放一段内容,但可以预览它。 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. 在这种情况下,Init()方法将返回代码PVMFErrLicenseRequiredPreviewAvailable,这表示完全播放需要许可证,但预览可用。 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. 现在我播放的WAV文件是由我在android SDK本身使用SpeechToText工具生成的。 I don't know what license holding me from playing this file. 我不知道什么牌照让我玩这个文件。

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 在PresetReverb的情况下

In presetReverb documentation 在presetReverb文档中

The PresetReverb is an output mix auxiliary effect and should be created on Audio session 0 . PresetReverb是输出混合辅助效果, 应在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 . 为了将MediaPlayer或AudioTrack提供给此效果,必须明确地将它们附加到它,并且必须指定发送级别 Use the effect ID returned by getId() method to designate this particular effect when attaching it to the MediaPlayer or AudioTrack. 使用getId()方法返回的效果ID在将其附加到MediaPlayer或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. 您只能使用全局音频会话0来构建PresetReverb。

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

Now we can attach it with MediaPlayer or AudioTrack using 现在我们可以使用MediaPlayer或AudioTrack附加它

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

My full PresetReverb code is 我的完整PresetReverb代码是

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. 注意:如果您正在寻找良好的混响效果或回声,请更好地使用EnvironmentalReverb。 I am somewhat disappointed with the performance of PresetReverb. 我对PresetReverb的表现感到有些失望。

In the case of EnvironmentalReverb 在EnvironmentalReverb的情况下

From the documentation of EnvironmentalReverb 来自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 . EnvironmentalReverb是输出混合辅助效果,应在音频会话0上创建。为了将MediaPlayer或AudioTrack提供给此效果,必须明确地将它们附加到它,并且必须指定发送级别 Use the effect ID returned by getId() method to designate this particular effect when attaching it to the MediaPlayer or AudioTrack. 使用getId()方法返回的效果ID在将其附加到MediaPlayer或AudioTrack时指定此特定效果。

Exactly like PresetReverb, but when I wrote 完全像PresetReverb,但是当我写作时

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. 此外,当我们将播放器的会话ID传递给构造函数(player.getAudioSessionId())时,似乎不需要使用EnvironmentalReverb实例附加播放器。 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) 对于其他AudioEffect儿童(均衡器,BassBoost,虚拟器)

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. 注意:不建议使用会话0将插入效果(均衡器,低音增强,虚拟器)附加到全局音频输出混音。

see documentation 文档

Regarding Error (-22,0) 关于错误(-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. 这是我所知道的一切。

我遇到了同样的问题,使用音频会话0你必须使用权限MODIFY_AUDIO_SETTINGS

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: 因此,将下面的行添加到AndroidManifest.xml实际上解决了根本问题:

<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(). 此外,您需要设置PresetReverb并将其附加到AudioTrack,以便您执行AudioTrack.write()和AudioTrack.play()之前进行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM