EarSketch - Day 1

Print Return to index

Table of Contents

Intro to Digital Audio Workstations Intro to Programming Questions and Exercises Answers

Introduction to DAWs - Digital Audio Workstations

What’s a DAW?

A DAW, or digital audio workstation, is a program that is designed for the recording, editing and playing of digital audio files. A DAW allows you to edit and mix multiple audio sources simultaneously against a musical timing grid. This is important because it allows for a simple way to line up various audio clips with each other based on a set measure or beat. Within a DAW, it is possible to apply effects to these audio files and control how these effects change over time. In addition, it should be noted that a DAW manipulates audio files in a way that is non-destructive to the original file. Many effects can be applied to any audio clip within a DAW without altering the original source file. We will be running programming scripts through our DAW, called Reaper, in order to create music.

The Reaper interface

Create a new project

To create a new project, click on the new project icon with the green star located in the upper left hand corner of the Reaper interface.

Create project button

Opening a project

To open a project, click on the open project icon with the green arrow in the upper left hand corner of the Reaper interface and navigate to the desired project.

Open project button

Playing a project

The play head (below left) indicates at what point the project will begin to play. Before playing a project in Reaper, the play head should be placed at the beginning of the clip. This can be done by simply dragging the triangular top of the play head to the beginning of the clip or by pressing the rewind button in the transport bar (below right)

Play head icon

The transport bar

Once the play head is in the correct position, press the play button on the transport bar to play the project.

Measures

In music, a measure is a segment of time defined by a given number of beats of a given duration. In the EarSketch environment a measure is defined by four beats. One measure can hold four quarter notes, eight eighth notes, sixteen sixteenth notes, and so on.

Measure Numbers

The number boxed in red is the measure number, followed by the beat number and the sub-beat number. The red box is at the first measure, third beat, and no sub-beats.

Measure number on Reaper timeline

Tracks

In music, there are different components of a song. For example, you may have vocals, drums and guitar. In the creation of such a song in a digital audio workstation, each of these will have its own separate track. This allows the volume as well as other effects placed on each instrument to be changed independently of one another. A single track in reaper is shown below.

A track on the Reaper timeline

Adding a track

To add a new track to your project, you can navigate to Insert -> New Track

Manipulating clips on the track

To add a clip of audio to an already-existing track, simply locate the file on your computer and drag and drop the file into the desired track.

Track control panel

Once the clip is placed within a track, it is possible to click and drag the clip to place it in a different position.

Clips can also be manipulated to fill more time by looping, or be truncated to fill less time on the track. To adjust the play time of a clip, bring the mouse pointer to the right edge of a clip. The pointer will change to represent the clip edge and arrows indicating that the clip can be adjusted.

Manipulating a clip on the track

It is possible to listen to only one track in a multi-track project. To do this, press the solo button of the track that you wish to listen to. When a particular track is soloed, all other tracks will be silent and the solo button will appear yellow. When a track is not soloed, the button will retain its normal grey color.

Finalizing a Project

To save a project, choose File -> Save or click the button with the grey arrow in the top left corner of the interface.

Save project button

Rendering a project combines all of the tracks into one audio file. There are many different file types that a project can be rendered to. The two main file types that we will be dealing with (WAV and MP3) are further discussed later in this section.

To save your project to an audio file, choose File -> Render and the following screen should appear:

Render dialog screen

  1. Rendering the Master Mix of your project renders all of the tracks to a single file, as opposed to rendering only specific tracks.
  2. Make sure that you save your file to the proper place so that you are able to find it easily.
  3. The Output format of your file should be either a WAV file or an MP3. In general, WAV files are best for when you wish to save the file on your local computer. WAV files preserve the quality of audio that you hear in Reaper. MP3 files are best for when you wish to share your song with others on the Internet. MP3 files have somewhat reduced quality, but attain a smaller file size (about 10% the size of a WAV file). When rendering to WAV, be sure to make sure that the WAV bit depth is set to 16 bit PCM!
  4. Click ‘Render 1 file...’ to render your project.

Play audio file in audio player

Once your project is rendered, you should be able to open the new file in a program, like the Windows Media Player, that will play it. Alternatively, you can double click on your file and allow the computer to open it with the default audio player.

Introduction to Programming

About the EarSketch software

The EarSketch DAW contains a scripting language for musical remixing that is based on the Python programming language. Python is a full-featured language that is used by many large companies, particularly Google. Here you’ll make your first EarSketch project.

Creating your first project

  1. Double-click the EarSketch icon on the desktop. This opens Komodo, the text editor we'll be using to write code, and Reaper, the DAW.
  2. In Komodo, Create a new file by going to the “File” menu and selecting “New,” then “New File.” Alternately, press Control + N.
    An empty Komodo file

  3. Save as “lastname-day1-example1.py” in "EarSketch Scripts" in the Documents Folder
  4. Type the following program into the Komodo window exactly as it appears here. Note that the quotation marks on lines 1 and 3 are single quotation marks. The words may appear in different colors on your screen than they do here.
    # Day 1 Sample Project 1
    # A very simple EarSketch script
    
    from earsketch import *
    
    # initialize Reaper
    init()
    setTempo(120)
    
    # Add a music file to track 1
    insertMedia(DRUM_N_BASS_DRUMS2_1M, 1)
    
    # Set the project cursor to be at the beginning of the file
    finish()
    
  5. Save the updated file (“File” > “Save” or Control + S).

To listen to the project, Reaper will need to load the script and run it. Go to the Reaper window.

From the “Actions” menu, select “Run Earsketch script

Actions dropdown

A window will pop up asking you to select your file. Navigate to the location where your script was saved, select it, and press “open”.

Select your script file

After clicking “Open,” Reaper will ask you if you want to save the existing project. Because your work is stored in the python file, there’s no need to save any Reaper files, so click "no." Finally, hit the play button on the Reaper interface and enjoy the music you've created!

Questions and Exercises

  1. What menu do you access within Reaper to run an EarSketch script?
  2. Why might we want to be able to control Reaper programmatically rather than using the standard GUI (Graphical user interface)? What kind of benefits can a computational approach have on music remixing?

Anatomy of an Earsketch script

The code above might be pretty confusing. To try to make it clearer, let’s look at the component parts of the script. Basically, there are three things happening. There’s a setup section, that allows your script to access EarSketch functionality and sets up a new project in Reaper; a music section, making up the content of your composition (for now is just a single line); and finally, a finish section, that completes your project and gets it ready to play within Reaper.

'''
Day 1 Sample Project 1
A very simple EarSketch script
'''

The above line is title information, which is not required, but allows you and others to easily understand what this file is about. Three single-quote characters, looking like this ''', means that you can add comments to your file. Comments are code that is not executed. Comments must start and end with three single quotes, as in the example above. Alternately, you can put a # at the beginning of each line of a comment, as in the example below. Comments like these are used to add context to files and can be used to explain what is happening. It’s useful to remember in computer programming that you’re really writing for two audiences: the computer that will be executing the instructions, but also for other humans who want to understand what is going on in the program. It is always important to not only have functioning code, but to also have code that is understandable for others.

# initialize Reaper
init()
setTempo(120)

The setup section covers a bunch of housekeeping work, and also establishes a basic tempo for the project. The import statement from earsketch import * sets up the basic EarSketch commands to be used. This is essential for running EarSketch projects, as without it, none of the special repaer commands will work! init() creates a new project in Reaper. Finally, setTempo(120) establishes the tempo for the project, setting it to 120 beats per minute.

# Add a music file to track 1
insertMedia(DRUM_N_BASS_DRUMS1_4M, 1)

While it’s very simple at the moment, this is the section where most music will be created. insertMedia() is the function we use to add music files to particular tracks. In this example, we’re telling insertMedia() to take the file called “DRUM_N_BASS_DRUMS1_4M,” add it to the first track, placing the clip at the first measure of that track.

# Set the project cursor to be at the beginning of the file
finish()

Finally, this finishing section will look the same in all of your projects. As well as adding any effects or other processing-intensive components of your work to the project files, it tells Reaper to move the cursor to the very beginning of the project, so that all you have to do to hear your project is to hit play in the Reaper interface. Without it, you would have to manually move the DAW cursor to the beginning of your project to play it.

Questions and Exercises

  1. What are the three main components of an EarSketch script?
  2. What is the purpose of a comment? Why should comments be used?
  3. What part of an EarSketch script contains the main content of your musical compositions?

Multi-track projects

In the last handout, we created the simplest possible EarSketch project, just a single track with a single file in it. Now, let’s add another track.

  1. If it’s not already open, open “day1-example1.py” from Earsketch Scripts Folder with Komodo Save it as “day1-example2.py
  2. Revise the program in Komodo so that it matches the program below. There’s nothing really new here: the only difference from the previous project is that the new, second insertMedia() call is putting a new file onto track 2.
    '''
    Day 1 Sample Project 2
    A multi-track project
    '''
    
    from earsketch import *
    
    # initialize Reaper
    init()
    setTempo(120)
    
    # Add a music file to track 1 (Lead)    
    insertMedia(DRUM_AND_BASS_MASTERBASS1_4M, 1)
    
    # Add a music file to track 2 (Drums)
    insertMedia(DRUM_N_BASS_DRUMS2_1M, 2)
    
    # Set the project cursor to be at the beginning of the file
    finish()
    
  3. Run the project in Reaper. You’ll have to once again Run Earsketch Script from the action menu and navigate to your recently saved script in order to run your project. Again, when Reaper asks you if you wish to save the Reaper project, press no.

At this point, you should have a Reaper project that is playing two music tracks simultaneously.

Constants and Variables

We refer to each sound clip by its own unique name typed in uppercase letters. These names are called constants. A constant is a way of referring to something by using another name to save typing. In actuality, each sound clip is really a long file path that points to the particular file location. In this case, using a constant keeps us from having to type the whole path to find a particular sound file. For example, when we want to use insertMedia() to place the drum section in the example above, we can just type “DRUM_N_BASS_DRUMS1_4M” and the correct location to find the sample is understood. Without a constant, in order to reach the same file, you may have to type something like “/Users/student/EarSketch/sound/drum_n_bass/DRUM_N_BASS_DRUM_1.wav”. That's a lot of typing! The reason this works is that EarSketch automatically defines all the locations for the various sample files.

Constants are just a particular kind of variable. Variables are used in the same ways as constants are, as a shorthand to save typing, but unlike constants, the values that variables have can change over time. One good example of a variable is something like currentTime: the value is constantly changing, but referring to the idea of it using that phrase always makes sense. A good example of a constant, however, is something like MY_BIRTHDAY. The day you were born on won’t ever change. Naming variables and constants well is important, as it helps to keep code understandable. In addition, a standard convention is to name constants in all upper-case. This makes sure that constants are easily distinguished from variables in code.

Questions and Exercises

  1. Which of the following are constants?
    a. musicFile
    b. HIP_HOP_FOLDER
    c. SCRATCH_2M
    d. measure
  2. Try adding other samples in place of the ones in the example, including ones from other types of music. Note the names of the constants for the files you particularly like.
  3. In the example, samples were placed on the first two tracks in Reaper. Try adding more samples to new tracks using insertMedia()

Music with more than one section

  1. Open day1-example2.py and save as “day1-example3.py
  2. Edit the script to match the following program. This code looks a lot like the previous script, but with a new function called fitMedia().
    '''
    Day 1 Sample Project 3
    Music with A and B sections
    '''
    
    from earsketch import *
    
    # initialize Reaper
    init()
    setTempo(120)
    
    # Create an A section just like usual     
    insertMedia(DRUM_AND_BASS_MASTERBASS1_4M, 1, 1)     #Lead
    insertMedia(DRUM_N_BASS_DRUMS1_4M, 2, 1)            #Drums
    
    # fit a 2 measure B section between measures 5 and 7
    fitMedia(DRUM_N_BASS_DRUMS3_1M, 1, 5, 7)            #Drums breakout
    
    # Then back to section A at measure 7    
    insertMedia(DRUM_AND_BASS_MASTERBASS1_4M, 1, 7)     #Lead
    insertMedia(DRUM_N_BASS_DRUMS1_4M, 2, 7)            #Drums
    
    # Set the project cursor to be at the beginning of the file
    finish()
  3. Open this script in Reaper and run it. You should hear musical output that starts with guitar and drums, then has just a keyboard section, then the drum and guitar section again.

Here we’re learning a new thing about the insertMedia() function. First, let’s talk about how insertMedia() itself works. The function can take a number of values that are called parameters. Parameters provide a way to customize a function in order to make it do what you want. The way we’ve been using it, we tell Reaper the disk location of the sample we want to use as the first parameter, and the number of the track that we want that sample to appear on as the second parameter. insertMedia() can also take a third parameter, telling it where to place the sample in the track. So, when Reaper sees:

insertMedia(DRUM_AND_BASS_MASTERBASS1_4M, 1, 7)

Reaper knows to take the guitar sample defined by the constant “DRUM_AND_BASS_MASTERBASS1_4M” and place it on the first track at the seventh measure of the project.

Another new method here is fitMedia(). It’s a lot like insertMedia(), but will automatically make a sample fit into space defined by the parameters. In the example above, we see that fitMedia() is called like this:

fitMedia(DRUM_AND_BASS_MASTERBASS1_4M, 1, 5, 7)

This code tells Reaper to take DRUM_AND_BASS_MASTERBASS1_4M and place it on the first track beginning at the start of the fifth measure and ending at the start of the seventh measure.

What’s the difference?

It may be unclear at this point what the difference is between insertMedia() and fitMedia(), or why you would want to use one instead of the other. These functions reflect different ways of interacting with clips on the timeline of the DAW.

insertMedia() is the equivalent of taking a sound file and dropping into a track. Just like on the timeline, it’s possible to change where the clip is placed: with a mouse you can slide the clip along the timeline, while in the python code you affect the placement with the parameter that controls the measure.

fitMedia() is the same functionality as insertMedia() but with the added ability to make the clip fit arbitrary lengths. This is the equivalent of dragging on the ends of a clip in the DAW timeline: fitMedia() will loop a sample to fill the space it needs to fit if the clip is shorter than the specified length, or will cut off the clip early to fit into fewer measures.

Questions and Exercises

  1. Now that we have full control over placing samples on particular tracks and where those samples are placed in the track (note the parameters being used in the insertMedia() and fitMedia() functions), try substituting samples of your choice however you please! Some samples are different lengths, so be sure to note how the measures line up between sections, or use fitMedia().
  2. What popular songs can you think of that have A and B sections?

Time to get random

You may be wondering why using programming to create music projects is interesting. One way that programming really shines is by being able to include things like randomness in projects, meaning that the music will be different every time the script runs. Further, programming allows us to express ourselves musically in ways that are difficult or even impossible to do by hand. In your already open “day1-example3.py” file, save a new version named “day1-example4.py.” Enter this code into Komodo:

'''
Day 1 Sample Project 4
Using randomFile()
'''

from earsketch import *

# initialize Reaper
init()
setTempo(120)

# Create an A section just like usual     
fitMedia(DRUM_AND_BASS_MASTERBASS1_4M, 1, 1, 5)     #Lead
fitMedia(DRUM_N_BASS_DRUMS2_1M, 2, 1, 5)        	#Drums

# fit a 2 measure B section between measures 5 and 7
fitMedia(DRUM_N_BASS_DRUMS3_1M, 1, 5, 7)      		#Drums breakout

# Then back to section A at measure 7    
fitMedia(DRUM_AND_BASS_MASTERBASS1_4M, 1, 7, 11)     #Lead
fitMedia(DRUM_N_BASS_DRUMS2_1M, 2, 7, 11)       	#Drums

# Add random extra scratch sounds
for measure in range(1,11):
   randomFile = selectRandomFile(HIP_HOP_SCRATCH_FOLDER)
   fitMedia(randomFile, 3, measure, measure + .5)

# Set the project cursor to be at the beginning of the file
finish()

When playing this script, every measure of the project should contain a short clip of a file randomly chosen from the folder located at TECHNO_DRUM_FOLDER.

Let’s take a closer look at the code block that makes this happen and break it down into steps.

for measure in range(1,11):
	randomFile = selectRandomFile(HIP_HOP_SCRATCH_FOLDER)
	fitMedia(randomFile, 3, measure, measure + .5)

for is an example of a loop. A loop is a way to repeat a particular piece of code as long as particular conditions are met. In this case, the loop is being controlled by an index variable called measure within a certain range of values. The range is being defined by the range() function, where passing it (1,11) can be read as “the measures between 1 and 11, ending on (but excluding) the eleventhth measure”. So, this loop is telling Reaper “for each iteration of the loop, execute the code below.”

There are two important terms to know when talking about the range function: inclusive and exclusive. The first number in the range is inclusive, meaning that it is included within set of numbers being counted. The second number in the range function is exclusive, meaning that it is NOT included within the set of numbers being counted. We can now see that range(1,11), as shown in the above example, includes all of the numbers from 1 to 11, including one, and excluding 11. So, range(1,11) means 1, 2, 3, 4, 5, 6, 7, 8, 9, 10.

randomFile is a simple variable that is being assigned the output from a new function selectRandomFile(). selectRandomFile() is straightforward: it takes a folder of music samples (also referred to by a constant, like the files themselves) and chooses one sample at random. During each loop, the function is called again, overwriting the previous contents of the randomFile variable. This means that every time through the loop produces a new random sample (although, because it’s random, there is a small chance that the new sample will not be different from the previous one!).

Another important thing to note here is that this script uses fitMedia() to place all of the samples in this example. There are two reasons for this. One is to show that different ways of implementing code can have the same effect. Another reason is to make inserting different sounds into this script simpler: because fitMedia() will automatically scale a sample to fit a particular space, there’s no reason to worry about measures not aligning properly. This is particularly useful when making a remix, because you can plan musical sections based on the length you want them to be without having to think about the length of the samples you’re using!

Randomness and Python

It’s possible to use python’s own random functions in EarSketch projects. To call them in a manageable way, it’s helpful to add a new import in the setup section of your script :

from random import *

This allows us to easily access the standard Python random() functions. We can use this to set up variables to randomly affect the length of the clip being inserted by insertMediaSection(), as well as where the clip is being placed.

Here’s an example as to how one could use random functions in an EarSketch script:

# randInt(a, b) returns a random integer between a and b

# here, our clip will be positioned randomly within the measure
startBeat = randint(1,4)

# in this case, our clip will be between one half and 1 measure long
beatLength = randint(2,4)

Questions and Exercises

  1. Make a project that's at least 12 measures long, uses randomness, and has both an A and a B section.

Answers to Questions and Exercises

Click here to see answers

Questions and Exercises #1:

  1. setup section, music section, and finish section
  2. Comments let text exist in a program that will not be executed as code. Comments should be used because they can help improve code clarity, which allows other people and your future self to better understand your code.
  3. In the music section

Questions and Exercises #2:

    b and c are constants
  1. The bold constants in example #2 should have been changed to new constants that you enjoy, for example:
    # Add a music file to track 1 (Lead)    
    insertMedia(DRUM_N_BASS_MASTER_1, 1)
    
    # Add a music file to track 2 (Drums)
    insertMedia(DRUM_N_BASS_DRUM_1, 2)
    							
  2. There are many possible ways to edit your music section to accomplish this. One solution might look like this:
    # Add a music file to track 1 (Lead)    
    insertMedia(DRUM_N_BASS_MASTER_1, 1)
    
    # Add a music file to track 2 (Drums)
    insertMedia(DRUM_N_BASS_DRUM_1, 2)
    
    #Add a music file to track 3 (Bass)
    insertMedia(HIP_HOP_BASS10_2M, 3)
    							

Questions and Exercises #3

  1. There are no incorrect solutions to this problem, as long as the script runs.
  2. There are many possible solutions to the question.

Questions and Exercises #4

There are many possible solutions to this problem. Here is an example of a correct solution:

'''
Day 1 Sample Project 5
Example project with randomness
'''
from earsketch import *
from random import *

# initialize Reaper
init()
setTempo(120)

# Create an A section just like usual     
fitMedia(DRUM_AND_BASS_MASTERBASS1_4M, 1, 1, 5)      #Lead
fitMedia(DRUM_N_BASS_DRUMS2_1M, 2, 1, 5)        #Drums

# fit a 2 measure B section between measures 5 and 7
fitMedia(DRUM_N_BASS_DRUMS3_1M, 1, 5, 7)      #Drums breakout

# Then back to section A at measure 7    
fitMedia(DRUM_AND_BASS_MASTERBASS1_4M, 1, 7, 11)     #Lead
fitMedia(DRUM_N_BASS_DRUMS2_1M, 2, 7, 11)       #Drums

# Add random extra scratch sounds
for measure in range(1,11):
    # start on beat 1, 2, or 3 of the measure
    startBeat = randint(1,3)
    # play from start of loop through to beat 2 or 3
    beatLength = randint(2,3)
    randomFile = selectRandomFile(HIP_HOP_SCRATCH_FOLDER)
    fitMedia(randomFile, 3, (measure, startBeat, 0), (measure, beatLength))

# Set the project cursor to be at the beginning of the file
finish()