Difference between revisions of "220a-spring-2021/hw2"

From CCRMA Wiki
Jump to: navigation, search
Line 17: Line 17:
 
Experiment with envelope parameters (attack/decay and sustain level) to create a shorter (staccato) "percussive" sound
 
Experiment with envelope parameters (attack/decay and sustain level) to create a shorter (staccato) "percussive" sound
 
Experiment with envelope parameters (attack/decay and sustain level) to create a longer (legato) sound (e.g., a swell)
 
Experiment with envelope parameters (attack/decay and sustain level) to create a longer (legato) sound (e.g., a swell)
(1a-voice.ck) Turn in your ChucK code that plays the shorter sound followed by the longer sound.
+
(1a-voice.ck) Turn in ChucK code that plays the shorter sound followed by the longer sound.
  
 
* 1b. Create a control function: “playNote()”
 
* 1b. Create a control function: “playNote()”
Using this sample code below, create a chuck function that takes 3 input arguments that control the sound created in 1a; parameters include the oscillator frequency, the velocity (amplitude), the duration of the note. Play 3 different kinds of sounds by calling this function with different inputs.
+
Using this sample code below, add a ChucK function that takes 3 input arguments that control the sound created in 1a; parameters include the oscillator frequency, the velocity (amplitude), the duration of the note; free feel to further modify this function to your liking (e.g., do you also want to control the filter cutoff frequency with each note?).  Play 4 different kinds of sounds by calling this function with different inputs.
 
  <nowiki>// play a note (assumes "osc" and "e" are globals)
 
  <nowiki>// play a note (assumes "osc" and "e" are globals)
 
fun void playNote( float pitch, float velocity, dur T )
 
fun void playNote( float pitch, float velocity, dur T )
Line 38: Line 38:
 
}</nowiki>
 
}</nowiki>
  
(1b-function-notes.ck) Turn in chuck code including the definition of your function and a section that repeatedly calls your function.
+
(1b-play.ck) Turn in chuck code including the definition of your function and a section that repeatedly calls your function.
  
 
* 1c. Make it polyphonic
 
* 1c. Make it polyphonic
Convert your single oscillator in to an array of 4 oscillators
+
Convert your single oscillator into an array of 4 oscillators
It is recommended to use a for-loop to connect the oscillator instances to the rest of the signal path (including filters, envelopes, and dac)
+
Consider using a for-loop to connect the oscillators to the rest of the signal path (including filters, envelopes, and dac)
In the same oscillator initialization loop, set each oscillator to a different frequency according to a chord.
+
In the same oscillator initialization loop, set each oscillator to a different frequency of a chord of your choosing
  
Here is some starter code for experimenting with chords
+
(1c-chord.ck) Turn in chuck code that uses all the above to play a single chord of your choosing.
 +
 
 +
By the way, here is some starter code for experimenting with chords:
  
 
  // chord root in MIDI note number; 60 is Middle C
 
  // chord root in MIDI note number; 60 is Middle C
Line 59: Line 61:
 
  }
 
  }
  
(1c-chord.ck) Turn in chuck code that uses all the above to play a single chord of your choosing.
+
* 1d. Design a new function "playChord()" -- like 1b but to play an entire chord instead of single note.
 
+
How would your playChord() look?  What parameters should it accept? (e.g., root of the chord and intervals?)
* 1d. Make another control function (like 1b) but to play entire chords instead of single notes.
+
However you design the function's interface, the function should set the respective frequencies on your oscillators, and sound the chord.
Give the control function one extra input to set the root of the chord
+
(1d-chords.ck) Use the above function to play a sequence of four different chords of your choosing.  Additionally, vary at least one other musical element from chord to chord (e.g., relative loudness, duration).
Calculate new frequency values based on new root and set corresponding oscillator frequencies
+
As an additional challenge, you may also modify the control function to select between multiple types of chords.  
+
(1d-chords.ck) Turn in chuck code that uses all the above to play a sequence of four different chords of your choosing (either the same type of chord transposed to different roots or multiple types of chords)Vary at least one other musical element (e.g., timing or loudness).
+
  
* 1e. Make 2 or 3 changes to fine-tune your instrument, to your liking, such as:  
+
* 1e. Make 2 or 3 changes to further fine-tune your instrument to your liking.  Possible modifications include:
 
Change the oscillator type to something you haven’t used before
 
Change the oscillator type to something you haven’t used before
 
Modulate the filter cutoff independently (by spork ~ a concurrent function), perhaps sweeping it using Math.sin()
 
Modulate the filter cutoff independently (by spork ~ a concurrent function), perhaps sweeping it using Math.sin()
 
Re-tune the chord(s) using floating point (rather than integer) MIDI note numbers
 
Re-tune the chord(s) using floating point (rather than integer) MIDI note numbers
 
Add reverb (NRev, PCRev, JRev), a delay w/ feedback, or another effect
 
Add reverb (NRev, PCRev, JRev), a delay w/ feedback, or another effect
(1e-more.ck) A more-to-your-liking version of 1d-chords.ck incorporating the fine-tunings you've made (feel free to use your original chord sequence or cha ge it up)
+
Or something else
 +
(1e-more.ck) A more-to-your-liking version of 1d-chords.ck incorporating the fine-tunings you've made (use your original chord sequence or feel free to change it up)
  
* 1f. (1f-chord-statement.ck) Craft a mini musical statement (30-45 seconds) by calling your control function multiple times across time, with different input parameters.
+
* 1f. (1f-chord-stmt.ck) Craft a mini musical statement (30-45 seconds) by calling your control function multiple times across time, with different input parameters. Feel free to experiment; how might you make it sound more "musical" to your ears?
  
 
'''Part 2: spork, shred, and seas of sound'''
 
'''Part 2: spork, shred, and seas of sound'''
In part 1, we constructed and then controlled sounds with many oscillators in the main thread of ChucK. Alternatively, we could write functions that create new UGens to play “their own” sounds when sporked, and call them several times simultaneously to get polyphony.  
+
In the previous Part, we constructed and then controlled sounds with several oscillators in the main thread of ChucK. Alternatively, we could write functions that create new UGens "on-the-fly" to play dynamically when sporked; these functions can be called repeated to layer the sounds in order to create polyphony (a mixture of several simultaneous voices).
 
+
* 2a. Write a function sound()that makes a sound
+
* 2a. Write a function makeSound() that makes a sound, encapsulating all the UGens and variables it would need
This function can play a single sound using any combination of oscillators, filters, and envelopes.  
+
This function can use any combination of oscillators, filters, and envelopes; you'll need to develop a clear idea of what UGens you need to create "locally" inside the function for each sound -- and what UGens are "globally" shared. Call this function (using spork) from your main while loop.  
Call this function (using spork) before your main while loop.  
+
 
Note: this could be as simple as wrapping the code you wrote in part 1a in its own function.
 
Note: this could be as simple as wrapping the code you wrote in part 1a in its own function.
 +
 +
Feel free to start from the code and modify:
 +
 +
<nowiki> // globally shared ugens
 +
NRev reverb => dac;
 +
.1 => reverb.mix;
 +
 +
// function
 +
fun void makeSound()
 +
{
 +
    // "local" ugens
 +
    TriOsc s;
 +
    // connect to global ugens outside the function
 +
    s => reverb;
 +
   
 +
    // randomize frequency
 +
    Math.random2f(30,1000) => s.freq;
 +
    // randomize duration
 +
    Math.random2f(50,150)::ms => now;
 +
}
 +
 +
while( true )
 +
{
 +
    // go!
 +
    spork ~ makeSound();
 +
    // randomize wait until next one
 +
    Math.random2f(100,400)::ms => now;
 +
}</nowiki>
  
 
* 2b. Parameterize the sound  
 
* 2b. Parameterize the sound  

Revision as of 22:11, 16 April 2021

Homework #2: Block-Rockin' Synths

a hand-drawn sketch of a unsettling scene of music synthesis

Due Date

  • milestone: 2021.4.21 (in-class) Wednesday
  • final: 2021.4.26, 11:59pm, Monday
  • in-class listening: 2021.4.28, Wednesday


Instructions

Part 1: Crafting a sound

  • 1a. Create a pitched sound using an oscillator, a filter, and an envelope

Oscillator: choose among TriOsc, SawOsc, or SqrOsc (as discussed in class, the SinOsc is not amenable for filtering because sine waves have no overtones; the filter cannot change the "timbre" of the SinOsc) Filter: hook up your oscillator to a LPF (low pass filter) ugen and experiment with setting the filter's cutoff frequency (using the .freq parameter) (again, a LPF will have a more noticeable effect on signals rich in frequencies (e.g., SqrOsc), compared to, say, a sine wave). Next, use an ADSR to envelope the signal coming out of the LPF. (see adsr.ck) Experiment with envelope parameters (attack/decay and sustain level) to create a shorter (staccato) "percussive" sound Experiment with envelope parameters (attack/decay and sustain level) to create a longer (legato) sound (e.g., a swell) (1a-voice.ck) Turn in ChucK code that plays the shorter sound followed by the longer sound.

  • 1b. Create a control function: “playNote()”

Using this sample code below, add a ChucK function that takes 3 input arguments that control the sound created in 1a; parameters include the oscillator frequency, the velocity (amplitude), the duration of the note; free feel to further modify this function to your liking (e.g., do you also want to control the filter cutoff frequency with each note?). Play 4 different kinds of sounds by calling this function with different inputs.

// play a note (assumes "osc" and "e" are globals)
fun void playNote( float pitch, float velocity, dur T )
{
    // set freq (osc is your oscillator)
    pitch => Std.mtof => osc.freq;
    // set velocity
    velocity => osc.gain;
    // open env (e is your envelope)
    e.keyOn();
    // A through end of S
    T-e.releaseTime() => now;
    // close env
    e.keyOff();
    // release
    e.releaseTime() => now;
}

(1b-play.ck) Turn in chuck code including the definition of your function and a section that repeatedly calls your function.

  • 1c. Make it polyphonic

Convert your single oscillator into an array of 4 oscillators Consider using a for-loop to connect the oscillators to the rest of the signal path (including filters, envelopes, and dac) In the same oscillator initialization loop, set each oscillator to a different frequency of a chord of your choosing

(1c-chord.ck) Turn in chuck code that uses all the above to play a single chord of your choosing.

By the way, here is some starter code for experimenting with chords:

// chord root in MIDI note number; 60 is Middle C
60 => int root;
// array of intervals relative to the root; this is a major seventh chord
[0,4,7,11] @=> int chord[];

// print out the MIDI note numbers and frequencies for the chord
for( int i; i < chord.size(); i++ )
{
    // print MIDI note, frequency
    <<< root+chord[i], Std.mtof(root+chord[i]) >>>;
}
  • 1d. Design a new function "playChord()" -- like 1b but to play an entire chord instead of single note.

How would your playChord() look? What parameters should it accept? (e.g., root of the chord and intervals?) However you design the function's interface, the function should set the respective frequencies on your oscillators, and sound the chord. (1d-chords.ck) Use the above function to play a sequence of four different chords of your choosing. Additionally, vary at least one other musical element from chord to chord (e.g., relative loudness, duration).

  • 1e. Make 2 or 3 changes to further fine-tune your instrument to your liking. Possible modifications include:

Change the oscillator type to something you haven’t used before Modulate the filter cutoff independently (by spork ~ a concurrent function), perhaps sweeping it using Math.sin() Re-tune the chord(s) using floating point (rather than integer) MIDI note numbers Add reverb (NRev, PCRev, JRev), a delay w/ feedback, or another effect Or something else (1e-more.ck) A more-to-your-liking version of 1d-chords.ck incorporating the fine-tunings you've made (use your original chord sequence or feel free to change it up)

  • 1f. (1f-chord-stmt.ck) Craft a mini musical statement (30-45 seconds) by calling your control function multiple times across time, with different input parameters. Feel free to experiment; how might you make it sound more "musical" to your ears?

Part 2: spork, shred, and seas of sound In the previous Part, we constructed and then controlled sounds with several oscillators in the main thread of ChucK. Alternatively, we could write functions that create new UGens "on-the-fly" to play dynamically when sporked; these functions can be called repeated to layer the sounds in order to create polyphony (a mixture of several simultaneous voices).

  • 2a. Write a function makeSound() that makes a sound, encapsulating all the UGens and variables it would need

This function can use any combination of oscillators, filters, and envelopes; you'll need to develop a clear idea of what UGens you need to create "locally" inside the function for each sound -- and what UGens are "globally" shared. Call this function (using spork) from your main while loop. Note: this could be as simple as wrapping the code you wrote in part 1a in its own function.

Feel free to start from the code and modify:

 // globally shared ugens
NRev reverb => dac;
.1 => reverb.mix;

// function
fun void makeSound()
{
    // "local" ugens
    TriOsc s;
    // connect to global ugens outside the function
    s => reverb;
    
    // randomize frequency
    Math.random2f(30,1000) => s.freq;
    // randomize duration
    Math.random2f(50,150)::ms => now;
}

while( true )
{
    // go!
    spork ~ makeSound();
    // randomize wait until next one
    Math.random2f(100,400)::ms => now;
}
  • 2b. Parameterize the sound

Give the function made in 2a a few inputs to control things like oscillator pitch, filter cutoff, and envelope times, for example:

function void sound(float freq, float velocity, dur attackDuration, dur decayDuration) {}

Call this function (using spork) before your main while loop.

  • 2c. Make the sound many times

Now, call the function (using spork) several times simultaneously (back to back without passing time) before the main while loop, something like:

spork ~ sound( 110, .5, 50::ms, 2.0::second ); spork ~ sound( 220, .5, 30::ms, 1.5::second ); spork ~ sound( 330, .5, 10::ms, 1.0::second );

Give different input parameters in each call, as in the varying numbers in the above example. Consider the sound as a whole and fine tune the input parameters of each function call to craft a wholly unique sound

  • 2d. Make a helper function to trigger your multipart sound.

Wrap all of the spork ~ sound() calls into one function, like:

function void bigSound()
{
    spork ~ sound(110, 10, 1000);
    spork ~ sound(220, 10, 1000); 
    spork ~ sound(330, 10, 1000); 
}

Call this helper function (no need to spork it) before your main while loop. You’re now calling a function that sporks another function! Your function may have 0-4 input arguments. [Note: If you spork ~ mySound(), you would need to pass time after the spork ~ sound(110...); etc. calls to make sure the sporked shreds make sound.]

  • 2e. Make another interesting sound by creating another similar function to 2d and modify the parameters to create a different sounding result, something like:

function void otherBigSound() { spork ~ sound(90, 5000, 50); spork ~ sound(92, 5005, 50); spork ~ sound(94, 5010, 50); }

  • 2f. Play with your functions and parameters to create one sparse (sparse.wav) texture and one (dense.wav) dense texture, each lasting for 10-15 seconds and then going to silence in a musically graceful way (e.g., finishing each note currently sounding). Record a wav file of each and comment on the different strategies you used to create them.

Part 3: Make a Musical Statement Create a musical statement (60-90 seconds) that calls functions from part 1 and 2. Include at least one long and one short sound from part 1, as well as a moment of sparsity and density as explored in part 2. You can think of this as a sequencer or generative music tool.

You may find the following creative prompts helpful: How can you transition between sparsity and density? Would you like it to be abrupt (perhaps to create contrast) or gradual, smooth, or imperceptible? How do textures created with short sounds differ from those with long sounds? How about layering textures of differing density? How can you vary filter parameters over time to give your sounds/textures a different feel? Think of rhythm and timing - to what degree are the time intervals between your sounds regular and predictable? Does this vary over time or for different kinds of sounds? Are some sounds “structural” and others “decorative”? Think of form - does your statement have a beginning, middle, and/or end? Is there a “story” or an idea that develops? Could it work with half the duration? What makes the listener want to know or be able to anticipate what comes next?


Deliverables

turn in all files by putting them in your 220a CCRMA webpage and submit ONLY your webpage URL to Canvas

Your webpage should include:

  • 1) your hw2 should live at https://ccrma.stanford.edu/~YOURID/220a/hw2
  • 2) ChucK (.ck) files, as applicable, for Parts 1 through 5
  • 3) sound (.wav) files, as applicable, for Parts 1 through 5
  • 4) comments and reflections as you work through the homework
  • 5) notes/title for you mursical statement (Part 5)
  • 6) submit ONLY your webpage URL to Canvas