adafruit / circuitpython

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

audiofilters: Add Distortion effect #9776

Open relic-se opened 3 weeks ago

relic-se commented 3 weeks ago

New audio effects class, audiofilters.Distortion, to distort audio samples using one of the available modes available in the audiofilters.DistortionMode enum.

Todo:

Comments:

Parameters, documentation copy and algorithms are mostly credited to Godot Engine under the MIT License.

Example Code:

import board
import audiobusio
import audiofilters
import audiocore
import digitalio
import adafruit_debouncer

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)

effect = audiofilters.Distortion(
    buffer_size=1024,
    channel_count=wave.channel_count,
    sample_rate=wave.sample_rate,
    mix=0.0,
    pre_gain=0.0,
    post_gain=-10.0,
    drive=0.5,
)
effect.play(wave, loop=True)
audio.play(effect)

button_mix_pin = digitalio.DigitalInOut(board.GP3)
button_mix_pin.direction = digitalio.Direction.INPUT
button_mix = adafruit_debouncer.Debouncer(button_mix_pin)

button_mode_pin = digitalio.DigitalInOut(board.GP4)
button_mode_pin.direction = digitalio.Direction.INPUT
button_mode = adafruit_debouncer.Debouncer(button_mode_pin)

modes = [
#    (Mode, pre_gain, drive, post_gain),
    (audiofilters.DistortionMode.CLIP, 0.0, 0.5, -10.0),
    (audiofilters.DistortionMode.LOFI, 0.0, 0.9, -2.0),
    (audiofilters.DistortionMode.OVERDRIVE, 20.0, 0.5, -15.0),
    (audiofilters.DistortionMode.WAVESHAPE, 10.0, 0.75, -20.0),
]
mode_index = 0

# Initial state
print("off")
print(effect.mode)

while True:
    button_mix.update()
    if button_mix.rose:
        effect.mix = not effect.mix
        print("on" if effect.mix else "off")

    button_mode.update()
    if button_mode.rose:
        mode_index = (mode_index + 1) % len(modes)
        effect.mode, effect.pre_gain, effect.drive, effect.post_gain = modes[mode_index]
        print(effect.mode)
RAWJUNGLE commented 3 weeks ago

I think we need to add more fluff for the full effects package as well.

relic-se commented 3 weeks ago

I think we need to add more fluff for the full effects package as well.

* Maybe a bitcrasher?

I don't know exactly what you mean by "fluff", but the audiofilters.DistortionMode.LOFI is a bitcrusher. In fact, it may need to be renamed to better represent that.