如何将 midi 文件转换为按键(在 Python 中)?
How to convert midi files to keypresses (in Python)?
我正在尝试读取 MIDI 文件,然后将每个音符(MIDI 编号)转换为键盘上的模拟按键(A、f、h、J、t...)。
我可以像这样使用 python-midi 库读取任何 MIDI 文件:
pattern = midi.read_midifile("example.mid")
而且我还可以像这样用 pywin32 模拟按键:
shell = win32com.client.Dispatch("WScript.Shell")
shell.SendKeys(key)
但我不知道如何将 midi 数字(在 midi 文件中)实际转换为按键。
更准确地说,我正在尝试将 MIDI 数字转换为音符,然后根据 virtualpiano.net(61 键)将音符转换为按键,以便程序可以通过按下相应的按钮来弹奏钢琴键盘(你可以在钢琴的设置中按下按键辅助来查看哪个键是哪个按钮)
当然我也必须在按键之间等待,但这很容易。
感谢任何帮助。 (Windows 10 64 位 (32 位 Python 2.7))
先检查this个问题。这是关于如何模拟按键的一般思路,它可能看起来很多,但它只是一大堆按键。然后将 midi 转换为键盘按钮,您将在音符和键盘按钮之间创建字典映射。
我知道您真正需要的是一种将 MIDI 音符编号转换为标准记谱法音符的方法。
以下是来自维基百科的一些元素:
... GM specifies that note number 69 plays A440, which in turn fixes middle C as note number 60 ...
Converting from midi note number (d) to frequency (f) is given by the following formula:
f = 2 (d-69)/12 * 440 Hz
(来自 MIDI Tuning Standard - Frequency values)
最后来自 C (musical note) - Designation by octave
Scientific designation |Octave name | Frequency (Hz) | Other names
C4 | One-lined | 261.626 | Middle C
所以C4是midi音符69,midi音符之间用半音(*)隔开。由于一个八度音阶有 12 个半音,因此在 midi note 81 处会得到 C5,而著名的 A440(midi note 69)是 A4 科学记数法。
以table
为例
Midi note | Scientific notation
60 | C4
62 | D4
64 | E4
65 | F4
67 | G4
69 | A4
70 | B4
71 | C5
你会在 midi 66 处得到 F♯4...
(*)在音乐上就是所谓的平均律。 Midi 允许更精细的音高定义,但它会远远超出这个答案。
如果您看一下您正在使用的 midi
模块,您会发现有一些常量可用于将音符转换为它们的 MIDI 编号,反之亦然。
>>> import midi
>>> midi.C_0 # note C octave 0
0
>>> midi.G_3 # G octave 3
43
>>> midi.Gs_4 # G# octave 4
56
>>> midi.A_8 # A octave 8
105
>>> midi.NOTE_VALUE_MAP_SHARP[0]
C_0
>>> midi.NOTE_VALUE_MAP_SHARP[56]
Gs_4
>>> midi.NOTE_VALUE_MAP_SHARP[105]
A_8
打开一个带有 read_midifile()
returns 一个 Pattern
对象的 MIDI 文件,它看起来像这样(取自示例):
>>> midi.read_midifile('example.mid')
midi.Pattern(format=1, resolution=220, tracks=\
[midi.Track(\
[midi.NoteOnEvent(tick=0, channel=0, data=[43, 20]),
midi.NoteOffEvent(tick=100, channel=0, data=[43, 0]),
midi.EndOfTrackEvent(tick=1, data=[])])])
NoteOnEvent
包含时间、MIDI number/pitch 和速度,您可以检索:
>>> on = midi.NoteOnEvent(tick=0, channel=0, data=[43, 20])
>>> on.pitch
43
>>> midi.NOTE_VALUE_MAP_SHARP[on.pitch]
'G_3'
现在所有这些都很有趣,但您实际上并不需要将 MIDI 编号转换为音符,您只需将其转换为 http://virtualpiano.net/ 使用的该音符的键盘键即可。
Middle C 等于 MIDI 60,此音符对应虚拟钢琴键盘上的第 25 个键,通过按字母 t
激活。下一个音符 Cs_5 是大写的 MIDI 61 T
(<shift>-t)
。从那里你可以计算出 MIDI 数字到支持的虚拟钢琴键的映射;是这样的:
midi_to_vk = (
[None]*36 +
list('1!2@34%6^78*9(0qQwWeErtTyYuiIoOpPasSdDfgGhHjJklLzZxcCvVbBnm') +
[None]*31
)
您将面临的下一个问题是发送按键事件。请注意,在 MIDI 中,多个音符可以同时播放,也可以及时重叠。这意味着您可能需要能够同时发送多个按键事件。
我认为您无法使用计算机键盘处理速度。还有就是时间问题,你说这对你来说不是问题。
我正在尝试读取 MIDI 文件,然后将每个音符(MIDI 编号)转换为键盘上的模拟按键(A、f、h、J、t...)。
我可以像这样使用 python-midi 库读取任何 MIDI 文件:
pattern = midi.read_midifile("example.mid")
而且我还可以像这样用 pywin32 模拟按键:
shell = win32com.client.Dispatch("WScript.Shell")
shell.SendKeys(key)
但我不知道如何将 midi 数字(在 midi 文件中)实际转换为按键。
更准确地说,我正在尝试将 MIDI 数字转换为音符,然后根据 virtualpiano.net(61 键)将音符转换为按键,以便程序可以通过按下相应的按钮来弹奏钢琴键盘(你可以在钢琴的设置中按下按键辅助来查看哪个键是哪个按钮)
当然我也必须在按键之间等待,但这很容易。
感谢任何帮助。 (Windows 10 64 位 (32 位 Python 2.7))
先检查this个问题。这是关于如何模拟按键的一般思路,它可能看起来很多,但它只是一大堆按键。然后将 midi 转换为键盘按钮,您将在音符和键盘按钮之间创建字典映射。
我知道您真正需要的是一种将 MIDI 音符编号转换为标准记谱法音符的方法。
以下是来自维基百科的一些元素:
... GM specifies that note number 69 plays A440, which in turn fixes middle C as note number 60 ...
Converting from midi note number (d) to frequency (f) is given by the following formula:
f = 2 (d-69)/12 * 440 Hz
(来自 MIDI Tuning Standard - Frequency values)
最后来自 C (musical note) - Designation by octave
Scientific designation |Octave name | Frequency (Hz) | Other names C4 | One-lined | 261.626 | Middle C
所以C4是midi音符69,midi音符之间用半音(*)隔开。由于一个八度音阶有 12 个半音,因此在 midi note 81 处会得到 C5,而著名的 A440(midi note 69)是 A4 科学记数法。
以table
为例Midi note | Scientific notation
60 | C4
62 | D4
64 | E4
65 | F4
67 | G4
69 | A4
70 | B4
71 | C5
你会在 midi 66 处得到 F♯4...
(*)在音乐上就是所谓的平均律。 Midi 允许更精细的音高定义,但它会远远超出这个答案。
如果您看一下您正在使用的 midi
模块,您会发现有一些常量可用于将音符转换为它们的 MIDI 编号,反之亦然。
>>> import midi
>>> midi.C_0 # note C octave 0
0
>>> midi.G_3 # G octave 3
43
>>> midi.Gs_4 # G# octave 4
56
>>> midi.A_8 # A octave 8
105
>>> midi.NOTE_VALUE_MAP_SHARP[0]
C_0
>>> midi.NOTE_VALUE_MAP_SHARP[56]
Gs_4
>>> midi.NOTE_VALUE_MAP_SHARP[105]
A_8
打开一个带有 read_midifile()
returns 一个 Pattern
对象的 MIDI 文件,它看起来像这样(取自示例):
>>> midi.read_midifile('example.mid')
midi.Pattern(format=1, resolution=220, tracks=\
[midi.Track(\
[midi.NoteOnEvent(tick=0, channel=0, data=[43, 20]),
midi.NoteOffEvent(tick=100, channel=0, data=[43, 0]),
midi.EndOfTrackEvent(tick=1, data=[])])])
NoteOnEvent
包含时间、MIDI number/pitch 和速度,您可以检索:
>>> on = midi.NoteOnEvent(tick=0, channel=0, data=[43, 20])
>>> on.pitch
43
>>> midi.NOTE_VALUE_MAP_SHARP[on.pitch]
'G_3'
现在所有这些都很有趣,但您实际上并不需要将 MIDI 编号转换为音符,您只需将其转换为 http://virtualpiano.net/ 使用的该音符的键盘键即可。
Middle C 等于 MIDI 60,此音符对应虚拟钢琴键盘上的第 25 个键,通过按字母 t
激活。下一个音符 Cs_5 是大写的 MIDI 61 T
(<shift>-t)
。从那里你可以计算出 MIDI 数字到支持的虚拟钢琴键的映射;是这样的:
midi_to_vk = (
[None]*36 +
list('1!2@34%6^78*9(0qQwWeErtTyYuiIoOpPasSdDfgGhHjJklLzZxcCvVbBnm') +
[None]*31
)
您将面临的下一个问题是发送按键事件。请注意,在 MIDI 中,多个音符可以同时播放,也可以及时重叠。这意味着您可能需要能够同时发送多个按键事件。
我认为您无法使用计算机键盘处理速度。还有就是时间问题,你说这对你来说不是问题。