Granular Synthesis
Due Monday, March 13, 2023 by 11:59PM Eastern
(NOTE: This due date is the Monday after Spring Break. Although this gives 3 weeks for this project from its posting date, it is designed to be completed within 2 weeks like prior projects. If you work on this in the two weeks leading to Spring Break, you should be able to enjoy Spring Break without any homework from this class. So please start early!)
Peer Grading Due: Monday March 20, 2023 by 11:59PM Eastern
IMPORTANT HANDIN NOTE: We are asking students to include a .wav for each section of part1( ), part2( ), part3( ), and part4( ) in their submission. This is to make the peer grading process easier for everyone (and to avoid safety issues in running other students’ code directly).
Granular synthesis is an extremely versatile technique to create sounds closely associated with the world of electronic and computer music.
In this project, you will experiment with some of the possibilities by creating 4 directed examples and a short but open-ended composition.
We will introduce two techniques: Grains from sound files, and synthesized grains.
Grains from Sound Files
- The file
p4.zip
contains everything you need to get started. You might begin by loadingproj4base.sal
file, which should process the includedsample.wav
. See the.sal
code for documentation on how it works. As is,proj4base.sal
usesfile-grain
to produce individual grains andmake-granulate-score
to make a Nyquist score consisting of many grains. - Copy
proj4base.sal
toproj4.sal
, which you will hand in. - Find some sounds of your own choosing to granulate. Often, non-music sources are the most interesting. Sometimes, music works well if it is highly stretched (see below). Use a mono (1-channel) sound file as input. If you have a stereo file, convert it to mono before you continue.
- Try it out: Modify
proj4.sal
to granulate your sound. Note how the code referencessample.wav
as"./sample.wav"
. The"./"
means “in the current directory”; otherwise, Nyquist will look in the default sound file directory, so be sure to use the"./"
prefix to reference your sound file, and put your sound file in the same directory asproj4.sal
. - Edit your sound to have a length of at most 10s (that’s all you need, and it will conserve our server disk space).
Part 1 – Simple Granular Stretch
- In
proj4.sal
define the functionpart1()
that will produce a granular synthesis sound (taking grains from your chosen sound file) with the following parameters:- Grain duration = 100ms
- Grain IOI = 50ms
- Total resulting sound duration = (approximately) 3s
- Stretch factor = 3 (thus the grains are taken from a roughly 1s interval of the sound file, which is “stretched” by a factor of 3 to produce about 3s of sound).
- Do not change the playback speed of grains and include all the grains in the sound (density is 1.0).
- The use of randomization of the file time of each grain is optional. You can use the default randomness value of 1s (from
proj4base.sal
‘smake-granulate-score
function, but you might also like to hear a less scrambled time-stretch effect by setting randomness to 0.
- When you are finished,
play part1()
should play about 3s of sound. Store this sound wave in part1.wav.
Part 2 – Pitch Shifted Grains by Changing Sample Rates
- Changing Pitch: Rather than playing the grains back at the original speed, grain pitch can be changed by resampling them so that they play faster or slower. Recall that sounds are immutable, so how do you play a sound faster or slower? Answer: the
sound
behavior makes a sound stretchable and shiftable. Grain is already in an environment with a stretch factor and the stretch factor has already been applied to compute grain, so if we just wrotesound(grain)
orsound(grain) ~ 1.5
, the current environment stretch factor would be applied again – not good. Instead, we use “absolute stretch” (~~
) to replace the stretch factor in the environment with an absolute value while evaluatingstretch()
. The result is that the grain is resampled to make it longer or shorter, depending on the value of the stretch factor. Find the expression(sound(grain) ~~ (1.0 / speed)
in the functionfile-grain
to see how this works in the code. - In
proj4.sal
modifymake-granulate-score
to accept aspeed:
keyword parameter (default value 1) that passes thespeed
value through the score to calls onfile-grain
so that you can control the pitch shifting of grains. - In
proj4.sal
define the functionpart2()
that will produce a granular synthesis sound (taking grains from your chosen sound file) with the following parameters:- Grains are transposed up by one octave (a factor of 2)
- [The remaining parameters are the same as in Part 1.]
- Grain duration = 100ms
- Grain IOI = 50ms
- Total resulting sound duration = (approximately) 3s
- Stretch factor = 3 (thus the grains are taken from a roughly 1s interval of the sound file, which is “stretched” by a factor of 3 to produce about 3s of sound).
- Include all the grains in the sound (density is 1.0).
- The use of randomization of the file time of each grain is optional. You can use the default randomness value of 1s (from
proj4base.sal
‘smake-granulate-score
function, but you might also like to hear a less scrambled time-stretch effect by setting randomness to 0.
- When you are finished,
play part2()
should play about 3s of sound. The sound should of course be an octave higher (but the same duration) as in Part 1. Store this sound wave in part2.wav.
Part 3 – Lower Density, Sparse Grains
- Rather than playing all the grains, creating a dense overlapped texture, you can randomly drop grains to produce a sparser texture. The
make-granulate-score
function includes adensity
parameter that gives the probability (from 0 to 1) of appending any given grain to the score as it is constructed. - In
proj4.sal
define the functionpart3()
that will produce a granular synthesis sound (taking grains from your chosen sound file) with the following parameters:- Density is 10% (0.1)
- [Note that many of the remaining parameters are also different from Parts 1 and 2.]
- Grain duration = 20ms
- Grain IOI = 10ms
- Total resulting sound duration = (approximately) 3s
- Stretch factor = 0.3 (thus the grains are taken from a roughly 10s interval of the sound file, which is “stretched” by a factor of 0.3 to produce about 3s of sound). If the sound you chose to granulate is shorter than 10s, then adjust the parameters to granulate all of your sound and produce about 3s of output.
- The use of randomization of the file time of each grain is optional.
- When you are finished,
play part3()
should play about 3s of sound. The sound should be about the original pitch of your sound file, but the sound should be stuttering or pulsing irregularly with short grains of sound. Store this sound wave in part3.wav.
- When you are finished,
Part 4 – Synthesized Grains
- Rather than pulling grains from a sound file, you can synthesize grains. It is common to use simple techniques such as sine tones, table-lookup oscillators or FM, and granular synthesis gives many additional parameters including grain density, grain duration, pitch distributions, etc.
- In
proj4.sal
, modifymake-granulate-score
to accept another parameter to select synthesized grains. E.g. you can add a boolean parametersinegrain
(default #f) to enable callingsine-grain
instead offile-grain
. Alternatively, you could provide the name of the grain function to use in a parameter tomake-granulate-score
, e.g.grainfunc
(defaultquote(file-grain)
). - In addition, the grains in the score generated by
make-granulate-score
should be different when synthesized grains are selected. The functionsine-grain
is already (partially) implemented, and has two keyword parameters:low
andhigh
. Inmake-granulate-score
, you can put these parameters into the score, or you can just use the default values. - You will need to complete the implementation of
sine-grain
to randomly choose the pitch to synthesize, based on the keyword parameterslow
andhigh
. - In
proj4.sal
define the functionpart4()
that will produce a granular synthesis sound using synthesized grains with the following parameters (which are otherwise the same as Part 1):- Grain duration = 100ms
- Grain IOI = 50ms
- Total resulting sound duration = (approximately) 3s
- When you are finished,
play part4()
should play about 3s of sound. The sound should consist of clean, rapid, bubbly sinusoidal sounds with a diversity random pitches. Store this sound wave in part4.wav. - Notice how different this sounds from Part 1, even thought the grain parameters are about the same and only the content of the short (100ms) grains is different.
At this point, since you have modified proj4.sal
for each part of the project, you should go back and test part1()
, part2()
, part3()
and part4()
to make sure they all still work as expected. Merely loading proj4.sal
should not play sounds automatically.
Composition With Granular Synthesis
Copy your proj4.sal
file to proj4comp.sal
so that you do not “break” anything in Parts 1-4.
Using all the tools that you have built, create a 20- to 40-second composition. In your piece, you should at least include:
- Substantial use of granular synthesis, with
- Dynamic amplitude, and
- Dynamic pitch control
You may wish to alter your code further to incorporate amplitude and pitch control. Pattern generators (see Chapter 5) are an excellent way to get some control over variations in parameters. You should also experiment with other parameters. In fact, ALL parameters should be considered fair game for experimentation. Shorter and longer grains have a very different sound. Very high stretch factors, very small ioi, and other changes can be very interesting, so please spend some time to find amazing sounds.
You are also free to make many granular synthesis sounds and mix them in Nyquist or in an audio editor such as Audacity.
Create the plain text file proj4comp.txt to explain:
- how you vary the amplitude and pitch.
- Also include any additional effects that you added.
- Lastly include your motivation or inspiration behind your composition.
Grading Criteria
Grading will be based on meeting the technical specifications of the assignment:
- the code should work, it should be readable, and it should have well-chosen parameters that indicate you understand what all the parameters mean.
- be sure to define
part1
,part2
,part3
andpart4
functions in yourproj4.sal
. - loading your
proj4.sal
code should not immediately compute sounds.
- be sure to define
- submissions are anonymous.
- It’s best to envision what you want to do, write it down in comments, then implement your design. You can use the sample code, but should show understanding of what you are doing — make this your own creation.
- Your composition should be 20 to 40 seconds long.
- the use of granular synthesis should be clearly audible and clearly related to the sound that you analyzed.
- Your piece should show musical results, effective granular synthesis, mixing quality, and general effort. Bonus points may also be awarded for exceptional work.
Turning In Your Work
Please hand in a zip file containing the following anonymous files (in the top level, not inside an extra directory). Note that the following must be strictly adhered to for the convenience of machine and human graders (including you as a peer grader):
- Code for parts 1-4, named
proj4.sal
- Code created for your composition, named
proj4comp.sal
, Note: Code should be clearly commented in case we want to run it. - 4 Sound Files (.wavs), one each for parts1-4 named part1.wav, part2.wav, part3.wav, and part4.wav
- Your composition audio, named
proj4comp.wav
(or.aiff
). - Input sound for parts 1-4, named whatever you want, but it should be the filename assumed in parts 1, 2 and 3 so that
part1()
,part2()
andpart3()
will run. - A text file containing a statement about your composition (be sure to include the 3 points mentioned above), named
proj4comp.txt
- Please DO NOT include or submit
sample.wav
fromp4.zip
! It should not be needed to run your code, and we do not need another copy from every student, thank you.