Skip to content

Add new audiospeed.Resampler module#11057

Open
relic-se wants to merge 4 commits into
adafruit:mainfrom
relic-se:resampler
Open

Add new audiospeed.Resampler module#11057
relic-se wants to merge 4 commits into
adafruit:mainfrom
relic-se:resampler

Conversation

@relic-se

@relic-se relic-se commented Jun 17, 2026

Copy link
Copy Markdown

Automatically resamples source sample to match destination sample rate. Shares fixed point speed functionality with audiospeed.SpeedChanger.

Demonstration using pico_test_synth with raspberry_pi_pico:

import array
import audiobusio
import audiocore
import audiomixer
import audiospeed
import board
import math
import time

IN_SAMPLE_RATE = 32000
OUT_SAMPLE_RATES = (8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200, 96000)

# Set up audio output
audio = audiobusio.I2SOut(bit_clock=board.GP20, word_select=board.GP21, data=board.GP22)

# Generate one period of sine wave
length = IN_SAMPLE_RATE // 440
sine_wave = array.array("H", [0] * length)
for i in range(length):
    sine_wave[i] = min(max(int(math.sin(math.pi * 2 * i / length) * (2 ** 15) + 2 ** 15), -65536), 65535)
sine_wave = audiocore.RawSample(sine_wave, sample_rate=IN_SAMPLE_RATE)

# Process sample through resampler
resampler = audiospeed.Resampler(sine_wave)

# Test each sample rate
for x in OUT_SAMPLE_RATES:
    mixer = audiomixer.Mixer(sample_rate=x, samples_signed=False)
    audio.play(mixer)
    mixer.play(resampler, loop=True)
    
    print(x, resampler.rate)
    time.sleep(1)
    
    mixer.stop_voice()
    audio.stop()
    mixer.deinit()
    del mixer

Notes:

  • Some resampling rates slightly alter pitch. I'm chocking this up to the lack of linear interpolation.
  • The property audiospeed.Resampler.rate exists as a getter primarily for testing purposes. This can be removed if desired.
  • audiospeed.SpeedChanger is assigned a sample within the constructor. I decided to use the play/stop/playing paradigm instead to allow swapping samples. source could be added to the constructor of audiospeed.Resampler as an optional argument if desired. I decided to match the implementation of SpeedChanger by assigning the source only in the constructor.

For interest: @todbot @gamblor21 @kevinjwalters

@relic-se relic-se marked this pull request as draft June 17, 2026 19:12
@relic-se relic-se marked this pull request as ready for review June 17, 2026 19:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant