Table Operations

In the discussion of GEN routines in the preceding section, we’ve been using a couple of table-reading opcodes, but without saying much about what they do or how to use them. The time has come to rectify that situation.

Csound has more than three dozen opcodes that can be used with tables. You can read the data from tables in order to use the data in an instrument; edit the data in a table one data item at a time while the score is playing; write new data automatically to a table while the score is playing, and read it out; copy one table to another; mix the contents of two tables; morph between tables; write table data to a file on disk; or load data from a file on disk into a table.

The first point to understand is that these opcodes all make use of previously allocated tables, which are created using GEN routines (either via f-statements in the score or using the ftgen family of opcodes). The integer that refers to the table is specified using the ifn argument in the manner shown in the prototype for the opcode. If Csound can’t find the table you’re requesting, you’ll get an error message in the Console, and nothing will happen.


image

Note Some table opcodes can switch from one table to another while operating. In the prototype for an opcode of this type (such as tableikt), the table number is specified as kfn.


Reading from Tables

The basic tools for reading data from tables are the table and tablei opcodes. We have already seen these at work in the section on GEN routines, a few pages back. They’re identical except that the latter interpolates between two adjacent values in the table when it needs to, thus producing a smoother output.

For a quick illustration of interpolation, let’s suppose that step 2 in a small table contains a value of 10, while step 3 contains a value of 15. If the index (the point in the table that is to be read by the opcode) happens to be 2.5, halfway between 2 and 3, then tablei will output a value of 12.5—halfway between 10 and 15. Given an index of 2.5, however, table will output a value of 10, because it only reads the integer part of the index.

These opcodes can run at i-time, k-rate, or a-rate. Here is the k-rate prototype for tablei:


  kres tablei kndx, ifn [, ixmode] [, ixoff] [, iwrap]

In this prototype, the output is kres. The kndx argument is the index—the point in the table that is to be read. kndx will quite often be a moving value. It may ramp up or down, for instance, or be varied randomly. ifn is the table number. The remaining three arguments are optional but useful. ixmode is a switch that tells tablei the type of value to look for in the kndx input. If ixmode is 0, kndx is interpreted as a raw number. For instance, if the table is 512 elements long and you want to read the entire table, you’ll need to sweep the kndx input from 0 to 511. However, if ixmode is set to 1, the kndx input is assumed to be normalized to a 0–1 range, so you can read the whole table by sweeping through that range. Since a phasor outputs a sweep from 0 to 1 during its cycle, an ixmode setting of 1 is convenient to use with phasor. If you need to use ixmode 0 for some reason, you’ll need to multiply the output of the phasor by the length of the table before sending it to kndx in order to read the entire contents of the table.

If you aren’t sure of the length of the table, you can get it with the tableng opcode. This could be useful if you’re selecting different tables on the fly, and they’re not all of the same length.

The easiest way to explain the other two optional parameters may be by example. Let’s return to the example given in the section “Your Own Data” a page or two back, but with a couple of minor changes:


  giPitchTable ftgen 0, 0, 8, -2, 7.00, 7.04, 7.07, 7.10, 8.00,
    8.04, 8.07, 8.10

  instr 1
  iWave ftgentmp 0, 0, 8192, 10, 4, 3, 2, 1
  kfreq init 100
  kfreqval init 8.00
  kstep init 0
  ktrig metro 8

  if ktrig == 1 then
    kfreqval table kstep, giPitchTable
    kfreq = cpspch(kfreqval)
    kstep = kstep + 1
    if kstep > 7 then
      kstep = 0
    endif
  endif

  asig oscil 0.7, kfreq, iWave
  outs asig, asig
  endin

If you play this instrument for a few seconds, you’ll hear it stepping rapidly through an ascending arpeggio. (I’ve moved the table up into the orchestra header, because in the next section we’ll be writing data to it.)

The ixoff argument is an offset. It tells the opcode where in the table you want to start reading. If you replace the call to table with the following line, you’ll hear the difference:


  kfreqval table kstep, giPitchTable, 0, 4

The argument to ixmode is the default (0), so that won’t change anything. We have to specify it, because we’re going to pass a non-default value of 4 to ixoff. At this point, the table will be read starting at index 4, so we’ll hear the upper half of the arpeggio. And when we hit the end of the table, the output will “pin.” You’ll hear the B-flat sustain for a bit before the cycle starts over, again starting from index 4 in the table. Essentially, ixoff adds its value to the kndx input. We’re sending kndx integers from 0 to 7, but table is translating these into a series of integers from 4 to 11. There’s nothing past table position 7, so table keeps outputting that value in response to an index of 8, 9, 10, or 11. This may not be what you want musically.

To remedy the situation, we’ll use the other optional argument, iwrap:


  kfreqval table kstep, giPitchTable, 0, 4, 1

Now the table will start being read at index 4, as before, but when the index (as adjusted by ixoff) goes up to and past 8, table will wrap around, starting over at index 0. Now we’ll hear steps 4, 5, 6, and 7 followed by steps 0, 1, 2, and 3. The cycle will then repeat.

Other opcodes also read from tables. We’ve been using oscil, which reads from a table, for many of the examples of this book. oscil doesn’t have to play a sine wave; it will happily read data of almost any kind from a table. Its more specialized cousins include oscil1 and osciln.

oscil1 reads through a table exactly once, at k-rate. Its start can be delayed and its duration (the amount of time it takes to read the table) specified. When it reaches the end of the table, it “pins” at the last value in the table and stays there. It’s useful for attack transients; you could use it instead of using a linseg or other envelope generator, and get similar results. osciln is somewhat like oscil1, but it operates at a-rate, making it a good choice for playing back sampled (digitally recorded) attack transients. It can also loop a sample several times and then stop.

Writing to Tables

For writing new data to small tables by specifying one value at a time, the tablew opcode should be used. After copying the example from the previous section into your .csd file, add this new instrument:


  instr 2
  ktrig metro 2
  krand init 0
  kval1 init 0
  kval2 init 0

  if ktrig == 0 kgoto done
  krand random 0, 10
  if krand < 5 kgoto done

  ; select the data in two randomly chosen steps:
  krand1 random 0, 7
  krand1 = int(krand1)
  kval1 table krand1, giPitchTable
  krand2 random 0, 7
  krand2 = int(krand2)
  kval2 table krand2, giPitchTable

  ; swap the data:
  tablew kval1, krand2, giPitchTable
  tablew kval2, krand1, giPitchTable

  done:
  endin

To hear the result, play both instruments 1 and 2 at the same time from the score:


  i1 0 10
  i2 0 10

The new instrument chooses two steps in the giPitchTable at random and copies the values from those steps into the internal variables kval1 and kval2. It then swaps them, writing each into the table, using tablew, at the index of the other. When you play the score, you should hear the arpeggio as before, but it will mutate gradually as values in the table are swapped. For more variety, you may want to seed the random number generator in the orchestra header:


  seed 0

This instrument uses a random number to decide whether to do a swap operation; you can make swaps more likely by adjusting if krand < 5 to test for some other number. It uses the kgoto syntax to skip the swapping if the test fails. For more on kgoto, see “Logic and Flow Control” in Chapter 6.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.151.220