K509 • Week 3

RTcmix: more about pitch, and sound file input

This week we'll look at instruments that take audio — say from sound files — as input, as well as a few additional synthetic instruments. See the rest of the tutorial for explanation.

Your assignment is to read the rest of the tutorial, while running and changing the "tut" scores, as before. Then write at least two scores that take audio input, using instruments such as STEREO, REVMIX, TRANS and COMBIT. Find some way to vary the "inskip" for the input sound file during a loop. Write your result to an output sound file. Be ready to play and discuss your scores in class during week four.



One of the more confusing things we encountered last week was the business of pitch computation and dynamic pitch changes (while an instrument plays a note — e.g., glissando). Here's some more detail about that.

RTcmix supports several different pitch representations: octave-point-pitch-class (oct.pc or pch), frequency in Hz (cps), linear octaves (oct), letter names and MIDI note numbers. Instruments expect pitch to be specified in a particular way, using one or two of the representations above. For example, WAVETABLE understands pch or cps; TRANS understands only pch. No instrument understands letter names or MIDI note numbers, so these must be converted to another form prior to calling the instrument. There are many pitch conversion functions that do this: cpspch, pchcps, octcps, pchmidi, pchlet, etc.

The tutorial explains the hazard of doing arithmetic — specifically subtraction — on oct.pc: subtracting a major second (.02) from 8.01 gives 7.99, a very high pitch in oct.pc, instead of 7.11. The pchadd function is the safe way to perform arithmetic on oct.pc values: pchadd(8.01, -.02) gives the right answer.

If it weren't for the pchadd function, we would need to use the pitch representation known as "linear octaves" ("oct"). But even with pchadd, it's still useful to understand how linear octaves work. As with oct.pc, a linear octave is a decimal number that has the octave number to the left of the decimal point. But to the right of the decimal point is a fraction of the intervallic distance between the given octave number and the octave above. For example, 8.00 is middle C, and 8.5 is halfway between middle C and the C above — so it's an F#. Because linear octaves use the first two numbers after the decimal point as 10ths and 100ths of an octave — rather than as a representation of semitones — you can perform arithmetic safely using this pitch format. Unfortunately, linear octaves aren't as easy for us to translate at sight into familiar pitch names. We can see that 8.07 is 7 semitones above middle C, but its linear octave equivalent, 8.58333, looks more obscure.

To get pitch into and out of linear octave format, use pitch conversion functions, such as octpch and pchoct. Without pchadd, you would need to convert oct.pc to linear octaves, do the arithmetic, and then convert the result back to oct.pc. (This is exactly what pchadd does internally.)

	linoct1 = octpch(8.01)
	linoct2 = octpch(0.02)
	pitch = pchoct(linoct1 - linoct2)
	// pitch is now 7.11 in oct.pc

Unfortunately, the conversion functions cited above cannot help us when we use a table — or other source of changing values (e.g., MIDI, OSC, random or LFO streams) — to specify dynamic pitch changes in oct.pc. The conversion functions operate on a single value, instead of a list or stream of values. Instead, we use a different function, makeconverter.

	// gliss table with values expressed in linear octaves (gliss down a M2)
	gliss = maketable("line", "nonorm", 1000, 0,0, 1,octpch(-.02))

	// initial pitch in linear octave format
	init_pitch = octpch(8.01)

	// do the arithmetic in linear octaves, adding gliss to constant pitch
	pitch_linoct = init_pitch + gliss
	
	// convert resulting stream of linear octave values to oct.pc for instrument
	pitch = makeconverter(pitch_linoct, "pchoct")

	WAVETABLE(start, dur, amp, pitch, pan)
The makeconverter function is a kind of filter that takes a stream of values in one format and converts them to a stream of values in another format. All of the single-value conversion functions (e.g., cpspch, ampdb, etc.) have makeconverter analogs.

A simpler solution to the gliss problem above would be to work only with frequency in Hz, but then it's harder to make a glissando that moves evenly across a specific musical interval.

There is a whole system of control-stream processing — operations on streams of data, such as tables, random and low-frequency oscillators — that work on the model illustrated above for makeconverter. For example, you can take real-time MIDI input, scale that to a range of linear octave values, add offsets from a random number generator, convert to oct.pc, and pass the resulting stream of pitch data to a single WAVETABLE note.


-John Gibson