Exemple #1
0
def play_tone(waves, duration=0.1):
    if SPEAKER is None:
        speaker_init()
    wave_sum = waves.pop()
    while waves:
        for i, w in enumerate(waves.pop()):
            wave_sum[i] += w
    wave_sample = audioio.RawSample(wave_sum)
    SPEAKER.play(wave_sample, loop=True)
    time.sleep(duration)
    return SPEAKER.stop()




    omegas = [ 2*math.pi*x for x in freqs ]
    wave = array.array("H", [0] * 100)
    dt = 1./SAMPLE_RATE
    for w in omegas:
        for i in range( len(wave) ):
            wave[i] += int(math.sin(w*dt*i) * 2**15)
    wave_sample = audioio.RawSample(wave)
    SPEAKER.play(wave_sample, loop=True)
    time.sleep(duration)
    SPEAKER.stop()
    return
Exemple #2
0
def _play_to_pin(tune, base_tone, min_freq, duration, octave, tempo):
    """Using the prepared input send the notes to the pin
    """
    pwm = isinstance(base_tone, pulseio.PWMOut)
    for note in tune.split(","):
        piano_note, note_duration = _parse_note(note, duration, octave)
        if piano_note in PIANO:
            if pwm:
                base_tone.frequency = int(PIANO[piano_note])
                base_tone.duty_cycle = 2**15
            else:
                # AudioOut interface changed in CP 3.x
                if sys.implementation.version[0] >= 3:
                    pitch = int(PIANO[piano_note])
                    sine_wave = sine.sine_wave(16000, pitch)
                    sine_wave_sample = audioio.RawSample(sine_wave)
                    base_tone.play(sine_wave_sample, loop=True)
                else:
                    base_tone.frequency = int(16000 *
                                              (PIANO[piano_note] / min_freq))
                    base_tone.play(loop=True)

        time.sleep(4 / note_duration * 60 / tempo)
        if pwm:
            base_tone.duty_cycle = 0
        else:
            base_tone.stop()
        time.sleep(0.02)
def waveform_sawtooth(length, waves, volumes):
    for vol in volumes:
        waveraw = array.array("H", [
            midpoint +
            round(vol * sawtooth((idx + 0.5) / length * twopi + math.pi))
            for idx in list(range(length))
        ])
        waves.append((audioio.RawSample(waveraw), waveraw))
Exemple #4
0
 def _generate_sample(self, length=100, volume=None):
     if self._sample is not None:
         return
     self._sine_wave = array.array("H", Express._sine_sample(length, volume))
     if sys.implementation.version[0] >= 3:
         self._sample = audioio.AudioOut(board.SPEAKER)
         self._sine_wave_sample = audioio.RawSample(self._sine_wave)
     else:
         raise NotImplementedError("Please use CircuitPython 3.0 or higher.")
Exemple #5
0
def alarm_audio():
    tone_volume = 1  # Increase this to increase the volume of the tone.
    frequency = 440  # Set this to the Hz of the tone you want to generate.
    length = 8000 // frequency
    sine_wave = array.array("H", [0] * length)
    for i in range(length):
        sine_wave[i] = int((1 + math.sin(math.pi * 2 * i / length)) *
                           tone_volume * (2**15 - 1))
    return audioio.RawSample(sine_wave)
 def _generate_sample(self, length=100):
     if self._sample is not None:
         return
     self._sine_wave = array.array("H", Express._sine_sample(length))
     if sys.implementation.version[0] >= 3:
         self._sample = audioio.AudioOut(board.SPEAKER)
         self._sine_wave_sample = audioio.RawSample(self._sine_wave)
     else:
         self._sample = audioio.AudioOut(board.SPEAKER, self._sine_wave)
Exemple #7
0
 def __init__(self):
     self.duration = 0
     self.start = 0
     tone_volume = 1  # volume is from 0.0 to 1.0
     frequency = 440  # Set this to the Hz of the tone you want to generate.
     length = 4000 // frequency
     sine_wave = array.array("H", [0] * length)
     for i in range(length):
         sine_wave[i] = int((1 + math.sin(math.pi * 2 * i / length))
                            * tone_volume * (2 ** 15 - 1))
     self.sine_wave_sample = audioio.RawSample(sine_wave)
Exemple #8
0
def play_sin():
    channels = 2
    length = 8000 // 400
    sine_wave = array.array("H", [0] * channels * length)
    for i in range(length):
        for j in range(channels):
            sine_wave[i * channels + j] = int(
                math.sin(math.pi * 2 * i / length) * (2**13) + 2**15)

    sample = audioio.RawSample(sine_wave, channel_count=2, sample_rate=8000)
    audio.play(sample, loop=True)
    time.sleep(1)
    audio.stop()
Exemple #9
0
def start_tone(frequency):
    global _sample

    length = 100
    if length * frequency > 350000:
        length = 350000 // frequency
    _sine_wave = array.array("H", _sine_sample(length))
    _sample = audioio.AudioOut(board.SPEAKER)
    _sine_wave_sample = audioio.RawSample(_sine_wave)

    _sine_wave_sample.sample_rate = int(len(_sine_wave) * frequency)
    if not _sample.playing:
        _sample.play(_sine_wave_sample, loop=True)
Exemple #10
0
def make_waveforms(waves, type, samplerate):
    cyclelength = round(samplerate // A4refhz)
    length = cyclelength  ### a default which some waves will change

    #cycles = 1
    #cycles = 3    ### for perfect fifth
    #cycles = 4    ### for major chord

    ### TODO consider volume modification for internal speaker
    ### vs non speaker use

    ### major chord has longer sample which initially works
    ### but will blow up later with four levels
    if type == "majorchord":
        volumes = [23000]
    else:
        volumes = [23000]  ### 30000 clips 
        #volumes = [10000, 18000, 23000, 30000]

    ### Make some waves at different volumes
    for vol in volumes:
        ### Need to create a new array here as audio.RawSample appears not
        if type == "square":
            waveraw = array.array("h", [-vol] * (length // 2) + [vol] * (length - length // 2))
        else:
            waveraw = array.array("h", [0] * length)
            if type == "sawtooth":
                for i in range(length):
                    waveraw[i] = round((i / (length - 1) - 0.5) * 2 * vol)
            elif type == "supersaw":
                halflength    = length // 2
                quarterlength = length // 4
                for i in range(length):
                    ### TODO replace this with a gen function similar to sine
                    waveraw[i] = round(((i / (length - 1) - 0.5 +
                                         i % halflength / (halflength - 1) - 0.5 +
                                         i % quarterlength / (quarterlength - 1) - 0.5)
                                       ) * 2 / 3 * vol)
            elif type == "noise":
                waveraw = array.array("h", [0] * length)
                for i in range(length):
                    waveraw[i] = random.randint(0, 65536)
            else:
                return ValueError("Unknown type")

        waves.append(audioio.RawSample(waveraw))
    def playSound(sample_size=8000):
        (frequency, pulse_width) = readAnalogInputs()
        length = sample_size // frequency
        waveform = array.array("H", [0] * length)
        for t in range(length):
            v = (1.3 * math.sin(math.pi / length) * t)
            v = v + ((1.1 * math.sin(math.pi / length) * (t * 3)))
            v = v + ((1.4 * math.sin(math.pi / length) * (t * 5)))
            waveform[t] = int(v)

        # Play that wave, baby!
        self.speaker_enable.value = True
        wave_sample = audioio.RawSample(waveform)

        audio.play(wave_sample,
                   loop=True)  # keep playing the sample over and over
        time.sleep(pulse_width / 1000)  # until...
        audio.stop()  # we tell the board to stop
    def update(self, shape, frequency):
        if shape == self.shape and frequency == self.frequency:
            return

        if frequency != self.frequency:
            self.reallocate(frequency)
            self.frequency = frequency

        self.shape = shape
        if shape == shapes.SINE:
            self.make_sine()
        elif shape == shapes.SQUARE:
            self.make_square()
        elif shape == shapes.TRIANGLE:
            self.make_triangle()
        elif shape == shapes.SAWTOOTH:
            self.make_sawtooth()

        self.dac.stop()
        self.dac.play(audioio.RawSample(self.sample, channel_count=1, sample_rate=64000), loop=True)
Exemple #13
0
def play_tones(arr):
    cflag = 0
    audio = audioio.AudioOut(board.A0)
    for note, l in XY:
        if cflag == 0:
            pixels.fill((255, 0, 0))
            cflag = 1
        else:
            pixels.fill((0, 255, 0))
            cflag = 0
        if note != 0:
            length = SAMPLERATE // (note)
            sine_wave = array.array("H", [0] * length)
            for i in range(length):
                sine_wave[i] = int(
                    math.sin(math.pi * 2 * i / 18) * (2**15) + 2**15)
            sine_wave_sample = audioio.RawSample(sine_wave)
            audio.play(sine_wave_sample, loop=True)
        time.sleep(l * 0.4)
    audio.play(sine_wave_sample, loop=False)
def tone(pin, frequency, duration=1, length=100):
    """
    Generates a square wave of the specified frequency on a pin

    :param ~microcontroller.Pin Pin: Pin on which to output the tone
    :param float frequency: Frequency of tone in Hz
    :param int length: Variable size buffer (optional)
    :param int duration: Duration of tone in seconds (optional)
    """
    if length * frequency > 350000:
        length = 350000 // frequency
    try:
        # pin with PWM
        #pylint: disable=no-member
        with pulseio.PWMOut(pin,
                            frequency=int(frequency),
                            variable_frequency=False) as pwm:
            pwm.duty_cycle = 0x8000
            time.sleep(duration)
        #pylint: enable=no-member
    except ValueError:
        # pin without PWM
        sample_length = length
        square_wave = array.array("H", [0] * sample_length)
        for i in range(sample_length / 2):
            square_wave[i] = 0xFFFF
        if sys.implementation.version[0] >= 3:
            square_wave_sample = audioio.RawSample(square_wave)
            square_wave_sample.sample_rate = int(len(square_wave) * frequency)
            with audioio.AudioOut(pin) as dac:
                if not dac.playing:
                    dac.play(square_wave_sample, loop=True)
                    time.sleep(duration)
                dac.stop()
        else:
            sample_tone = audioio.AudioOut(pin, square_wave)
            sample_tone.frequency = int(len(square_wave) * frequency)
            if not sample_tone.playing:
                sample_tone.play(loop=True)
                time.sleep(duration)
            sample_tone.stop()
Exemple #15
0
            voiceidx = ( voiceidx + 1 ) % len(oscvcas)

    if oscvcatouse is None:
        oscvcatouse = nextoscvca
        next = ( nextoscvca + 1 ) % len(oscvcas)  ### advance next

    return (oscvcatouse, next)

### The next oscillator / vca to use to 
nextoscvca = 0

wavenames = waveform_names()
wavename = wavenames[1]  ### TODO - "grep" sawtooth or replace these with enum
waves = []
make_waveforms(waves, wavename, basesamplerate)             
silenceat0 = audioio.RawSample(array.array("H",[0]))

### The voice for extrachannel - a non ADSR wave played with AudioOut
### object to A0
### TODO - move more stuff into here
extravoice = [audio_out_a0, 0]
### Set the output to 0 (0V) rather than its normal midpoint 32768 (1.65V)
### to allow for the imperfectections in the external mixer
audio_out_a0.play(silenceat0)

### Initial ADSR values
attack  = 0.050
release = 0.500
decay = 0.1
sustain = 0.8  ### 80% level
    if counter > (len(pitch_frequencies_low) - 1):
        counter = 0
    elif counter < 0:
        counter = (len(pitch_frequencies_low) - 1)

    if note_range == 0:
        FREQUENCY = pitch_frequencies_low[counter]
    else:
        FREQUENCY = pitch_frequencies_high[counter]

    pixels[led_color_data[counter]["pixel"]] = led_color_data[counter]["color"]

    # Any time we get a sound with a magnitude greater than the value of blowThresshold, trigger the
    # current pitch (can be changed at top where it is defined)
    if magnitude > blowThresshold:
        length = SAMPLERATE // FREQUENCY  #create length of sample
        sine_wave = array.array("H", [0] *
                                length)  # create an array for a sine wave
        for i in range(length):
            sine_wave[i] = int(
                math.sin(math.pi * 2 * i / 18) * (2**15) +
                2**15)  # fill the array with values

        audio = audioio.AudioOut(board.SPEAKER)
        sine_wave_sample = audioio.RawSample(sine_wave)
        audio.play(sine_wave_sample, loop=True)  # Play the sample
        time.sleep(pitchLength)  # Play for length of pitchLength
        audio.stop()  # we tell the board to stop
        audio.deinit()

    pixels.show()  #show the desired neopixel light up on board
Exemple #17
0
# Lissajous version 1
import array, math
import board, audioio
length = 1000
samples_xy = array.array("H", [0] * length * 2)
# Created interleaved x, y samples
for idx in range(length):
    samples_xy[2 * idx] = round(
        math.sin(math.pi * 2 * idx / length) * 10000 + 10000)
    samples_xy[2 * idx + 1] = round(
        math.sin(math.pi * 2 * 3 * idx / length + math.pi / 2) * 10000 + 10000)
    output_wave = audioio.RawSample(samples_xy,
                                    channel_count=2,
                                    sample_rate=100 * 1000)
dacs.play(output_wave, loop=True)
while True:
    pass
timeout = time.monotonic()

while True:
    print((light.value, ))

    # determine height of pixels
    pixel_height = map_range(light.value, DARK, BRIGHT, 0, num_pixels)
    pixels.fill((0, 0, 0))
    for p in range(pixel_height):
        pixels[p] = wheel(int(p / num_pixels * 255))
        pixels.show()

    # determine squeek
    freq = int(map_range(light.value, DARK, BRIGHT, 440, 8800))
    sine_wave = audioio.RawSample(wave_array,
                                  channel_count=1,
                                  sample_rate=freq)
    cpx_audio.stop()
    cpx_audio.play(sine_wave, loop=True)

    # check no activity
    if light.value > ACTIVITY_THRESHOLD:
        timeout = time.monotonic()  # reset our timeout

    # 4 seconds no activity
    if time.monotonic() - timeout > 4:
        break

pixels.fill((255, 0, 0))
pixels.show()
play_file("03_no_sanctuary.wav")
Exemple #19
0
def makeSoundWave(frequency):
    length = SAMPLERATE // frequency
    sine_wave = array.array("H", [0] * length)
    for i in range(length):
        sine_wave[i] = int(math.sin(math.pi * 2 * i / 18) * (2**15) + 2**15)
    return audioio.RawSample(sine_wave)
Exemple #20
0
for i in range(llength):
    low_freq_wave[i] = int(
        (1 + math.sin(math.pi * 2 * i / llength)) * tone_volume * (2**15 - 1))

frequency = 2100  # Set this to the Hz of the tone you want to generate.
# 2670 Hz
length = 8000 // frequency
high_freq_wave = array.array("H", [0] * length)
for i in range(length):
    high_freq_wave[i] = int(
        (1 + math.sin(math.pi * 2 * i / length)) * tone_volume * (2**15 - 1))

analog_in = AnalogIn(board.A1)
a = audioio.AudioOut(board.A0)
pulse_width = 0.3
sine_wave_sample_hi = audioio.RawSample(high_freq_wave)
sine_wave_sample_lo = audioio.RawSample(low_freq_wave)

while True:
    print("transmit:")
    transmission = input()
    print("transmitting '%s'" % transmission)
    for c in transmission:
        print("byte: %c" % c)
        frame = hamming.generate_hamming_frame(c)
        print(frame)
        for m in frame:
            if m == 1:
                a.play(sine_wave_sample_hi, loop=True)
            else:
                a.play(sine_wave_sample_lo, loop=True)
Exemple #21
0
# Lissajous version 1
import array, math
import board, audioio

dacs = audioio.AudioOut(left_channel=board.A0, right_channel=board.A1)

length = 1000
baseFreq = 100
#print("length = " + length.tostring())
#print("base frea = " + baseFreq)
vP = 15000
center = 15000
samples_xy = array.array("H", [0] * length * 2)
# Created interleaved x, y samples
for idx in range(length):
    samples_xy[2 * idx] = round(
        math.sin(math.pi * 2 * idx / length) * vP + center)
    samples_xy[2 * idx + 1] = round(
        math.sin(math.pi * 2 * 3 * idx / length + math.pi / 2) * vP + center)
output_wave = audioio.RawSample(samples_xy,
                                channel_count=2,
                                sample_rate=baseFreq * length)
dacs.play(output_wave, loop=True)
while True:
    pass
def makewaves(waves, type, samplerate):
    cyclelength = round(samplerate // A4refhz)
    length = cyclelength  ### a default which some waves will change

    #cycles = 1
    #cycles = 3    ### for perfect fifth
    #cycles = 4    ### for major chord

    ### TODO consider volume modification for internal speaker
    ### vs non speaker use

    ### major chord has longer sample which initially works
    ### but will blow up later with four levels
    if type == "majorchord":
        volumes = [23000]  ### 32000 would go out of bounds
    else:
        volumes = [
            30000
        ]  # running too tight on memory for multiple values at 96 samples TODO review this

    ### Make some waves at different volumes
    for vol in volumes:
        ### Need to create a new array here as audio.RawSample appears not
        if type == "square":
            waveraw = array.array("h", [-vol] * (length // 2) + [vol] *
                                  (length - length // 2))
        else:
            if type == "sawtooth":
                waveraw = array.array("h", [0] * length)
                for i in range(length):
                    waveraw[i] = round((i / (length - 1) - 0.5) * 2 * vol)
            elif type == "supersaw":
                waveraw = array.array("h", [0] * length)
                halflength = length // 2
                quarterlength = length // 4
                for i in range(length):
                    ### TODO replace this with a gen function similar to sine
                    waveraw[i] = round(
                        ((i / (length - 1) - 0.5 + i % halflength /
                          (halflength - 1) - 0.5 + i % quarterlength /
                          (quarterlength - 1) - 0.5)) * 2 / 3 * vol)
            elif type == "supersupersaw":
                cycles = 2
                length = cycles * cyclelength
                waveraw = array.array("h", [0] * length)
                ### TODO add two 5ths
                twothirdsclen = 2 * cyclelength // 3
                halfclen = cyclelength // 2
                thirdclen = cyclelength // 3
                quarterclen = cyclelength // 4
                sixthclen = cyclelength // 6
                eighthlen = cyclelength // 8
                for i in range(length):
                    ### TODO replace this with a gen function similar to sine
                    waveraw[i] = round(
                        (2 / 8 * (i / (cyclelength - 1) - 0.5) + 1 / 8 *
                         (i % twothirdsclen /
                          (twothirdsclen - 1) - 0.5) + 1 / 8 *
                         (i % halfclen / (halfclen - 1) - 0.5) + 1 / 8 *
                         (i % thirdclen / (thirdclen - 1) - 0.5) + 1 / 8 *
                         (i % quarterclen / (quarterclen - 1) - 0.5) + 1 / 8 *
                         (i % sixthclen / (sixthclen - 1) - 0.5) + 1 / 8 *
                         (i % eighthlen / (eighthlen - 1) - 0.5)) * 2 * vol)
            elif type == "sine":
                waveraw = array.array("h", [0] * length)
                for i in range(length):
                    waveraw[i] = round(
                        math.sin(math.pi * 2 * i / length) * vol)
            elif type == "sineoct2":
                waveraw = array.array("h", [0] * length)
                for i in range(length):
                    waveraw[i] = round(
                        (math.sin(math.pi * 2 * i / length) * 2 / 3 +
                         math.sin(math.pi * 2 * i / length * 2) * 1 / 3) * vol)
            elif type == "sinefifth":
                cycles = 2
                length = cycles * cyclelength
                waveraw = array.array("h", [0] * length)
                for i in range(length):
                    waveraw[i] = round(
                        (math.sin(math.pi * 2 * i / cyclelength) +
                         math.sin(math.pi * 2 * i / cyclelength * 3 / 2)) *
                        vol / 2)
            # elif type == "sinemajorchord":
            # cycles = 4
            # length = cycles * cyclelength
            # waveraw = array.array("h", [0] * length)
            # for i in range(length):
            # waveraw[i] = round((math.sin(math.pi * 2 * i / cyclelength) +
            # math.sin(math.pi * 2 * i / cyclelength * 5/4) +
            # math.sin(math.pi * 2 * i / cyclelength * 6/4)
            # ) * vol / 2.5)
            else:
                raise ValueError("Unknown type")

        waves.append(audioio.RawSample(waveraw))
        ### Keep x position within legal values (if needed)
        ##dac_a0_x = min(dac_a0_x, dac_x_max)
        ##dac_a0_x = max(dac_a0_x, 0)
        dac_a1_y = round((sine * pcy + cosine * pcx + halfrange_y) * mult_y)
        ### Keep y position within legal values (if needed)
        ##dac_a1_y = min(dac_a1_y, dac_y_max)
        ##dac_a1_y = max(dac_a1_y, 0)
        rawdata[idx] = dac_a0_x - dac_x_mid  ### adjust for "h" array
        rawdata[idx + 1] = dac_a1_y - dac_y_mid  ### adjust for "h" array
        idx += 2

    if use_wav:
        ### 200k (maybe 166.667k) seems to be practical limit
        ### 1M permissible but seems same as around 200k
        output_wave = audioio.RawSample(rawdata,
                                        channel_count=2,
                                        sample_rate=200 * 1000)

        ### The image may "warp" sometimes with loop=True due to a strange bug
        ### https://github.com/adafruit/circuitpython/issues/1992
        if poor_wav_bug_workaround:
            while True:
                dacs.play(output_wave)
                if time.monotonic() - prev_t >= frame_t:
                    break
        else:
            dacs.play(output_wave, loop=True)
            while time.monotonic() - prev_t < frame_t:
                pass
            if not leave_wav_looping:
                dacs.stop()
Exemple #24
0
maxsustain = 1.0
maxdecay = 2.000

### TODO - experimental
### a short burst of fading noise designed to play at 8000 at start of play
### These eventually spits a memory error with 1000
dacmidpoint = 32768
samplerate = 8000
sampleraw = array.array("h", [0] * 600)
for i in range(1,len(sampleraw) - 1):
    sampleraw[i] = round(random.randint(-20000,20000 + 1) *
                         (len(sampleraw) - (abs(i - len(sampleraw) // 2) * 2)) /
                         len(sampleraw))
sampleraw[0]    = dacmidpoint
sampleraw[len(sampleraw) - 1] = dacmidpoint
sample = audioio.RawSample(sampleraw, sample_rate=samplerate)
del sampleraw

triggertransient = False

print("Ready to play")

while True:
    (msg, channel) = midi.read_in_port()
    if isinstance(msg, adafruit_midi.NoteOn) and msg.velocity != 0:
#        if debug:
#            print("NoteOn", msg.note, msg.velocity)
        lastnote = msg.note
        pitchbend = (pitchbendvalue - 8192) * pitchbendmultiplier
        basefreq = round(A4refhz * math.pow(2, (lastnote - midinoteA4 + pitchbend) / 12.0))
        osc1.frequency = basefreq
 def _generate_sample(self, length=100):
     if self._sample is not None:
         return
     self._sine_wave = array.array("H", PyBadger._sine_sample(length))
     self._sample = audioio.AudioOut(board.SPEAKER)
     self._sine_wave_sample = audioio.RawSample(self._sine_wave)
noise_vol = 10000
half_wave_len = int(sample_len / magic_factor / 2)
for idx in range(0, sample_len):
    # change "polarity" to create small square wave with lots of noise
    if idx % half_wave_len == 0:
        square_offset = 0 - square_offset
    sample = random.randint(midpoint + square_offset - noise_vol,
                            midpoint + square_offset + noise_vol)
    noise_wave_raw[idx] = sample
noise_wave_raw[0] = midpoint # start at midpoint

#noise_wave_raw = array.array("H",
#                             [random.randint(midpoint-5000, midpoint+5000)
#                              for x in range(sample_len)])
#noise_wave_raw = array.array("h", [0] * sample_len)
noise_wave = audioio.RawSample(noise_wave_raw)
del noise_wave_raw

midi_channel = 10
midi = adafruit_midi.MIDI(midi_in=usb_midi.ports[0],
                          in_channel=midi_channel-1,
                          in_buf_size=6)

last_note = None

# Read any incoming MIDI messages (events) over USB
# looking for note on, note off to turn noise on and off
while True:
    #gc.collect()
    #print(gc.mem_free())
    #print(gc.mem_free())
def play_raw(data):
    duration = length / (wav.sample_rate * wav.channel_count * wav.bits_per_sample / 8)
    sample = audioio.RawSample(sine_wave, channel_count=2, sample_rate=8000)
    audio.play(sample, loop=True)
    time.sleep(1)
    audio.stop()
import time
import array
import math
import audioio
import board
import audiobusio

sample_rate = 8000
tone_volume = .1  # Increase or decrease this to adjust the volume of the tone.
frequency = 440  # Set this to the Hz of the tone you want to generate.
length = sample_rate // frequency  # One freqency period
sine_wave = array.array("H", [0] * length)
for i in range(length):
    sine_wave[i] = int(
        (math.sin(math.pi * 2 * frequency * i / sample_rate) * tone_volume + 1)
        * (2**15 - 1))

# For Feather M0 Express, ItsyBitsy M0 Express, Metro M0 Express
audio = audiobusio.I2SOut(board.D1, board.D0, board.D9)
# For Feather M4 Express
# audio = audiobusio.I2SOut(board.D1, board.D10, board.D11)
# For Metro M4 Express
# audio = audiobusio.I2SOut(board.D3, board.D9, board.D8)
sine_wave_sample = audioio.RawSample(sine_wave, sample_rate=sample_rate)

while True:
    audio.play(sine_wave_sample, loop=True)
    time.sleep(1)
    audio.stop()
    time.sleep(1)