A sound can be represented mathematically by a sine wave, with a certain amplitude, frequency, and phase. We can randomly select frequencies from a list specified on Wikipedia at http://en.wikipedia.org/wiki/Piano_key_frequencies that complies with the following formula:
The variable n in this formula is the number of the piano key. We will number the keys from 1 to 88. We will also select the amplitude, duration, and phase at random.
We will begin by initializing random values, then generate sine waves, compose a melody, and finally, plot the generated audio data with Matplotlib.
Initialize to random values:
NTONES = int(sys.argv[1])
amps = 2000. * numpy.random.random((NTONES,)) + 200. durations = 0.19 * numpy.random.random((NTONES,)) + 0.01 keys = numpy.random.random_integers(1, 88, NTONES) freqs = 440.0 * 2 ** ((keys - 49.)/12.) phi = 2 * numpy.pi * numpy.random.random((NTONES,))
Write a
generate
function to generate sine waves:
def generate(freq, amp, duration, phi): t = numpy.linspace(0, duration, duration * RATE) data = numpy.sin(2 * numpy.pi * freq * t + phi) * amp return data.astype(DTYPE)
Once we have generated a few tones, we only need to compose a coherent melody. For now, we will just concatenate the sine waves—this does not give a nice melody, but could serve as a starting point for more experimenting:
for i in xrange(NTONES): newtone = generate(freqs[i], amp=amps[i], duration=durations[i], phi=phi[i]) tone = numpy.concatenate((tone, newtone))
Plot the generated audio data with Matplotlib:
matplotlib.pyplot.plot(numpy.linspace(0, len(tone)/RATE, len(tone)), tone) matplotlib.pyplot.show()
The generated audio data plot is shown as follows:
The source code for this example is as follows:
import scipy.io.wavfile import numpy import sys import matplotlib.pyplot RATE = 44100 DTYPE = numpy.int16 # Generate sine wave def generate(freq, amp, duration, phi): t = numpy.linspace(0, duration, duration * RATE) data = numpy.sin(2 * numpy.pi * freq * t + phi) * amp return data.astype(DTYPE) if len(sys.argv) != 2: print "Please input the number of tones to generate" sys.exit() # Initialization NTONES = int(sys.argv[1]) amps = 2000. * numpy.random.random((NTONES,)) + 200. durations = 0.19 * numpy.random.random((NTONES,)) + 0.01 keys = numpy.random.random_integers(1, 88, NTONES) freqs = 440.0 * 2 ** ((keys - 49.)/12.) phi = 2 * numpy.pi * numpy.random.random((NTONES,)) tone = numpy.array([], dtype=DTYPE) # Compose for i in xrange(NTONES): newtone = generate(freqs[i], amp=amps[i], duration=durations[i], phi=phi[i]) tone = numpy.concatenate((tone, newtone)) scipy.io.wavfile.write('generated_tone.wav', RATE, tone) # Plot audio data matplotlib.pyplot.plot(numpy.linspace(0, len(tone)/RATE, len(tone)), tone) matplotlib.pyplot.show()