This program, Timmy The Techno Generator, uses a sequencer, sampled drum sounds, and a bass voice to randomly generate a techno-type beat. The sequencer is divided into 16 beats- some beats have predefined events and some have random events. The drum sounds come from a referenced directory of sounds that comes natively with ChucK's programming environment, MiniAudicle. The bass voice was created with three oscillators, two of which are detuned unison voices, while the other is a sine sub oscillator. The pitches are randomly selected from the dorian mode which is weighted to favor certain scale degrees.I have included a sound demo of an interation of the program (with post processing added), and the code if anyone wants to peruse it.
Audio Demo
Download the .ck file to open in MiniAudicle
assignment_3_timmy_the_techno_beat_generator.ck |
// Assignment_3_Timmy_The_Techno_Beat_Generator
// 11-7-2013
/* Timmy is a program that generates two sound
components- a drum beat and a bass line.
These are synced to a sequencer that produces
both random and fixed events. Therefore, it is
best to listen to it a couple of times.
Make sure the /audio directory is in the same
folder as this file.
*/
// sound chain
Gain DrumBus => dac;
0.3 => DrumBus.gain;
// Gain is mono output, so Pan2 can't be chucked into it
// or else it'll be summed to mono
SndBuf Kick => DrumBus;
0.9 => Kick.gain;
SndBuf Snare => DrumBus;
1 => Snare.gain;
SndBuf HihatClose => Pan2 HihatClosepan => dac;
0.2 => HihatClose.gain;
-0.7 => HihatClosepan.pan;
SndBuf HihatOpen => Pan2 HihatOpenpan => dac;
SndBuf Cow => Pan2 Cowpan => dac;
0.2 => Cow.gain;
0.7 => Cowpan.pan;
SndBuf Clap => DrumBus;
SndBuf Click => Pan2 Clickpan => dac;
0.3 => Click.gain;
SndBuf2 FX => dac;
0.4 => FX.gain;
SndBuf RandomDrum => Pan2 RandomDrumpan => dac;
// Bass voice
Gain BassBus => dac;
SinOsc SubBass => BassBus;
0.8 => SubBass.gain;
TriOsc Bass => BassBus;
0.7 => Bass.gain;
// unison voice for detuning
TriOsc Bass2 => BassBus;
0.7 => Bass2.gain;
// Turn off Bass for now
0 => BassBus.gain;
// load .wav files into sound buffers
me.dir() + "/audio/kick_04.wav" => Kick.read;
me.dir() + "/audio/snare_02.wav" => Snare.read;
me.dir() + "/audio/hihat_01.wav" => HihatClose.read;
me.dir() + "/audio/hihat_04.wav" => HihatOpen.read;
me.dir() + "/audio/cowbell_01.wav" => Cow.read;
me.dir() + "/audio/clap_01.wav" => Clap.read;
me.dir() + "/audio/click_05.wav" => Click.read;
me.dir() + "/audio/stereo_fx_03.wav" => FX.read;
// define array for RandomDrum sound buffer
string RandomDrumArray[5];
me.dir() + "/audio/kick_04.wav" => RandomDrumArray[0];
me.dir() + "/audio/snare_01.wav" => RandomDrumArray[1];
me.dir() + "/audio/cowbell_01.wav" => RandomDrumArray[2];
me.dir() + "/audio/clap_01.wav" => RandomDrumArray[3];
me.dir() + "/audio/click_05.wav" => RandomDrumArray[4];
// set play position to end to silence samples
Kick.samples() => Kick.pos;
Snare.samples() => Snare.pos;
HihatClose.samples() => HihatClose.pos;
HihatOpen.samples() => HihatOpen.pos;
Cow.samples() => Cow.pos;
Clap.samples() => Clap.pos;
Click.samples() => Click.pos;
FX.samples() => FX.pos;
RandomDrum.samples() => RandomDrum.pos;
// establish timing durations
.25::second => dur quarter;
29::second + now => time later;
// define Dorian bass pitches, notes are repeated to increase probablility of selection
[38, 38, 38, 40, 41, 41, 43, 45, 45, 47, 47, 48, 48, 48, 50, 50, 50] @=> int BassNote[];
// starts music
while( now < later )
{
// Intro hihat swell
-.3 => HihatOpen.rate;
0.4 => HihatOpen.gain;
5::second => now;
1 => HihatOpen.rate;
0.2 => HihatOpen.gain;
-0.7 => HihatOpenpan.pan;
// define counter variable for structure of sequencer
0 => int counter;
while( counter < 193 )
{
// define 16 step sequence
counter % 16 => int beat;
<<< counter, beat >>>;
if( counter == 0 )
{
0 => FX.pos;
}
// randomly pick a note for the bass voice
Math.random2(0, (BassNote.cap() - 1)) => int BassNoteChoice;
// define random varibale to decide several things
Math.random2(0, 7) => int NotePlay;
// define random variable for random drum sound buffer
Math.random2(0, 4) => int RandomDrumChoice;
// and it's panning
Math.random2f(-1.0, 1.0) => float RandomPan;
// series of 16 if statements defines what will happen on each beat
if( beat == 0 )
{
0 => Kick.pos;
Std.mtof(BassNote[BassNoteChoice]) => Bass.freq;
// detuning unison voice to affect timbre but not pitch
Std.mtof(BassNote[BassNoteChoice]) + 0.2 => Bass2.freq;
// transposing sub bass down 1 octave
Std.mtof(BassNote[BassNoteChoice]) / 2 => SubBass.freq;
.35 => BassBus.gain;
// mute open hi hat
0 => HihatOpen.gain;
}
if( beat == 1 )
{
if( NotePlay < 2 )
{
.35 => BassBus.gain;
}
else
{
0 => BassBus.gain;
}
// placing the bass voice settings in different
// layers causes slight variations in the melody
// like note off vs. note change
Std.mtof(BassNote[BassNoteChoice]) => Bass.freq;
Std.mtof(BassNote[BassNoteChoice]) + 0.2 => Bass2.freq;
Std.mtof(BassNote[BassNoteChoice]) / 2 => SubBass.freq;
// sound settings for random drum sound buffer
RandomDrumArray[RandomDrumChoice] => RandomDrum.read;
RandomPan => RandomDrumpan.pan;
0.2 => RandomDrum.gain;
0 => RandomDrum.pos;
}
if( beat == 2 )
{
0 => HihatClose.pos;
if( NotePlay < 5 )
{
.35 => BassBus.gain;
}
else
{
0 => BassBus.gain;
}
Std.mtof(BassNote[BassNoteChoice]) => Bass.freq;
Std.mtof(BassNote[BassNoteChoice]) + 0.2 => Bass2.freq;
Std.mtof(BassNote[BassNoteChoice]) / 2 => SubBass.freq;
if( NotePlay < 4 )
{
0 => Cow.pos;
}
}
if( beat == 3 )
{
if( NotePlay < 4 )
{
0 => Cow.pos;
}
else
{
0 => Click.pos;
// reuse the pan variable from the RandomDrum SndBuf
RandomPan => Clickpan.pan;
}
}
if( beat == 4 )
{
0 => Kick.pos;
0 => Snare.pos;
if( NotePlay < 3 )
{
Std.mtof(BassNote[BassNoteChoice]) => Bass.freq;
Std.mtof(BassNote[BassNoteChoice]) + 0.2 => Bass2.freq;
Std.mtof(BassNote[BassNoteChoice]) / 2 => SubBass.freq;
}
}
if( beat == 5 )
{
if( NotePlay < 3 )
{
0 => Click.pos;
RandomPan => Clickpan.pan;
}
}
if( beat == 6 )
{
0 => HihatClose.pos;
if( NotePlay < 2 )
{
0 => BassBus.gain;
}
}
if( beat == 7 )
{
if( NotePlay < 6 )
{
.35 => BassBus.gain;
0 => Kick.pos;
}
else
{
0 => BassBus.gain;
}
Std.mtof(BassNote[BassNoteChoice]) => Bass.freq;
Std.mtof(BassNote[BassNoteChoice]) + 0.2 => Bass2.freq;
Std.mtof(BassNote[BassNoteChoice]) / 2 => SubBass.freq;
}
if( beat == 8 )
{
0 => Kick.pos;
Std.mtof(BassNote[BassNoteChoice]) => Bass.freq;
Std.mtof(BassNote[BassNoteChoice]) + 0.2 => Bass2.freq;
Std.mtof(BassNote[BassNoteChoice]) / 2 => SubBass.freq;
.35 => BassBus.gain;
}
if( beat == 9 )
{
if( NotePlay < 2 )
{
Std.mtof(BassNote[BassNoteChoice]) => Bass.freq;
Std.mtof(BassNote[BassNoteChoice]) + 0.2 => Bass2.freq;
Std.mtof(BassNote[BassNoteChoice]) / 2 => SubBass.freq;
.35 => BassBus.gain;
}
}
if( beat == 10 )
{
0 => HihatClose.pos;
if( NotePlay < 4 )
{
RandomDrumArray[RandomDrumChoice] => RandomDrum.read;
RandomPan => RandomDrumpan.pan;
0.3 => RandomDrum.gain;
0 => RandomDrum.pos;
}
}
if( beat == 11 )
{
if( NotePlay < 4)
{
Std.mtof(BassNote[BassNoteChoice]) => Bass.freq;
Std.mtof(BassNote[BassNoteChoice]) + 0.2 => Bass2.freq;
Std.mtof(BassNote[BassNoteChoice]) / 2 => SubBass.freq;
.35 => BassBus.gain;
}
else
{
0 => BassBus.gain;
RandomDrumArray[RandomDrumChoice] => RandomDrum.read;
RandomPan => RandomDrumpan.pan;
0.2 => RandomDrum.gain;
0 => RandomDrum.pos;
}
}
if( beat == 12 )
{
0 => Kick.pos;
0 => Snare.pos;
0 => Clap.pos;
}
if( beat == 13 )
{
if( NotePlay < 6 )
{
RandomDrumArray[RandomDrumChoice] => RandomDrum.read;
RandomPan => RandomDrumpan.pan;
0.3 => RandomDrum.gain;
0 => RandomDrum.pos;
}
if( NotePlay < 4 )
{
Std.mtof(BassNote[BassNoteChoice]) => Bass.freq;
Std.mtof(BassNote[BassNoteChoice]) + 0.2 => Bass2.freq;
Std.mtof(BassNote[BassNoteChoice]) / 2 => SubBass.freq;
.35 => BassBus.gain;
}
}
if( beat == 14 )
{
if( NotePlay < 5)
{
0 => HihatOpen.pos;
0.2 => HihatOpen.gain;
}
else
{
0 => HihatClose.pos;
}
}
if( beat == 15 )
{
0 => Kick.pos;
if( NotePlay < 3 )
{
0 => Cow.pos;
}
}
if( counter == 96 )
{
// play stereo fx half way through song
0 => FX.pos;
}
// advance sequence by 1 beat and increment counter
quarter / 2 => now;
counter++;
}
}
// Fade out bass voice at the end of the piece
.35 => float Fadegain;
for( 140 => int Fade; Fade > 0; Fade-- )
{
Fadegain => BassBus.gain;
Fadegain - .0025 => Fadegain;
10::ms => now;
}
<<< "Thanks for listening -- Timmy" >>>;