This task is part of project03 which is due at 23:00 EDT on 2025-09-23.
You have the option to work with a partner on this task if you wish. Working with a partner requires more work to coordinate schedules, but if you work together and make sure that you are both understanding the code you write, you will make progress faster and learn more.
You can download the starter code for this task using this link.
You can submit this task using this link.
Put all of your work for this task into the file
musicalMeasures.py
(which is provided among the starter files)
For this problem set, you have a choice: you may complete this task OR
the treeParts task, but you do not need to complete both.
treeParts is
graphics-oriented and works with turtle graphics, while musicalMeasures
(this task) is based on audio and music instead, using the wavesynth
library.
This task will help you practice the material on custom functions and how
to use several functions together to achieve a complicated result. For
this task, you will work with the wavesynth.py
audio library.
For this task, you will be writing code to create a song that involves repetition which has notes and beats layered over each other. You are free to decide what specific melody, harmony, and rhythm you want to use, but there are some restrictions about which functions you must write and how they should interact. (Note: the audio can be quite loud, so you may want to turn down your sound first until you can find the right volume).
Click here to download test_song.wav
You will need to write three base functions that work together to produce the song:
melody which creates a melody using
addNoterhythm which creates a drum line using
addBeatharmony which creates a harmony
using chord (a provided
function).Additionally, you will create phrase
which will call melody,
rhythm, and
harmony
and will use rewind at least twice to overlap
them (you may not use rewind
in your melody,
rhythm, or
harmony functions. Finally,
you will write a song function which
calls phrase multiple times
(possibly in addition to doing other stuff).
The chord, melody, rhythm, harmony, and phrase functions must
each return the current pitch to whatever pitch it was when they
started, so that they are easier to use
together without having to keep track of what changes each one makes. The
melody and
harmony functions must
each call a pitch-changing function such as climbUp, however, so you
cannot just leave the pitch completely unchanged. However, there is no
specific sequence of notes that you must create.
Note that the climbUp/climbDown functions snap the pitch to the
nearest in-key pitch, so when mixed with halfStepUp/halfStepDown
and/or setPitch, it isn't always possible to arrive back at the pitch
you started at by retracing your steps. You can instead use
currentPitch at the start of a function and setPitch at the end to
avoid this problem.
You are also free to modify the provided chord
function, as long as you still call
addNote at least twice and it
still restores the original pitch when it's
done. You are free to decide what
arguments each function should use, and even how many arguments they
should have. However, you must write one additional function called
main which has zero arguments. Your main
must call song, and we will use
main to test your code.
One final constraint: your main function must not
crash and must be able to complete within about 5
seconds. Because wavesynth takes longer the more audio it produces, we
recommend sticking with shorter note durations when submitting (using
variables and arguments for these would make this easy).
We've provided examples for the following functions:
Once more, you are encouraged to come up with your own song here, these examples are just to illustrate one way to satisfy the requirements and fit things together.
wavesynth.py UsageRemember to consult the wavesynth quick-reference
section for examples of the functions
available and what they do, as well as a quick summary of some music
concepts if you're struggling to figure out how to achieve what you want.
We have provided a file named test_musicalMeasures.py which can be used
to check some of the constraints specified above, but you should rely on
Potluck for thorough testing. We recommend that you test each function as
you build it, because the lessons you learn from debugging your earlier
functions will help you improve the later functions.
song, expect to wait a few seconds (maybe as many as 10-20)
for the audio to play. When you submit to Potluck, your main
function must be able to complete within about 5 seconds.melody example
This example shows one way that melody could work. Your melody can use
completely different notes, but like this one, it should put the pitch
back where it started by the end.
In []:PrintssetPitch(D4) print("Starting at pitch D4...") melody(0.2, 2) print("...final pitch is:", currentPitchName()) printTrack() playTrack()Starting at pitch D4... ...final pitch is: D4 a 0.2s keyboard note at D4 (60% vol) and a 0.2s keyboard note at D4 (60% vol) and a 0.2s keyboard note at D4 (60% vol) and a 0.2s keyboard note at D4 (60% vol) and a 0.2s keyboard note at F4 (60% vol) and a 0.2s keyboard note at A4 (60% vol) and a 0.2s keyboard note at F4 (60% vol) and a 0.2s keyboard note at D4 (60% vol)Audio
rhythm example
This example shows one way that rhythm could work. Your rhythm can use
completely different beats.
In []:Printsrhythm(0.2) printTrack() playTrack()a 0.2s snare beat (8% vol) and a 0.2s snare beat (8% vol) and a 0.2s snare beat (8% vol) and a 0.2s snare beat (8% vol) and a 0.6s rest and a 0.2s snare beat (8% vol)Audio
harmony example
This example shows one way that harmony could work. Your harmony can use
completely different notes, but it must call chord at least twice, and
like melody, it must return to the starting pitch when done.
In []:PrintssetPitch(D4) print("Starting at pitch D4...") harmony(0.2, 1) print("...final pitch is:", currentPitchName()) printTrack() playTrack()Starting at pitch D4... ...final pitch is: D4 at 0s a 0.2s keyboard note at D4 (18% vol) at 0s a 0.2s keyboard note at Gb4 (18% vol) at 0s a 0.2s keyboard note at A4 (18% vol) at 0.2s a 0.2s keyboard note at E4 (18% vol) at 0.2s a 0.2s keyboard note at Ab4 (18% vol) at 0.2s a 0.2s keyboard note at B4 (18% vol)Audio
phrase example
This example shows one way that phrase could work. In this case we call
melody, then rewind to the beginning, then call rhythm, rewind again, and
finally call harmony so that all three stack up on top of each other.
Because each function individually returns to the starting pitch,
it's easy for phrase to do the same.
In []:PrintssetPitch(D4) print("Starting at pitch D4...") phrase(0.2, 2, 1) print("...final pitch is:", currentPitchName()) printTrack() playTrack()Starting at pitch D4... ...final pitch is: D4 a 0.2s keyboard note at D4 (60% vol) and a 0.2s keyboard note at D4 (60% vol) and a 0.2s keyboard note at D4 (60% vol) and a 0.2s keyboard note at D4 (60% vol) and a 0.2s keyboard note at F4 (60% vol) and a 0.2s keyboard note at A4 (60% vol) and a 0.2s keyboard note at F4 (60% vol) at 1.4s a 0.2s keyboard note at D4 (60% vol) at 0s a 0.2s snare beat (8% vol) at 0.2s a 0.2s snare beat (8% vol) at 0.4s a 0.2s snare beat (8% vol) at 0.6s a 0.2s snare beat (8% vol) at 1.4s a 0.2s snare beat (8% vol) and a -1.6s rest at 0s a 0.8s keyboard note at C3 (18% vol) at 0s a 0.8s keyboard note at E3 (18% vol) at 0s a 0.8s keyboard note at G3 (18% vol) at 0.8s a 0.8s keyboard note at D3 (18% vol) at 0.8s a 0.8s keyboard note at Gb3 (18% vol) at 0.8s a 0.8s keyboard note at A3 (18% vol)Audio
song example
This example shows the full song, which calls phrase multiple times.
In []:PrintssetPitch(A4) print("Starting at pitch D4...") song(0.2) print("...final pitch is:", currentPitchName()) printTrack() playTrack()Starting at pitch D4... ...final pitch is: A4 a 0.2s keyboard note at A4 (60% vol) and a 0.2s keyboard note at A4 (60% vol) and a 0.2s keyboard note at A4 (60% vol) and a 0.2s keyboard note at A4 (60% vol) and a 0.2s keyboard note at C5 (60% vol) and a 0.2s keyboard note at E5 (60% vol) and a 0.2s keyboard note at C5 (60% vol) at 1.4s a 0.2s keyboard note at A4 (60% vol) at 0s a 0.2s snare beat (8% vol) at 0.2s a 0.2s snare beat (8% vol) at 0.4s a 0.2s snare beat (8% vol) at 0.6s a 0.2s snare beat (8% vol) at 1.4s a 0.2s snare beat (8% vol) and a -1.6s rest at 0s a 0.8s keyboard note at G3 (18% vol) at 0s a 0.8s keyboard note at B3 (18% vol) at 0s a 0.8s keyboard note at D4 (18% vol) at 0.8s a 0.8s keyboard note at A3 (18% vol) at 0.8s a 0.8s keyboard note at Db4 (18% vol) at 0.8s a 0.8s keyboard note at E4 (18% vol) and a 0.2s keyboard note at B4 (60% vol) and a 0.2s keyboard note at B4 (60% vol) and a 0.2s keyboard note at B4 (60% vol) and a 0.2s keyboard note at B4 (60% vol) and a 0.2s keyboard note at G4 (60% vol) and a 0.2s keyboard note at B4 (60% vol) and a 0.2s keyboard note at G4 (60% vol) at 3s a 0.2s keyboard note at E4 (60% vol) at 1.6s a 0.2s snare beat (8% vol) at 1.8s a 0.2s snare beat (8% vol) at 2s a 0.2s snare beat (8% vol) at 2.2s a 0.2s snare beat (8% vol) at 3s a 0.2s snare beat (8% vol) and a -1.6s rest at 1.6s a 0.8s keyboard note at A3 (18% vol) at 1.6s a 0.8s keyboard note at Db4 (18% vol) at 1.6s a 0.8s keyboard note at E4 (18% vol) at 2.4s a 0.8s keyboard note at G3 (18% vol) at 2.4s a 0.8s keyboard note at B3 (18% vol) at 2.4s a 0.8s keyboard note at D4 (18% vol) and a 0.2s keyboard note at A4 (60% vol) and a 0.2s keyboard note at A4 (60% vol) and a 0.2s keyboard note at A4 (60% vol) and a 0.2s keyboard note at A4 (60% vol) and a 0.2s keyboard note at C5 (60% vol) and a 0.2s keyboard note at E5 (60% vol) and a 0.2s keyboard note at C5 (60% vol) at 4.6s a 0.2s keyboard note at A4 (60% vol) at 3.2s a 0.2s snare beat (8% vol) at 3.4s a 0.2s snare beat (8% vol) at 3.6s a 0.2s snare beat (8% vol) at 3.8s a 0.2s snare beat (8% vol) at 4.6s a 0.2s snare beat (8% vol) and a -1.6s rest at 3.2s a 0.8s keyboard note at G3 (18% vol) at 3.2s a 0.8s keyboard note at B3 (18% vol) at 3.2s a 0.8s keyboard note at D4 (18% vol) at 4s a 0.8s keyboard note at A3 (18% vol) at 4s a 0.8s keyboard note at Db4 (18% vol) at 4s a 0.8s keyboard note at E4 (18% vol) and a 0.2s keyboard note at E5 (60% vol) and a 0.2s keyboard note at D5 (60% vol) and a 0.2s keyboard note at C5 (60% vol) and a 0.2s keyboard note at B4 (60% vol) at 5.6s a 0.8s keyboard note at A4 (60% vol) at 4.8s a 1s keyboard note at G3 (18% vol) at 4.8s a 1s keyboard note at B3 (18% vol) at 4.8s a 1s keyboard note at D4 (18% vol)Audio
main must not crash
main function must run without crashing.main song parts must each set the current pitch back to what it started at when done.
main function without any arguments, starting at several different pitches. We will measure how the current pitch changes, including where it is at the start and end of each inner function call. We will check to make sure that the pitch at the end of each phrase, melody, rhythm, harmony, and chord call is the same as the pitch before that function call started.chord
def to define chordaddNote
chord, call addNote in at least 2 places.melody
def to define melodyaddNote
melody, call addNote in at least 2 places.melody, call climbUp, climbDown, halfStepUp, halfStepDown, leapUp, leapDownwavesynth.climbUp, wavesynth.climbDown, wavesynth.halfStepUp, wavesynth.halfStepDown, wavesynth.leapUp, or wavesynth.leapDown in at least one place.rewind
melody, do not call rewind or wavesynth.rewind.rhythm
def to define rhythmaddBeat
rhythm, call addBeat in at least 2 places.rewind
rhythm, do not call rewind or wavesynth.rewind.harmony
def to define harmonychord
harmony, call chord in at least 2 places.harmony, call climbUp, climbDown, halfStepUp, halfStepDown, leapUp, leapDownwavesynth.climbUp, wavesynth.climbDown, wavesynth.halfStepUp, wavesynth.halfStepDown, wavesynth.leapUp, or wavesynth.leapDown in at least one place.rewind
harmony, do not call rewind or wavesynth.rewind.phrase
def to define phrasemelody
phrase, call melody in at least one place.rhythm
phrase, call rhythm in at least one place.harmony
phrase, call harmony in at least one place.rewind
phrase, call rewind or wavesynth.rewind in at least 2 places.song
def to define songphrase
song, call phrase in at least 2 places.main with 0 parameters
def to define main with 0 parameterssong
main with 0 parameters, call song in at least one place.= or by defining a parameter for a function) you must also later use that variable as part of another expression. If you need to create a variable that you won't use, it must have the name _, but you should only do this if absolutely necessary.