在UWP应用程序中切换音频

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在UWP应用程序中切换音频相关的知识,希望对你有一定的参考价值。

我正在构建一个具有可选音频支持的应用程序,它将具有某种背景声音(如在每个页面中继续播放的循环音轨)。

我所做的是创建一个音频管理器,允许我管理我的声音,这应该根据用户的设置静音/取消静音。

不幸的是,这不会发生,即使用户禁用它,音频也会继续播放。

这是我的代码示例:

public static async Task StartSoundManager()
{            
    // Get audio stream from app folder
    // ...
    BackgroundSound.SetSource(currentStream, currentFile.ContentType);
    BackgroundSound.IsLooping = true;  
    ToggleSounds();
}

public static void ToggleSounds()
{                        
    BackgroundSound.IsMuted = !Settings.IsAudioOn;
}

public bool IsAudioOn
{
    // standard getter
    set
    {
        // save value
        SoundManager.ToggleSounds();
    }
}

经过一些测试,IsMuted设置正确(我也尝试将音量设置为0)但更改设置时没有任何反应。

你们有没有想过为什么这么简单的任务没有按预期工作?在我看来,你在设置源码后无法改变音量,这感觉非常错误。

编辑:更完整的课程

public static class AudioManager
{

    public const string BACKGROUND = "BACKGROUND.mp3";

    private static readonly MediaElement BackgroundSound = new MediaElement();

    public static async Task StartSoundManager()
    {
        // Get folder
        var folder =
                await (await Package.Current.InstalledLocation.GetFolderAsync("Assets")).GetFolderAsync("Audio");

        var currentFile = await folder.GetFileAsync(BACKGROUND);
        var currentStream = await currentFile.OpenAsync(FileAccessMode.Read);
        BackgroundSound.SetSource(currentStream, currentFile.ContentType);

        // Set mode and volume
        BackgroundSound.IsLooping = true;
        ToggleSounds();
    }

    public static void ToggleSounds()
    {   
        BackgroundSound.IsMuted = !Settings.IsAudioOn; // IsAudioOn is false, still the sound plays
    }

}
答案

MediaElement是一个XAML控件,为了让MediaElement.IsMuted property工作,我们需要将MediaElement添加到Visual Tree中。例如,在您的代码中,我们可以将BackgroundSound更改为公共字段,如:

public static readonly MediaElement BackgroundSound = new MediaElement();

然后在页面(例如MainPage)中将其添加到页面:

protected override async void OnNavigatedTo(NavigationEventArgs e)
{
    await AudioManager.StartSoundManager();

    rootGrid.Children.Add(AudioManager.BackgroundSound);
}

在此之后,你的ToggleSounds方法应该能够工作。

但是既然你想继续在每一页上玩,那么在页面中添加MediaElement可能不是一个好习惯,在这里我建议你使用MediaPlayer class代替MediaElement,如:

public static class AudioManager
{
    public const string BACKGROUND = "BACKGROUND.mp3";

    private static readonly MediaPlayer BackgroundSound = new MediaPlayer();

    public static void StartSoundManager()
    {
        BackgroundSound.Source = MediaSource.CreateFromUri(new Uri($"ms-appx:///Assets/Audio/{BACKGROUND}"));

        BackgroundSound.IsLoopingEnabled = true;

        ToggleSounds();

        BackgroundSound.Play();
    }

    public static void ToggleSounds()
    {
        BackgroundSound.IsMuted = !Settings.IsAudioOn; // IsAudioOn is false, still the sound plays
    }
}

有关详细信息,请参阅Play audio and video with MediaPlayer

另一答案

我有类似的情况。我有一个ToggleMenuFlyoutItem用于在应用程序范围内打开和关闭声音,写入本地设置:

toggle menu flyout

这是XAML:

        <Button IsTabStop="False" Style="{StaticResource qButtonStyleFinal}" TabIndex="2" x:Name="btnMore" BorderBrush="{x:Null}" Foreground="{x:Null}"
            Content="1" Grid.Column="37" Margin="5" HorizontalAlignment="Center" Grid.Row="1" Grid.RowSpan="4" Grid.ColumnSpan="2" MaxWidth="60" MaxHeight="60">
        <Button.Background>
            <ImageBrush ImageSource="ms-appx:///Assets/more_project.png" Stretch="Uniform" />
        </Button.Background>
        <Button.Flyout>
            <MenuFlyout>
                <ToggleMenuFlyoutItem x:Name="mfiToggleSounds" Text="sound effects" IsChecked="{x:Bind Mode=TwoWay, Path=Model.Sounds}"></ToggleMenuFlyoutItem>
                <MenuFlyoutItem x:Name="mfiExportExcel" Text="export to Excel" Tapped="mfiExportExcel_Tapped" />
                <MenuFlyoutItem x:Name="mfiExportCSV" Text="export to CSV" Tapped="mfiExportCSV_Tapped" />
                <MenuFlyoutItem x:Name="mfiEmailDeveloper" Text="email developer" Tapped="mfiEmailDeveloper_Tapped" />
            </MenuFlyout>
        </Button.Flyout>
    </Button>

更改在属性集事件中处理:

    private bool _sounds = true;

        public bool Sounds
    {
        get => _sounds;

        set
        {
            _sounds = value;
            NotifyPropertyChanged();
            var localSettings = ApplicationData.Current.LocalSettings;
            localSettings.Values["sounds"] = _sounds;
        }
    }

设置加载在主页Page_Loaded事件上,如下所示:

            // retrieve settings
        var localSettings = ApplicationData.Current.LocalSettings;
        if (localSettings.Values.ContainsKey("sounds"))
        {
            clsGlobal.statModel.Sounds = (bool)localSettings.Values["sounds"];
        }

当我播放声音时,会包含一个简单的if条件:

if (clsGlobal.statModel.Sounds && clsGlobal.fileInputs.ContainsKey("problem.wav"))
                {
                    var snd1 = clsGlobal.fileInputs["problem.wav"];
                    if (snd1 != null)
                    {
                        snd1.Reset();
                        snd1.Start();
                    }
                }

我正在使用AudioGraph API来获取声音。比MediaPlayer路线工作得更好,因为这给了我一个奇怪的情况,在第一次请求时有时不会播放声音。 AudioGraph对我来说效果更好,播放声音非常快。

以上是关于在UWP应用程序中切换音频的主要内容,如果未能解决你的问题,请参考以下文章

UWP:后台任务中的音频媒体捕获

在 UWP 中播放流中的音频

在 UWP 中使用 NAudio 播放多个音频文件

在uwp仿IOS的页面切换效果

在 UWP 应用中使用 AudioGraph 将音频输出发送到两台设备

如何检测其他应用程序的音频是不是在后台播放? (UWP,Windows 10)