Play a sound in Python assuming that the keyboard is a piano keyboard

ピアノの鍵盤

!! Yahho Kon'nichiwa </ b> </ span> I'm Ozaki, who loves physics (@ sena0801masato).

This time, assuming that the keyboard is a piano keyboard, I would like to use Python to play sounds from a personal computer. I came up with the idea when I was impressed by the anime "Your Lie in April" lol I'm not familiar with music at all, so please tell me.

Who is the target of this article

――I want to play the scale from my computer! --I want to use only standard modules --I don't want to download the sound source --You are using Windows

What I want to improve in the future

――I want to be able to use the downloaded sound source instead of the beep sound. --I want to output chords ――I want to keep producing a single sound by pressing and holding

About the scale

When you think of scales, you think of Doremi Fasorashi. In addition to these 7 notes, 5 notes of the black key are added to make a total of 12 notes, and the game starts again from the do one octave higher.

The standard frequency of the scale is 440Hz of La, and the frequency doubles when it goes up by one octave. Therefore, the frequency is multiplied by $ 2 ^ {1/12} $ in 1 semitone rather than double in 12 semitones.

This time, the octave containing the reference la (440Hz) was set as the 4th stage, and the variable name was defined with the sound as the pitch.

sound ドイツ語のsound階表記
Do C4
Do# Cis4
Re D4
Re# Dis4
Mi E4
Fa F4
Fa# Fis4
So G4
So# Gis4
La(440Hz) A4
La# Ais4
Shi H4
High de C5

Difficulties

I was wondering how the program would receive keyboard input. I couldn't use input because it wasn't like a piano to press enter to fix the pitch every time, so I finally used getch. getch reads the keystrokes and returns the read characters, but there was a very good standard library in the console where nothing echoed back and you didn't even have to press Enter. (It took me a while to get to this ... It seems that I usually use Pygame etc.)

Completed code

digital_piano_ver01.py


from winsound import Beep
from msvcrt import getch

#Definition of how many times the semitone shift is
onestep_pitch = 2 ** (1.0/12.0)
#Define the time to make a sound in milliseconds
duration = 300

#Define a function to make a sound
def play_pitch(frequency, duration):
    Beep(frequency, duration)
#Define a function to raise or lower a semitone
def down_pitch(base_pitch):
    return int(round(base_pitch / onestep_pitch))
def up_pitch(base_pitch):
    return int(round(base_pitch * onestep_pitch))

#Define the frequency of each pitch
A4 = 440
Ais4 = up_pitch(A4)
H4 = up_pitch(Ais4)
C5 = up_pitch(H4)
Cis5 = up_pitch(C5)
D5 = up_pitch(Cis5)
Dis5 = up_pitch(D5)
E5 = up_pitch(Dis5)

Gis4 = down_pitch(A4)
G4 = down_pitch(Gis4)
Fis4 = down_pitch(G4)
F4 = down_pitch(Fis4)
E4 = down_pitch(F4)
Dis4 = down_pitch(E4)
D4 = down_pitch(Dis4)
Cis4 = down_pitch(D4)
C4 = down_pitch(Cis4)
H3 = down_pitch(C4)
Ais3 = down_pitch(H3)
A3 = down_pitch(Ais3)

#Associate the keyboard with the pitch. Of the keyboard"d"Is C4, that is, the sound of do, etc.
pitchs = {}
pitchs["a"] = A3
pitchs["w"] = Ais3
pitchs["s"] = H3
pitchs["d"] = C4
pitchs["r"] = Cis4
pitchs["f"] = D4
pitchs["t"] = Dis4
pitchs["g"] = E4
pitchs["h"] = F4
pitchs["u"] = Fis4
pitchs["j"] = G4
pitchs["i"] = Gis4
pitchs["k"] = A4
pitchs["o"] = Ais4
pitchs["l"] = H4
pitchs[";"] = C5
pitchs["@"] = Cis5
pitchs[":"] = D5
pitchs["["] = Dis5
pitchs["]"] = E5

while True:
    #Recognize the entered key
    bytes_keyboard = getch()
    #Convert from byte string to string
    str_keyboard = bytes_keyboard.decode("utf-8")
    #Align strings to lowercase
    pitch = str_keyboard.lower()
    print("Scale", pitch)
    #Makes a sound when the pressed key is in the dictionary
    if pitch in pitchs:
        play_pitch(pitchs[pitch], duration)
    #Press q to exit
    elif pitch == 'q':
        break

Summary

For the time being, I made something like a piano. But there is still room for improvement. What I'm really worried about is that I can't play chords, and even if I press and hold it, the sound is cut off in the defined milliseconds. I'm wondering if these two can't be done using asynchronous processing, so please let me know if anyone can. Another idea is that if you generate a sound from a waveform, you can express a chord and a sound that is attenuated by pressing and holding it. I just thought that the electronic pianos that were actually sold were amazing lol

Then! </ B> </ span>

References

[winsound --- Audio playback interface for Windows] (https://docs.python.org/ja/3/library/winsound.html) msvcrt --- Useful routines for MS VC ++ runtime system I wanted to get a key event in Python, but I couldn't do it ← I did. [Making GUI sound play software with Tkinter (4) --Making sound with Python] (https://takasa-5.blogspot.com/2017/04/tkinter-gui4.html)

Recommended Posts