問題点
☑️同時に鳴らせる音を3つにしたかったけど方法がわからず
☑️鍵盤を離すと音が途切れるようにしてあるので、前の鍵盤を離してから次の鍵盤を押さないと、次の鍵盤の音が途切れてしまう
pyxelをシーケンサーにしたい💫
import pyxel
import mido
import time
# Pyxel の初期化
pyxel.init(256, 64, fps=30)
pyxel.NUM_SOUNDS = 3 # 同時発音数を 3 に制限
# MIDI ノート番号から Pyxel のノート文字列を生成する関数
def midi_to_pyxel_note(midi_note):
note_names = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
# MIDI ノート 36 (C2) を Pyxel の C0 に対応させる (調整が必要かもしれません)
base_midi_note = 36
if midi_note < base_midi_note:
return "C0" # 下限
octave = (midi_note - base_midi_note) // 12
note_index = (midi_note - base_midi_note) % 12
if octave > 7:
return "B7" # 上限
return f"{note_names[note_index]}{octave}"
# Pyxel のサウンドバンクに初期設定 (矩形波、固定スピード)
fixed_speed = 22050 // 10 # 適当な固定値
initial_notes = "A3"
initial_tones = "0"
initial_effects = "n"
initial_volume = "7"
for i in range(pyxel.NUM_SOUNDS):
pyxel.sounds[i].set(notes=initial_notes, tones=initial_tones, volumes=initial_volume, effects=initial_effects, speed=fixed_speed)
class App:
def __init__(self):
self.inport = None
self.playing_notes = {} # 再生中の MIDI ノートと Pyxel サウンド ID の対応
try:
self.inport = mido.open_input('MPK mini 3')
pyxel.run(self.update, self.draw)
except OSError as e:
print(f"MIDI デバイスが見つかりません: {e}")
except Exception as e:
print(f"エラーが発生しました: {e}")
finally:
if self.inport:
self.inport.close()
def update(self):
if self.inport:
received_message = self.inport.poll()
if received_message:
print(f"poll() の戻り値の値: {received_message}") # デバッグ用
if received_message.type == 'note_on':
if received_message.velocity > 0:
midi_note = received_message.note
if midi_note not in self.playing_notes:
# 空いているサウンド ID を探す
available_sound_id = -1
for i in range(pyxel.NUM_SOUNDS):
if i not in self.playing_notes.values():
available_sound_id = i
break
if available_sound_id != -1:
pyxel_note = midi_to_pyxel_note(midi_note)
try:
pyxel.sounds[available_sound_id].set(notes=pyxel_note, tones=initial_tones, volumes=initial_volume, effects=initial_effects, speed=fixed_speed)
pyxel.play(0, available_sound_id)
self.playing_notes[midi_note] = available_sound_id
except ValueError as e:
print(f"ValueError during sound set: {e}, pyxel_note: {pyxel_note}, midi_note: {midi_note}")
except Exception as e:
print(f"Unexpected error during sound set/play: {e}")
elif received_message.type == 'note_off':
midi_note = received_message.note
print(f"Note Off received for note: {midi_note}") # デバッグ用
if midi_note in self.playing_notes:
del self.playing_notes[midi_note]
# キーを離したらチャンネル 0 の再生を停止する
pyxel.stop(0)
def draw(self):
pyxel.cls(0)
pyxel.text(10, 10, "Playing MIDI Chords (Up to {} notes)".format(pyxel.NUM_SOUNDS), 7)
if __name__ == "__main__":
App()