-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Description
CircuitPython version
Adafruit CircuitPython 8.0.5 on 2023-03-31; Raspberry Pi Pico W with rp2040
Board ID:raspberry_pi_pico_w
Code/REPL
import board
import synthio
import audiobusio
lck_pin, bck_pin, dat_pin = board.GP28, board.GP27, board.GP26
audio = audiobusio.I2SOut(bit_clock=bck_pin, word_select=lck_pin, data=dat_pin)
melody = synthio.MidiTrack(b"\0\x90H\0*\x80H\0\6\x90J\0*\x80J\0\6\x90L\0*\x80L\0\6\x90J\0" +
b"*\x80J\0\6\x90H\0*\x80H\0\6\x90J\0*\x80J\0\6\x90L\0T\x80L\0" +
b"\x0c\x90H\0T\x80H\0\x0c\x90H\0T\x80H\0", tempo=640)
audio.play(melody)
Behavior
A single repeating tone is heard on the audio output, instead of the tune.
Description
@todbot discovered during testing #7825 that the new code wasn't working. I tested the original synthio, and it also doesn't work. The underlying cause is probably the same thing (incomplete handling of the needs of the audio implementation).
Additional information
I think it's due to the "single buffer" flag being true
. It affects rp2040 (and probably atmel-samd and maybe nrf?), boards that actually use the "single buffer" flag to change behavior.
synthio needs to be modified to be more like a WaveFile, returning false for its single buffer flag and alternately returning two different halves of its buffer.
Introducing an otherwise unneeded AudioMixer object may be a workaround, at least for MidiFile in 8.0.4:
import board
import synthio
import audiomixer
import audiobusio
lck_pin, bck_pin, dat_pin = board.GP28, board.GP27, board.GP26
audio = audiobusio.I2SOut(bit_clock=bck_pin, word_select=lck_pin, data=dat_pin)
melody = synthio.MidiTrack(b"\0\x90H\0*\x80H\0\6\x90J\0*\x80J\0\6\x90L\0*\x80L\0\6\x90J\0" +
b"*\x80J\0\6\x90H\0*\x80H\0\6\x90J\0*\x80J\0\6\x90L\0T\x80L\0" +
b"\x0c\x90H\0T\x80H\0\x0c\x90H\0T\x80H\0", tempo=640)
mixer = audiomixer.Mixer(sample_rate=melody.sample_rate, channel_count=1)
audio.play(mixer)
mixer.voice[0].play(melody)
it appears a similar audiomixer workaround works in #7825. (weirdly in 8.0.5, it seemed to also work with the mixer.voice[].play
call before the audio.play
call, unless my testing wasn't with the code I intended; when "reset_buffer" is called on an audiomixer, as it is at the beginning of playback on rp2040 audio_dma_setup_playback
) all samples are stopped.