fix(audio): resolve ES7210 microphone popping sound by correcting OSR and clock division configuration
This commit is contained in:
+39
-34
@@ -2,9 +2,8 @@ import time
|
||||
import machine
|
||||
from machine import Pin, I2S
|
||||
import board_config
|
||||
import audio_util
|
||||
|
||||
def play_raw_pcm(filename, channels=2, rate=16000, bits=16, volume=90):
|
||||
def play_ram_pcm(audio_chunks, channels=2, rate=16000, bits=16, volume=90):
|
||||
from audio_util import ES8311
|
||||
|
||||
# 1. Start MCLK PWM using board config parameters
|
||||
@@ -38,16 +37,11 @@ def play_raw_pcm(filename, channels=2, rate=16000, bits=16, volume=90):
|
||||
amp_pin = Pin(board_config.audio_amp_pin, Pin.OUT, value=on_val)
|
||||
|
||||
try:
|
||||
print(f"Streaming raw audio to speaker from '{filename}'...")
|
||||
with open(filename, 'rb') as f:
|
||||
buf = bytearray(2048)
|
||||
while True:
|
||||
bytes_read = f.readinto(buf)
|
||||
if bytes_read == 0:
|
||||
break
|
||||
i2s.write(buf[:bytes_read])
|
||||
print(f"Streaming raw audio to speaker from RAM ({len(audio_chunks)} chunks)...")
|
||||
for chunk in audio_chunks:
|
||||
i2s.write(chunk)
|
||||
except Exception as e:
|
||||
print("Error during raw playback:", e)
|
||||
print("Error during RAM playback:", e)
|
||||
finally:
|
||||
time.sleep_ms(100) # Let buffer play out
|
||||
amp_pin.value(off_val) # Disable amp
|
||||
@@ -58,10 +52,10 @@ def play_raw_pcm(filename, channels=2, rate=16000, bits=16, volume=90):
|
||||
|
||||
def main():
|
||||
display = board_config.display_instance
|
||||
print("=== Dynamic Audio Loopback Utility Script ===")
|
||||
print("=== Dynamic RAM-based Audio Loopback Script ===")
|
||||
print(f"Board Detected: {board_config.BOARD_TYPE}")
|
||||
|
||||
# Initialize buttons using polling Pins instead of BoardButtons class (to avoid edge-triggered interrupt storms)
|
||||
# Initialize buttons using polling Pins instead of BoardButtons class
|
||||
key_pin = Pin(18, Pin.IN, Pin.PULL_UP)
|
||||
boot_pin = Pin(0, Pin.IN, Pin.PULL_UP)
|
||||
|
||||
@@ -71,8 +65,6 @@ def main():
|
||||
return board_config.touch.is_touched()
|
||||
return key_pin.value() == 0
|
||||
|
||||
filename = "local_audio_test.pcm"
|
||||
|
||||
while True:
|
||||
if display:
|
||||
display.clear(0)
|
||||
@@ -81,13 +73,13 @@ def main():
|
||||
display.line(10, 20, 390, 20, 1)
|
||||
display.text("1. Press KEY button to record 10s", 15, 60, 1)
|
||||
display.text("2. Playback will start automatically", 15, 80, 1)
|
||||
display.text("Ready...", 15, 120, 1)
|
||||
display.text("Ready (RAM-based)...", 15, 120, 1)
|
||||
else:
|
||||
display.text("Touch Audio Loopback Test", 10, 10, 1)
|
||||
display.line(10, 20, 310, 20, 1)
|
||||
display.text("1. Press screen/KEY to record 10s", 10, 50, 1)
|
||||
display.text("2. Playback starts automatically", 10, 70, 1)
|
||||
display.text("Ready...", 10, 100, 1)
|
||||
display.text("Ready (RAM-based)...", 10, 100, 1)
|
||||
display.show()
|
||||
|
||||
print("Ready: Press and hold key/screen to record...")
|
||||
@@ -129,8 +121,6 @@ def main():
|
||||
display.text("Speak now!", 10, 80, 1)
|
||||
display.show()
|
||||
|
||||
# We record as long as the button is pressed (or up to 10 seconds max)
|
||||
|
||||
# 1. Start MCLK PWM using board config parameters
|
||||
mclk_pwm = None
|
||||
if board_config.audio_mclk_pin is not None:
|
||||
@@ -139,26 +129,28 @@ def main():
|
||||
mclk_pwm.freq(board_config.audio_mclk_freq)
|
||||
mclk_pwm.duty_u16(32768)
|
||||
|
||||
# 2. Configure I2S RX (Stereo 16kHz)
|
||||
# 2. Configure I2S RX (Stereo 16kHz) - ibuf set to 16000 for safety
|
||||
i2s_rx = I2S(1,
|
||||
sck=Pin(board_config.audio_i2s_sck),
|
||||
ws=Pin(board_config.audio_i2s_ws),
|
||||
sd=Pin(board_config.audio_i2s_rx_sd),
|
||||
mode=I2S.RX,
|
||||
ibuf=8000,
|
||||
ibuf=16000,
|
||||
rate=16000,
|
||||
bits=16,
|
||||
format=I2S.STEREO)
|
||||
|
||||
# 3. Wake up and configure the microphone chip (ES7210 vs ES8311)
|
||||
init_ok = False
|
||||
if board_config.audio_mic_codec == "ES7210":
|
||||
from audio_util import ES7210
|
||||
mic_adc = ES7210(board_config.i2c_bus)
|
||||
mic_adc.init(sample_rate=16000, bit_width=16)
|
||||
init_ok = mic_adc.init(sample_rate=16000, bit_width=16)
|
||||
else:
|
||||
from audio_util import ES8311
|
||||
mic_adc = ES8311(board_config.i2c_bus)
|
||||
if mic_adc.init(sample_rate=16000):
|
||||
init_ok = True
|
||||
mic_adc.set_volume(80)
|
||||
try:
|
||||
mic_adc._write(0x14, 0x1A) # Enable analog mic input & PGA
|
||||
@@ -166,19 +158,32 @@ def main():
|
||||
mic_adc._write(0x17, 0xC8) # Set ADC digital volume
|
||||
except:
|
||||
pass
|
||||
|
||||
if not init_ok:
|
||||
print("Microphone codec initialization failed! Aborting recording.")
|
||||
i2s_rx.deinit()
|
||||
if mclk_pwm:
|
||||
mclk_pwm.deinit()
|
||||
if display:
|
||||
display.clear(0)
|
||||
display.text("Codec Init Failed!", 15, 80, 1)
|
||||
display.show()
|
||||
time.sleep(3)
|
||||
continue
|
||||
|
||||
# Record loop
|
||||
buffer = bytearray(1024)
|
||||
# Record loop to RAM - using ticks_ms for safe timing
|
||||
buffer = bytearray(2048)
|
||||
audio_chunks = []
|
||||
total_bytes = 0
|
||||
start_rec_time = time.time()
|
||||
start_rec_time = time.ticks_ms()
|
||||
max_duration_ms = 10000 # 10 seconds
|
||||
|
||||
try:
|
||||
with open(filename, 'wb') as f:
|
||||
while (time.time() - start_rec_time) < 10:
|
||||
bytes_read = i2s_rx.readinto(buffer)
|
||||
if bytes_read > 0:
|
||||
f.write(buffer[:bytes_read])
|
||||
total_bytes += bytes_read
|
||||
while time.ticks_diff(time.ticks_ms(), start_rec_time) < max_duration_ms:
|
||||
bytes_read = i2s_rx.readinto(buffer)
|
||||
if bytes_read > 0:
|
||||
audio_chunks.append(bytes(buffer[:bytes_read]))
|
||||
total_bytes += bytes_read
|
||||
except Exception as e:
|
||||
print("Recording failed:", e)
|
||||
finally:
|
||||
@@ -186,12 +191,12 @@ def main():
|
||||
if mclk_pwm:
|
||||
mclk_pwm.deinit()
|
||||
|
||||
print(f"Recorded {total_bytes} bytes to '{filename}'.")
|
||||
print(f"Recorded {total_bytes} bytes in RAM ({len(audio_chunks)} chunks).")
|
||||
|
||||
# Wait for release of key/trigger to debounce
|
||||
time.sleep_ms(200)
|
||||
|
||||
# 4. Playback
|
||||
# 4. Playback from RAM
|
||||
if display:
|
||||
display.clear(0)
|
||||
if board_config.BOARD_TYPE == 'WAVESHARE_RLCD':
|
||||
@@ -206,7 +211,7 @@ def main():
|
||||
display.text(f"Bytes: {total_bytes}", 10, 80, 1)
|
||||
display.show()
|
||||
|
||||
play_raw_pcm(filename, channels=2, rate=16000, bits=16, volume=95)
|
||||
play_ram_pcm(audio_chunks, channels=2, rate=16000, bits=16, volume=95)
|
||||
|
||||
if display:
|
||||
display.clear(0)
|
||||
|
||||
Reference in New Issue
Block a user