Thursday, September 8, 2011

Sound Synthesis

Physically, sound is an oscillation of a mechanical medium that makes the surrounding air also oscillate and transport the sound as a compression wave. Mathematically, the oscillations can be described as
where t is the time, and f the frequency of the oscillation. Sound on a computer is a sequence of numbers and in this post we will see how to generate a musical tone with numpy and how to write it to a file wav file. Each musical note vibrates at a particular frequency and the following script contains a function to generate a note (tone(...)), we'll use this function to generate the A tone creating an oscillation with f = 440 Hz.
from import write
from numpy import linspace,sin,pi,int16
from pylab import plot,show,axis

# tone synthesis
def note(freq, len, amp=1, rate=44100):
 t = linspace(0,len,len*rate)
 data = sin(2*pi*freq*t)*amp
 return data.astype(int16) # two byte integers

# A tone, 2 seconds, 44100 samples per second
tone = note(440,2,amp=10000)

write('440hzAtone.wav',44100,tone) # writing the sound to a file

Now we can play the file 440hzAtone.wav with an external player. This plot shows a part of the signal generated by the script:
And using the plotSpectrum function defined in a previous post we can verify that 440 Hz is the fundamental frequency of the tone.


  1. thanks ! i´ve been looking for a simple way of doing this, but what i find on google uses csound and fluidsynth, i hope your method becomes the one used to give blender3d audio synthesis abilities

  2. Hi thanks for your code it is just was I need!
    I have one question. I get a "click" sound at the end on the generated tone. It is a problem of my hardware or the code? How can I get rid of that click sound? I have try changing the paramenters but the click sound is still there.
    Thanks in advance

  3. It's because the wave is stopped suddenly.

  4. Thanks, hence to avoid the click I need to fade out the sound. How can I do that?

    1. A possible solution to avoid the click sound is to decrease the amplitude as a function of the lenght of the note instead of using a contact amplitude

      something like this

      amp_decay = np.linspace(amp, 0, len * rate)
      data = np.sin(2*np.pi*freq*t)*(amp_decay)

  5. Ok; in case i want to play the (data) Int. as a sound ...
    how can i do that ??

    1. HI there..
      iam still new with python and need your help if you can ...
      all i need now is that i have :
      X=0 to 180
      and data=0.5 cos(2*pi*X)
      and i need to play the data as sound when ever X is changed how can i do that ??
      it's may be so easy but i really need help with that

  6. If I load the wav into Audacity and view the spectrum, the peak is at 443 Hz. Something is a bit off here, it should be exactly 440Hz.

    1. It would be at 440 ONLY if you used the correct number of samples for the FFT, with the data you are using it may be that 440 Hz isnt a multiple of your frequency resolution.