###実現したい内容
pygameを用いてMIDIデバイスの入力を受け取り、リアルタイムでSin波で演奏
複数音の出力および、ベロシティの対応
発生してる問題
キーを押した時と離した時にプツプツとノイズが発生していしまいます。
音声のサスティン中に問題はありません。
色々と試してみたのですがうまくいきません
pygame.midi.Input.readの処理時間の問題でしょうか?
ご教示願います
コード
python
1#import部================================= 2import pygame.midi 3 4import math 5import numpy as np 6import pyaudio 7import struct 8#========================================= 9""" 10""" 11#pyAudip制御関連============================= 12if __name__ == '__main__': 13 p = pyaudio.PyAudio() 14 stream = p.open(format=pyaudio.paInt16,channels=1, rate=44100, output=1,stream_callback=None )# ストリームを開く 15 pos = 0 #posは波形生成時のタイムスタンプ 16 17 18#Midi制御関連============================= 19 20 pygame.init() 21 pygame.midi.init() 22 input_id = pygame.midi.get_default_input_id() 23 i = pygame.midi.Input(input_id) 24 25#----------------------------------------- 26 27def End(): #終了処理(必ず入れる) 28 i.close() 29 pygame.midi.quit() 30 pygame.quit() 31 stream.close() 32 p.terminate() 33 34#========================================= 35 36 37 38#Key管理================================ 39""" 40Key情報 41音程 0~127 まで オクターブごとに+12 42鍵盤を押したときの強さ 0~127 まで !0のときは鍵盤が押されていない 43 44keyID: 144 = 通常の鍵盤 45 [176,7,x,0] = Volume xは 0~127 まで 46 47""" 48#押されてるキーを保持するaリスト 49key_list = [] 50 51def Key_input(): 52 if i.poll(): 53 midi_events = i.read(1) #一度すべてのイベントを取り出す 54 state = midi_events[0][0] #読み取る値の取り出し 55 56 if 144 == state[0]: #鍵盤かの判定 57 if 0 != state[2]: #押された強さ 58 key_list.append(state[1:3]) 59 else : #離れたとき 60 for item in range(len(key_list)): 61 if key_list[item][0] == state[1]: 62 del key_list[item] 63 break 64 65 66 67 68#========================================= 69""" key_listには[MIDIノーツ番号,ベロシティ]""" 70 71#周波数とか作るところ======================= 72 73 74def ToNote(): 75 76 note_list=[] #notelist 初期化 77 78 for item in range(len(key_list)): 79 f = round(440.0 * (2**((key_list[item][0]-69)/12)) ,5) #周波数計算 80 a = round(key_list[item][1]/127.0,3) #音量計算 81 note_list.append([f,a]) #Listに追加 82 83 return note_list 84 85 86 87#========================================= 88 89 90 91#実際の波形を作成========================= 92def createData(freqList = [], start_pos=0): #オシレーター 93 data = [] 94 print(freqList) 95 if len(freqList)!= 0: 96 97 amp = 1.0 / len(freqList) #使用時は波形データにampを乗算する 98 99 end_pos = start_pos + 0.01 * 44100 #タイムスタンプ 100 101 for n in np.arange(start_pos, end_pos): 102 s = 0.0 #波形データをゼロクリア 103 for item in range(len(freqList)): 104 f = freqList[item][0] 105 s += amp * np.sin(2 * np.pi * f * n / 44100)*freqList[item][1] 106 # 振幅が大きい時はクリッピング 107 if s > 1.0: s = 1.0 108 if s < -1.0: s = -1.0 109 data.append(s) #末尾に追加 110 data = [int(x * 32767.0) for x in data] #値を32767~-32767間にする 111 112 113 # バイナリに変換 114 data = struct.pack("h" * len(data), *data) # listに*をつけると引数展開される 115 116 else : 117 118 end_pos = 0 #音がならない場合はタイムスタンプを0に 119 120 return data, end_pos 121 122#==================================== 123 124 125#再生================================ 126def play(stream,data): #再生用関数、ストリームと波形データを引数に 127 128 # チャンク単位でストリームに出力し音声を再生 129 chunk = 1048 130 sp = 0 # 再生位置ポインタ 131 buffer = data[sp:sp+chunk] 132 while buffer: 133 stream.write(buffer) 134 sp = sp + chunk 135 buffer = data[sp:sp+chunk] 136 137#========================================== 138 139 140#Main部==================================== 141if __name__ == '__main__': 142 143 144 while True: 145 146 Key_input() #キーの取得 147 148 note_list = ToNote() #押されているキーリストからノートのリストを作成 149 150 data, pos = createData(freqList = note_list,start_pos=pos) #波形の生成 151 play(stream,data) #出音 152 153 End() 154

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2018/02/16 08:55
2018/02/16 09:36 編集
2018/02/16 09:48
退会済みユーザー
2018/02/16 10:54
2018/02/16 11:01
退会済みユーザー
2018/02/16 23:44