ChucK on the command line - Programming for Musicians and Digital Artists: Creating music with ChucK (2015)

Programming for Musicians and Digital Artists: Creating music with ChucK (2015)

Appendix G. ChucK on the command line

The command line is one of the oldest and most venerated computer UIs. With decades of continued development, the presence of a command-line interface within every major commercial OS is a testament to its power and versatility. ChucK’s roots are in the command line; its original release was as a command-line application. In this chapter we’ll review command-line usage of ChucK, through the chuck command.

The command line on Mac OS and Windows share enough similarities that we cover them both in this appendix. But we must first cover a few foundational aspects of command-line usage that are unique to either OS, so Windows users should feel free to skip the Mac OS–specific section (G.1), and likewise Mac OS users can pass over the Windows-specific section (G.2). Users of the miniAudicle (appendix A) can ignore all of this.

G.1. Mac OS command-line basics

The command line in Mac OS is accessed by opening the Terminal application. This can be found in the Utilities folder, which is within the Applications folder. When you first open Terminal, a window will open and display the initial shell prompt, which might look something like this:

My-Computer-Name:~ my-user-name$

My-Computer-Name and my-user-name will be whatever your respective computer name and username are. The $ indicates Terminal is ready to accept commands. Command-line prompts vary greatly, and yours might have been customized or inherited from some other user. But some form of prompt appears in Terminal, and you can enter commands followed by pressing the Return key.

Commands are usually run serially, one after another, which means once you run a command, you have to wait until it finishes before running another one. Every time a command finishes and the shell is ready for a new command, it will print the shell prompt again, indicating that it’s ready.

Try entering the chuck command. This command is installed by default by the ChucK installer, so assuming you’ve run that already, you should be ready to go. Type the word chuck (all lowercase) into the Terminal window and then hit Return. It should look something like this:

My-Computer-Name:~ my-user-name$ chuck

[chuck]: no input files... (try --help)

My-Computer-Name:~ my-user-name$

That’s not super exciting; let’s give it a program to run. We’ll use miniAudicle to create it. Open miniAudicle, and then select File > Open Example. Select otf_06.ck, and then select File > Save As and save the file to your Documents directory. This is important: make sure you save it to precisely the Documents folder and not any subfolder, because you’ll have to type in the full name later.

Now, back in Terminal, enter the chuck command again, this time telling it the file you want to run. After typing chuck, type a space and then the filename (Documents/ otf_06.ck), and then press Return:

My-Computer-Name:~ my-user-name$ chuck Documents/otf_06.ck

At this point, you should hear sound coming out—you’ve successfully run ChucK from the command line! If you don’t hear sound, then you might have saved the program to a different folder than Documents, or your Documents directory may have a different name. In either case be sure you’re entering the correct filename for the command to work!

Let’s go ahead and stop the running program with Ctrl-C: hold the Control key and then hit the C key. This is the universal shell keybinding to terminate the active command, if there is one. Once you start it, chuck will usually continue making sound for as long as you let it, so you need to kill it with Ctrl-C (don’t worry, ChucK doesn’t mind; it’s used to it). After you type Ctrl-C, the sound should stop, and you’ll see something like this in the Terminal:

^C[chuck]: cleaning up...

My-Computer-Name:~ my-user-name$

For those who are completely new to the command line, we’ll take a minute to break down what has happened. You entered the chuck command, followed by a space, followed by the name of the file you want to run. This second part, the filename, is an argument to the chuck command. Similar to how functions in ChucK code have arguments, shell commands can also have arguments. But unlike ChucK code, you can usually have as many or as few shell arguments as you want, in any order, and the command can figure it out. The only requirement is that each argument has to have a space in between it and the next one. Finally, when you’ve finished listening to the results of your chuck command, you shut it down with Ctrl-C.

With all of that in mind, let’s try an experiment. By the way, the shell prompt hereafter will be abbreviated to just $, for clarity.

$ chuck Documents/otf_06.ck Documents/otf_06.ck

Here you run the same program twice, at the same time, by giving chuck two arguments, each of which is the same file. You could run otf_06.ck six times in parallel the same way, by simply repeating the filename six times, or as many times as you want. Ctrl-C the command when you’ve finished listening. From now on, you should implicitly do this with every program you run, and we won’t explicitly tell you to for brevity’s sake.

Running the same program in parallel is fun, but you can do better. Let’s run two different example programs at the same time. Open the otf_05.ck example in mini-Audicle and save it to your Documents directory as before. But before running both programs at once, you can make your life slightly easier by entering this command:

$ cd Documents

Remember, you only type the part that comes after the shell prompt $, and then hit Return. The cd command stands for change directory, which means it puts you in the directory specified in its (single) argument. Here you’re putting your shell session into the Documents directory. We’ll talk more on that later. For now, run your next chuck command:

$ chuck otf_05.ck otf_06.ck

This should play both programs simultaneously: bass plops and high-pitched plops. Cool!

So far you’ve learned the basics of ChucK on the command line. Before we move on, let’s return to that cd command. Every shell session has a notion of a current working directory, and the cd command allows you to change it. Typically if you are dealing with files in a particular directory, you’ll want to make that the current directory so you don’t have to type long path names every time, as you did with the Documents directory. If you want to go with a directory within another directory, you can use cd multiple times to jump there, or you can type out the full path in one go, for example:

$ cd "Documents/My ChucK Programs/project1"

This will take you to the project1 directory, which is contained in the My ChucK Programs directory, which is within Documents. cd will fail if any of these directories don’t exist.

Also note that the entire path is surrounded by double quotes. On the command line, a space is almost always used to separate individual arguments. So if there are spaces within a single argument, you need a way to indicate that the space is part of the argument and not a separator between arguments. Surrounding the entire argument in double quotes is just the way. You can also use single quotes, for example, 'Documents/My ChucK Programs/project1', which accomplishes the same thing. The minor differences in how the shell interprets double quotes compared to single quotes aren’t important for our purposes.

There are two special incantations of cd that are frequently useful. cd with no arguments changes the working directory to your home directory, and cd .. (with two periods as the argument) takes you up one directory, to whatever folder encloses your current directory.

Two more commands will come in handy as you hop around the command line. ls lists the contents of the current directory, and pwd prints the full path of your current directory in case you’re unsure. For example, assuming you’re still in the Documents directory from the previous section, you’ll see this:

$ ls

otf_05.ck otf_06.ck

$ pwd

/Users/your-user-name/Documents

There are thousands more common commands available in the command line, and entire books have been written about just those. Fortunately, knowing these basic Terminal commands is enough to make your command-line ChucK sessions a lot easier to work with.

G.2. The command line on Windows

To start, open the command prompt. On Windows 7 and earlier, click the Start button > All Programs > Accessories > Command Prompt. On Windows 8, you can open a command prompt by moving the mouse to the upper-right corner, selecting Search, ensuring that Apps is the selected category, typing Command into the search box, and selecting Command Prompt from the search results.

When the command prompt opens, you should see a black window open with text that looks similar to (but probably not exactly like) this:

Microsoft Windows [Version 6.1.7601]

Copyright (c) 2009 Microsoft Corporation. All rights reserved.

C:\Users\Username>

The first two lines are system information. On the last line, the current directory is printed, followed by the > character, which is called the shell prompt. The current directory is the directory from which relative path names are interpreted, so if you type myChuckProgram.ck, it will refer to the file C:\Documents and Settings\Username \myChuckProgram.ck in this case. The shell prompt indicates that the command line is ready for you to enter commands. When we show text from the command prompt, you should enter only the part that comes after the > prompt (sometimes we may only show the command prompt, for brevity).

Start by running the chuck command, which should have been installed when you ran the ChucK installer. Type the word chuck (all lowercase) and then hit Enter. You should see the following:

C:\Users\Username>chuck

[chuck]: no input files... (try --help)

C:\Users\Username>

This isn’t very interesting—let’s try running some actual code. Open miniAudicle, select Open Example, and then choose otf_06.ck from the examples browser. Then select Save As and save the file to the current directory in the command prompt (in our case, C:\Documents and Settings\Username). Now that you have a source code file in your current directory, you can run it like so:

>chuck otf_06.ck

Here, you supply the chuck command with an argument. Similar to function arguments, command-line arguments are parameters or input data that are given to the command for processing. Here you’re passing only a single filename, but you could specify any number of filenames to run, or a command-line flag, which tells chuck how to run rather than what to run (you’ll see some concrete examples of this later).

When you run this command, you should hear the sound of reverberating sine plops; if not, you should make sure your computer volume is high enough and that there aren’t any other issues with sound output. Also, if you didn’t save the file to the correct directory, or the file’s name is something other than otf_06.ck (all lowercase), then this command probably won’t work.

The chuck command will keep running until the program finishes or until you stop it manually. otf_06.ck runs indefinitely, but you can terminate it by entering Ctrl-C into the command prompt. If you’re not familiar with this key sequence, just hold the Control key on your keyboard, then press C, and then release both keys. Ctrl-C kills whichever program is currently running on the command prompt. This may sound mean to constantly do to chuck, but starting, stopping, and restarting chuck, while editing your code in between, is the essence of command-line ChucKing.

After you terminate chuck, it should print a brief exit message and then return you to the shell prompt, indicating that the shell is ready for another command:

C:\Users\Username>chuck otf_06.ck

[chuck]: cleaning up...

C:\Users\Username>

Now enter your next command. This one runs otf_06.ck two times, in parallel:

>chuck otf_06.ck otf_06.ck

You should hear two sets of sine plops running. You could run otf_06.ck any number of times, in parallel, simply by specifying that many times to the chuck command. Ctrl-C out of chuck when finished listening. You can run two or more different programs simultaneously, simply by specifying whichever programs you want to run as arguments to chuck.

Now, let’s run two different programs. In miniAudicle, open the otf_05.ck example and save it to the same directory as you did otf_06.ck. To run them both in parallel, you need to enter only

>chuck otf_05.ck otf_06.ck

You should now hear two different programs running, one with low-pitched sine plops and the other with higher-pitched plops.

There are a few additional commands that are useful when working on the Windows command prompt. We previously discussed the notion of a current directory; this is a directory by which all relative paths are interpreted, allowing you to enter otf_06.ck instead of the full path (for example, C:\Documents and Settings\Administrator\ otf_06.ck). You can see what files are in the current directory using the dir command; dir will print out the name of every file in the current directory.

You can also change the current directory using cd. You need to provide an argument to tell cd which directory you want to change to:

C:\Users\Username>cd "My Documents"

C:\Users\Username\My Documents>cd C:\

C:\>

Your prompt moves first to the My Documents directory and then the C:\ (root) directory, and the text leading up to the shell changes to match at each step. Notice that we enclosed the entire My Documents argument in double quotes. In the command line, spaces are normally used to separate distinct arguments, but My Documents is a single argument that happens to have a space within it. To distinguish spaces within an argument and spaces separating two arguments, you must enclose any arguments with spaces in them between double-quote characters. C:\ has no spaces in it, so you don’t have to use double quotes when you pass it as an argument.

There’s one special version of cd that comes in handy often. cd .. will change to whichever directory encloses the current directory, for example:

C:\Users\Username>cd ..

C:\Users>

There are many more cool commands and functions you can use on the command line, but these should be enough to get you to the interesting stuff—on-the-fly (OTF) programming in ChucK!

G.3. On-the-fly programming

On-the-fly programming is one of the most powerful features of ChucK, and command-line chuck has all of the OTF features of miniAudicle and even a few more. All of these features existed in chuck before miniAudicle was ever created. To begin, start chuck with the --loop argument. Windows users: here we use $ to represent the shell prompt. Which character specifically isn’t important; you can just pretend it’s a >.

$ chuck --loop

--loop is a command-line option or flag. It’s a special argument that, instead of telling chuck what program to run, tells it how it should run, what mode of operation it should use, or some other parameter. In this case, --loop tells chuck to keep operating continuously, even if it has no files to run. This is step 1 to on-the-fly programming on the command line.

Next, open a new Terminal or command-prompt window. You need a new window because chuck --loop is going to monopolize the entire first window as it continuously processes the OTF commands you send to it. In the new Terminal window, cd to the directory where you previously saved the otf_05 and otf_06 examples. Now execute this command:

$ chuck + otf_05.ck otf_06.ck

Note the + argument that comes before the filenames; this tells chuck to add the files to the local VM, which is the chuck --loop instance you ran in the other window. This is more or less the same as clicking the Add Shred button in miniAudicle. You should also see in the other window a status message indicating that the shreds were added:

[chuck](VM): sporking incoming shred: 1 (otf_05.ck)...

[chuck](VM): sporking incoming shred: 2 (otf_06.ck)...

To stop these from running, instead of using Ctrl-C, go back to the second Terminal window and enter this command:

$ chuck --clear.vm

This OTF command removes all of the shreds from the local VM and clears public classes, the exact analogue of Clear VM in miniAudicle. Suppose now that you add just otf_06.ck:

$ chuck + otf_06.ck

Check the text that gets printed out in the --loop window, specifically the shred number, which is the number right before the filename (it will probably be 1 in this case, but it could be anything). This shred number will become important for later commands.

[chuck](VM): sporking incoming shred: 1 (otf_06.ck)...

Now, make some changes to otf_06.ck. For example, you could change the SinOsc to a SawOsc or change the root note (the number 69 on line 35 of the program) to a different pitch. Once you’ve finished, you can use the replace command from the command line:

$ chuck = 1 otf_06.ck

The = removes the shred with the specified ID and replaces it with the file you provide. The 1 corresponds to the shred number from earlier; if the shred number is different, you’ll want to put whatever it is instead of 1.

Finally, if you want to stop the shred entirely without replacing, the - (remove) command is available:

$ chuck - 1

Again, you’ll want to substitute 1 with whatever shred ID was printed by the VM instance when the program was first added.

There are a few more OTF programming directives that come in handy on the command line. -- invokes remove-last, removing whichever shred was most recently sporked:

$ chuck --

----------------------------------------

[chuck](VM): removing recent shred: 2 (otf_06.ck)...

The --status command causes the local VM to print out status information about running time and currently active shreds. The ^ (caret character) can also be used as shorthand for --status:

$ chuck --status

$ chuck ^

The status information is printed out in whichever window the VM is running in, looking something like this:

[chuck](VM): status (now == 0h3m40s, 9729280.0 samps) ...

[shred id]: 1 [source]: otf_05.ck [spork time]: 11.46s ago

[shred id]: 2 [source]: otf_06.ck [spork time]: 11.46s ago

As you can see, this is the command line’s version of miniAudicle’s Virtual Machine monitor. --time is similar but just prints out the running time of the VM:

$ chuck --time

----------------------------------------

[chuck](VM): the values of now:

now = 18350080.000000 (samp)

= 416.101587 (second)

= 6.935026 (minute)

= 0.115584 (hour)

= 0.004816 (day)

= 0.000688 (week)

Lastly, --kill stops the VM remotely when you want to shut the entire VM down:

$ chuck --kill

----------------------------------------

[chuck](VM): KILL received....

Ctrl-C also works to shut the VM down—just make sure you enter Ctrl-C into the window the chuck --loop command is running in.

G.4. ChucK command-line reference

This section covers options that you can use when invoking chuck from the command line. Typing and entering

$ chuck –h

will list all of the command-line options available:

chuck --[options|commands] [+-=^] [file1 [file2 [file3 [...]]]]

[options] = version|halt|loop|audio|silent|dump|nodump|server|about|probe|

channels:|out:|in:|dac:|adc:|srate:|bufsize:|bufnum:|

shell|empty|remote:|port:|verbose:|level:|blocking|callback| adaptive:|

deprecate:{stop|warn|ignore}|chugin-load:{auto|off}|chugin-

path:|chugin:|--caution-to-the-wind

[commands] = add|remove|replace|remove.all|status|time|kill|clear.vm

[+-=^] = shortcuts for add, remove, replace, status

G.4.1 Source ChucK files

ChucK can run one or more processes in parallel and interactively. The programmer only needs to specify them all on the command line, and they’ll be compiled and run in the VM. Each input source file (.ck suffix by convention) will be run as a separate shred (user-level ChucK threads) in the VM. Shreds can spork additional shreds and interact with existing shreds. Thanks to the ChucK timing mechanism, shreds don’t necessarily need to know about each other in order to be precisely shreduled in time; they only need to keep track of their own time, so to speak. Additionally, more shreds can be added/removed/replaced manually at runtime, using OTF programming.

G.4.2 Basic command-line ChucK options

· --version— Prints version information and then exits.

· --probe— Probes the system for all audio devices and MIDI devices and prints them.

· --about/--help— Prints the usage message, with the ChucK URL.

· --verbose:(N)/-v(N)— Sets the reporting level to (N), from 0–10; 0 is none, 10 is all, default is 1. Sets higher levels to see more information and warnings regarding ChucK’s internal operation.

· --halt/-t (Default)— Tells the VM to halt and exit if there are no more shreds in the VM.

· --loop/-l— Tells the ChucK VM to continue executing even if there are no shreds currently in the VM. This is useful because shreds can be added later on the fly. It’s legal to specify this option without any input files, for example: $ chuck --loop will infinite time-loop the VM, waiting for incoming shreds.

G.4.3 Audio options

· --audio/-a (Enabled by default)— Uses real-time audio output.

· --silent/-s— Disables real-time audio output. Computations in the VM aren’t changed, except that the actual timing is no longer clocked in real time and there’s no live sound output. Timing manipulations (such as operations on now) still function fully. This is useful for synthesizing audio to disk or network. Also, it’s handy for running a non-audio program.

· --srate:(N)— Sets the internal sample rate to (N) Hz. By default, ChucK runs at 44100 Hz on OS X and Windows and 48000 Hz on Linux. Even if the VM is running in --silent mode, the sample rate is still used by some unit generators to compute audio, which is important for computing samples and writing to a file. Not all sample rates are supported by all devices!

· --bufsize:(N)— Sets the internal audio buffer size to (N) sample frames. Larger buffer size often reduces audio artifacts due to system/program timing. Smaller buffers reduce audio latency. The default is 512. If (N) is not a power of 2, the next power of 2 larger than (N) is used. For example, $ chuck --bufsize:950 sets the buffer size to 1024.

· --adaptive:(N) (For power users. Default: 0)— Enables adaptive block processing with a block size of (N). This option can greatly speed up your ChucK programs, but feedback loops in your UGen graph won’t work unless they’re delayed by (N) or more samples. As with --bufsize, (N) must be a power of 2 or is rounded to the next larger power of 2. The adaptive block size should generally not be larger than the bufsize.

· --dac:(N)— Opens audio output device #(N) for real-time audio. By default, (N) is 0.

· --adc:(N)— Opens audio input device #(N) for real-time audio input. By default, (N) is 0.

· --channels:(N)/-c(N)— Opens (N) number of input and output channels on the audio device. By default, (N) is 2.

· --in:(N)/-i(N)— Opens (N) number of input channels on the audio device. By default (N) is 2.

· --out:(N)/-o(N)— Opens (N) number of output channels on the audio device. By default (N) is 2.

G.4.4 Network options

· --remote:(hostname)/-@hostname)— Sets the hostname to connect to if accompanied by the OTF programming commands. (hostname) can be the name or IP address of the host. The default value is 127.0.0.1 (localhost).

· --port:(N)/-p(N)— Sets the port to use for sending or receiving OTF programming commands.

G.4.5 ChuGin options

· --chugin-load:{auto|off} (Default: auto)— Indicates whether to automatically load ChuGins (auto) or disable ChuGin loading entirely (off).

· --chugin-path:(path)/-G(path)— Adds (path) to the list of paths searched for ChuGin to load. Any .ck files in the ChuGin path are also loaded and executed when chuck is run. By default, on Mac OS X the paths consist of /usr/lib/chuck and /Library/Application Support/ChucK/ChuGins. On Windows the only default path is C:\Program Files\ChucK\chugins. On Linux, the only path in the default list is /usr/lib/chuck.

· --chugin:(path)/-g(path)— Loads the ChuGin at file (path). This may be used to specify additional ChuGins to load that are not in the ChuGin path discussed previously.

G.4.6 Advanced options

· --deprecate:{stop|warn|ignore} (Default: warn)— Indicates how to handle deprecated classes, UGens, and functions. Stop will cause a program to not compile if it uses any deprecated features. Warn will issue a warning. Ignore will cause the program to compile normally without complaint. For example, $ chuck --deprecate:stop file.ck will cause chuck to stop compilation if file.ck uses any deprecated features.

· --dump/+d— Dumps the virtual instructions emitted to stderr, for all the files after this flag on the command line, until a nodump is encountered (see next option). For example, $ chuck foo.ck +d bar.ck will dump the virtual ChucK instructions for bar.ck (only), with argument values, to stderr. --dump can be used in conjunction with --nodump to selectively dump files.

· --nodump/-d (Default state)— Ceases the dumping of virtual instructions for files that come after this flag on the command line, until a dump is encountered (see previous option). For example, $ chuck +d foo.ck -d bar.ck +d doo.ck will dump foo.ck, then doo.ck, but not bar.ck.

These options are useful for debugging ChucK itself and for other entertainment purposes:

· --callback— Utilizes a callback for buffering (default).

· --blocking— Utilizes blocking audio I/O (advanced usage, necessary for some audio interfaces).

· --caution-to-the-wind— Warning: do not use unless you absolutely positively know what you’re doing! Enables the Std.system function in the ChucK standard library. An attacker can potentially use this function to run arbitrary malicious software on your computer.

· --shell (Advanced usage)— Enables ChucK shell mode. ChucK shell is a shell environment for live coding and OTF programming in ChucK. For more information, see Salazar et al., “miniAudicle and ChucK Shell: New Interfaces for ChucK Development and Performance,” inProceedings of the International Computer Music Conference, 2006. http://soundlab.cs.princeton.edu/publications/miniAudicle_icmc2006.pdf.

· --empty— Used in conjunction with --shell. Disables creation of a VM environment in the ChucK shell instance to allow for connecting to a remote VM.