Direction 1 (Creative): Create a more detailed cover of a song on TheoryTab#
In Assignment 2, you created a simple cover of a song by fetching its notes from TheoryTab and synthesizing them directly. In this direction, you will make a much more detailed cover, using TheoryTab, Pyquist, and any other music software you’d like.
The core idea is to stop treating a song as one undifferentiated stream of notes and start treating it as an arrangement: several independent parts, each with its own notes and its own sound, layered together. At a high level, you will (1) build a list of pq.Score objects representing parts for at least three instruments, (2) route each part through its own instrument function to render it as a pq.Audio stem, and (3) mix your stems together into a final composition.
You may cover any song, whether or not it is on TheoryTab, and you may write an original song instead if you prefer. Computer music does not have to sound like something you’d hear on the radio — you’ll be graded on your technical achievement and how well you realized your creative intent, not on the aesthetics of the result.
Steps#
Download the starter code file 3-1-cover.ipynb. Unlike for the autograded assignments, this starter code is merely a suggestion. You’re free to implement however you want, assuming it conforms to the requirements below.
Pick a song and fetch it. Find a song on TheoryTab, right click “Open in Hookpad”, and copy the link address. Fetch it with
fetch_theorytab, which returns a metronome plus a melody and harmony score. Passingharmony_as_notes=Falsegives you the chords asroot/intervals/inversionrather than pre-voiced notes, which makes them much easier to rearrange.Arrange your parts. Build
parts: list[pq.Score], with one score per instrument and at least three scores total. This is where your symbolic work happens: revoicing chords, transposing or inverting the melody, adding a counter-melody or a drum part, and repeating or reordering sections. Note that a TheoryTab entry usually covers only a single short section of a song, so you will need to extend it to reach the required length, or chain multiple sections from the same song together.Design an instrument per part. Write one instrument function per part. Each is called as
instrument(**event.kwargs), so its parameters must line up with the kwargs of the events in its part. Synthesis technique is up to you — additive synthesis, samples from FreeSound, noise bursts, whatever serves the part.Render your stems. Render each part with its instrument to produce
stems: list[pq.Audio].Mix. Combine your stems into a single
pq.Audioand write it out ascomposition.wav. If you’d rather mix in a DAW, export your stems from Python and mix them externally, but the stems themselves must still be produced by your code.
Requirements#
Your composition is between 60 and 300 seconds long, at 44.1kHz or 48kHz. Stereo is preferred but not required.
Your code builds a list of at least 3
pq.Scoreobjects representing parts for different instruments.Each part is non-trivial. A part consisting of a single sound event does not count, and neither does a part that is exactly the unmodified melody or harmony returned by TheoryTab.
Your code defines a separate instrument function per part, and renders each part with its corresponding instrument to produce one
pq.Audiostem per part.Your stems are mixed into the final composition. Mixing may be done in external audio software, but in that case your code must still export the individual stems.
A non-trivial portion of
composition.wavis reproduced when your submitted code is re-executed. Using an external DAW is fine, but composing the piece in the DAW and generating only a sound effect in Python is not.You use at least 3 of the techniques listed below, and you name which 3 in
CREATIVE.md.Any external audio you use (FreeSound samples, field recordings, etc.) is attributed in
CREATIVE.md.
Techniques (choose at least 3):
Harmony arrangement. Take the chord info from TheoryTab (with
harmony_as_notes=False) and arrange it with more interesting voicings, rhythms, etc.Harmony manipulation. Perturb the harmony in some significant fashion. E.g., change a major song to minor, or add a gear-shift key change by transposing melody and harmony.
Amplitude modulation. Add tremolo to one of your instrument sounds by multiplying it with a sinusoidal amplitude envelope.
Reharmonization. Change the harmony to other chords while keeping the melody intact.
Melody manipulation. Perturb the melody in some significant fashion. Invert it, reverse it, transpose it, etc.
Counterpoint. Add a second melody that harmonizes with the first.
Drums. Add a percussive instrument or instruments, e.g., using samples from FreeSound or noise bursts.
Dynamics. Volume gets louder or softer over time, or instrument timbres evolve over time.
Mixing. Explore interesting time-varying mixing techniques, like volume or panning automation.
Submission#
Your submission must conform to the creative format. Bundle the following into a single .zip file (under 100MB) and submit it via Gradescope.
composition.wavorcomposition.mp3— your final composition, 60-300 seconds.CREATIVE.md— use the open-ended template and leave all## Section Headingsunchanged. Your write-up must state:The title of the song and its composer/songwriter (or that it’s an original).
Which 3 techniques you chose, how you implemented each one, and where in the song each one occurs.
What your 3+ parts are and which instrument function renders each one.
Attribution for any external audio you used.
src/— your Python/Pyquist code plus any sound assets it needs. Anything we canpip installdoes not need to be included. At minimum this directory should contain something like:cover.ipynborcover.py— the code that builds your parts, renders your stems, and (if you mixed in Python) produces your composition.Any assets or sound files that your code depends on
Note
The Gradescope autograder only checks the top-level structure of your zip file. It does not verify the specific contents of your src/ directory. Making sure the files above are present, complete, and runnable is up to you.