Skip to content

Commit a307e7a

Browse files
authored
Added mouse click operation
1 parent 2c6f2f7 commit a307e7a

File tree

3 files changed

+65
-19
lines changed

3 files changed

+65
-19
lines changed

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
BSD 3-Clause License
22

3-
Copyright (c) 2022, Yoshiyuki Kobayashi
3+
Copyright (c) 2022, Frieve-A
44
All rights reserved.
55

66
Redistribution and use in source and binary forms, with or without

README.md

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Harmony Visualizer
22
A tool for visualizing the harmony of MIDI input.
33

4+
(英語に続き日本語の解説があります)
5+
46
![Harmony Visualizer](./images/harmony_visualizer.png)
57

68
A tool for visualizing the harmony of the sound using virtual overtones based on MIDI input.
@@ -31,20 +33,30 @@ Follow the steps below to execute the Python code of the Feature Visualizer.
3133

3234
## How to use
3335

34-
Connect your MIDI keyboard to your PC and launch the app.
36+
If a MIDI keyboard is available, connect the MIDI keyboard to your PC and launch the app.
3537

36-
When you play a note with the MIDI keyboard, the notes you play are displayed in different colors on the keyboard for each note name. For example, Do is displayed in red, and So is displayed in blue which is a little closer to green.
38+
When you play a note with the MIDI keyboard or click on the keyboard, the notes you play are displayed in different colors on the keyboard for each note name. For example, Do is displayed in red, and So is displayed in blue which is a little closer to green.
3739

3840
Above the keyboard display, a vertical line is displayed to indicate the volumme of the virtual overtones. For example, if you play Do, a vertical line indicating the second overtone is displayed at the Do position one octave higher, and the third overtone is displayed at the So position.
3941

4042
If you input two or more sounds at the same time and the overtones are in harmony with each other, the overtones that are in harmony with the input sound are connected by a curve. The numbers on the curve indicate which overtones are in harmony.
4143

4244
The graph on the upper left shows the volume of each overtone as a polar coordinate graph with a radius as a pitch and an angle that makes one round in one octave.
4345

46+
To hold the display, press the CTRL key on your computer keyboard or press the damper pedal on your MIDI keyboard.
47+
4448
Play your favorite songs and visually enjoy the harmony of the overtones!
4549

4650
<br>
4751

52+
## Keyboard shortcuts
53+
54+
ESC : Exit the app
55+
56+
F11 : Switch to full screen
57+
58+
<br>
59+
4860
---
4961

5062
<br>
@@ -77,17 +89,26 @@ https://github.com/Frieve-A/harmony_visualizer/releases
7789

7890
## 使い方
7991

80-
PCにMIDIキーボードを接続してアプリを起動します。
92+
MIDIキーボードが利用できる場合、PCにMIDIキーボードを接続してアプリを起動します。
8193

82-
MIDIキーボードで音を弾くと、弾いた音は音名毎にそれぞれ異なる色で鍵盤上に色分け表示されます。例えばドは赤色で、ソは少しグリーン寄りの青で表示されます。
94+
MIDIキーボードで音を弾くか、鍵盤上をクリックすると、弾いた音は音名毎にそれぞれ異なる色で鍵盤上に色分け表示されます。例えばドは赤色で、ソは少しグリーン寄りの青で表示されます。
8395

8496
鍵盤表示の上には、仮想的な倍音の大きさを示す縦線が表示されます。例えばドを弾いた場合、1オクターブ上のドの位置に2倍音、ソの位置に3倍音を示す縦線が表示されます。
8597

8698
2つ以上のを同時に入力しその倍音同士が調和している場合、入力した音と調和している倍音は曲線で結ばれます。曲線の上の数字は調和しているのが何番目の倍音であるかを示しています。
8799

88100
左上のグラフはそれぞれの倍音の強度を、半径を音程とし、角度を1オクターブで1周するように設定した極座標グラフで表示したものです。
89101

102+
表示をホールドするには、パソコンのキーボードのCTRLキーを押すか、MIDIキーボードのダンパーペダルを踏みます。
103+
90104
好きな楽曲を演奏し、倍音同士が調和する様子を視覚的に楽しみましょう!
91105

106+
## キーボードショートカット
107+
108+
ESC : アプリを終了
109+
110+
F11 : フルスクリーンへの切り替え
111+
112+
92113

93114

harmony_visualizer.py

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,47 @@ def main():
116116
terminated = False
117117
last_time = time.perf_counter() - 10
118118
harmony_radius = np.zeros(128)
119+
mouse_click_note = -1
119120
while (not terminated):
120121
current_time = time.perf_counter()
121122
last_wait_ms = (current_time - last_time) * 1000
122123
last_time = current_time
123124

125+
# handle events
126+
for event in pygame.event.get():
127+
if event.type == QUIT:
128+
terminated = True
129+
elif event.type == KEYDOWN:
130+
if event.key == K_ESCAPE:
131+
terminated = True
132+
elif event.key == K_F11:
133+
full_screen = not full_screen
134+
if full_screen:
135+
screen = pygame.display.set_mode(screen_size, FULLSCREEN)
136+
else:
137+
screen = pygame.display.set_mode(screen_size)
138+
elif event.key == K_LCTRL or event.key == K_RCTRL:
139+
damper = True
140+
elif event.type == KEYUP:
141+
if event.key == K_LCTRL or event.key == K_RCTRL:
142+
damper = False
143+
elif event.type == MOUSEBUTTONDOWN and event.button == 1:
144+
for key in [key for key in keyboard[21:109] if key.black_key]:
145+
if event.pos[0] >= key.x - black_key_width / 2 and event.pos[0] < key.x + black_key_width / 2 and event.pos[1] >= keyboard_top and event.pos[1] < keyboard_top + black_key_height:
146+
mouse_click_note = key.note_no
147+
if mouse_click_note < 0:
148+
for key in [key for key in keyboard[21:109] if not key.black_key]:
149+
if event.pos[0] >= key.x - white_key_width / 2 and event.pos[0] < key.x + white_key_width / 2 and event.pos[1] >= keyboard_top and event.pos[1] < keyboard_top + white_key_height:
150+
mouse_click_note = key.note_no
151+
if mouse_click_note >= 0:
152+
keyboard[mouse_click_note].key_on = True
153+
keyboard[mouse_click_note].attack = 1.0
154+
keyboard[mouse_click_note].db = 96.0
155+
156+
elif event.type == MOUSEBUTTONUP and event.button == 1:
157+
keyboard[mouse_click_note].key_on = False
158+
mouse_click_note = -1
159+
124160
# midi in
125161
for midi_in in midi_ins:
126162
if midi_in.poll():
@@ -141,6 +177,8 @@ def main():
141177
damper = midi_event[0][2] > 0
142178
# print(midi_event)
143179

180+
# mouse in
181+
144182
# update keyboard status
145183
overtone_list = []
146184
harmony_buf = [[] for i in range(128)]
@@ -256,20 +294,7 @@ def main():
256294
# draw
257295
pygame.display.update()
258296

259-
# handle keyboard events
260-
for event in pygame.event.get():
261-
if event.type == QUIT:
262-
terminated = True
263-
elif event.type == KEYDOWN:
264-
if event.key == K_ESCAPE:
265-
terminated = True
266-
elif event.key == K_F11:
267-
full_screen = not full_screen
268-
if full_screen:
269-
screen = pygame.display.set_mode(screen_size, FULLSCREEN)
270-
else:
271-
screen = pygame.display.set_mode(screen_size)
272-
297+
# wait
273298
pygame.time.wait(10)
274299

275300
for midi_in in midi_ins:

0 commit comments

Comments
 (0)