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 )