# Laser Harp v3 - by Jack Tommaney

import board, time, math, digitalio
from adafruit_debouncer import Button
import audiobusio
import synthio

# Audio / Synth Setup

audio = audiobusio.I2SOut(
    bit_clock=board.GP21,
    word_select=board.GP20,
    data=board.GP22
)

# Synth initialization
synth = synthio.Synthesizer(sample_rate=22050)
audio.play(synth)

# Envelope for all notes
envelope = synthio.Envelope(
    attack_time=0.01,
    decay_time=0.3,
    release_time=0.1,
    attack_level=1.0,
    sustain_level=0.5,
)

# C, Eb, F, G, Bb, C in pentatonic scale
NOTE_FREQS = [262, 311, 349, 392, 466, 523]

# 1 Note object per string
NOTES = [
    synthio.Note(frequency=freq, envelope=envelope, amplitude=0.6)
    for freq in NOTE_FREQS
]

# String setup

def make_button(pin):
    io = digitalio.DigitalInOut(pin)
    io.switch_to_input(pull=digitalio.Pull.UP)
    return Button(io, value_when_pressed=False)

string1_db = make_button(board.GP0)
string2_db = make_button(board.GP1)
string3_db = make_button(board.GP2)
string4_db = make_button(board.GP15)
string5_db = make_button(board.GP4)
string6_db = make_button(board.GP5)

buttons = [string1_db, string2_db, string3_db, string4_db, string5_db, string6_db]

# Map each button to a Note object
button_to_note = {
    0: NOTES[0],
    1: NOTES[1],
    2: NOTES[2],
    3: NOTES[3],
    4: NOTES[4],
    5: NOTES[5],
}


# Play polyphonic sounds based on string presses

while True:
    for b in buttons:
        b.update()

    # Check events and press/release notes
    for i, b in enumerate(buttons):
        note = button_to_note[i]

        if b.pressed:
            print(f"String {i+1} PRESSED, freq {NOTE_FREQS[i]} Hz")
            synth.press(note)

        if b.released:
            print(f"String {i+1} RELEASED, freq {NOTE_FREQS[i]} Hz")
            synth.release(note)

    time.sleep(0.001) # faster cycle rate = more responsive harp