|
import io |
|
from pydub import AudioSegment |
|
from pydub.generators import Sine |
|
from pydub.playback import play |
|
from pynput.keyboard import Key, Listener |
|
import threading |
|
from math import log2 |
|
|
|
# Function to generate a sine wave tone |
|
def generate_tone(frequency, duration=500): |
|
tone = Sine(frequency).to_audio_segment(duration=duration) |
|
return tone |
|
|
|
# Function to play the generated tone |
|
def play_tone(tone): |
|
try: |
|
play(tone) # play the audio using pydub.playback.play |
|
except Exception as error: |
|
print(f"Error in playing tone: {error}") |
|
|
|
# Mapping keyboard keys to piano notes (simplified) |
|
key_to_note = { |
|
'a': 261.63, # C4 |
|
'w': 277.18, # C#4/Db4 |
|
's': 293.66, # D4 |
|
'e': 311.13, # D#4/Eb4 |
|
'd': 329.63, # E4 |
|
'f': 349.23, # F4 |
|
't': 369.99, # F#4/Gb4 |
|
'g': 392.00, # G4 |
|
'y': 415.30, # G#4/Ab4 |
|
'h': 440.00, # A4 |
|
'u': 466.16, # A#4/Bb4 |
|
'j': 493.88, # B4 |
|
'k': 523.25, # C5 |
|
'o': 554.37, # C#5/Db5 |
|
'l': 587.33, # D5 |
|
'p': 622.25, # D#5/Eb5 |
|
';': 659.25, # E5 |
|
'\'': 698.46, # F5 |
|
']': 739.99, # F#5/Gb5 |
|
'\\': 783.99, # G5 |
|
'z': 830.61, # G#5/Ab5 |
|
'x': 880.00, # A5 |
|
'c': 932.33, # A#5/Bb5 |
|
'v': 987.77, # B5 |
|
'b': 1046.50, # C6 |
|
} |
|
|
|
# Function to handle key press |
|
def on_press(key): |
|
try: |
|
if hasattr(key, 'char') and key.char in key_to_note: |
|
frequency = key_to_note[key.char] |
|
tone = generate_tone(frequency) |
|
threading.Thread(target=play_tone, args=(tone,)).start() |
|
except Exception as error: |
|
print(f"Error in key press handler: {error}") |
|
|
|
# Function to handle key release |
|
def on_release(key): |
|
if key == Key.esc: |
|
return False # Stop listener |
|
|
|
# Main function to start the keyboard listener |
|
def start_keyboard_piano(): |
|
with Listener(on_press=on_press, on_release=on_release) as listener: |
|
listener.join() |
|
|
|
def frequency_to_note(frequency): |
|
note_names = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] |
|
octave = 4 |
|
index = int(round(12 * log2(frequency / 440.0))) + 49 |
|
return note_names[index % 12] + str(octave + index // 12) |
|
|
|
if __name__ == "__main__": |
|
try: |
|
print("Key Note") |
|
sharp_keys = [key for key, frequency in key_to_note.items() if '#' in frequency_to_note(frequency)] |
|
natural_keys = [key for key, frequency in key_to_note.items() if '#' not in frequency_to_note(frequency)] |
|
print(' '.join([frequency_to_note(key_to_note[key]) for key in sharp_keys])) |
|
print(' '.join([frequency_to_note(key_to_note[key]) for key in natural_keys])) |
|
start_keyboard_piano() |
|
except Exception as error: |
|
print(f"Error in main function: {error}") |
I have tested this on MacOS but Python libraries has issues in Windows you need to take extra steps to install them.
Good luck 🤞