Adafruit_CircuitPython_Wave でwavファイルを再生

目次
前回は、audiocore とaudomixerでwavファイルを再生した。 引き続き、 CircuitPython で、RaspberryPi Picoから音源再生。
audiocore.WaveFile() は、wavファイルをそのまま再生するのはいいが、ちょっとeffectをかけたい場合に不便。
.wavファイルをデータイメージでloadして、 audiocore.RawSample() で再生してみる。
adafruit_wave.py
Adafruit_CircuitPython_Wave は、.wav ファイルをデータとしてloadできる
上記から、 adafruit_wave.py をもってきて、Macなら /Volumes/CIRCUITPY/lib 配下にコピーする。
bash
cp adafruit_wave.py /Volumes/CIRCUITPY/lib配線
- GP26(A0) とGNDをスピーカーに接続
- GP0 - タクトスイッチ - GNDを接続

操作
起動すると、 sample.wav を再生。
タクトスイッチを押すと、再生中のデータ(0.5秒分)を繰り返す。
温泉がすきすきすきすき...
sample.wav
source code
wavfile_play.py · Gistpython
import adafruit_wave
import audiocore
import digitalio
import board
import audiobusio
import array
import time
try:
from audioio import AudioOut
except ImportError:
try:
from audiopwmio import PWMAudioOut as AudioOut
except ImportError:
pass # not always supported by every board!
# repeat button
button = digitalio.DigitalInOut(board.GP0)
button.switch_to_input(pull=digitalio.Pull.UP)
# Audio Out
a = AudioOut(board.A0)
# .wav open
filename = "sample.wav"
w = adafruit_wave.open(filename)
# read 0.5sec sample
sample_sec = 1/2
framerate = int(w.getframerate() / 2)
#
# main loop
#
current_channel = 0
new_c = 1 - current_channel
is_end = False
sample_data = [0, 0]
next_time = 0
while is_end is False:
if next_time > time.monotonic_ns():
continue
next_time = time.monotonic_ns() + (sample_sec * 1000_000_000)
if button.value is False:
# repeat play
a.stop()
# play start
a.play(sample_data[current_channel])
else:
new_c = 1 - current_channel
if sample_data[new_c] != 0:
a.play(sample_data[new_c]) # ready to play channel
# read next time data from file
data = w.readframes(framerate)
if len(data) <= 0:
# end of file
is_end = True
break
wave = array.array("h", data)
sample_data[current_channel] = audiocore.RawSample(wave, sample_rate=16000)
current_channel = new_c
print(".", end="")
print("")
print("end")demo
制限
FileIOは重い。0.5秒単位ならまだいいが、0.2秒単位のloadにするとブツブツと雑音が混じる。
