Signals, like anything else, are processed by a computer as sequences of binary digits, or bits. A bit has only two possible values, which can be interpreted as true or false, positive or negative, or most commonly as zero or one. The latter representation makes it easier to define mathematical operations on binary digits, but these are carried on a much lower level of programming than the one in which we are interested here. When we talk about processing a signal, we are usually referring to mathematical operations on higher level representations of these bits, given by integers and decimal, or floating point numbers appearing on the screen.
Numbers can be arbitrarily large, but there is a limit to what computers can actually process. This measure is given by the bit depth, which simply means how many slots of zeros or ones we have at hand to represent each number. If, for example, our bit depth is 3, it means that we can represent the integers from zero to seven. This is because there are two choices (zero or one) for the first slot, two for the second, and two for the third, in a total of 222 = 8 possible combinations of three binary digits. We could similarly represent the integers from minus four to three by taking one of the three bits in every number to represent its sign. The operation used to represent signed bits in this fashion is called two’s complement, but we shall not have to deal with binary representations of integers here.
Digital signals are not just discrete in amplitude, but also in time. If on one hand the amplitude resolution is given by the bit depth, on the other the time resolution is given by the sampling rate. The default sampling rate in Csound is 44100 herz, which means there are that many samples per second of audio per channel. We can declare the sampling rate as an orchestra statement using the ‘sr’ orchestra statement.
In the above line, we set the sampling rate to 44100 herz. However, not every event in Csound is processed at the sampling rate. Due to performance reasons, it is oftent convenient to define some variables at a somewhat slower rate. Obviously we cannot do that for our sound source, otherwise we would either lose quality, or produce artifacts, or both. But we can perfectly apply an envelope, for example, at a slower rate than the sampling rate without prejudice. We call that slower rate the control rate, and declare it as ‘kr’. Whenever that is the case, instead of applying the envelope to each sample one at a time, Csound takes small “vectors” of samples and processes them together at the control rate. So in that regard, the variables we declare at the control rate work as scalars, that is, they are applied to all samples of each vector.
Also due to performance reasons, it is best to have a signal vector size that is a highly composite number. Even though 44100 is indeed highly composite (44100 = 2^23^25^2*7^2), we get better results with powers of two. Thus we normally prefer to define the vector size directly, rather than as a rate. That is because standard sampling rates are almost never powers of two, so we would end up with a fraction as our vector size, which makes no sense. In order to define the vector size, we use the ‘ksmps’ orchestra statement.
So now we are processing 44100 samples per second, 256 samples at a time. How many times per second we do process blocks of 256 samples is what we call the control rate. Instrument 1 below illustrates the use of different signal rates by applying a simple adsr envelope to a sine wave. Before declaring instrument 1, however, we will fill a table with a sine function from within the orchestra, for demonstration purposes. Declaring a function from the orchestra works much the same way as the ‘f’ score statement, only we use the ‘ftgen’ opcode and separate arguments by comas.
Note in the above line that we have tacitly declared yet another variable speed. The name ‘gisine’ consists of a mandatory ‘g’, which stands for global, id est, a variable that is accessible to all instruments in the orchestra, by a mandatory ‘i’, which stands for instrument rate, which we will discuss in a bit, and by an arbitrary name, here ‘sine’ for natural reasons. In Csound, instrument rate variables are initialized every time we call an instrument from the score.
Instrument 1 below exemplifies the use of the three most common varible rates in Csound. The variable ‘asig’ has its values defined over the sampling rate, whereas ‘kenv’ is updated sr/ksmps times per second. Still good enough for an envelope. Finally, the variable iamp gets called once per score event. Note that the first letter of each of these variables is not optional.
News & Events
Subscribe at the bottom of the page to be informed of news as they arrive.
RunloopSound Released on the App Store
Aug 12, 2016
RunloopSound brings the world of Csound to iOS devices. With a gorgeous user interface and complete integration to all major cloud providers, RunloopSound allows you to keep designing incredible sounds wherever you go.