adafruit / circuitpython

CircuitPython - a Python implementation for teaching coding with microcontrollers
https://circuitpython.org
Other
4.1k stars 1.22k forks source link

Stopping playback of source or sink connected to `audiofilters.Filter` causes device to become unresponsive #9778

Open dcooperdalrymple opened 20 hours ago

dcooperdalrymple commented 20 hours ago

CircuitPython version

Adafruit CircuitPython 9.2.0 on 2024-10-28; Pimoroni Pico Plus 2 with rp2350b

Code/REPL

import board
import audiobusio
import audiocore
import audiodelays
import audiofilters
import time

audio = audiobusio.I2SOut(bit_clock=board.GP0, word_select=board.GP1, data=board.GP2)

wave_file = open("StreetChicken.wav", "rb")
wave = audiocore.WaveFile(wave_file)

effect1 = audiofilters.Filter( # No filter specified, passes audio through
    sample_rate=wave.sample_rate,
    bits_per_sample=wave.bits_per_sample,
    channel_count=wave.channel_count,
)
effect1.play(wave, loop=True)

effect2 = audiodelays.Echo(
    sample_rate=wave.sample_rate,
    bits_per_sample=wave.bits_per_sample,
    channel_count=wave.channel_count,
)
effect2.play(effect1)

audio.play(effect2)

time.sleep(2)
effect1.stop()

Behavior

The echo effect is heard for a moment at around half speed, then output audio suffers terrible distortion and the device requires hard reset. USB device (/dev/ttyACM0) is not recognized.

Description

No response

Additional information

I've tested this in a slightly different scenario where audiodelays.Echo precedes audiofilters.Filter, and this error does not happen if audiodelays.Echo is stopped first. If audiofilters.Filter is stopped, the error described above occurs.

...
effect1 = audiodelays.Echo(
    sample_rate=wave.sample_rate,
    bits_per_sample=wave.bits_per_sample,
    channel_count=wave.channel_count,
)
effect1.play(wave, loop=True)

effect2 = audiofilters.Filter( # No filter specified, passes audio through
    sample_rate=wave.sample_rate,
    bits_per_sample=wave.bits_per_sample,
    channel_count=wave.channel_count,
)
effect2.play(effect1)

audio.play(effect2)

time.sleep(2)
effect1.stop() # No error
#effect2.stop() # Error
dcooperdalrymple commented 20 hours ago

I've just tested this scenario but with using two audiofilters.Filter objects and got the error. Then again with two audiodelays.Echo objects and wasn't able to recreate the crash. So, it looks like I'm to blame here (https://github.com/adafruit/circuitpython/pull/9744). I'll do more investigation into what could be causing the fault.