Odroid-Go: Unmute+Mute buzzer before/after Playback (#52)

On ODROID-GO the buzzer makes noises when it is on and nothing is being played. Don't know if this
is common on ESP32 devices...
This commit is contained in:
Jens Diemer
2026-02-21 07:44:45 +01:00
committed by GitHub
parent d3e009966d
commit 84d3f83966
2 changed files with 58 additions and 12 deletions
@@ -31,8 +31,15 @@ class AudioManager:
STREAM_ALARM = 2 # Alarms/alerts (highest priority)
_instance = None # Singleton instance
def __init__(self, i2s_pins=None, buzzer_instance=None, adc_mic_pin=None):
def __init__(
self,
i2s_pins=None,
buzzer_instance=None,
adc_mic_pin=None,
pre_playback=None,
post_playback=None,
):
"""
Initialize AudioManager instance with optional hardware configuration.
@@ -40,6 +47,8 @@ class AudioManager:
i2s_pins: Dict with 'sck', 'ws', 'sd' pin numbers (for I2S/WAV playback)
buzzer_instance: PWM instance for buzzer (for RTTTL playback)
adc_mic_pin: GPIO pin number for ADC microphone (for ADC recording)
pre_playback: Optional callback called before starting playback
post_playback: Optional callback called after stopping playback
"""
if AudioManager._instance:
# If instance exists, update configuration if provided
@@ -53,12 +62,15 @@ class AudioManager:
AudioManager._instance = self
self._i2s_pins = i2s_pins # I2S pin configuration dict (created per-stream)
self._buzzer_instance = buzzer_instance # PWM buzzer instance
self._adc_mic_pin = adc_mic_pin # ADC microphone pin
self._current_stream = None # Currently playing stream
self._current_recording = None # Currently recording stream
self._volume = 50 # System volume (0-100)
self._i2s_pins = i2s_pins # I2S pin configuration dict (created per-stream)
self._buzzer_instance = buzzer_instance # PWM buzzer instance
self._adc_mic_pin = adc_mic_pin # ADC microphone pin
self.pre_playback = pre_playback
self.post_playback = post_playback
self._current_stream = None # Currently playing stream
self._current_recording = None # Currently recording stream
self._volume = 50 # System volume (0-100)
# Build status message
capabilities = []
@@ -68,7 +80,7 @@ class AudioManager:
capabilities.append("Buzzer (RTTTL)")
if adc_mic_pin:
capabilities.append(f"ADC Mic (Pin {adc_mic_pin})")
if capabilities:
print(f"AudioManager initialized: {', '.join(capabilities)}")
else:
@@ -131,6 +143,11 @@ class AudioManager:
stream: Stream instance (WAVStream or RTTTLStream)
"""
self._current_stream = stream
if self.pre_playback:
try:
self.pre_playback()
except Exception as e:
print(f"AudioManager: pre_playback callback error: {e}")
try:
# Run synchronous playback in this thread
@@ -142,6 +159,12 @@ class AudioManager:
if self._current_stream == stream:
self._current_stream = None
if self.post_playback:
try:
self.post_playback()
except Exception as e:
print(f"AudioManager: post_playback callback error: {e}")
def play_wav(self, file_path, stream_type=None, volume=None, on_complete=None):
"""
Play WAV file via I2S.
@@ -62,9 +62,32 @@ blue_led.on()
print("odroid_go.py init buzzer")
buzzer = PWM(Pin(BUZZER_PIN, Pin.OUT, value=1), duty=5)
dac_pin = Pin(BUZZER_DAC_PIN, Pin.OUT, value=1)
dac_pin.value(1) # Unmute
AudioManager(i2s_pins=None, buzzer_instance=buzzer)
class BuzzerCallbacks:
__slots__ = ("dac_pin",)
def __init__(self):
self.dac_pin = Pin(BUZZER_DAC_PIN, Pin.OUT, value=1)
def unmute(self):
print("Unmute buzzer")
self.dac_pin.value(1) # Unmute
def mute(self):
print("Mute buzzer")
self.dac_pin.value(0) # Mute
buzzer_callbacks = BuzzerCallbacks()
AudioManager(
i2s_pins=None,
buzzer_instance=buzzer,
# The buzzer makes noise when it's unmuted, to avoid this we
# mute it after playback and vice versa unmute it before playback:
pre_playback=buzzer_callbacks.unmute,
post_playback=buzzer_callbacks.mute,
)
AudioManager.set_volume(40)
AudioManager.play_rtttl("Star Trek:o=4,d=20,b=200:8f.,a#,4d#6.,8d6,a#.,g.,c6.,4f6")
while AudioManager.is_playing():