一度はうごいたがその後無音に。。。。製品が2個とも悪いのかも、あきらめた
**「ステレオ WAV でも再生できる」**ようにします。
やり方は ステレオ → モノラルにソフトで変換(L+R を平均)して I2S に流す方式です。
👉 MAX98357A が モノラル接続でも確実に鳴る一番安全な方法です。
方針(重要)
-
WAV が
-
モノラル → そのまま再生
-
ステレオ → L/R を平均してモノラル化して再生
-
-
対応フォーマット
-
PCM
-
16bit
-
mono / stereo 両対応
-
ステレオ対応版:WAV 再生コード(Pico W + MAX98357A)
from machine import Pin, I2S
import struct
# ==============================
# I2S ピン設定
# ==============================
BCLK_PIN = 10 # GP10
WS_PIN = 11 # GP11
DIN_PIN = 12 # GP12
WAV_FILE = "test.wav"
# ==============================
# WAV ヘッダ解析
# ==============================
def read_wav_header(f):
if f.read(4) != b'RIFF':
raise ValueError("RIFF形式ではありません")
f.read(4)
if f.read(4) != b'WAVE':
raise ValueError("WAVE形式ではありません")
# fmt チャンク探索
while True:
cid = f.read(4)
size = struct.unpack("<I", f.read(4))[0]
if cid == b'fmt ':
fmt = f.read(size)
break
else:
f.seek(size, 1)
audio_format, channels, sample_rate = struct.unpack("<HHI", fmt[:8])
bits = struct.unpack("<H", fmt[14:16])[0]
print("==== WAV 情報 ====")
print("チャンネル数 :", channels)
print("ビット深度 :", bits)
print("サンプル周波数:", sample_rate, "Hz")
if audio_format != 1:
raise ValueError("PCM形式のみ対応")
if bits != 16:
raise ValueError("16bitのみ対応")
if channels not in (1, 2):
raise ValueError("mono / stereo のみ対応")
# data チャンク探索
while True:
cid = f.read(4)
size = struct.unpack("<I", f.read(4))[0]
if cid == b'data':
return sample_rate, channels, size
else:
f.seek(size, 1)
# ==============================
# ステレオ → モノラル変換
# ==============================
def stereo_to_mono(data):
out = bytearray(len(data) // 2)
for i in range(0, len(data), 4):
l = struct.unpack_from("<h", data, i)[0]
r = struct.unpack_from("<h", data, i + 2)[0]
m = (l + r) // 2
struct.pack_into("<h", out, i // 2, m)
return out
# ==============================
# WAV 再生
# ==============================
with open(WAV_FILE, "rb") as f:
rate, channels, data_size = read_wav_header(f)
audio = I2S(
0,
sck=Pin(BCLK_PIN),
ws=Pin(WS_PIN),
sd=Pin(DIN_PIN),
mode=I2S.TX,
bits=16,
format=I2S.MONO,
rate=rate,
ibuf=40000
)
print("▶ 再生開始")
BUF_SIZE = 1024 * (2 if channels == 2 else 1)
remaining = data_size
while remaining > 0:
raw = f.read(min(BUF_SIZE, remaining))
if not raw:
break
if channels == 2:
raw = stereo_to_mono(raw)
audio.write(raw)
remaining -= len(raw)
audio.deinit()
print("■ 再生終了")-------------------------------------------------------------
0 件のコメント:
コメントを投稿