1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
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
)
|