やりたい事:440HzのSin波を作って鳴らしてみたけど、スピーカの特性によるのか矩形波のようなBEEP音になっていた。試しにコードの波形を作って鳴らしてみる
どうせならマイナーな、ラドミの和音の波形を作ってみる。
できたこと:和音の波形を作ってI2S制御のスピーカから再生した。
課題:和音が再生されたがノイズがひどい。また、単音の場合もi2s.write()でデータを送信する都度音が途切れる。callback方式で実装しても音が途切れる。どうやったら途切れることなく連続再生できるのか不明(Git上のサンプルコードを調べると何かわかるかも)*1
まとめ:やっぱり音のプログラムは難しい。MicroPython等のインタプリタで制御するにはハード側でcacheを持たせる等いろいろ工夫しないと、音が途切れる症状が出ると思われる。
周波数 1周期にかかるclock数(44.1KHz) -------------------------------------- # ラ A3 220.000 200 clock # ド C4 261.626 169 clock # ミ E4 329.628 134 clock
ラドミの和音による波形データを作るプログラムは以下
from math import pi
from math import sin
from machine import I2S
from machine import Pin
# code (A3_C4_E4)
# A3 220.000 200 clock
# C4 261.626 169 clock
# E4 329.628 134 clock
A3_CYCLE = 200
C4_CYCLE = 169
E4_CYCLE = 134
MAX_VOLUME = 0x7fff
volume = int(MAX_VOLUME * 0.5)
def dump2Bls(buf, len=128, onHex=False):
for i in range(len):
data = buf[i*2+1] << 8
data += buf[i*2]
if onHex:
print(f'{data:02x} ',end='')
if data >= 0x8000:
print(data - 0x10000)
else:
print(data)
def toI16(data):
if data == 0:
lb = 0
ub = 0
elif (data > 0) and (data <= 0x7fff):
lb = data & 0xff
ub = (data >> 8) & 0xff
elif (data < 0) and (data >= (0x8000 * -1)):
data = 0x10000 + data
lb = data & 0xff
ub = (data >> 8) & 0xff
else:
lb = None
ub = None
return (ub, lb)
i2s = I2S(0, sck=Pin(18), ws=Pin(19), sd=Pin(20), mode=I2S.TX, bits=16, format=I2S.MONO, rate=44100, ibuf=20_000)
buffer_size = 44100 * 2 # *2 means 2byte(16bit) and 1sec
buf = bytearray(buffer_size) #
for i in range(int(len(buf)/2)):
a3 = sin( 2 * pi * i / A3_CYCLE)
c4 = sin( 2 * pi * i / C4_CYCLE)
e4 = sin( 2 * pi * i / E4_CYCLE)
tone = int(volume * (a3 + c4 + e4 ) / 2)
i16 = toI16(tone)
buf[i * 2] = i16[1]
buf[i * 2 + 1] = i16[0]
while True:
i2s.write(buf)ノイズがひどくて聞くに堪えない。なぜノイズが乗るのか分からない。和音の作り方がまずいのかも。Excelで波形を描画させたが特に非連続な部分は見つけられず

*1:WAVフォーマットに仕上げてPCで再生させることにより、データの問題か再生装置の問題かを切り分けられそうだ