Generating sounds

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:

Generating sounds

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.

How to do it...

We will begin by initializing random values, then generate sine waves, compose a melody, and finally, plot the generated audio data with Matplotlib.

  1. Initialization.

    Initialize to random values:

    • the amplitude between 200 to 2000,
    • the duration to 0.01 to 0.2,
    • the frequencies using the formula already mentioned
    • the phase to values between 0 and 2 pi
    • 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,))
  2. Generate sine waves.

    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)
  3. Compose.

    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))
  4. Plot the data.

    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:

    How to do it...

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()

How it works...

We created a WAV file with randomly generated sounds. The concatenate function was used to concatenate sine waves.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset