RTcmix for Linux: Part 1
The MINC scripting language provides both a powerful and easy-to-learn interface to RTcmix. More terminology: a MINC script is referred to as a scorefile. If you understand C, using MINC will be trivial. Some major differences are no semicolons at the end of each line and no functions (sorry). The art of using MINC (RTcmix) to make music is the primary focus of several semester-long college and graduate courses offered at several higher education institutions around the world. There's no way I can do it complete justice here. Instead, we'll take a look at some scorefiles which illustrate various features.
To execute a scorefile, simply pipe it into CMIX with stdin.
CMIX < scorefile
from the command line will fire it off. Internally, this syntax passes the scorefile to a parser (compiled by yacc/bison) which in turn passes events to a scheduler. When used in real-time performance mode (i.e., with external control sources), the RTcmix parser listens to a TCP socket, parsing data on the fly. In this instance, parser and scheduler are implemented using the linuxthreads library. The following scorefiles are included with version 3.0 of RTcmix and were designed by John Gibson.
Listing 1 illustrates a reasonably simple scorefile which uses two RTcmix instruments. There are dozens more. WAVETABLE, as the name implies, is a wavetable lookup instrument. REVERBIT, also descriptive, runs a reverberation effect on an audio stream. In this example, the output of WAVETABLE is piped into REVERBIT, then out to your audio device and/or an audio file.
Let's step through the scorefile a bit:
This command is necessary for all RTcmix scorefiles. It sets up the audio device to run in stereo at 44100hz. An optional third parameter allows you to configure the audio buffer size to reduce latency in performance (e.g., when controlling RTcmix from another application). Default is 8,192 frames.
Next we declare which “instruments” we're going to use:
As mentioned above, RTcmix supports the dynamic loading of libraries. These commands load the instruments at run-time. This allows for a smaller memory footprint than loading all the instruments simultaneously. It also allows you to write a score that uses multiple instruments.
The next few lines are commented out. Uncommenting them will allow audio to be written to a soundfile as well as the audio device. The set_option command (de)activates various RTcmix features. For example: set_option("AUDIO_OFF") will turn off writing to the audio device—useful when your scorefile forces your computer to stretch beyond its means.
In order to map the audio from one source to another, eventually to your speakers or a soundfile, we call:
bus_config("WAVETABLE", "aux 0-1 out") bus_config("REVERBIT", "aux 0-1 in", "out 0-1")
As mentioned earlier, one of RTcmix's newest features is the ability to route audio streams. In an attempt to keep tradition with established mixing convention, we've adopted a “bus” paradigm. Internal buses are labeled as “aux”, which can be read from (as “in”) or written to (as “out”). Input devices are labeled “in”, and output buses (audio devices) “out.” The convention for bus designation is: bus_type “number” [in or out for aux]. So “out 0” would be an output channel (e.g., a speaker) and “in 0” a line in or mic. This is not to be confused with “aux 0 in” which is the specification of an internal bus that is being read from by a particular instrument.
So, the statements above first route WAVETABLE's output to aux (internal bus) 0 and 1. Then REVERBIT's bus_config is set up to read from aux 0 and 1 (WAVETABLE's output) and write its output to a stereo audio device (out 0-1). It is possible to have multiple bus configurations for the same instrument. Each inherits the most recent call.
The next line in the score sets a global variable totdur. Variables are auto declared at init time (i.e., when the RTcmix parser reads your file). There are no reserved global variable names.
In order to set “control rate” update of internal synthesis parameters (e.g., amplitude envelope updates) we use the reset command. So reset(2000) updates 2,000 times every 44,100 samples—every 20.5 samples.
The following two lines are a bit less self-descriptive:
setline(0,0, 1,1, 5,0) makegen(2, 10, 10000, 1,.5,.3,.1)
As with many packages that have developed over a number of years, RTcmix has its share of legacy issues. Unit generators in Cmix are defined by the makegen statement. Makegens are used for various internal aspects of a particular instrument: an amplitude envelope, waveform for a lookup, pitch vibrato, and so forth. The setline command is a related statement, used specifically to set an amplitude envelope. The time-value pairs set an amplitude of 0 at time 0, 1 at time 1 and zero at time 5. Time in this sense is relative and will be stretched accordingly to the duration of your “note” (see below). The WAVETABLE instrument needs some kind of waveform to read in order to make sound. It stores this information in “slot 2”. Slot 1 is used for the amplitude envelope defined by the setline. Yes, you could substitute a makegen command for that setline (gen24). Gen10 specifies loading a sinusoid into the respective slot (in this case 2). The size (in samples) of the wavetable in this case is 10,000. Remaining arguments are amplitudes for successive harmonics. That's about as complicated as it gets, at least in this article.
After assigning some more global variables, we seed the random number generator with:
The actual music making is done by the following lines:
for (st = 0; st < totdur; st = st + .45) WAVETABLE(st, dur, amp, freq, random())This is a simple for loop which executes until st is greater than totdur (defined earlier). The parameters to WAVETABLE (as well as all other RTcmix functions and instruments) are referred to as p-fields. In the case of WAVETABLE:
p0 = start time
p1 = duration
p2 = digital amplitude (in this case between 0 and 32767)
p3 = frequency (in hz)
p4 = stereo spread
The last few lines of the score reset the amplitude envelope with setline(0,1, 1,1), because we want a slightly different one for our REVERBIT function, which we call with: REVERBIT(st=0, insk=0, totdur, amp, revtime, revpct, rtchandel, cf).
The p-fields for REVERBIT are:
p0 = start time
p1 = inskip, which is the time to start reading input. (Use 0 for bus_configs; some other value when reading in from a file.)
p2 = duration
p3 = amplitude multiplier (generally between 0 and 1)
p4 = reverb time
p5 = reverb percentage
p6 = right channel delay
p7 = cutoff frequency for low-pass filter (in hz)
p8 (optional) = apply DC blocking filter (boolean)
That's it. Simply type the following to execute the score:
CMIX < WAVETABLE_REVERBIT_1.scoListing 2 is a musically simpler example, but illustrates the powerful ability of RTcmix to process an incoming audio stream in real time.
To set up our audio device for simultaneous reading and writing, we use the set_option command again:
It's necessary to have this command executed before the rtsetparams call, as it sets an internal flag that rtsetparams uses when performing actual setup of the audio device. As before, we set up the device for 44K stereo, but this time decreasing the internal buffer size for real-time performance to 512 frames.
To tell RTcmix to read from the audio device, we use:
The MIC argument is necessary only in IRIX versions of RTcmix. We could just as well say:
rtinput("some_file.aiff")to read an audio file instead.
|Designing Electronics with Linux||May 22, 2013|
|Dynamic DNS—an Object Lesson in Problem Solving||May 21, 2013|
|Using Salt Stack and Vagrant for Drupal Development||May 20, 2013|
|Making Linux and Android Get Along (It's Not as Hard as It Sounds)||May 16, 2013|
|Drupal Is a Framework: Why Everyone Needs to Understand This||May 15, 2013|
|Home, My Backup Data Center||May 13, 2013|
- Designing Electronics with Linux
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Dynamic DNS—an Object Lesson in Problem Solving
- New Products
- Using Salt Stack and Vagrant for Drupal Development
- Validate an E-Mail Address with PHP, the Right Way
- Build a Skype Server for Your Home Phone System
- A Topic for Discussion - Open Source Feature-Richness?
- Why Python?
- Tech Tip: Really Simple HTTP Server with Python
- Not free anymore
1 hour 32 min ago
5 hours 19 min ago
- Reply to comment | Linux Journal
5 hours 27 min ago
- Understanding the Linux Kernel
7 hours 42 min ago
10 hours 11 min ago
- Kernel Problem
20 hours 14 min ago
- BASH script to log IPs on public web server
1 day 41 min ago
1 day 4 hours ago
- Reply to comment | Linux Journal
1 day 4 hours ago
- All the articles you talked
1 day 7 hours ago
Enter to Win an Adafruit Pi Cobbler Breakout Kit for Raspberry Pi
It's Raspberry Pi month at Linux Journal. Each week in May, Adafruit will be giving away a Pi-related prize to a lucky, randomly drawn LJ reader. Winners will be announced weekly.
Fill out the fields below to enter to win this week's prize-- a Pi Cobbler Breakout Kit for Raspberry Pi.
Congratulations to our winners so far:
- 5-8-13, Pi Starter Pack: Jack Davis
- 5-15-13, Pi Model B 512MB RAM: Patrick Dunn
- 5-21-13, Prototyping Pi Plate Kit: Philip Kirby
- Next winner announced on 5-27-13!
Free Webinar: Hadoop
How to Build an Optimal Hadoop Cluster to Store and Maintain Unlimited Amounts of Data Using Microservers
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Some of key questions to be discussed are:
- What is the “typical” Hadoop cluster and what should be installed on the different machine types?
- Why should you consider the typical workload patterns when making your hardware decisions?
- Are all microservers created equal for Hadoop deployments?
- How do I plan for expansion if I require more compute, memory, storage or networking?