mirror of
https://git.exozy.me/a/Never-Gonna-Give-Beep-Up
synced 2024-11-22 06:17:29 +00:00
48 lines
1.5 KiB
Python
48 lines
1.5 KiB
Python
import math
|
|
from pyaudio import PyAudio, paUInt8
|
|
|
|
def generate_sine_wave(frequency, duration, volume=0.2, sample_rate=22050):
|
|
''' Generate a tone at the given frequency.
|
|
|
|
Limited to unsigned 8-bit samples at a given sample_rate.
|
|
The sample rate should be at least double the frequency.
|
|
'''
|
|
if sample_rate < (frequency * 2):
|
|
print('Warning: sample_rate must be at least double the frequency '
|
|
f'to accurately represent it:\n sample_rate {sample_rate}'
|
|
f' ≯ {frequency*2} (frequency {frequency}*2)')
|
|
|
|
num_samples = int(sample_rate * duration)
|
|
rest_frames = num_samples % sample_rate
|
|
|
|
pa = PyAudio()
|
|
stream = pa.open(
|
|
format=paUInt8,
|
|
channels=1, # mono
|
|
rate=sample_rate,
|
|
output=True,
|
|
)
|
|
|
|
# make samples
|
|
s = lambda i: volume * math.sin(2 * math.pi * frequency * i / sample_rate)
|
|
samples = (int(s(i) * 0x7F + 0x80) for i in range(num_samples))
|
|
|
|
# write several samples at a time
|
|
for buf in zip( *([samples] * sample_rate) ):
|
|
stream.write(bytes(buf))
|
|
|
|
# fill remainder of frameset with silence
|
|
stream.write(b'\x80' * rest_frames)
|
|
|
|
stream.stop_stream()
|
|
stream.close()
|
|
pa.terminate()
|
|
|
|
generate_sine_wave(
|
|
# see http://www.phy.mtu.edu/~suits/notefreqs.html
|
|
frequency=440, # Hz, waves per second C6
|
|
duration=0.2, # seconds to play sound
|
|
volume=0.25, # 0..1 how loud it is
|
|
sample_rate=44100, # number of samples per second: 11025, 22050, 44100
|
|
)
|