简体   繁体   English

按下无限循环

[英]Key down infinite loop

iam making an application which plays a sound when a key is down, the sound stops immediately when the key is released. Iam制作了一个应用程序,该应用程序在按下键时会播放声音,而在释放键时声音会立即停止。

The problem I found is that if you press a key it plays the first miliseconds of it and then infinite loop it until you release the key. 我发现的问题是,如果您按一个键,它会播放它的前几毫秒,然后无限循环播放,直到您松开该键为止。

The code iam currently using is the following: iam当前使用的代码如下:

        public class Foo
        {

            public static int GetStream1(string path)
            {
                return Bass.BASS_StreamCreateFile(path, 0, 0, BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_PRESCAN);
            }
            public static int GetStream2(string path)
            {
                return Bass.BASS_StreamCreateFile(path, 0, 0, BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_PRESCAN);
            }
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            Bass.BASS_Init(1, 44100, BASSInit.BASS_DEVICE_DEFAULT, this.Handle);
            Bass.BASS_Init(2, 44100, BASSInit.BASS_DEVICE_DEFAULT, this.Handle);


                if (e.KeyCode == Keys.D1)
                {
                    if (beatload1.Text == "Waiting 01.wav")
                    {
                        MessageBox.Show("No beat loaded");
                        return;
                    }
                    Beat1.Image = Beatpadpc.Properties.Resources.white_square_button;
                    try
                    {
                        Bass.BASS_SetDevice(1);
                        Bass.BASS_ChannelPlay(Foo.GetStream1(path1.Text), false);
                    }
                    catch (FileNotFoundException)
                    {
                        MessageBox.Show("File has been moved." + "\n" + "Please relocate it now!");
                    }
                }

                if (e.KeyCode == Keys.D2)
                {
                    if (beatload2.Text == "Waiting 02.wav")
                    {
                        MessageBox.Show("No beat loaded");
                        return;
                    }
                    Beat2.Image = Beatpadpc.Properties.Resources.white_square_button;
                    try
                    {
                        Bass.BASS_SetDevice(2);
                        Bass.BASS_ChannelPlay(Foo.GetStream2(path2.Text), false);
                    }
                    catch (FileNotFoundException)
                    {
                        MessageBox.Show("File has been moved." + "\n" + "Please relocate it now!");
                    }
               }
        }

        private void Window_KeyUp(object sender, KeyEventArgs e)
        {
         if (e.KeyCode == Keys.D1)
            {
                Beat1.Image = Beatpadpc.Properties.Resources.black_square_button;
                Bass.BASS_StreamFree(Foo.GetStream1(path1.Text));
                Bass.BASS_SetDevice(1);
                Bass.BASS_Free();
            }
            if (e.KeyCode == Keys.D2)
            {
                Beat2.Image = Beatpadpc.Properties.Resources.black_square_button;
                Bass.BASS_StreamFree(Foo.GetStream2(path2.Text));
                Bass.BASS_SetDevice(2);
                Bass.BASS_Free();
            }
}

So is there a way to play 1 or more sounds at the same time without them getting looped for ever? 那么,有没有一种方法可以同时播放1个或多个声音而不会让它们永远循环播放呢?

Add a private member to your class: 将私人成员添加到您的班级:

private Dictionary<Key, Boolean> KeyIsDown;

In your OnKeyDown method, set KeyIsDown(currentKey) = true; 在您的OnKeyDown方法中,设置KeyIsDown(currentKey)= true; In your OnKeyUp method, set KeyIsDown(currentKey) = false; 在您的OnKeyUp方法中,设置KeyIsDown(currentKey)= false;

Then add a delegate for the onIdle event. 然后为onIdle事件添加一个委托。 Whenever the delegate is called check each key in KeyIsDown using an if statement instead of foreach and process each key as you like depending on whether KeyIsDown(aKey) is true or false. 每当调用委托时,使用if语句而不是foreach来检查KeyIsDown中的每个键,并根据KeyIsDown(aKey)是true还是false来根据需要处理每个键。

Since I do not have the Bass class that your code refers to, I can only come to a close approximation of what it should look like. 由于我没有您的代码所引用的Bass类,因此我只能近似地看它的外观。 You will have to make the real adaptations yourself. 您将必须自己进行真正的改编。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Input;

namespace WinformExcercise1
{
   public partial class Form1 : Form
   {
      private Dictionary<Keys, bool> keyIsDown = new Dictionary<Keys,bool>();
      private Timer timer;
      private int stream1;

      public Form1()
      {
         InitializeComponent();

         keyIsDown.Add(Keys.J, false);
         keyIsDown.Add(Keys.K, false);
         keyIsDown.Add(Keys.L, false);

         setupPlayer();
         this.KeyPreview = true;
      }

      private void setupPlayer()
      {
         // Bass.BASS_SetDevice(1);
         stream1 = Foo.GetStream2(path1.Text);
         // all code that is called once for setting things up goes here
      }

      private void Form1_KeyDown(object sender, KeyEventArgs e)
      {
         if (true == keyIsDown.ContainsKey(e.KeyCode))
         {
            keyIsDown[e.KeyCode] = true;
         }
      }

      private void Form1_KeyUp(object sender, KeyEventArgs e)
      {
         if (true == keyIsDown.ContainsKey(e.KeyCode))
         {
            keyIsDown[e.KeyCode] = false;
         }
      }

      private void Form1_Load(object sender, EventArgs e)
      {
         // This makes the computer constantly call the playKeys method
         timer = new Timer();
         timer.Interval = 1000;
         timer.Tick += new EventHandler(playKeys);
         timer.Enabled = true;
      }

      private void playKeys(Object source, EventArgs e)
      {
         // You have to add the next 8 lines once for each key you are watching
         // What I have here only does something for the J key.
         if (true == keyIsDown[Keys.J])
         {
            Bass.BASS_Init(1, 44100, BASSInit.BASS_DEVICE_DEFAULT, this.Handle);
         }
         else
         {
            Bass.BASS_StreamFree(Stream1);
         }
      }


   }
}

haha nice, i was just posting a similar answer then philogon, but with a slight difference: 哈哈,很好,我刚刚发布了一个类似philogon的答案,但略有不同:

private Dictionary<Key, bool> myKeys;

while initializing you add all keys you want to press (eg Keys.D1, Keys.D2), all with "false". 在初始化时,您要添加所有要按下的键(例如,Keys.D1,Keys.D2),并且全部带有“ false”。 write a function like: 写一个像这样的函数:

private bool getKeyState(Keys k) 

this function can be used everytime a key is pressed. 每次按键时均可使用此功能。 the parameter will be the key, which is pressed. 参数将是被按下的键。 if its already pressed, ignore it. 如果已经按下,则忽略它。 if not, yeah play the bass. 如果不是,是的。

and then, i'd write a function like: 然后,我会写一个像这样的函数:

private void updateKeyDictionary(Key, boolean state)

here you could check with "getKeyState" you get the current state of the key - if it's the same state, do nothing, otherwise update. 在这里,您可以使用“ getKeyState”进行检查,以获取密钥的当前状态-如果状态相同,则什么也不做,否则进行更新。 with some nice linq-expression this tasks could be done in 2-3 lines 使用一些不错的linq-expression可以完成2-3行

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM