This task is part of project03 which is due at 23:00 EDT on 2024-09-24.
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
addNote
rhythm
which creates a drum line using
addBeat
harmony
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.
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