It turns out that digital audio files are split up into frames that are typically either 8-bits or 16-bits. So a wave file is essentially list of 8-bit or 16-bit numbers that represent the pressure on the microphone. The frame rate dictates how many of these frames go by per second.
In thirty minutes, I was successfully able to come up with code for creating a .wav file at any frequency:
Some of my ideas: The array type works perfectly for storing the samples - it is far more efficient than a Python list. Note also that I am using a "generator expression", which works similarly to a list comprehension but does not need to actually create the list. In the future I plan on using generators for creating the signals.
import wave import math import array #Create a 16 bit wave width = 2 #16 bits is 2 bytes maxval = 65535 sample_rate=44100 channels = 1 samples = array.array('h') #Signed short # Create a sine wav, of frequency fFreq nSamples = sample_rate*2 #two seconds long fFreq = 440 w = fFreq*2*math.pi / sample_rate amplitude = 65535/2 #Loudest amplitude samples.extend( (amplitude * math.sin(w*x)) for x in xrange(nSamples) ) f = wave.open('c:\\a440.wav', 'wb') f.setnchannels(channels) f.setframerate(sample_rate) f.setsampwidth(width) f.writeframes(samples.tostring()) f.close()
It is weird that 16-bit sound is in the "signed short" format, instead of being unsigned.
On a less serious note, I then saw the beep method winsound module, and was amused:
There's no way to control the volume, though, so this can get annoying.
import winsound # so retro! winsound.Beep(440,10) winsound.Beep(600,10) #bonus stage! for i in range(40,400,30): winsound.Beep(i,90)
Next I'll be writing some sweet audio effects.