UnityWwise具体某一音频的暂停恢复和终止播放

Posted 加油小五

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UnityWwise具体某一音频的暂停恢复和终止播放相关的知识,希望对你有一定的参考价值。

【Unity】【Wwise】具体某一音频的暂停、恢复和终止播放

以下内容为个人拙见,欢迎大家指正讨论。

Wwise在Unity中提供的方法中,并没有直接提供(看起来没有直接提供。。)暂停音效的方法。
在游戏中较为常见的需要停止音效(或者说控制音效播放状态)的场景,有在切换场景Loading读条时、某种游戏内置音乐播放器中等等。

音效控制场景建议

  • 对于切换场景时(或氛围变化)的音乐切换,推荐在Wwise中创建切换事件来实现,这也是使用Wwise的原因之一,在Wwise中可以圆滑的处理音频之间的切换,也可以通过总线来控制一整组的音频。
  • 对于单一音频的控制,则有以下几种方式(重点是第3条):

音效播放状态控制

  1. Wwise的Unity集成包里提供的组件AkEvent

    该组件上面提供了Stop()方法

    • 优点:简单
    • 缺点:不灵活,依赖于组件;没有暂停、恢复方法。
  2. 在Wwise工程中定义对应的Stop、Pause、Resume事件,通过发送事件来控制音效

    // xxx指代某命名的音频
    AkSoundEngine.Post("Stop_xxx");
    AkSoundEngine.Post("Pause_xxx");
    AkSoundEngine.Post("Resume_xxx");
    
    • 优点:较为灵活,可以在任意地方调用
    • 缺点:需要定义3倍于播放事件的操控事件,在Wwise中的工作量巨大;对同一音效的控制分离,难于管理
  3. 封装Wwise提供的方法来实现Stop、Pause、Resume三种控制
    既然在AkEvent中有Stop方法,那么可以深入查看一下内部是怎么实现的,最后就找到了以下方法

    public static AKRESULT ExecuteActionOnEvent(uint in_eventID, 
    	AkActionOnEventType in_ActionType, 
    	UnityEngine.GameObject in_gameObjectID, 
    	int in_uTransitionDuration,
    	AkCurveInterpolation in_eFadeCurve)
    

    其中的参数AkActionOnEventType有以下几种类型

    所以由此可以进行以下封装(其中WwiseLogger是自己封装的,方便release中剔除):

    /// <param name="soundId">In <see cref="AK.EVENTS"/>.</param>
    public void Pause(uint soundId, GameObject soundSource = null)
    
    	// NOTE 经过试验,Wwise的暂停和恢复走的是计数机制,暂停多少次,就需要恢复多少次才能够正常恢复。
    	if (soundId == InvalidSoundId)
    	
    		WwiseLogger.LogMessage(WwiseLogger.LogLevel.Warning, string.Format("Invalid soundId.", soundId));
    		return;
    	
    
    	var result = AkSoundEngine.ExecuteActionOnEvent(soundId, AkActionOnEventType.AkActionOnEventType_Pause, soundSource);
    	if (result != AKRESULT.AK_Success)
    		WwiseLogger.LogMessage(WwiseLogger.LogLevel.Warning, string.Format("Pause wwise event with id <0> failed.", soundId), result);
    	else
    		WwiseLogger.LogMessage(WwiseLogger.LogLevel.Normal, string.Format("Pause event with id <0>.", soundId));
    
    
    /// <summary>
    /// Should call the same times with Pause.
    /// </summary>
    /// <param name="soundId">In <see cref="AK.EVENTS"/>.</param>
    public void Resume(uint soundId, GameObject soundSource = null)
    
    	// NOTE 经过试验,Wwise的暂停和恢复走的是计数机制,暂停多少次,就需要恢复多少次才能够正常恢复。
    	if (soundId == InvalidSoundId)
    	
    		WwiseLogger.LogMessage(WwiseLogger.LogLevel.Warning, string.Format("Invalid soundId.", soundId));
    		return;
    	
    
    	var result = AkSoundEngine.ExecuteActionOnEvent(soundId, AkActionOnEventType.AkActionOnEventType_Resume, soundSource);
    	if (result != AKRESULT.AK_Success)
    		WwiseLogger.LogMessage(WwiseLogger.LogLevel.Warning, string.Format("Resume wwise event with id <0> failed.", soundId), result);
    	else
    		WwiseLogger.LogMessage(WwiseLogger.LogLevel.Normal, string.Format("Resume event with id <0>.", soundId));
    
    
    
    /// <summary>
    /// Stop Audio.
    /// </summary>
    /// <param name="soundId">Wwise event id, defined in <see cref="AK.EVENTS"/></param>
    /// <param name="soundSource">发声源</param>
    /// <param name="transitionDuration">停止所需时间,单位为毫秒(ms)</param>
    /// <param name="curveInterpolation">音量变化曲线</param>
    public void Stop(uint soundId, GameObject soundSource = null, int transitionDuration = 0, AkCurveInterpolation curveInterpolation = AkCurveInterpolation.AkCurveInterpolation_Linear)
    
    	var result = AkSoundEngine.ExecuteActionOnEvent(soundId, AkActionOnEventType.AkActionOnEventType_Stop,
    		soundSource == null ? gameObject : soundSource, transitionDuration, curveInterpolation);
    	if (result != AKRESULT.AK_Success)
    	
    		WwiseLogger.LogMessage(WwiseLogger.LogLevel.Warning, string.Format("Stop event with id <0> failed.", soundId), result);
    		return;
    	
    
    

    需要注意的是,经过试验,wwise的暂停和恢复走的是计数机制,暂停多少次,就需要恢复多少次才能够正常恢复。

    • 优点:非常灵活,无需定义大量时间
    • 缺点:基于计数的暂停和恢复在复杂的游戏业务里可能会难以正确控制

如何在 C# 中暂停和恢复音频

【中文标题】如何在 C# 中暂停和恢复音频【英文标题】:how to pause and resume audio in c# 【发布时间】:2015-08-11 14:27:32 【问题描述】:

我正在开发 wpf 应用程序。我想暂停和恢复音频,但歌曲从头开始播放。

//c# code

System.Media.SoundPlayer sp = new System.Media.SoundPlayer(@"D:\Intro.wav");
private void play_Click(object sender, EventArgs e)  

    sp.Play();
    play_btn.Enabled = false;
    stop_btn.Enabled = true; 


private void stop_Click(object sender, EventArgs e) 

    sp.Stop();
    stop_btn.Enabled = false;
    play_btn.Enabled = true;

【问题讨论】:

被问到before。 但是没有得到满意的回答,所以还需要回答。 @goobering,已回答,但回答根本不被接受(经常发生)。我的评论是说“使用搜索”的一种外交方式。 SoundPlayer API 不支持暂停。您是否尝试过操作 Stream 对象?如果您不能选择使用 MediaElement,请将其添加到问题中。现在问题的格式是重复的,因为链接的问题确实有一个使用不同 API 的答案。 【参考方案1】:

使用System.Windows.Controls.MediaElement 而不是System.Media.SoundPlayer。它有一个Pause 函数。

<Grid> 
    <Grid.RowDefinitions> 
        <RowDefinition Height="320*"/> 
        <RowDefinition Height="50*"/> 
    </Grid.RowDefinitions> 
    <MediaElement x:Name="MediaPlayer" Grid.RowSpan="1" LoadedBehavior="Manual"/> 
    <StackPanel Orientation="Horizontal" Grid.Row="1" HorizontalAlignment="Center"> 
        <Button x:Name="btnPlay" Content="Play" Click="btnPlay_Click" Width="50" Height="25" Margin="5"/> 
        <Button x:Name="btnStop" Content="Stop" Click="btnStop_Click" Width="50" Height="25" Margin="5"/> 
        <Button x:Name="btnMoveBack" Content="Back" Click="btnMoveBack_Click" Width="50" Height="25" Margin="5"/> 
        <Button x:Name="btnMoveForward" Content="Forward" Click="btnMoveForward_Click" Width="50" Height="25" Margin="5"/> 
    </StackPanel> 
</Grid>

private void IsPlaying(bool flag) 
 
    btnPlay.IsEnabled = flag; 
    btnStop.IsEnabled = flag; 
    btnMoveBack.IsEnabled = flag; 
    btnMoveForward.IsEnabled = flag; 
 

private void btnPlay_Click(object sender, RoutedEventArgs e) 
 
    IsPlaying(true); 
    if (btnPlay.Content.ToString() == "Play") 
     
        MediaPlayer.Play(); 
        btnPlay.Content = "Pause"; 
     
    else 
     
        MediaPlayer.Pause(); 
        btnPlay.Content = "Play"; 
     
 

private void btnStop_Click(object sender, RoutedEventArgs e) 
 
    MediaPlayer.Pause(); 
    btnPlay.Content = "Play"; 
    IsPlaying(false); 
    btnPlay.IsEnabled = true; 
 

private void btnMoveBack_Click(object sender, RoutedEventArgs e) 
 
    MediaPlayer.Position -= TimeSpan.FromSeconds(10); 
 

private void btnMoveForward_Click(object sender, RoutedEventArgs e) 
 
    MediaPlayer.Position += TimeSpan.FromSeconds(10); 

【讨论】:

代码更可能取自here。【参考方案2】:

Soundplayer 不支持暂停和恢复。您可以改用 WPF MediaElement。

如果您必须使用 Soundplayer,您可以每秒使用静音歌曲启动一个新线程。之后,您必须在暂停方法中将响亮的静音。在 Resume Method 中,您必须检查哪个线程处于最佳时间。

但我认为这将是最可怕的解决方案。

干杯

【讨论】:

那将是一个可怕的解决方案。如果音轨是 10 分钟长,你最终会得到 36000 个线程!

以上是关于UnityWwise具体某一音频的暂停恢复和终止播放的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C# 中暂停和恢复音频

如何使用暂停和恢复创建 ProgressDialog

如果您的应用程序播放视频并暂停背景音频,您如何在完成后让背景音频恢复?

多线程基础知识总结

播放自己的音频后恢复 Spotify

如何在 C++ 中暂停和恢复 POSIX 线程?