from pyo import *
import random

#############################################
#   Andrew Chao - andrewchao7000@gmail.com  #
#   6/1/2026                                #
#############################################

server = Server(duplex=0).boot()
server.start()

#ambience
brown_noise = BrownNoise(mul=0.05)
floor_rumble = Tone(brown_noise, freq=120, mul=2.0).mix(2).out()

pitched_0 = Reson(brown_noise, freq=60, q=10, mul=5.0).mix(2).out()
pitched_1 = Reson(brown_noise, freq=170, q=10, mul=2.0).mix(2).out()
pitched_2 = Reson(brown_noise, freq=310, q=10, mul=1.0).mix(2).out()

chord_mix = pitched_0 + pitched_1 + pitched_2
ambient_space = Freeverb(chord_mix, size=0.9, damp=0.5, bal=0.5).mix(2).out()

#ball bounce stuff below


#this is based of the default C Major pentatonic so like [0,2,4,7,9]
PENTATONIC_NOTES = [36, 38, 40, 43, 45,  # Octave 3
                    48, 50, 52, 55, 57,  # Octave 4
                    60, 62, 64, 67, 69]  # Octave 5

#this is just a scale so +12 -12 for new octave changes
OCTAVE_SHIFT = 0
PENTATONIC_NOTES = [x + OCTAVE_SHIFT for x in PENTATONIC_NOTES]

NUM_VOICES = 8
voices = []

ATTACK = 0.08 #seconds to climb to MAX vol
DECAY = 0.4 #seconds to fall to RESTING vol
SUSTAIN = 0.1 #RESTING volume at 10% max vol
RELEASE = 3.0 #seconds for note to fade into silence
DURATION = 3.5 #how long it stays active before it closes

for i in range(NUM_VOICES):
    ADSR = Adsr(attack=ATTACK, decay=DECAY, sustain=SUSTAIN, release=RELEASE, dur=DURATION, mul=0)
    OSC = Sine(freq=440, mul=ADSR)

    voices.append({'ADSR': ADSR, 'OSC': OSC})

#mix all the voices together
mixed_voices = Mix([v['OSC'] for v in voices], voices=2)


#add reverb
reverb = Freeverb(mixed_voices, size=0.95, damp=0.5, bal=0.5).out()

voice_index = 0

def play_bounce_sound(volume):
    global voice_index

    #picks a random pentatonic note from our list
    midi_note = random.choice(PENTATONIC_NOTES)
    #convert the midi number to its coorisponding frequcny
    freq = midiToHz(midi_note)

    voice = voices[voice_index]

    voice['OSC'].setFreq(freq) # - 15 sounds nice (dont try -radius lol it sounds terrible since it breaks the harmonic)
    voice['ADSR'].setMul(volume)
    voice['ADSR'].play()

    #increase index cycles around in a loop
    voice_index = (voice_index + 1) % NUM_VOICES
