在 UWP 应用中切换音频

Posted

技术标签:

【中文标题】在 UWP 应用中切换音频【英文标题】:Toggling audio in an UWP app 【发布时间】:2016-08-19 11:10:55 【问题描述】:

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

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

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

这是我的代码示例:

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
    


【问题讨论】:

不会停止()/播放()更有意义吗?至少你会知道代码是否真正运行:) 否,因为该设置还会切换一次性声音。这个想法是编写声音逻辑,就好像它总是打开一样,然后使用音量/静音来给用户一个选择。另外,我不明白为什么IsMuteVolume 属性不起作用,这迫使我把这件事复杂化了。 您使用的BackgroundSound 是什么?是MediaElement 吗?我可以使用MediaElement 重现您的问题。 IsMuted 财产在我身边运作良好。您能否分享一个可以重现您的问题的minimal reproducible example? @JayZuo-MSFT 添加了更多代码。我一设置音源就开始播放声音,之后就无法静音了。 【参考方案1】:

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。

【讨论】:

我正在用MediaPlayer 做一些测试,但它甚至没有编译,因为它说MediaPlayer 没有无参数构造函数。 @StepTNT 您使用的操作系统版本是什么? MediaPlayer.MediaPlayer constructor 在 Windows 10 周年更新(版本 10.0.14393.0)中引入,您需要最新的 Windows 10 SDK 并将您的项目的目标版本设置为“Windows 10 周年版(10.0; Build 14393)”。 我无法删除尚未收到更新的人(包括我)。如何使 10586 和 AU 都可以使用? @StepTNT 对于构建 10586,我们必须使用 MediaElement。可以使用ApiInformation class来检测是否可以使用MediaPlayer。如果没有,您可以改用MediaElement 这给我们带来了最初的问题:如何在不添加 XAML 树的情况下将其静音?【参考方案2】:

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

这是 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 应用中使用 AudioGraph 将音频输出发送到两台设备

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

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

Windows UWP 应用程序中的 MediaElement 不播放音频

在 UWP 中在后台播放音频的最简单方法是啥?