Release Notes for 4.23 ====================== I am hoping that this will be the last release for a while, so we can integrate a number of the new ideas floating about into the code, and test it thoroughly. Much of the new code here comes from Istvan Varga, and it has not been extensively tested. This is particularly relating to the named instruments and user opcodes. As peopel are already distributing code based on these changes this release has been a little rushed. Bug Fixes --------- Dynamic loading of Unix libraries corrected Various bugs in use of LineIn for opcodes fixed wguide2 improved (argument checking) Language Changes ---------------- Negative table numbers now allowed in GENs 1, 23 and 28 Named instruments and user opcodes completely reworked. Opcode Fixes ------------ madsr failed to do anything; now seems to works as I expect gettempo now returns correct answer, or at least a consistent one. oscbnk revised soundin extensively revised, and certainly better sfont opcodes improved (see below) one change delay in Tck/Tk sliders and controls removed (Unix mainly) Seeding random numbers from the clock in rand etc is now at higher resolution in Windows and Linux (and probably other UNIX-like systems) schedule and schedwhen may take named instruments New Opcodes ----------- bqrez -- A second-order multi-mode filter (Matt Gerassimoff) schedkwhennamed -- like schedkwhen but allows named instrument at i-rate New Gens -------- None Other Changes: ------------- Realtime MIDI under Windows may now work? Extract utility corrected; as it was it did not work at all except extracting from the start of an audio file Internal changes related to XINCODE CoreAudio support in OSX allows -o dac to work. Bug remains with periods on silence or silent sections caused by no events. A new version for OSX with a GUI is available; currently it does not work with realtime audio. Known Bugs ========== The following bugs are known but not yet fixed (still!). [8 and 9 should be fixed by the mythical new parser] 6: PVOC can glitch (mail of Mon, 19 Jun 2000 00:45:23 +0200) 8. Spaces in arguments to opcodes can be ignored, giving oddities 9. Mismatched closing bracket can give crash (mail of Fri, 19 Oct 2001 19:00:56 +0100) 10.Harmon can loop infinitely. Patched for now .......using my new bug numbers....... 005: VCO uncertainties Windows GUI Changes ------------------- Dither checkbox reinstated in EXTRAS window. No idea why it got lost. ==John ff Christmas Eve 2002 ======================================================================== MANUAL ================= SoundFont2-related opcodes ifilhandle sfload "filename" sfplist ifilhandle sfilist ifilhandle sfpassign istartindex, ifilhandle ipreindex sfpreset iprog, ibank, ifilhandle, ipreindex a1, a2 sfplay ivel, inotnum, xamp, xfreq, ipreindex [, iflag, ioffset] a1 sfplaym ivel, inotnum, xamp, xfreq, ipreindex [, iflag, ioffset] a1, a2 sfinstr ivel, inotnum, xamp, xfreq, instrNum, ifilhandle [, iflag, ioffset] a1 sfinstrm ivel, inotnum, xamp, xfreq, instrNum, ifilhandle [, iflag, ioffset] a1, a2 sfplay3 ivel, inotnum, xamp, xfreq, ipreindex [, iflag, ioffset] a1 sfplay3m ivel, inotnum, xamp, xfreq, ipreindex [, iflag, ioffset] a1, a2 sfinstr3 ivel, inotnum, xamp, xfreq, instrNum, ifilhandle [, iflag, ioffset] a1 sfinstr3m ivel, inotnum, xamp, xfreq, instrNum, ifilhandle [, iflag, ioffset] DESCRIPTION Csound now supports SoundFont2 format. These opcodes allow to manage the sample-structure of SoundFont2 files. INITIALIZATION filename - name of the SoundFont2 file (complete pathname). You must use "/" to separate directories even under Windows. It must be typed within double-quotes. ifilhandle - unique number generated by sfload opcode to be used as an identifier of a SoundFont2 file, since several SoundFont2 files can be loaded and activated at the same time. istartindex - starting preset index set by the user in bulk preset assignments (see below). ipreindex - preset index iprog - program number of a bank of presets of a SoundFont2 file ibank - number of a specific bank of a SoundFont2 file ivel - velocity value inotnum - note number value iflag - flag regarding the behaviour of xfreq (see below). ioffset - playing starting offset, in samples instrNum - number of an instrument of a SoundFont2 file. PERFORMANCE xamp - amplitude correction factor xfreq - frequency value or frequency correction factor (depending by iflag, see below) SoundFont2 is a widespread standard which allow to embed banks of wavetable-based sounds into a binary file. In order to understand the usage of these opcodes, the user must know some notion about SF2 format. So a brief description of this format follows. The SoundFont2 format is made by generator and modulator objects. All current Csound opcodes regarding SF2 support generator section only, so we will only deal with the generator-related structure of SF2 format, omitting the modulators. There are several levels of generators having a hierarchical structure. The most basic kind of generator object is a sample. Samples can or can't be be looped and are associated to a MIDI note number, called base-key. When a sample is associated with a range of MIDI note numbers, with a range of velocities, with a transposition (coarse and fine tuning), with a scale tuning, and with a level scaling factor, such sample makes up a split. A set of splits, together with a name, makes up an instrument. When an instrument is associated with a key range, with a velocity range, with a level scaling factor, and with a transposition, it makes up a layer. A set of layers, together with a name, makes up a preset. Presets are normally the final sound-generating structures ready for the user. They generate sound according to the settings of their lower-level components. Here is a picture of that structure: Both sample data and structure data is embedded in the same SoundFont2 binary file. A single SF2 file can contain up to a maximum of 128 banks of 128 preset programs, for a total of 16384 presets each one. Maximum number of layers, instruments, splits and samples is not defined, and probably is only limited by the computer memory. sfload opcode loads an entire SF2 file in memory. It returns a file handle to be used by other opcodes. Several instances of sfload can placed in the header section of an orchestra, allowing to work with more-than-one SF2 files at the same time. sfplist prints a list of all presets of a previously loaded SF2 file to the console. sfilist prints a list of all instruments of a previously loaded SF2 file to the console. sfpassign assigns all presets of a previously loaded SF2 file to a sequence of progressive index numbers, to be used later with the opcodes sfplay and sfplaym. The user can enstabilish the first index number by setting startindex argument. Any number of sfpassign instances can be placed in the header section of an orchestra, each one assigning presets belonging to different SF2 files. The user must take care that preset index numbers of different SF2 files don't cross themselves. sfpreset assigns an existing preset of a previously-loaded SF2 file to an index number, to be used later with the opcodes sfplay and sfplaym. The user must previously know the program and the bank numbers of the preset in order to fill the corresponding arguments. Any number of sfpreset instances can be placed in the header section of an orchestra, each one assigning a different preset belonging to the same (or different) SF2 file to different index numbers. sfplay plays a preset generating a stereo sound. ivel argument doesn't directly affect output amplitude, but informs sfplay opcode about what sample has to be choosen in multi-sample velocity-splitted presets. inotnum argument sets the frequency of the output when iflag = 0. When iflag == 1, inotnum doesn't directly affect the frequency of the output (see below). Adjustment of amplitude can be done by varying the xamp argument, that actually is a multiplier factor. The behaviour of xfreq depends from the value of iflag argument: when iflag = 0 (or missing as this value is the default) xfreq argument is a multiplier of a the default frequency assigned by SF2 preset to the inotenum value. This can correct the default frequency (for example to obtain vibrato or some other frequency -shift effect). when iflag = 1 xfreq argument should contain the actual frequency of the output sound in cps. This allow the user to use any kind of micro-tuning based scales. However this flag is designed to work correctly only with presets tuned to the default equal temerament. Don't try to use this flag value with preset already having non-standard tunings or with drum-kit-based presets, since unespected results could occurr. Notice that both xamp and xfreq arguments can contain k-rate signals as well as a-rate signals, but the user must be sure that both arguments are filled with variables of the same rate, or sfplay will not work correctly. ioffset argument allows to start the sound from a sample different from the first one. User should be sure that its value is within the length of the specific sound played in that moment, otherwise Csound will probably crash. The user must be sure that ipreindex argument is filled with a number containing a previously assigned preset, otherwise Csound will crash. sfplaym opcode is a mono version of sfplay. It should be used with mono preset, or with the stereo presets in wich stereo output is not required, because is a bit faster than sfplay. sfinstr plays an SF2 instrument instead of a preset (an SF2 instrument is the base of a preset layer). instrnum argument contains the instrument number, and the user must be sure that such number belongs to an existent instrument of a determinate soundfont bank. Notice that both xamp and xfreq arguments can contain k-rate signals as well as a-rate signals, but, also in this case, the user must be sure that both arguments are filled with variables of the same rate, or sfinstr will not work correctly. sfinstrm plays is a mono version of sfinstr. This is the fastest opcode of the SF2 family. sfplay3, sfplay3m, sfinstr, sfinstr3m are cubic-interpolation versions of previous opcodes. Difference of sound-quality is noticeable specially in bass-frequency-transposed samples. In high-freq-transposed samples the difference is less noticeable, and I suggest to use linear-interpolation versions, because they are faster. These Csound opcodes only handle sampling structure of SF2 files, because support of modulator objects (amplitude envelopes, frequency modulation, filter envelopes and modulation) is very basic and trivial in SF2 standard; so, adding any kind of modulation or processing to the sample data is completely left to the Csound user, bypassing all restrictions forced by the SF2 standard. ------------------------------------------------------------------------ bqrez bqrez -- A second-order multi-mode filter. Description A second-order multi-mode filter. Syntax ar bqrez asig, xfco, xres [, imode] Initialization imode (optional, default=0) -- low-pass, high-pass, band-pass, band-reject, or all-pass mode: 0 = low-pass (default) 1 = high-pass 2 = band-pass 3 = band-reject 4 = all-pass Performance asig -- input signal xfco -- filter cut-off frequency in Hz. As of version 3.50, may i-,k-, or a-rate. xres -- amount of resonance. Values of 1 to 100 are typical. Resonance should be one or greater. 100 gives a 20dB gain at the cutoff frequency. bqrez is a resonant low-pass filter created using the laplace s-domain equations for low-pass, high-pass, and band-pass filters normalized to a frequency. The bi-linear transform was used which contains a frequency transform constant from s-domain to z-domain to exactly match the frequencies together. Alot of trigonometric identities where used to simplify the calculation. It is very stable across the working frequency range up to the nyquist frequency. All filter modes can be frequency modulated as well as the the resonance can also be frequency modulated. Examples Here is an example of the bqrez opcode. It uses the files bqrez.orc and bqrez.sco. Example 1. Example of the bqrez opcode borrowed from the "rezzy" opcode in Kevin Conder's manual. /* bqrez.orc */ /* Written by Matt Gerassimof from example by Kevin Conder */ ; Initialize the global variables. sr = 44100 kr = 4410 ksmps = 10 nchnls = 1 ; Instrument #1. instr 1 ; Use a nice sawtooth waveform. asig vco 32000, 220, 1 ; Vary the filter-cutoff frequency from .2 to 2 KHz. kfco line 200, p3, 200 ; Set the resonance amount to one. kres init 25 a1 bqrez asig, kfco, kres out a1 endin /* bqrez.orc */ /* bqrez.sco */ /* Written by Kevin Conder */ ; Table #1, a sine wave for the vco opcode. f 1 0 16384 10 1 ; Play Instrument #1 for three seconds. i 1 0 3 e /* bqrez.sco */ See Also biquad, moogvcf, rezzy Credits Author: Matt Gerassimoff November 2002 ======================================================================== NAMED INSTRUMENTS ----------------- As a recent addition to the orchestra syntax, instruments can be defined with string names. Such named instruments are callable from the score, and are supported by a number of opcodes. SYNTAX ------ A named instrument is declared as shown below: instr Name[, Name2[, Name3[, ...]]] [...] endin A single instrument can have any number of names, and any of these names can be used to call the instrument. Additionally, it is possible to use numbers as name, denoting a standard numbered instrument, so the following declaration is also valid: instr 100, Name1, 99, Name2, 1, 2, 3 An instrument name may consist of any number of letters, digits, and the underscore (_) character, however, the first character must not be a digit. Optionally, the instrument name may be prefixed with the '+' character (see below), for example: instr +Reverb For all instrument names, a number is automatically assigned (note: if the message level (-m) is not zero, these numbers are printed to the console during orchestra compilation), following these rules: * any unused instrument numbers are taken up in ascending order, starting from 1 * the numbers are assigned in the order of instrument name definition, so named instruments that are defined later will always have a higher number (except if the '+' modifier is used) * if the instrument name was prefixed with '+', the assigned number will be higher than that of any of the (both numbered and named) other instruments without '+'. If there are multiple '+' instruments, the numbering of these will follow the order of definition, according to the above rule. Using '+' is mainly useful for global output or effect instruments, that must be performed after the other instruments. An example for instrument numbers: instr 1, 2 endin instr Instr1 endin instr +Effect1, Instr2 endin instr 100, Instr3, +Effect2, Instr4, 5 endin In this example, the instrument numbers are assigned as follows: Instr1: 3 Effect1: 101 Instr2: 4 Instr3: 6 Effect2: 102 Instr4: 7 USING NAMED INSTRUMENTS ----------------------- Named instruments can be called by using the name in double quotes as the instrument number (note: the '+' character should be omitted). Currently (as of Csound 4.22.4), named instruments are supported by: * 'i' and 'q' score events (NOTES: 1. in score files, unmatched quotes, and spaces or other invalid characters in the strings should be avoided, otherwise (at least with current version) unpredictable behavior may occur (this problem does not exist for -L line events). However, there is checking for undefined instruments, and in such cases, the event is simply ignored with a warning. 2. Stand-alone utilities (score sort and extract) do not support named instruments. It is still possible to sort such scores by using the -t0 option of the main Csound executable) * real-time line events (-L) * event, schedkwhen, subinstr, and subinstrinit opcodes * massign, pgmassign, prealloc, and mute opcodes Additionaly, there is a new opcode (nstrnum) that returns the number of a named instrument: insno nstrnum "name" With the above example, nstrnum "Effect1" would return 101. If an instrument with the specified name does not exist, an init error occurs, and -1 is returned. EXAMPLE ------- ; ---- orchestra ---- sr = 44100 ksmps = 10 nchnls = 1 prealloc "SineWave", 20 prealloc "MIDISineWave", 20 massign 1, "MIDISineWave" gaOutSend init 0 instr +OutputInstr out gaOutSend clear gaOutSend endin instr SineWave a1 oscils p4, p5, 0 vincr gaOutSend, a1 endin instr MIDISineWave iamp veloc inote notnum icps = cpsoct(inote / 12 + 3) a1 oscils iamp * 100, icps, 0 vincr gaOutSend, a1 endin ; ---- score ---- i "SineWave" 0 2 12000 440 i "OutputInstr" 0 3 e AUTHOR ------ Istvan Varga 2002 ======================================================================== USER DEFINED OPCODES -------------------- opcode Name, outtypes, intypes [xinarg1[, xinarg2[, xinarg3[, ... ]]] xin] [setksmps iksmps] [...] [ xout xoutarg1[, xoutarg2[, xoutarg3[, ... ]]]] endop [xoutarg1[, ... ]] Name [xinarg1[, ... ]][, iksmps] DESCRIPTION ----------- The opcode and endop statements allow defining a new opcode that can be used the same way as any of the built-in Csound opcodes. These opcode blocks are very similar to instruments (and are, in fact, implemented as special instruments), but cannot be called as a normal instrument e.g. with the "i" score event. An opcode definition must precede the instrument (or other opcode) from which it is used, but it is possible to call the opcode from itself, allowing recursion of any depth that is limited only by available memory. Additionally, there is an experimental feature that allows running the opcode definition at a higher control rate than the kr value specified in the orchestra header. Similarly to instruments, the variables and labels of an opcode block are local, and cannot be accessed from the caller instrument (and the opcode cannot access variables of the caller, either). Some parameters are automatically copied at initialization, however: - all p-fields (including p1) - extra time (see also xtratim, linsegr, and related opcodes). This may affect the operation of linsegr/expsegr/linenr/envlpxr in the opcode definition. - MIDI parameters, if there are any Also, the release flag (see release opcode) is copied at performance time. Modifying the note duration in the opcode definition by assigning to p3, or using ihold, turnoff, xtratim, linsegr, or similar opcodes will also affect the caller instrument. Changes to MIDI controllers (for example with ctrlinit) will also apply to the instrument from which the opcode was called. setksmps sets the local ksmps value (see "iksmps" below). The xin and xout opcodes copy variables to and from the opcode definition, allowing communication with the calling instrument. The types of input and output variables are defined by "intypes" and "outtypes". NOTES: - xin and xout should be called only once, and xin should precede xout, otherwise an init error, and deactivation of the current instrument may occur. - these opcodes actually run only at i-time, and performance time copying is done by the user opcode call. This means that skipping xin or xout with kgoto has no effect, while skipping with igoto affects both init and performance time operation. INITIALIZATION -------------- Name - name of the opcode. It may consist of any combination of letters, digits, and underscore (_), but should not begin with a digit. If an opcode with the specified name already exists, it is redefined (a warning is printed in such cases). Some reserved words (like instr and endin) cannot be redefined. NOTE: redefinitions do not affect instruments that are defined before the new opcode. intypes - list of input types, any combination of the characters a, k, K, i, o, p, and j. A single 0 character can be used if there are no input arguments. Double quotes and delimiter characters (e.g. comma) are *not* needed. The meaning of the various types is shown in the following table: +------+-------------------+-------------------------+------------+ | Type | Description | Variable types allowed | Updated at | +------+-------------------+-------------------------+------------+ | a | a-rate variable | a-rate | a-rate | +------+-------------------+-------------------------+------------+ | k | k-rate variable | k- and i-rate, constant | k-rate | +------+-------------------+-------------------------+------------+ | K | k-rate with | k- and i-rate, constant | i- and | | | initialization | | k-rate | +------+-------------------+-------------------------+------------+ | i | i-rate variable | i-rate, constant | i-rate | +------+-------------------+-------------------------+------------+ | o | optional i-rate, | i-rate, constant | i-rate | | | defaults to zero | | | +------+-------------------+-------------------------+------------+ | p | optional i-rate, | i-rate, constant | i-rate | | | defaults to 1 | | | +------+-------------------+-------------------------+------------+ | j | optional i-rate, | i-rate, constant | i-rate | | | defaults to -1 | | | +------+-------------------+-------------------------+------------+ The maximum allowed number of input arguments is 24. Additionally to the user specified argument list, one optional i-rate input parameter is always added. This defaults to zero, and sets the local ksmps value of the opcode call (see "iksmps" below). outtypes - list of output types. The format is the same as in the case of intypes, however, the available types are slightly different: +------+-------------------+-------------------------+------------+ | Type | Description | Variable types allowed | Updated at | +------+-------------------+-------------------------+------------+ | a | a-rate variable | a-rate | a-rate | +------+-------------------+-------------------------+------------+ | k | k-rate variable | k-rate | k-rate | +------+-------------------+-------------------------+------------+ | K | k-rate with | k-rate | i- and | | | initialization | | k-rate | +------+-------------------+-------------------------+------------+ | i | i-rate variable | i-rate | i-rate | +------+-------------------+-------------------------+------------+ The maximum allowed number of output arguments is 24. iksmps - local ksmps value. Must be a positive integer, and also the ksmps of the calling instrument or opcode must be an integer multiple of this value. For example, if ksmps is 10 in the instrument from which the opcode was called, the allowed values for iksmps are 1, 2, 5, and 10. If iksmps is set to zero, the ksmps of the caller instrument or opcode is used (this is the default behavior). NOTE: local ksmps is implmented by splitting up a control period into smaller sub-kperiods, and temporarily modifying internal Csound global variables. This also requires converting the rate of k-rate input and output arguments (input variables receive the same value in all sub-kperiods, while outputs are written only in the last one). WARNING: when the local ksmps is not the same as the orchestra level ksmps value (as specified in the orchestra header), global a-rate operations must not be used in the opcode definition. These include: - any access to "ga" variables - a-rate zak opcodes (zar, zaw, etc.) - tablera and tablewa (these two opcodes may in fact work, but caution is needed) - in and out opcode family (these read from, and write to global a-rate buffers) In general, the local ksmps should be used with care, as it is an experimental feature, though it works correctly in most cases. PERFORMANCE ----------- xinarg1, xinarg2, ... - input arguments. The number and type of variables must agree with the declaration (see also the table at "intypes"). xoutarg1, xoutarg2, ... - output arguments. The number and type of variables must agree with the declaration (see also the table at "outtypes"). NOTE: the opcode call is always executed both at initialization and performance time, even if there are no a- or k-rate arguments. If there are many user opcode calls that are known to have no effect at performance time in an instrument, then it may save some CPU time to jump over groups of such opcodes with kgoto. EXAMPLES -------- /* ---- opcode_example.orc ---- */ sr = 44100 ksmps = 50 nchnls = 1 /* example opcode 1: simple oscillator */ opcode Oscillator, a, kk kamp, kcps xin ; read input parameters a1 vco2 kamp, kcps ; sawtooth oscillator xout a1 ; write output endop /* example opcode 2: lowpass filter with local ksmps */ opcode Lowpass, a, akk setksmps 1 ; need sr=kr ain, ka1, ka2 xin ; read input parameters aout init 0 ; initialize output aout = ain*ka1 + aout*ka2 ; simple tone-like filter xout aout ; write output endop /* example opcode 3: recursive call */ opcode RecursiveLowpass, a, akkpp ain, ka1, ka2, idep, icnt xin ; read input parameters if (icnt >= idep) goto skip1 ; check if max depth reached ain RecursiveLowpass ain, ka1, ka2, idep, icnt + 1 skip1: aout Lowpass ain, ka1, ka2 ; call filter xout aout ; write output endop /* example opcode 4: de-click envelope */ opcode DeClick, a, a ain xin aenv linseg 0, 0.02, 1, p3 - 0.05, 1, 0.02, 0, 0.01, 0 xout ain * aenv ; apply envelope and write output endop /* instr 1 uses the example opcodes */ instr 1 kamp = 20000 ; amplitude kcps expon 50, p3, 500 ; pitch a1 Oscillator kamp, kcps ; call oscillator kflt linseg 0.4, 1.5, 0.4, 1, 0.8, 1.5, 0.8 ; filter envelope a1 RecursiveLowpass a1, kflt, 1 - kflt, 10 ; 10th order lowpass a1 DeClick a1 out a1 endin /* ---- opcode_example.sco ---- */ i 1 0 4 e AUTHOR ------ Istvan Varga, 2002; based on code by Matt J. Ingalls ------------------------------------------------------------------------