-
-
Notifications
You must be signed in to change notification settings - Fork 22
Home
Welcome to the lick wiki!
LiCK, a Library for ChucK, was born out of frequent requests on the chuck-users mailing list to have a shared repository for various bits of reusable ChucK code.
LiCK includes:
- int, float, and Object Lists
- Functor objects, see e.g. http://c2.com/cgi/wiki?FunctorObject
- Interpolation/tween/easing functors
- Composite procedures for building loops
- Intervals, Chords, Scales, Arpeggiators, Patterns, Sequences, Sequencers
- Sample-based drum machine emulators
- HID device classes (keyboard, mouse, joystick, etc.)
- MIDI device classes (Alesis QX25, MAudio Ozone, MeeBlip, NanoPad, etc.)
- MIDI support for iOS apps (Animoog, EchoPad, GarageBand, Filtatron, Loopy, etc.)
- OSC support for desktop apps (IanniX, SooperLooper, etc.)
- LeapMotion, Monome, ControlOSC, TouchOSC integration
- Mono and stereo Delays, FeedbackMachines
- WaveShaper chugen, Distortion and Tremolo chugens
- Module, Module2, …, Module8; chuck a Ugen into a parameter (cv)
- PitShift-based pitch follower, harmonizers, and effects
- Chugin wrappers, including C*APS, CMT, TAP, SWH, and RubberBand LADSPA plugins
- “ChucK-Unit”, an Assert class for creating unit tests
LiCK requires:
- chuck-1.3.3.0 (chimera) or later, http://chuck.cs.princeton.edu
LiCK optional dependencies:
- Joel Matthys’ Fork of CCRMA ChuGins, https://github.com/jwmatthys/chugins
- the C* Audio Plugin Suite, http://quitte.de/dsp/caps.html
- TAP-plugins, http://tap-plugins.sourceforge.net/index.html
- Computer Music Toolkit (CMT), http://www.ladspa.org/cmt
- The SWH Plugins package for the LADSPA plugin system, http://plugin.org.uk
- Rubber Band Library, http://breakfastquay.com/rubberband
To install and use LiCK in your own ChucK scripts, use the import.ck script
$ chuck --loop &
$ chuck + import.ck
...
"LiCK imported." : (string)
$ chuck + my-script.ck
If you don’t want to include all of LiCK, use Machine.add(file name) to include individual LiCK source files. Do be careful to include the LiCK source files of dependencies as well.
Machine.add("FloatFunction.ck");
Machine.add("Interpolation.ck");
Machine.add("ExponentialOut.ck");
Hopefully, a future version of ChucK will support a proper include and namespace mechanism, simplifying the use of external libraries like LiCK.
LiCK is welcome to any contributions! Don’t worry too much about style or formatting, that can all be worked out later.
Please add the license header (HEADER.txt) to the top of each file and provide an author statement if you wish.
If you add classes to LiCK, be sure to update import.ck with the new classes and their dependencies in the correct order. If you have unit tests for those classes, be sure to update tests.ck with the new unit tests.
Examples should go in the examples directory.
ChucK doesn’t provide interfaces or explicit abstract classes, so LiCK uses empty or no-op classes to represent those concepts. For example, List.ck really aught to be an interface that ArrayList.ck and LinkedList.ck would implement. In LiCK, List.ck is a class with empty or no-op implementations of all its methods which are then overridden by ArrayList.ck.
There are a lot of small classes in LiCK, by design. Simplified access to all these small classes is provided by static methods (e.g. Loops.ck provides static methods that create and return instances of Loop.ck or Repeat.ck).
For those more comfortable with Smalltalk, C#, or Java-style collections than arrays, LiCK provides int, float, and Object Lists.
Lists are created and sized in manner similar to that of ChucK arrays
// create a new object list
ArrayList list;
// initially the size of the list is zero
Assert.assertTrue(0, list.size());
Assert.assertTrue(list.isEmpty());
// pass an argument to the size method to resize the array
list.size(16);
Assert.assertTrue(16, list.size());
Assert.assertFalse(list.isEmpty());
list.clear();
Assert.assertTrue(0, list.size());
Assert.assertTrue(list.isEmpty());
// or add elements to the list to resize it dynamically
Object foo;
list.add(foo);
Assert.assertTrue(1, list.size());
Assert.assertFalse(list.isEmpty());
Indexed access is provided via get and set methods
ArrayList list;
Object foo;
Object bar;
Object baz;
list.set(0, foo);
list.set(1, bar);
list.set(2, baz);
Assert.assertEquals(foo, list.get(0));
Assert.assertEquals(bar, list.get(1));
Assert.assertEquals(baz, list.get(2));
All the elements in a list can be accessed using a for loop over the indices
for (0 => int i; i < list.size(); i++)
{
list.get(i) @=> Object value;
Assert.assertNotNull(value);
}
an Iterator
list.iterator() @=> Iterator iterator;
while (iterator.hasNext())
{
iterator.next() @=> Object value;
Assert.assertNotNull(value);
}
or an internal iterator via any of the forEach methods
class AssertNotNull extends UnaryProcedure
{
fun void run(Object value)
{
Assert.assertNotNull(value);
}
}
AssertNotNull assertNotNull;
list.forEach(assertNotNull);
Int and float list implementations also provide similar behaviour.
IntArrayList intList;
intList.add(42);
intList.set(1, -42);
Assert.assertEquals(42, intList.get(0));
Assert.assertEquals(-42, intList.get(1));
FloatArrayList floatList;
floatList.size(16);
floatList.assign(3.14);
floatList.iterator() @=> Iterator iterator;
while (iterator.hasNext())
{
iterator.next() => float value;
Assert.assertEquals(3.14, value, 0.001);
}
LiCK provides a suite of Functor classes 1, objects that act as functions or procedures. Functor objects can be passed to methods, as shown above in the ArrayList.forEach(UnaryProcedure) example.
A procedure accepts argument(s)
class Write extends UnaryProcedure
{
fun void run(Object value)
{
<<<value>>>;
}
}
A function accepts argument(s) and returns a value
class Multiply extends FloatFloatFunction
{
fun float evaluate(float value0, float value1)
{
return value0 * value1;
}
}
A predicate accepts argument(s) and returns a boolean value
class AllPositive extends IntIntIntPredicate
{
fun int test(int value0, int value1, int value2)
{
return (value > 0) && (value1 > 0) && (value2 > 0);
}
}
A supplier returns a value
class Answer extends IntSupplier
{
fun int evaluate()
{
return 42;
}
}
Functor classes are provided for int, float, and Object arguments, in varying number of arguments. For Object functors, the prefix indicates the number of arguments, i.e. Unary is 1 argument, Binary is 2 arguments, Ternary is 3 arguments, Quaternary is 4 arguments. Thus a QuaternaryFunction accepts 4 Object arguments and returns an Object value.
Similarly, for int and float functors, the number of prefix repeats is the number of arguments, e.g. an IntIntIntIntFunction accepts four int arguments and returns an int value.
For convenience, all of the functions in Math are implemented as functors
// functors can be evaluated against scalar values
Log10 log10;
log10.evaluate(3.14) => float result;
// ...however, they really show their utility when you can pass them to a method
ArrayList list;
list.size(16);
list.assign(3.14);
list.transform(log10); // log10 is used to transform all the values in list
Interpolating functions.
Composite procedures.
LiCK provides classes that trigger samples for various vintage drum machines, such as the Oberheim DMX (OberheimDmx.ck) and the Roland TR-909 (RolandTr909.ck). To use these classes, find or record samples of each instrument and copy them to the paths in the source code, or alternatively edit the paths in the source code to match your samples directory.
For example, the samples directory layout for the Roland CR-78 defaults to
samples/RolandCr78/Claves.wav
samples/RolandCr78/ClosedHat.wav
samples/RolandCr78/CowBell.wav
samples/RolandCr78/Crash.wav
samples/RolandCr78/Guiro.wav
samples/RolandCr78/HighBongo.wav
samples/RolandCr78/Kick.wav
samples/RolandCr78/LowBongo.wav
samples/RolandCr78/LowConga.wav
samples/RolandCr78/Maracas.wav
samples/RolandCr78/OpenHat.wav
samples/RolandCr78/Rim.wav
samples/RolandCr78/Snare.wav
samples/RolandCr78/Tamborine.wav
Each sample is triggered by an IntProcedure that accepts a MIDI velocity value (0 .. 127) mapped to gain. The sample procedures also have rate and maxGain fields. Call these procedures directly in ChucK code
RolandCr78 cr78;
while (true)
{
cr78.kick.run(127);
400::ms => now;
cr78.snare.run(80);
400::ms => now;
}
or use a MIDI controller class, such as the nanoPAD (NanoPad.ck)
NanoPad nanoPad;
RolandCr78 cr78;
// assign sample triggers to nanoPAD buttons
cr78.kick @=> nanoPad.button1;
cr78.snare @=> nanoPad.button2;
cr78.closedHat @=> nanoPad.button3;
// open nanoPAD MIDI device 0
nanoPad.open(0);
Unit testing is a software verification, validation, and documentation method in which a programmer tests if individual units of source code are fit for use 2. LiCK provides support for unit testing via its Assert.ck class and the following implementation pattern.
ChucK doesn’t allow calling methods via reflection, so unit tests in LiCK should follow the pattern described below to be executed properly.
Each unit test should be a class which extends Assert.ck
class MyUnitTest extends Assert
{
}
Next, provide test methods that utilize assertXxx methods to make assertions about the class under test. Assertion messages are optional.
class MyUnitTest extends Assert
{
fun void testFoo()
{
assertTrue("this should be true", true);
}
fun void testBar()
{
assertFalse("this should be false", false);
}
}
Provide an pseudo-constructor method that sets exitOnFailure as desired, calls each of the testXxx methods, and prints out a message to stdout on success
class MyUnitTest extends Assert
{
{
true => exitOnFailure;
testFoo();
testBar();
<<<"MyUnitTest ok">>>;
}
fun void testFoo()
{
assertTrue("this should be true", true);
}
fun void testBar()
{
assertFalse("this should be false", false);
}
}
Finally, instantiate the unit test and allow ChucK time to pass.
class MyUnitTest extends Assert
{
{
true => exitOnFailure;
testFoo();
testBar();
<<<"MyUnitTest ok">>>;
}
fun void testFoo()
{
assertTrue("this should be true", true);
}
fun void testBar()
{
assertFalse("this should be false", false);
}
}
MyUnitTest myUnitTest;
1::second => now;
See http://www.junit.org for further documentation on assertions and unit testing in general.
For examples of actual unit tests, see e.g. [ArrayListTest.ck](https://github.com/heuermh/lick/blob/master/lick/collect/ArrayListTest.ck), [FloatArrayListTest.ck](https://github.com/heuermh/lick/blob/master/lick/collect/FloatArrayListTest.ck), or [IntArrayListTest.ck](https://github.com/heuermh/lick/blob/master/lick/collect/ArrayListTest.ck) in LiCK.