Search code examples
c#keypresskeydownbeep

Play a tone while key is down C#


I'm building a piano console application that plays a beep/tone with a specific frequency for a specific amount of time. Help Eventually play the tone as long as the key is pressed. P.S eventually play several tones at once

namespace something
{

 public class piano
 {

  [DllImport("kernel32.dll")]
  static extern bool Beep(uint dwFreq, uint dwDuration);

  public static void  Main (string [] args)
    {

     Console.WriteLine("This is a piano.");

  //The following code is wrong but you get the idea
     char x = KeyDown;
     switch(x)

     case "q":
     Beep(523,500);
     break;

     case "w":
     Beep(587,500);
     break;

     //etc

     default:
     break;
   }
  }
 }

Solution

  • In a console application you can detect when a key has been pressed, but not when it has been released. Therefore I would use a WinForms application.

    In a WinForms Form you can use the KeyDown and KeyUp events at form level. In order to activate them, you must set the KeyPreview property of the form to true. You can do this in the properties window or in code.

    Then you must remember which keys are pressed. I'm using a HashSet<Keys> for this.

    // Stores the keys in pressed state.
    private HashSet<Keys> _pressedKeys = new HashSet<Keys>();
    
    // Used in DisplayKeys method.
    private StringBuilder _sb = new StringBuilder();
    
    // Form constructor
    public frmKeyboard()
    {
        InitializeComponent();
        KeyPreview = true; // Activate key preview at form level.
    }
    
    private void frmKeyboard_KeyDown(object sender, KeyEventArgs e)
    {
        // Each time a key is pressed, add it to the set of pressed keys.
        _pressedKeys.Add(e.KeyCode);
        DisplayKeys();
    }
    
    private void frmKeyboard_KeyUp(object sender, KeyEventArgs e)
    {
        // Each time a key is released, remove it from the set of pressed keys.
        _pressedKeys.Remove(e.KeyCode);
        DisplayKeys();
    }
    
    private void DisplayKeys()
    {
        _sb.Clear();
        foreach (Keys key in _pressedKeys.OrderBy(k => k)) {
            _sb.AppendLine(key.ToString());
        }
        label1.Text = _sb.ToString();
    }
    

    Now, you can press one or more keys at a time and they will be displayed in a label.


    The simple Beep method will not let you play sounds simultaneously. For a possible solution see this thread on MSDN: Playing Sounds Simultaneously. Another alternative might be MIDI.NET.