在Xamarin中实现节拍器的正确方法

h6my8fg2  于 2023-03-27  发布在  其他
关注(0)|答案(1)|浏览(105)

我是Xamarin的新手,目前正在开发一个与音乐相关的应用程序。它的功能之一是节拍器,将bpm作为输入。节拍器通过按下单个按钮来设置ON/OFF,并使用SimpleAudioPlayer插件发出声音。
下面是我的实现,但感觉是关闭的:有一些滞后,这对节拍器来说并不理想。

// OFF by default
        bool _MetronomeOn = false;
        async private void btnMetronome_Clicked(object sender, EventArgs e)
        {

            _MetronomeOn = !_MetronomeOn;

            // While Metronome is On
            while (_MetronomeOn)
            {
                // Get the bpm from ui
                double bpm;
                if (!Double.TryParse(entryMetronome.Text, out bpm))
                    bpm = 90;

                double secInterval = 60 / bpm;
                var player = Plugin.SimpleAudioPlayer.CrossSimpleAudioPlayer.Current;
                player.Load("metronome.mp3");

                if (_MetronomeOn)
                {
                    // NOTE : Added Xam.Plugin.SimpleAudioPlayer nugget package 
                    player.Play();

                    await Task.Delay(TimeSpan.FromSeconds(secInterval));
                }
            }
        }

我不知道是什么原因造成的...我想可能是while实现,插件加载可能对resource很重...
任何帮助都将不胜感激:)
编辑:感谢Jason,我的第一步是加载mp3一次,而不是在每个循环中。我一开始尝试全局推送var播放器(在任何函数之外),但VS 2022不想让我这么做,我太新手了,找不到正确的类型。但我做到了:):
我在全局设置播放器,并在OnAppearing()方法中加载了一次mp3:

public partial class MainPage : ContentPage
    {
        // NOTE : Added Xam.Plugin.SimpleAudioPlayer nugget package to the Android Solution
        // The sound itself is loaded (not played) in OnAppearing()
        Plugin.SimpleAudioPlayer.ISimpleAudioPlayer player;

        public MainPage()
        {
            InitializeComponent();
        }

        // When the main view is launched and Shuffle Button animation
        protected override void OnAppearing()
        {
            base.OnAppearing();

            // Load the mp3. It must be in :
            // Android : Asset folder and build action is AndroidAsset
            // iOS :  Resource folder and build action is BundleResource
            player = Plugin.SimpleAudioPlayer.CrossSimpleAudioPlayer.Current;
            player.Load("metronome.mp3");
            ...
        }
        
        ...
    }

这有一个更好的结果。下一步是实现正确的计时器,我正在努力。

vddsk6oq

vddsk6oq1#

这里是完整的代码,谢谢大家。这是我修改的内容:

  • 加载的mp3只是一次把插件。SimpleAudioPlayer。ISimpleAudioPlayer播放器;作为全局变量,并在OnAppearing()方法中设置其参数和加载mp3
  • 添加了一个System.Timers.Timer来正确处理计时器。我删除了_MetronomeOn变量作为aTimer.Enabled属性,让我知道它是否正在运行。它现在工作起来很有魅力。不再有丑陋的whiles!

非常感谢!

namespace TestMetro
{
    public partial class MainPage : ContentPage
    {

        private static System.Timers.Timer aTimer;
        // NOTE : Added Xam.Plugin.SimpleAudioPlayer nugget package to the Android Solution
        // The sound itself is loaded (not played) in OnAppearing()
        Plugin.SimpleAudioPlayer.ISimpleAudioPlayer player;
        public MainPage()
        {
            InitializeComponent();
        }

        protected override void OnAppearing()
        {
            base.OnAppearing();

            // Load the mp3. It must be in :
            // Android : Asset folder and build action is AndroidAsset
            // iOS :  Resource folder and build action is BundleResource
            player = Plugin.SimpleAudioPlayer.CrossSimpleAudioPlayer.Current;
            player.Load("metronome.mp3");

            // Initiate the timer -- tick rate to be set below
            aTimer = new System.Timers.Timer();
            // Hook up the Elapsed event for the timer. 
            aTimer.Elapsed += OnMetronomeTick;
            aTimer.AutoReset = true;
            aTimer.Enabled = false;
        }

        private void OnMetronomeTick(object sender, ElapsedEventArgs e)
        {
            txtBPM.Text = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff",CultureInfo.InvariantCulture); 
            player.Play();
        }

        // REMOVED _MetronomeOn Var
        private void btnClick_Clicked(object sender, EventArgs e)
        {
            
            // Get the bpm from ui
            double bpm;
            if (!Double.TryParse(txtBPM.Text, out bpm))
                bpm = 90;

            double secInterval = (60 * 1000 / bpm);
            aTimer.Interval = secInterval;
            if (aTimer.Enabled)
                aTimer.Stop();
            else
                aTimer.Start();
        }
    }
}

相关问题