Skip to content

Instantly share code, notes, and snippets.

@SahilC
Created October 23, 2022 19:18
Show Gist options
  • Save SahilC/c670a941b2c9d950daee3efa52670d8c to your computer and use it in GitHub Desktop.
Save SahilC/c670a941b2c9d950daee3efa52670d8c to your computer and use it in GitHub Desktop.
Using `pyaudio` to sound the happy birthday tune.
#!/usr/bin/env python3
# pip install pyaudio
import pyaudio
import struct
import math
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
p = pyaudio.PyAudio()
# SO source link:- https://stackoverflow.com/a/53231212/985345
def data_for_freq(frequency: float, time: float = None):
"""get frames for a fixed frequency for a specified time or
number of frames, if frame_count is specified, the specified
time is ignored"""
frame_count = int(RATE * time)
remainder_frames = frame_count % RATE
wavedata = []
for i in range(frame_count):
a = RATE / frequency # number of frames per wave
b = i / a
# explanation for b
# considering one wave, what part of the wave should this be
# if we graph the sine wave in a
# displacement vs i graph for the particle
# where 0 is the beginning of the sine wave and
# 1 the end of the sine wave
# which part is "i" is denoted by b
# for clarity you might use
# though this is redundant since math.sin is a looping function
# b = b - int(b)
c = b * (2 * math.pi)
# explanation for c
# now we map b to between 0 and 2*math.PI
# since 0 - 2*PI, 2*PI - 4*PI, ...
# are the repeating domains of the sin wave (so the decimal values will
# also be mapped accordingly,
# and the integral values will be multiplied
# by 2*PI and since sin(n*2*PI) is zero where n is an integer)
d = math.sin(c) * 32767
e = int(d)
wavedata.append(e)
for i in range(remainder_frames):
wavedata.append(0)
number_of_bytes = str(len(wavedata))
wavedata = struct.pack(number_of_bytes + 'h', *wavedata)
return wavedata
# Frequency -> Hertz
# Time -> Seconds
def play(frequency: float, time: float):
"""
play a frequency for a fixed time!
"""
frames = data_for_freq(frequency, time)
stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, output=True)
stream.write(frames)
stream.stop_stream()
stream.close()
def play_me():
play(261, 0.5)
play(261, 0.5)
play(293, 1)
play(261, 1)
play(349, 1)
play(329, 1)
play(261, 0.5)
play(261, 0.5)
play(293, 1)
play(261, 1)
play(392, 1)
play(349, 1)
play(261, 0.5)
play(261, 0.5)
play(523, 1)
play(440, 0.5)
play(349, 0.5)
play(329, 0.5)
play(293, 0.5)
play(466, 0.5)
play(466, 0.5)
play(440, 1)
play(349, 1)
play(392, 1)
play(349, 2)
if __name__ == "__main__":
play_me()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment