Custom Functions and Song Structure
The song structure is the song’s organization over time. The goal is to create meaningful sections and transitions for the flow of your music. In this chapter, you’ll create your own function, custom functions, to structure your songs!
A song’s structure
A song can be divided into sections. A section is made up of several measures (musical time units), and it expresses an idea or feeling. Usually, musicians try to add contrast between different sections. Intro, Verse, Chorus, and Outro are examples of sections.
A common and simple form, or song structure, is ABA. A and B are two different sections, for example chorus and verse. The B section adds variety, while returning to the A section invokes familiarity. The code below creates an ABA form. Section B features contrasting sounds to Section A - a slower and louder bass, and an additional rattling:

# A-B-A Form: A song with A and B sections
# Setup
from earsketch import *
setTempo(120)
# Music
# Create an A section
fitMedia(RD_WORLD_PERCUSSION_KALIMBA_PIANO_7, 1, 1, 5) # main
fitMedia(RD_WORLD_PERCUSSION_DRUMPART_24, 2, 1, 5) # drums
fitMedia(RD_UK_HOUSE__EVOLVEPAD_2, 3, 1, 5) # bass line
setEffect(3, VOLUME, GAIN, -20, 1, 0, 5) # increasing volume of bass line
# Create a 4 measure B section between measures 5 and 9
fitMedia(RD_WORLD_PERCUSSION_KALIMBA_PIANO_1, 1, 5, 9) # main melody differs
fitMedia(RD_WORLD_PERCUSSION_DRUMPART_5, 2, 5, 9) # drums differ
fitMedia(RD_UK_HOUSE__EVOLVEPAD_3, 3, 5, 9) # contrasting bass: it's slower and louder
setEffect(3, VOLUME, GAIN, 5, 5, 5, 9) # increasing bass volume
fitMedia(RD_WORLD_PERCUSSION_SEEDSRATTLE_1, 4, 5, 9) # rattling: adding a new element
# Then back to section A at measure 9
fitMedia(RD_WORLD_PERCUSSION_KALIMBA_PIANO_7, 1, 9, 13) # main
fitMedia(RD_WORLD_PERCUSSION_DRUMPART_24, 2, 9, 13) # drums
fitMedia(RD_UK_HOUSE__EVOLVEPAD_2, 3, 9, 13) # bass line
setEffect(3, VOLUME, GAIN, 0, 9, -20, 13) # increasing volume of bass line
// A-B-A Form: A song with A and B sections
// Setup
setTempo(120);
// Music
// Create an A section
fitMedia(RD_WORLD_PERCUSSION_KALIMBA_PIANO_7, 1, 1, 5); // main
fitMedia(RD_WORLD_PERCUSSION_DRUMPART_24, 2, 1, 5); // drums
fitMedia(RD_UK_HOUSE__EVOLVEPAD_2, 3, 1, 5); // bass line
setEffect(3, VOLUME, GAIN, -20, 1, 0, 5); // increasing volume of bass line
// Create a 4 measure B section between measures 5 and 9
fitMedia(RD_WORLD_PERCUSSION_KALIMBA_PIANO_1, 1, 5, 9); // main melody differs
fitMedia(RD_WORLD_PERCUSSION_DRUMPART_5, 2, 5, 9); // drums differ
fitMedia(RD_UK_HOUSE__EVOLVEPAD_3, 3, 5, 9); // contrasting bass: it's slower and louder
setEffect(3, VOLUME, GAIN, 5, 5, 5, 9); // increasing bass volume
fitMedia(RD_WORLD_PERCUSSION_SEEDSRATTLE_1, 4, 5, 9); // rattling: adding a new element
// Then back to section A at measure 9
fitMedia(RD_WORLD_PERCUSSION_KALIMBA_PIANO_7, 1, 9, 13); // main
fitMedia(RD_WORLD_PERCUSSION_DRUMPART_24, 2, 9, 13); // drums
fitMedia(RD_UK_HOUSE__EVOLVEPAD_2, 3, 9, 13); // bass line
setEffect(3, VOLUME, GAIN, -20, 9, 0, 13); // increasing volume of bass line
Keep in mind that a musical phrase sounds most natural when sounds are arranged into groups of two, four, eight, sixteen, etc. So your sections should preferably have a size of two, four, eight, or sixteen measures.
Create your custom functions
In the previous example with the ABA song, the code is large, and the code is repeated for the second A section. There is a way to be more concise, thanks to custom functions! We will define a function that will represent section A, then call the function twice.
The difference with functions that you have used like fitMedia()
, is that fitMedia()
is already pre-defined by our team to play a sound. In a custom function, you get to define exactly what it does. Here is how you would define section A:
def sectionA():
# Write your instructions here. This is the body of the function.
fitMedia(RD_WORLD_PERCUSSION_KALIMBA_PIANO_7, 1, 1, 5) # main
fitMedia(RD_WORLD_PERCUSSION_DRUMPART_24, 2, 1, 5) # drums
fitMedia(RD_UK_HOUSE__EVOLVEPAD_2, 3, 1, 5) # bass line
setEffect(3, VOLUME, GAIN, -20, 1, 0, 5) # increasing volume of bass line
# This code is indented. When writing the rest of your script, make sure you stop indenting.
function sectionA() {
// Write your instructions here. This is the body of the function.
fitMedia(RD_WORLD_PERCUSSION_KALIMBA_PIANO_7, 1, 1, 5); // main
fitMedia(RD_WORLD_PERCUSSION_DRUMPART_24, 2, 1, 5); // drums
fitMedia(RD_UK_HOUSE__EVOLVEPAD_2, 3, 1, 5); // bass line
setEffect(3, VOLUME, GAIN, -20, 1, 0, 5); // increasing volume of bass line
}
-
sectionA()
is the name we chose for our function. You can choose any name you like. Try to name your function in a descriptive way so your code is easier to read. -
The instructions are the body of the function. They are indented.
Now we want to add section A from measures nine to thirteen. However, when we call sectionA()
, the sounds are placed from measures one to five. To remedy this issue, we will create parameters for our function.
Here is what your code could look like:
# A-B-A-B Form and custom functions: A song with A and B sections, using custom functions
# Setup
from earsketch import *
setTempo(120)
# Music
# Create an A section function
def sectionA(startMeasure, endMeasure):
fitMedia(RD_WORLD_PERCUSSION_KALIMBA_PIANO_7, 1, startMeasure, endMeasure) # main
fitMedia(RD_WORLD_PERCUSSION_DRUMPART_24, 2, startMeasure, endMeasure) # drums
fitMedia(RD_UK_HOUSE__EVOLVEPAD_2, 3, startMeasure, endMeasure) # bass line
setEffect(3, VOLUME, GAIN, -20, startMeasure, 0, endMeasure) # increasing volume of bass line
# Create a B section function
def sectionB(startMeasure, endMeasure):
fitMedia(RD_WORLD_PERCUSSION_KALIMBA_PIANO_1, 1, startMeasure, endMeasure) # main melody differs
fitMedia(RD_WORLD_PERCUSSION_DRUMPART_5, 2, startMeasure, endMeasure) # drums differ
fitMedia(RD_UK_HOUSE__EVOLVEPAD_3, 3, startMeasure, endMeasure) # contrasting bass: it's slower and louder
setEffect(3, VOLUME, GAIN, 5, startMeasure, 5, endMeasure) # increasing bass volume
fitMedia(RD_WORLD_PERCUSSION_SEEDSRATTLE_1, 4, startMeasure, endMeasure) # rattling: adding a new element
# Call my functions
sectionA(1, 5)
sectionB(5, 9)
sectionA(9, 13)
sectionB(13, 17)
// A-B-A-B Form and custom functions: A song with A and B sections, using custom functions
// Setup
setTempo(120);
// Music
// Create an A section function
function sectionA(startMeasure, endMeasure) {
fitMedia(RD_WORLD_PERCUSSION_KALIMBA_PIANO_7, 1, startMeasure, endMeasure); // main
fitMedia(RD_WORLD_PERCUSSION_DRUMPART_24, 2, startMeasure, endMeasure); // drums
fitMedia(RD_UK_HOUSE__EVOLVEPAD_2, 3, startMeasure, endMeasure); // bass line
setEffect(3, VOLUME, GAIN, -20, startMeasure, 0, endMeasure); // increasing volume of bass line
}
// Create a B section function
function sectionB(startMeasure, endMeasure) {
fitMedia(RD_WORLD_PERCUSSION_KALIMBA_PIANO_1, 1, startMeasure, endMeasure); // main melody differs
fitMedia(RD_WORLD_PERCUSSION_DRUMPART_5, 2, startMeasure, endMeasure); // drums differ
fitMedia(RD_UK_HOUSE__EVOLVEPAD_3, 3, startMeasure, endMeasure); // contrasting bass: it's slower and louder
setEffect(3, VOLUME, GAIN, 5, startMeasure, 5, endMeasure); // increasing bass volume
fitMedia(RD_WORLD_PERCUSSION_SEEDSRATTLE_1, 4, startMeasure, endMeasure); // rattling: adding a new element
}
// Call my functions
sectionA(1, 5);
sectionB(5, 9);
sectionA(9, 13);
sectionB(13, 17);
Transition Strategies
Now that you know how to create custom functions to structure your song, let’s look at transitions. Transitions help one section smoothly go into the next. They can connect verse and chorus, build up to a drop, mix between tracks (DJing), or change keys. The goal of a transition is to grab the listener’s attention and let them know a change is about to occur.
Following are some popular strategies for creating musical transitions:
-
Crash Cymbal: Placing a crash cymbal on the first beat of a new section.
-
Drum Fill: A rhythmic variation to fill the gap before a new section.
-
Track Silencing: Silence some tracks temporarily for dramatic effect.
-
Melody Variation: Introducing a variation of the chords, bass line, or melody before the new section. Often, a folder within the EarSketch sound library contains variations of a similar riff.
-
Riser: A note or noise that increases in pitch. It is very common in EDM (Electronic Dance Music) and creates an anticipation of a drop. You can use the search term "riser" in the Sound Browser. A reversed crash cymbal can be used as a riser, like YG_EDM_REVERSE_CRASH_1.
-
Snare Roll: A sequence of repeated snare hits, with increasing density, pitch, or amplitude. You can use a sound like RD_FUTURE_DUBSTEP_FILL_1 or HOUSE_BREAK_FILL_003, or with
makeBeat()
. -
Looping: Repeating a short segment of melody before a new section.
-
Crossfading: Decreasing the volume of one section while increasing the volume of a new section.
-
Anacrusis: When the melody of the new section starts a couple beats early.
Drum fills:
# Transition Techniques - Drum Fill: Transitioning between sections with a drum fill
# Setup
from earsketch import *
setTempo(130)
# Music
leadGuitar1 = RD_ROCK_POPLEADSTRUM_GUITAR_4
leadGuitar2 = RD_ROCK_POPLEADSTRUM_GUITAR_9
bass1 = RD_ROCK_POPELECTRICBASS_8
bass2 = RD_ROCK_POPELECTRICBASS_25
drums1 = RD_ROCK_POPRHYTHM_DRUM_PART_10
drums2 = RD_ROCK_POPRHYTHM_MAINDRUMS_1
drumFill = RD_ROCK_POPRHYTHM_FILL_4
# Section 1
fitMedia(leadGuitar1, 1, 1, 8)
fitMedia(bass1, 2, 1, 8)
fitMedia(drums1, 3, 1, 8)
# Drum Fill
fitMedia(drumFill, 3, 8, 9)
# Section 2
fitMedia(leadGuitar2, 1, 9, 17)
fitMedia(bass2, 2, 9, 17)
fitMedia(drums2, 3, 9, 17)
// Transition Techniques - Drum Fill: Transitioning between sections with a drum fill
// Setup
setTempo(130);
// Music
var leadGuitar1 = RD_ROCK_POPLEADSTRUM_GUITAR_4;
var leadGuitar2 = RD_ROCK_POPLEADSTRUM_GUITAR_9;
var bass1 = RD_ROCK_POPELECTRICBASS_8;
var bass2 = RD_ROCK_POPELECTRICBASS_25;
var drums1 = RD_ROCK_POPRHYTHM_DRUM_PART_10;
var drums2 = RD_ROCK_POPRHYTHM_MAINDRUMS_1;
var drumFill = RD_ROCK_POPRHYTHM_FILL_4;
// Section 1
fitMedia(leadGuitar1, 1, 1, 8);
fitMedia(bass1, 2, 1, 8);
fitMedia(drums1, 3, 1, 8);
// Drum Fill
fitMedia(drumFill, 3, 8, 9);
// Section 2
fitMedia(leadGuitar2, 1, 9, 17);
fitMedia(bass2, 2, 9, 17);
fitMedia(drums2, 3, 9, 17);
The track silencing technique only requires the modification of a couple fitMedia()
calls. An example is shown below.
# Transition Techniques - Track Silencing: Transitioning between sections with track silencing
# Setup
from earsketch import *
setTempo(120)
# Music
introLead = TECHNO_ACIDBASS_002
mainLead1 = TECHNO_ACIDBASS_003
mainLead2 = TECHNO_ACIDBASS_005
auxDrums1 = TECHNO_LOOP_PART_025
auxDrums2 = TECHNO_LOOP_PART_030
mainDrums = TECHNO_MAINLOOP_019
bass = TECHNO_SUBBASS_002
# Section 1
fitMedia(introLead, 1, 1, 5)
fitMedia(mainLead1, 1, 5, 9)
fitMedia(auxDrums1, 2, 3, 5)
fitMedia(auxDrums2, 2, 5, 8) # Drums drop out
fitMedia(mainDrums, 3, 5, 8)
# Section 2
fitMedia(mainLead2, 1, 9, 17)
fitMedia(auxDrums2, 2, 9, 17) # Drums enter back in
fitMedia(mainDrums, 3, 9, 17)
fitMedia(bass, 4, 9, 17)
// Transition Techniques - Track Silencing: Transitioning between sections with track silencing
// Setup
setTempo(120);
// Music
var introLead = TECHNO_ACIDBASS_002;
var mainLead1 = TECHNO_ACIDBASS_003;
var mainLead2 = TECHNO_ACIDBASS_005;
var auxDrums1 = TECHNO_LOOP_PART_025;
var auxDrums2 = TECHNO_LOOP_PART_030;
var mainDrums = TECHNO_MAINLOOP_019;
var bass = TECHNO_SUBBASS_002;
// Section 1
fitMedia(introLead, 1, 1, 5);
fitMedia(mainLead1, 1, 5, 9);
fitMedia(auxDrums1, 2, 3, 5);
fitMedia(auxDrums2, 2, 5, 8); // Drums drop out
fitMedia(mainDrums, 3, 5, 8);
// Section 2
fitMedia(mainLead2, 1, 9, 17);
fitMedia(auxDrums2, 2, 9, 17); // Drums enter back in
fitMedia(mainDrums, 3, 9, 17);
fitMedia(bass, 4, 9, 17);
The next example uses multiple risers and a crash cymbal during the transition.
# Transition Techniques - Risers: Transitioning between sections using risers and a crash cymbal
# Setup
from earsketch import *
setTempo(128)
# Music
synthRise = YG_EDM_SYNTH_RISE_1
airRise = RD_EDM_SFX_RISER_AIR_1
lead1 = YG_EDM_LEAD_1
lead2 = YG_EDM_LEAD_2
kick1 = YG_EDM_KICK_LIGHT_1
kick2 = ELECTRO_DRUM_MAIN_LOOPPART_001
snare = ELECTRO_DRUM_MAIN_LOOPPART_003
crash = Y50_CRASH_2
reverseFX = YG_EDM_REVERSE_FX_1
# Section 1
fitMedia(lead1, 1, 1, 17)
fitMedia(kick1, 2, 9, 17)
# Transition
fitMedia(reverseFX, 3, 16, 17)
fitMedia(synthRise, 4, 13, 17)
fitMedia(airRise, 5, 13, 17)
fitMedia(crash, 6, 17, 19)
# Section 2
fitMedia(lead2, 1, 17, 33)
fitMedia(kick2, 7, 25, 33)
fitMedia(snare, 8, 29, 33)
# Effects
setEffect(1, VOLUME, GAIN, 0, 16, 1, 17) # Adjusting volumes for better matching
setEffect(4, VOLUME, GAIN, -10)
setEffect(7, VOLUME, GAIN, -20)
setEffect(8, VOLUME, GAIN, -20)
// Transition Techniques - Risers: Transitioning between sections using risers and a crash cymbal
// Setup
setTempo(128);
// Music
var synthRise = YG_EDM_SYNTH_RISE_1;
var airRise = RD_EDM_SFX_RISER_AIR_1;
var lead1 = YG_EDM_LEAD_1;
var lead2 = YG_EDM_LEAD_2;
var kick1 = YG_EDM_KICK_LIGHT_1;
var kick2 = ELECTRO_DRUM_MAIN_LOOPPART_001;
var snare = ELECTRO_DRUM_MAIN_LOOPPART_003;
var crash = Y50_CRASH_2;
var reverseFX = YG_EDM_REVERSE_FX_1;
// Section 1
fitMedia(lead1, 1, 1, 17);
fitMedia(kick1, 2, 9, 17);
// Transition
fitMedia(reverseFX, 3, 16, 17);
fitMedia(synthRise, 4, 13, 17);
fitMedia(airRise, 5, 13, 17);
fitMedia(crash, 6, 17, 19);
// Section 2
fitMedia(lead2, 1, 17, 33);
fitMedia(kick2, 7, 25, 33);
fitMedia(snare, 8, 29, 33);
// Effects
setEffect(1, VOLUME, GAIN, 0, 16, 1, 17); // Adjusting volumes for better matching
setEffect(4, VOLUME, GAIN, -10);
setEffect(7, VOLUME, GAIN, -20);
setEffect(8, VOLUME, GAIN, -20);
Your full song
In programming we can create abstractions, the bundling of ideas to form a single concept. In music, we group musical ideas into sections. Functions are one kind of abstraction used in computer science. They pack multiple statements into one tool so they can be easily referred to. Abstractions can make the form of a program clearer.
Here is an example of a full song:
# Total Atlanta Song of Summer: creating a complete song with abstractions
# structure of the song: intro-A-B-A-B
from earsketch import *
setTempo(110)
# Sound variables
melody1 = EIGHT_BIT_ATARI_BASSLINE_005
melody2 = DUBSTEP_LEAD_018
melody3 = DUBSTEP_LEAD_017
melody4 = DUBSTEP_LEAD_013
bass1 = HIPHOP_BASSSUB_001
bass2 = RD_TRAP_BASSDROPS_2
brass1 = Y30_BRASS_4
shout = CIARA_SET_TALK_ADLIB_AH_4
piano = YG_RNB_PIANO_4
kick = OS_KICK02
hihat = OS_CLOSEDHAT03
# FUNCTION DEFINITIONS
# Adding drums:
def addingDrums(start, end, pattern):
# first, we create beat strings, depending on the parameter pattern:
if pattern == "heavy":
beatStringKick = "0---0---0---00--"
beatStringHihat = "-----000----0-00"
elif pattern == "light":
beatStringKick = "0-------0---0---"
beatStringHihat = "--0----0---0---"
# then we create the beat,
# on track 3 for the kick and track 4 for the hihat,
# from measures start to end:
for measure in range(start, end):
# here we will place our beat on "measure",
# which is first equal to "start",
# which is a parameter of the function
makeBeat(kick, 3, measure, beatStringKick)
makeBeat(hihat, 4, measure, beatStringHihat)
# Intro:
def intro(start, end):
fitMedia(melody1, 1, start, start + 1)
fitMedia(melody1, 1, start + 2, start + 3)
fitMedia(bass1, 2, start, start + 3)
# transition:
fitMedia(bass2, 2, start + 3, end)
fitMedia(shout, 3, start + 3.75, end)
# SectionA:
def sectionA(start, end):
fitMedia(melody2, 1, start, end)
fitMedia(brass1, 2, start, end)
setEffect(2, VOLUME, GAIN, -20, start, -10, end)
addingDrums(start, end, "heavy")
# Pitch modulation for transition:
setEffect(1, BANDPASS, BANDPASS_FREQ, 200, end - 2, 1000, end)
# SectionB:
def sectionB(start, end):
fitMedia(melody3, 1, start, start + 2)
fitMedia(melody4, 1, start + 2, end)
fitMedia(piano, 2, start, end)
addingDrums(start, end, "light")
# FUNCTION CALLS
intro(1, 5)
sectionA(5, 9)
sectionB(9, 13)
sectionA(13, 17)
sectionB(17, 21)
# Fade out:
for track in range(1, 5):
setEffect(track, VOLUME, GAIN, 0, 19, -60, 21)
# Lower hihat and kick volume:
setEffect(4, VOLUME, GAIN, -15)
setEffect(3, VOLUME, GAIN, -10)
// Total Atlanta Song of Summer: creating a complete song with abstractions
setTempo(110);
// Sound variables
var melody1 = EIGHT_BIT_ATARI_BASSLINE_005;
var melody2 = DUBSTEP_LEAD_018;
var melody3 = DUBSTEP_LEAD_017;
var melody4 = DUBSTEP_LEAD_013;
var bass1 = HIPHOP_BASSSUB_001;
var bass2 = RD_TRAP_BASSDROPS_2;
var brass1 = Y30_BRASS_4;
var shout = CIARA_SET_TALK_ADLIB_AH_4;
var piano = YG_RNB_PIANO_4;
var kick = OS_KICK02;
var hihat = OS_CLOSEDHAT03;
// FUNCTION DEFINITIONS
// Adding drums:
function addingDrums(start, end, pattern) {
// first, we create beat strings, depending on the parameter pattern:
if (pattern === "heavy") {
var beatStringKick = "0---0---0---00--";
var beatStringHihat = "-----000----0-00";
} else if (pattern === "light") {
beatStringKick = "0-------0---0---";
beatStringHihat = "--0----0---0---";
}
// then we create the beat,
// on track 3 for the kick and track 4 for the hihat,
// from measures start to end:
for (var measure = start; measure < end; measure++) {
// here we will place our beat on "measure",
// which is first equal to "start",
// which is a parameter of the function
makeBeat(kick, 3, measure, beatStringKick);
makeBeat(hihat, 4, measure, beatStringHihat);
}
}
// Intro:
function intro(start, end) {
fitMedia(melody1, 1, start, start + 1);
fitMedia(melody1, 1, start + 2, start + 3);
fitMedia(bass1, 2, start, start + 3);
// transition:
fitMedia(bass2, 2, start + 3, end);
fitMedia(shout, 3, start + 3.75, end);
}
// SectionA:
function sectionA(start, end) {
fitMedia(melody2, 1, start, end);
fitMedia(brass1, 2, start, end);
setEffect(2, VOLUME, GAIN, -20, start, -10, end);
addingDrums(start, end, "heavy");
// Pitch modulation for transition:
setEffect(1, BANDPASS, BANDPASS_FREQ, 200, end - 2, 1000, end);
}
// SectionB:
function sectionB(start, end) {
fitMedia(melody3, 1, start, start + 2);
fitMedia(melody4, 1, start + 2, end);
fitMedia(piano, 2, start, end);
addingDrums(start, end, "light");
}
// FUNCTION CALLS
intro(1, 5);
sectionA(5, 9);
sectionB(9, 13);
sectionA(13, 17);
sectionB(17, 21);
// Fade out:
for (var track = 1; track < 5; track++) {
setEffect(track, VOLUME, GAIN, 0, 19, -60, 21);
}
// Lower hihat and kick volume:
setEffect(4, VOLUME, GAIN, -15);
setEffect(3, VOLUME, GAIN, -10);
In this example, we have used a for
loop inside a custom function! We have used parameters of the function (start
and end
) inside the for loop.
Chapter 7 Summary
-
Sections are related musical units consisting of multiple measures. Each expresses an idea or feeling.
-
Transitions are passages of music used to connect consecutive musical sections.
-
The structure and variety found within a song is known as its form. A common musical form is A-B-A.
-
Custom functions are unique functions written by the programmer to accomplish a specific task. You have to create a custom function to be able to call it. You can create as many parameters as you want.
-
An abstraction is the bundling of ideas to form a single, often less complex, concept. Functions are an example of abstraction.
Questions
Which of these is NOT an example of a musical section?
-
Drums
-
Intro
-
Verse
-
Chorus
What is an abstraction?
-
A bundling of ideas to form a single concept
-
A variety of sounds throughout sections
-
Parts of a song that are related, but also are distinct from each other
-
A statement that returns a value to the function call
Which of these options correctly defines the function myFunction()
with the parameters startMeasure
and endMeasure
?
-
def myFunction(startMeasure, endMeasure):
-
def myFunction():
-
myFunction(startMeasure, endMeasure):
-
myFunction(2, 5)
Which of these options correctly defines the function myFunction()
with the parameters startMeasure
and endMeasure
?
-
function myFunction(startMeasure, endMeasure) {}
-
function myFunction() {}
-
myFunction(startMeasure, endMeasure){}
-
myFunction(2, 5)
Which of these is NOT an example of a transition?
-
Melody Consistency
-
Crash Cymbal
-
Riser
-
Track Silencing