From time to time it will be convenient for me to provide you with
some helper code that isn't already built into JES. Copying large
swaths of code into your .py file works, but it clutters up
your programs. As an alternative, you can copy the following two lines
into your .py file:
setLibPath('\\\\Dragon\\cls_compsci\\cs107')
from comp107Util import *
This code tells JES to load in all of the helper functions
(including range1) defined in
comp107Util.py so that you can use them in your programs. Note
that this will only work if you are running your programs on lab
machines. If you want to accomplish the same thing on your personal
computer, you would copy the code below into a new file named
comp107Util.py and replace the text
'\\\\Dragon\\cls_compsci\\cs107' with the location on your own
computer where you stored the new file. You would also need to change the line
sys.path.append('C:\\Program Files\\JES\\Sources')
In the file below to refer to the location on your computer where JES
is installed.
If that method doesn't work for some reason, you should be able to
copy the functions you need from the code below into your
.py file.
#A set of helper functions for use in comp107
#Nathan Sprague 1/23/2009
import os
import sys
#You'll need to change the following line if JES is installed somewhere
#else. On a Mac it will probably be something like:
#sys.path.append('/Applications/JES-3-1-1.app/Contents/Resources/Java')
sys.path.append('C:\\Program Files\\JES\\Sources')
from media import *
#range1 - Alternative to built in range function for 1 based indexing.
#The default starting point is 1 rather than 0.
#The ending point is increased by 1 relative the the built in range function.
#examples:
#>>>range1(2) #returns [1, 2]
#>>>range1(2,4) #returns [2, 3, 4]
#>>>range1(2, 6, 2) #returns [2, 4, 6]
#Nathan Sprague 1/20/2009
def range1(*args):
if len(args) == 1:
return range(1,args[0] + 1)
if len(args) == 2:
return range(args[0], args[1] + 1)
if len(args) == 3:
return range(args[0], args[1] + 1, args[2])
# Alyce Brady's version of copyInto, with additional error-checking on the upper-left corner
# Will copy as much of the original picture into the destination picture as will fit.
# copies the Picture origPic into the Picture destPic
# starting at location (upperLeftX, upperLeftY) in destPic.
# Returns the new Picture. (destPict is unchanged.)
def copyInto(origPict, destPict, upperLeftX, upperLeftY):
if not isinstance(origPict, Picture):
print "copyInto(origPict, destPict, upperLeftX, upperLeftY): First parameter is not a picture"
raise ValueError
if not isinstance(destPict, Picture):
print "copyInto(origPict, destPict, upperLeftX, upperLeftY): Second parameter is not a picture"
raise ValueError
if upperLeftX < 1 or upperLeftX > getWidth(destPict):
print "copyInto(origPict, destPict, upperLeftX, upperLeftY): upperLeftX must be within the destPict"
raise ValueError
if upperLeftY < 1 or upperLeftY > getHeight(destPict):
print "copyInto(origPict, destPict, upperLeftX, upperLeftY): upperLeftY must be within the destPict"
raise ValueError
newCanvas = duplicatePicture(destPict)
origPict.copyInto(newCanvas, upperLeftX-1, upperLeftY-1)
return newCanvas
#Version of copyInto that modifies the destination picture, and does not return a value.
def copyPictureInto(origPict, destPict, upperLeftX, upperLeftY):
if not isinstance(origPict, Picture):
print "copyInto(origPict, destPict, upperLeftX, upperLeftY): First parameter is not a picture"
raise ValueError
if not isinstance(destPict, Picture):
print "copyInto(origPict, destPict, upperLeftX, upperLeftY): Second parameter is not a picture"
raise ValueError
if upperLeftX < 1 or upperLeftX > getWidth(destPict):
print "copyInto(origPict, destPict, upperLeftX, upperLeftY): upperLeftX must be within the destPict"
raise ValueError
if upperLeftY < 1 or upperLeftY > getHeight(destPict):
print "copyInto(origPict, destPict, upperLeftX, upperLeftY): upperLeftY must be within the destPict"
raise ValueError
origPict.copyInto(destPict, upperLeftX-1, upperLeftY-1)
# Alyce Brady/ Pam Cutter: Function that crops a picture
# returns a Picture of size (width, height) that is
# a copy of the part of Picture pict starting at
# location (upperLeftX, upperLeftY) and having size (width, height)
def cropPicture(picture, upperLeftX, upperLeftY, width, height):
if not isinstance(picture, Picture):
print "crop(picture, upperLeftX, upperLeftY, width, height): First parameter is not a picture"
raise ValueError
if upperLeftX < 1 or upperLeftX > getWidth(picture):
print "crop(picture, upperLeftX, upperLeftY, width, height): upperLeftX must be within the picture"
raise ValueError
if upperLeftY < 1 or upperLeftY > getHeight(picture):
print "crop(picture, upperLeftX, upperLeftY, width, height): upperLeftY must be within the picture"
raise ValueError
return picture.crop(upperLeftX-1, upperLeftY-1, width, height)
#Crop out a segment of sound starting at start index, numSamples long.
#if asked to crop past the end of the sound, this will return as many samples
#as possible.
def cropSound(sound,startIndex,numSamples):
if not isinstance(sound,Sound):
print "cropSound(sound,startIndex,numSamples): Input is not a sound"
raise ValueError
if startIndex >= sound.getLength():
print "cropSound(sound,startIndex,numSamples): startIndex must be within the sound"
raise ValueError
newLength = min(numSamples, getNumSamples(sound) - startIndex + 1)
newSound = makeEmptySound(newLength, int(getSamplingRate(sound)))
for i in range(newLength):
v = getSampleValueAt(sound,i+startIndex)
setSampleValueAt(newSound, i+1, v)
return newSound
#copy sound into dest at startIndex. A new sound is returned (dest is not modified).
def copySoundInto(sound, dest, startIndex):
if not isinstance(sound, Sound):
print "copySoundInto(sound, dest, startIndex): First parameter is not a sound"
raise ValueError
if not isinstance(dest, Sound):
print "copySoundInto(sound, dest, startIndex): Second parameter is not a sound"
raise ValueError
newSound = duplicateSound(dest)
sound.copySoundInto(newSound, startIndex-1)
return newSound
#-------------------------------
#convertSamplingRate - convert a sound file to a new sampling rate
#Inputs: sound - the sound to convert
# newRate - the new sampling rate
#Returns: a copy of sound with the new sampling rate.
#-------------------------------
def convertSamplingRate(sound, newRate):
oldRate = getSamplingRate(sound)
numSamplesNew = int(getNumSamples(sound) * newRate / float(oldRate))
newSound = makeEmptySound(numSamplesNew, newRate)
for index in range1(numSamplesNew):
oldIndex = index * float(oldRate)/newRate
val = getSampleValueAt(sound, int(ceil(oldIndex)))
setSampleValueAt(newSound, index, val)
return newSound
#----------------------------------------------------------------------
#expFade (exponential 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 expFade(sound, factor):
ns = getNumSamples(sound)
newSound = duplicateSound(sound)
for i in range(1,ns+1):
val = getSampleValueAt(sound, i)
newVal = val * pow(exp(1), -(float(i)/ns * log(factor)))
setSampleValueAt(newSound, i, newVal)
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 = makeEmptySound(numSamples, sampleRate)
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 = makeEmptySound(numSamples, sampleRate)
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, sampleRate = 22050):
f = 8.1758 * 2**(note / 12.0) # midi to frequency conversion
return expFade(returnTone(f, dur, vol, sampleRate), 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 expFade(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 = makeEmptySound(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 = makeEmptySound(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 = makeEmptySound(s1NumSamples+s2NumSamples, int(getSamplingRate(s1)))
s1.copySoundInto(newSound, 1)
s2.copySoundInto(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 = makeEmptySound(1, int(getSamplingRate(sounds[0])))
for s in sounds:
newSound = appendSound(newSound, s)
return newSound