mirror of
https://git.exozy.me/a/Never-Gonna-Give-Beep-Up
synced 2024-11-22 12:17:31 +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
|
||
|
)
|