iam making an application which plays a sound when a key is down, the sound stops immediately when the key is released.
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:
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?
Add a private member to your class:
private Dictionary<Key, Boolean> KeyIsDown;
In your OnKeyDown method, set KeyIsDown(currentKey) = true; In your OnKeyUp method, set KeyIsDown(currentKey) = false;
Then add a delegate for the onIdle event. 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.
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. 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);
}
}
}
}