ckv tutorial

Have you installed ckv yet?

Installing ckv is the most complicated part, and only really tested on OS X (though I've tested it a little bit on Linux). I'm really sorry about this. Thankfully, you only have to do it once! I'm working on making this easier.

  1. Download and compile Lua. On OS X, that's make macosx && make install. On Linux, make linux && make install.
  2. Download and compile ffmpeg with ./configure && make && make install.
  3. Download and compile ckv with make. If you are on Linux, edit Makefile to say PLATFORM=LINUX at the top instead of PLATFORM=OSX.

Try ./ckv -h in the ckv/ directory. Does it work?

If you have any trouble, hop on our mailing list (instructions for this are on the home page) and ask for help.

Hello? Am I there?

Type this into a file called 1.ckv. I'm doing this in the ckv directory.

connect(mic, Delay(3 * second), speaker);

Run it with ./ckv 1.ckv. Then turn up your speakers and your microphone and start making noise! This should amuse you for at least 4 minutes. Then try changing the 3 in the code to something else. Once you've started playing with that number, you're good for at least another 7 minutes of entertainment.

Go ahead and play; I'll wait. When you're done, press Ctrl+C to quit.

This is a good time to learn about audio feedback. If you're not wearing headphones and run that script for a long time, you'll start hearing screeching noises that get louder and louder. Watch out for that. It happens when your speakers play back sounds more loudly than they were originally and your microphone picks them up. When your microphone hears the sound coming out of the speakers, it plays the sound back again, but even louder. So sounds keep getting louder and louder until your brain explodes and you can't hear anything any more.


Unit Generators (“ugen” for short) are things that use sound, create sound, or both. mic is a ugen that represents your computer's microphone. The sound it makes is whatever your microphone picks up. speaker is a ugen that represents your computer's speakers. Sounds you put into it come out of your speakers. Delay() is a ugen too.

To plug one ugen into another, use connect. It's an important command because you won't hear anything that you don't plug into speaker. However many ugens you give it, connect will connect them left to right. In the example, mic is connected to a Delay, and that Delay is connected to speaker.

What you should have heard when you ran the example was the computer playing back every sound you made 3 seconds later. That's because what Delay does is delay sounds. It's like mailing the sound to yourself 3 seconds in the future.

Delay() creates a new Delay ugen. Every time you write Delay() you get a new one, and you can have as many as you want. ckv only uses one set of speakers at a time, so just “speaker” is the same every time. (Notice it's lowercase and doesn't end in ()?)

What do you think this code does?

connect(mic, Delay(3 * second),
             Delay(3 * second), speaker);

Click here to see the answer. You can figure it out by running it, though.

It does the same as the first example, except with a 6-second delay instead of 3 seconds. The first Delay delays for 3 seconds, and the second delays for another 3 seconds.

The Most Annoying Example

Create a file 2.ckv and put this code into it.

noisemaker = Noise();
connect(noisemaker, speaker);
yield(3 * seconds);
disconnect(noisemaker, speaker);
print("Enough of that!");

You can hear it by running ./ckv 2.ckv and quit with Ctrl+C. This one will only make sound for a few seconds, but by changing the number around you can make it longer or shorter.


This example shows how to give ugens names. Noise() creates a Noise ugen, which we name noisemaker. A Noise outputs random numbers as fast as it can, which to us sounds like noise.

The noise plays for only 3 seconds because after we yield for 3 * seconds, we disconnect noisemaker from speaker.

print is an easy and useful command. It just prints stuff to the screen. To print more than one thing at a time, separate them with commas. Try this:

name = "Stella";
print("WELCOME", "TO", "CKV", "!!!");
print("NICE TO MEET YOU,", name);

Mic Check, 1, 2

Save this code as 3.ckv, then run it with ./ckv 3.ckv.

volume = Follower();
connect(mic, volume, blackhole);

while yield(0.01 * seconds) do
  print(string.rep(",", volume.last * 50))

Turn on your mic and start making noise (you, not the computer)! This script is silent, but prints a bunch of commas to your console. Scary, right?

As before, press Ctrl+C to quit.


volume, our Follower, outputs big numbers when the ugens you plug into it are loud, and low numbers when they're soft. So “volume” tells us about how loud mic is.

blackhole is a ugen that lets you plug whatever you want into it, but doesn't make any sound. It is useful because it sucks sound in. If nothing sucks sound out of a ugen, then it won't make any sound at all. It is like a gumball machine with no gravity to pull the gumballs out. We've been using speaker to suck sound out of ugens, but blackhole is just as good; you just can't hear it because they're no sound in space.

We connect volume to blackhole instead of speaker because even though we don't want to hear volume, we want to visualize its output in the terminal. And it will only generate output if we suck it out!

while yield(0.01 * seconds) do ... end is just a way of making stuff happen every 0.01 seconds. We use it to repeat the print() command every 0.01 seconds.

You use string.rep to repeat text over and over. For example, print(string.rep("BANG", 5)) makes it look like somebody fired a gun five times, printing BANGBANGBANGBANGBANG. We want a script that prints more ","s when we're louder, so we use string.rep to repeat the comma volume.last * 50 times. Since volume outputs numbers between 0 and 1, multiplying by 50 means that we'll see between 0 and 50 commas on every line of output.

Your Computer, a $2,000 Drum

So scrolling commas are pretty cool, I have to admit. But a script that doesn't make any sound?? That's just a waste. Let's fix that.

You know the drill: this time it's 4.ckv, which you run with ./ckv 4.ckv.

volume = Follower();
connect(mic, volume, blackhole);

wavey = SinOsc();
connect(wavey, speaker);

while yield(0.01 * seconds) do
  print(string.rep(",", volume.last * 50))
  wavey.freq = 200 + volume.last * 600;

If you can't hear anything, turn up the volume and make sure your speaker's on! This script turns your microphone into a percussive instrument! Tap it with your finger and see.


The only difference between this example and the last one is that this time we have a SinOsc ugen named wavey. A SinOsc makes sound at a particular frequency, which you can change. Frequencies range from 50 (probably lower than you can sing, maybe even so low your computer can't play it), to 500 (a note somewhere near the middle of a piano), to 5000 (annoyingly high, definitely higher than you can sing), and higher! A SinOsc will make sounds up to about 20,000. After that, it's so high that your computer will start making weird noises and will hurt your ears.

You can experiment with frequency by changing the number in this script:

connect(SinOsc(440), speaker)

You can play multiple frequencies at once by connecting multiple SinOscs to speaker.

connect(SinOsc(440), speaker)
connect(SinOsc(560), speaker)

Anyway, back to the main example. After printing out the commas, we change wavey's frequency based on the volume of the sound being picked up by your microphone. 200 + volume.last * 600 takes the current volume (a number between 0 and 1), multiplies it by 600, then adds 200. So the frequency will range between 200 (when you're not making any sound) to 800 (when you're being really loud). If you tap your microphone, wavey's frequency will quickly go to 800, then come back down to 200 after you stop making noise. Play along with some music!

Can you make the frequency go down when you tap the microphone instead of up? You only need to change the second-to-last line. Click here for the answer.

Change the second-to-last line from this:

wavey.freq = 200 + volume.last * 600;

to this:

wavey.freq = 800 - volume.last * 600;

Hot Tunes for Cool Users

iTunes, Windows Media Player, and Rhythmbox. What do they have in common? Answer: playing music in any of those isn't nearly as cool as playing it in ckv.

Time for 5.ckv.

connector = PassThru();
volume = Follower();

play("cool_runnings.mp3", connector);
connect(connector, volume, blackhole);
connect(connector, speaker);

while yield(0.01 * seconds) do
  print(string.rep(",", volume.last * 50))

Whoa there, before you run this one you oughta know that this example ain't no copy-paste job. There's some work you have to do first.

To start, you need to copy a music file to the ckv/ directory (next to your 5.ckv file). It can be nearly any format, but MP3 will definitely work. If you don't have a music file handy, you can use this short audio file. Once it's there, replace "cool_runnings.mp3" in the script with the name of the file.

Then you can run it with ./ckv 5.ckv.


PassThru is a ugen that lets audio plug into it pass right through. That sounds useless, but a PassThru is very handy as a splitter cable or mixer. If you connect many ugens to a PassThru, you can connect the PassThru to as many other ugens as you want and it will be as if you had plugged all of them in individually.

When you call SndIn:play, the second argument you give it is the ugen which to play through. If you don't specify (you only provide one argument, the filename), then it defaults to speaker. We pass a PassThru here so that we can plug the SndIn into both volume and speaker.


By now, you should understand unit generators, how to connect them, how to play with time, and print text to the screen. There's a lot more to learn, but I haven't written about it yet!

For inspiration and more code examples, check out the language and unit generator reference to see what cool noises you can make. Also, check out the code in the README, or in the example scripts that come with ckv's source code, like ex/01.ckv, and ex/02.ckv.

Good luck!