CS 107: Pictures and Sounds: Programming with Multimedia

Kalamazoo College

Spring 2008

Note Functions


#----------------------------------------------------------------------
#fade
#sound   - The sound to fade
#factor  - The factor that the sound should be reduced by.
#returns - A new sound that is gradually reduced in volume
#          by the desired factor
#----------------------------------------------------------------------
def fade(sound, factor):
  ns = getNumSamples(sound)
  amount_per = (factor - 1.0) / ns
  amount = 1.0;
  newSound = duplicateSound(sound)
  for s in getSamples(newSound):
    val = getSampleValue(s)
    setSampleValue(s, val / amount)
    amount = amount + amount_per
  return newSound

#----------------------------------------------------------------------
#returnTone
#freq - frequency in hertz
#dur - duration in milliseconds
#vol - volume from 0-127
#sampleRate - the sampling rate of the returned sound
#returns - a sine wave sound of the desired frequency.
#----------------------------------------------------------------------
def returnTone(freq, dur, vol, sampleRate = 22050):
  numSamples = int(dur/1000.0 * sampleRate)
  sound = makeEmptySoundFromNumSamples(numSamples)
  volFactor = vol / 127.0 * 32767
  for i in range(1, numSamples):
    val = sin(2 * pi * freq * i * 1.0/sampleRate)
    setSampleValueAt(sound, i, val * volFactor) 
  return sound

#----------------------------------------------------------------------
#returnSquareTone
#freq - frequency in hertz
#dur - duration in milliseconds
#vol - volume from 0-127
#sampleRate - the sampling rate of the returned sound
#returns - a square wave sound of the desired frequency
#----------------------------------------------------------------------
def returnSquareTone(freq, dur, vol, sampleRate = 22050):
  numSamples = int(dur/1000.0 * sampleRate)
  sound = makeEmptySoundFromNumSamples(numSamples)
  period = 1.0/freq * sampleRate
  volFactor = vol / 127.0 * 32767
  for i in range(1, numSamples):
    if (i % period) < (.5 * period):
      val = -1 * volFactor
    else:
      val = 1 * volFactor
    setSampleValueAt(sound, i, val) 
  return sound


#----------------------------------------------------------------------
#returnNote
#note - Note in MIDI encoding
#dur - duration in milliseconds
#vol - volume from 0-127
#returns - The desired note as a sine wave.
#----------------------------------------------------------------------
def returnNote(note, dur, vol):
  f = 8.1758 * 2**(note / 12.0)  # midi to frequency conversion
  return fade(returnTone(f, dur, vol), 10)


#----------------------------------------------------------------------
#returnSquareNote
#note - Note in MIDI encoding
#dur - duration in milliseconds
#vol - volume from 0-127
#returns - The desired note as a square wave.
#----------------------------------------------------------------------
def returnSquareNote(note, dur, vol):
  f = 8.1758 * 2**(note / 12.0)  # midi to frequency conversion
  return fade(returnSquareTone(f, dur, vol), 10)



#----------------------------------------------------------------------
#returnNotes - Return a series of musical notes at a given volume. 
#notes - an array of integers: [note#1, dur#1, note#2, dur#2...] 
#volume - a volume from 1-127
#returns - a single sound containing all of the requested notes
#----------------------------------------------------------------------
def returnNotes(notes, vol):
  newSound = makeEmptySoundFromNumSamples(1)
  for noteNum in range(0, len(notes), 2):
    n = returnNote(notes[noteNum],notes[noteNum+1], vol)
    newSound = appendSound(newSound, n)
  return newSound     

#----------------------------------------------------------------------
#returnSquareNotes - Return a series of musical notes at a given volume. 
#notes - An array of integers: [note#1, dur#1, note#2, dur#2...] 
#volume - A volume from 1-127
#returns - A single sound containing all of the requested notes
#----------------------------------------------------------------------
def returnSquareNotes(notes, vol):
  newSound = makeEmptySoundFromNumSamples(1)
  for noteNum in range(0, len(notes), 2):
    n = returnSquareNote(notes[noteNum],notes[noteNum+1], vol)
    newSound = appendSound(newSound, n)
  return newSound     

#----------------------------------------------------------------------
#appendSound
#s1, s2 - sounds
#returns - A new sound: s2 appended to the end of s1. 
#----------------------------------------------------------------------
def appendSound(s1, s2):
  s1NumSamples = getNumSamples(s1)
  s2NumSamples = getNumSamples(s2)
  newSound = makeEmptySoundFromNumSamples(s1NumSamples+s2NumSamples)
  copySoundInto(s1, newSound, 1)
  copySoundInto(s2, newSound, s1NumSamples+1)
  return newSound

#----------------------------------------------------------------------
#appendSounds
#sounds - a list of sounds
#returns - A single sound created by appending all 
#          of the individual sounds in order.
#----------------------------------------------------------------------
def appendSounds(sounds):
  newSound = makeEmptySoundFromNumSamples(1)
  for s in sounds:
    newSound = appendSound(newSound, s)
  return newSound