ChucK/sequencer.ck

From CSWiki
Revision as of 19:27, 11 March 2006 by Ssalazar (talk | contribs)

Jump to: navigation, search

Fairly simple sequencer. To use, first add sequencer.ck to you virtual machine. Then, from add any ChucK program, make the following function call:

sequencer.sequence( filename, beats_per_measure, volume_vector );

where filename is a string containing the path to the sample you want to play, beats_per_measure is the number beats that sample will play during each measure, and volume_vector is a vector of floats in the range [0, 1] used to determine the volume of each beat. This function call will not return, so you will have to use a separate source file for each call. Once sporking member functions works, you could also do that.

Each beat is equally spaced. Additionally, the volume vector can be larger or greater than the number of beats per measure, if desired; it is cycled through independently of the measure. For example, with a beats_per_measure of 4 and a volume vector of [1.0, 0.0], you will get 4 beats per measure, with the first and third beats having a volume of 1.0, and the second and fourth beats having a volume of 0.0. You'll notice that this lets programmers easily experiment with interesting polyrhythms, by deliberately misaligning the beats per measure and volume vectors for a given sequence, and across different sequences.

Additionally, if a volume of 0 is specified, the sample is simply not played, instead of being played at a volume of 0. In this way,

You can change the measure length using the following function call:

sequencer.change_measure_length( new_measure_length );

You should use this function rather than setting it directly, because setting it directly will probably cause currently running sequences to become misaligned.

sequencer.ck:

// sequencer.ck
// sequencer class for sequencing arbitrary samples 
// author: spencer salazar
// Feel free to use/modify/distribute as you see fit.  

public class sequencer
{
	static float measure_length;
	static Event new_measure;
	static int on;
	
	fun static void start()
	{
		while( on )
		{
			new_measure.broadcast();
			measure_length::second => now;
		}
	}
	
	fun static void stop()
	{
		0 => on;
	}

	fun static void set_measure_length( float new_ml )
	{
		// wait until the end of the measure
		new_measure => now;
		new_ml => measure_length;
	}

	fun static void sequence( string filename, float bpmeasure, float volumev[] )
	{
		new_measure => now;
	
		sndbuf buf => gain g => dac;
		filename => buf.read;
		.5 => g.gain;

		0 => int i;
		0 => int j;

		while( on )
		{		
			for( 0 => i; i < bpmeasure; i++ )
			{
				if( volumev[j] > 0 )
				/* only play the sample if its meant to be heard */
				{
					0 => buf.pos;
					volumev[j] => buf.gain;
				}
				
				j++;
				if( j >= volumev.cap() )
					0 => j;
				(measure_length/bpmeasure)::second => now;
			}
			//new_measure => now;
		}
	}

}

Event e @=> sequencer.new_measure;
1.5 => sequencer.measure_length;
1 => sequencer.on;

sequencer.start();