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

8

好的,简单来说这是我的要求...

我有一个WAV文件,我想打开它,添加一些效果,然后播放。

我使用 MediaPlayer 播放文件,并使用 PresetReverb 添加一些效果。

以下是我的代码

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();
      } 
   });
}

当我运行这段代码时,我在logcat中得到一个日志(不是我记录的)。

05-02 12:02:42.356: E/MediaPlayer(17250): Error (-22,0)

但是当我注释掉这些行时,问题就解决了。
PresetReverb pReverb = new PresetReverb(0,player.getAudioSessionId());
pReverb.setPreset(PresetReverb.PRESET_LARGEROOM);
pReverb.setEnabled(true);
player.attachAuxEffect(eReverb.getId());
player.setAuxEffectSendLevel(1.0f);

MediaPlayer正在成功播放文件,所以我的WAV文件没有问题。

感到有些失望后,我尝试使用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);

我在那里也遇到了相同的错误(错误代码为-22,0)。

所以要么我漏掉了一些非常明显的东西,要么AudioEffect家族类存在一些问题(无论是文档还是api本身)。有人可以解释一下吗?

编辑:我忘记添加了,当我调试代码时,错误被记录下来。

 player.start();

代码段被执行。在发布上述代码段之前,我已删除异常处理部分。但我确定,在执行时没有捕获到任何异常。

再次编辑:

这个链接中,我了解到错误-22是PVMFErrLicenseRequiredPreviewAvailable。

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

我使用PVMFErrLicenseRequiredPreviewAvailable进行谷歌搜索,找到了this文档。在第87页上,有一种情况是当某个内容没有有效的许可证用于完全播放时,但可以预览该内容。这种情况下,Init()方法将返回代码PVMFErrLicenseRequiredPreviewAvailable,表示需要许可证才能完全播放,但可提供预览。为了播放预览,应用程序必须删除当前源,然后添加带有本地数据源标志设置为预览模式的源。现在,我所播放的WAV文件是由我自己使用Android SDK中的SpeechToText工具生成的。我不知道什么许可证阻止我播放此文件。

嗨,Krishnabhadra,我尝试了你的解决方案,但在我的设备上没有发现任何回声效果。你能否请发送给我你的示例代码?先谢谢了。 - Rojesh
我在我的案例中遇到了错误(1,-22)。这是相同的问题吗? - Konstantin Konopko
3个回答

15

最终我让它工作了。我重新阅读了文档,玩弄了一下代码,突然间一切都起作用了。以下是我的发现,希望对未来的任何人有所帮助。

关于PresetReverb

在PresetReverb的文档中

PresetReverb是一个输出混音辅助效果,应该在音频会话0上创建为了将MediaPlayer或AudioTrack输入到此效果中,必须显式地将它们附加到该效果并指定发送级别。使用getId()方法返回的效果ID来指定MediaPlayer或AudioTrack附加到该特定效果时使用的效果。

这意味着

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

不被允许。您只能使用全局音频会话0来构建PresetReverb。

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

现在我们可以使用MediaPlayer或AudioTrack将其附加。

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

我的完整PresetReverb代码是

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

注意: 如果您正在寻找良好的混响效果或回声,请使用EnvironmentalReverb。我对PresetReverb的性能有些失望。

关于EnvironmentalReverb

根据EnvironmentalReverb的文档

EnvironmentalReverb是一个输出混音附加效果,应在音频会话0上创建。为了让MediaPlayer或AudioTrack输入此效果,必须明确地将它们附加到该效果,并指定发送级别。在将其附加到MediaPlayer或AudioTrack时,请使用getId()方法返回的效果ID来指定此特定效果。

与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

没出现错误,成功获得了良好的混响效果和回声。因此看起来是文档中的一个bug。同时,当我们将播放器的会话ID传递给构造函数(player.getAudioSessionId()),似乎没有必要将播放器与EnvironmentalReverb实例附加。奇怪。

为了完整起见,这个也按照文档所说正常工作。

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

针对其他音频效果组件(Equalizer、BassBoost、Virtualizer)

这些组件并不是我的问题的一部分,但是对于未来看到此问题的任何人...

注意:使用会话0将插入效果(均衡器、低音增强、虚拟增强器)连接到全局音频输出混音已被弃用。

请参阅文档

关于错误(-22,0)

可以说这个错误信息并不详细。我不知道为什么会出现无效许可证错误,当我们搞砸音频会话时会发生什么。不管怎样,当我更正了音频会话参数时,这个错误就消失了。这就是我所知道的全部。


非常好的解释。我将实现均衡器。按照您所说的做了,但在构建均衡器时崩溃了。那么应该怎么解决呢?请帮帮我。我的代码与AudioFxDemo的示例代码相同。 - Shreyash Mahajan
嗨,Krishnabhadra,我尝试了你的解决方案,但在我的设备上没有发现任何回声效果。你能否请发送给我你的示例代码?先谢谢了。 - Rojesh
为什么你写了 PresetReverb(1,0),我到处都看到的是 PresetReverb(0,0)。请解释一下为什么要将 1 作为参数写入。 - Zar E Ahmer

1

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


0

这行代码本质上解决了一个问题,但仍需要权限。

PresetReverb pReverb = new PresetReverb(1,0);

因此,将以下行添加到AndroidManifest.xml中实际上解决了根本问题:

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

哦,还有,您需要设置PresetReverb并将其附加到AudioTrack以在执行AudioTrack.write()和AudioTrack.play()之前发生。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接