Columns
Features Internals Departments |
Csound Program FlowNotes by rasmus ekman, Feb 1999 (reviewed April 2000) Somebody wanted to know the main program structure of
Csound. If you're going to add new ugens you will not
need to look at this section, instead see the manual
entry Adding New Modules to Csound. This
is a brief overview of the orch/score parsers, and the
program flow during a Csound run; a list of the functions
that are called and in which files they reside. It may be
of use to programmers who need to get into the parser or
event management mechanisms, and need a map of where to
begin looking. CONTENTSOVERVIEWThe last few lines of main( ) calls otran( ) (in Otran.c) and musmon( ) (in Musmon.c). otran( ) is top of orchestra parsing; musmon( ) does the score playing or "performance" part. PREPARATIONSParsing session optionsmain( ) calls readOptions( ) (in one_file.c) to read the .csoundrc file. Input file parsing: the scoreInput file parsing: the orchestraInstrument templatesThe text of each instr...endin block in the orch file is stored in an INSTRTXT struct. This begins with the equivalent of an OPTXT, followed by some info about the instrument (mostly things relevant for memory allocation: number of labels, max number of opcode arguments etc). The instruments are stored in numerical order in a list. The list is accessible throughout performance either by index to an array of pointers: INSTRTXT *instrtxtp[ ]; or as a linked list via INSTRTXT instxtanchor. (The instrtxtp array will contain null pointers for each instr in range 0 through to maxinsno which has not been defined. There used to be a hardcoded maximum number of instruments (200), but this has recently been made dynamic). The INSTRTXT struct of an instr is used as a template from which each new instrument instance is created as required by score (or other) events. (Note that INSTRTXT pointers are typecast to OPTXT structs as deemed convenient.) Opcodes in instr templatesThe OPTXT-equiv part of the INSTRTXT holds a chain of TEXT structs. Each TEXT struct holds the arguments for one opcode in the instrument. As they are encountered by the parser (otran( )), orchestra variable names (eg garvb, kamp etc) and pointers to their values are stored in four lists:
The ARGLST and ARGOFFS in/out lists in the TEXT struct of an opcode contains pointers to the names and the values of opcode arguments in these lists. (The lists are declared locally in Otran.c, some relevant structs and constants are in Oload.h.) So, all arguments to an opcode are stored as pointers to the actual constant or variable value in the appropriate list, and their names are also kept around throughout performance. This is set up in insprep( ) (in Otran.c), which is called from otran( ) after reading the orchestra. (See also the support functions lgbuild( ), plgndx( ) etc in Otran.c.) Preparing for the performancemusmon( ) then calls playevents( ) (in Musmon.c), which does the actual performance. PERFORMANCEplayevents( ) collects several kinds of input: MIDI (file or live input) events, score events from the sorted .sco file, or score events started in realtime by various means. The user arguments of each event is passed around in an EVTBLK struct. playevents( ) switches on the score event type (i, f, s, t etc) to determine action. Most event types except i- (instr) and f-statements (ftables) are handled locally. playevents( ) also counts up the k-rate clock kcounter, and calls kperf( ) (in Insert.c). kperf( ) goes through the k-rate opcode list of each active instrument in the playlist (see below), and makes the actual calls to the k- and a-rate opcode functions used by each instrument. It returns to playevents( ) for each event scheduled from score (instrument turnon, ftable generation, or instrument turnoff). It may also return early if a "realtime" event is detected (this includes MIDI input or MIDI file events, and live text input through a named pipe). Initialization of instr eventsplayevents( ) starts instrument events by calling insert( ) (in Insert.c), passing the EVTBLK for the concrete event. This function creates or reuses or ties instruments. To get a new instrument performance copy it calls instance( ) (in Oload.c) to allocate memory for opcodes, get ftables etc. In instance( ) the requested instrument template (INSTRTXT struct) is used to init an (INSDS struct. The INSDS struct has one OPDS struct chain ("thread") for i-time opcodes, and one for k-rate (a-rate opcodes are of course called at k-rate). It also has pointers for the lists in which it can appear: The list of all allocated instrument instances in performance, and the list of currently active instr instances. insert( ) then calls all the i-time opcodes with the user arguments in the concrete EVTBLK to init the instrument for performance. If there are five events of instr 7, it will thus exist in five (simultaneous or sequentially used) copies throughout the performance. If copies are sequentially used, the instrument data space may be taken over by a later instr copy. Score event inputOther events
This exposition could go on and on, but...re, 25 Feb 1999 (reviewed April 2000)
|
Structs from CS.HOPDS - in Cs.hThis struct holds the info for one opcode in a concrete instrument instance in performance. typedef struct opds { struct opds * nxti; /* Next opcode in init-time chain */ struct opds * nxtp; /* Next opcode in perf-time chain */ SUBR iopadr; /* Initialization (i-time) function pointer */ SUBR opadr; /* Perf-time (k- or a-rate) function pointer */ OPTXT *optext; /* Orch file template part for this opcode */ INSDS *insdshead; /* Owner instrument instance data structure */ } OPDS; EVTBLK - in Cs.hThis struct holds the data for one score event. typedef struct event { char *strarg; /* Original argument list string of event */ char opcod; /* Event type */ short pcnt; /* Number of p-fields */ float p2orig; /* Event start time */ float p3orig; /* Length */ float offtim; /* k-time to turn off this event */ float p[PMAX+1]; /* All p-fields for this event */ } EVTBLK; INSDS - in Cs.hThis struct holds the info for a concrete instrument event instance in performance. typedef struct insds { struct opds * nxti; /* Chain of init-time opcodes */ struct opds * nxtp; /* Chain of performance-time opcodes */ struct insds * nxtinstance; /* Next allocated instance */ struct insds * prvinstance; /* Previous allocated instance */ struct insds * nxtact; /* Next in list of active instruments */ struct insds * prvact; /* Previous in list of active instruments */ struct insds * nxtoff; /* Next instrument to terminate */ FDCH fdch; /* Chain of files used by opcodes in this instr */ AUXCH auxch; /* Extra memory used by opcodes in this instr */ MCHNBLK *m_chnbp; /* MIDI note info block if event started from MIDI */ short m_pitch; /* MIDI pitch, for simple access */ short m_veloc; /* ...ditto velocity */ short xtratim; /* Extra release time requested with xtratim opcode */ short relesing; /* Flag to indicate we're releasing, test with release opcode */ short insno; /* Instrument number */ short actflg; /* Set if instr instance is active (performing) */ float offbet; /* Time to turn off event, in score beats */ float offtim; /* Time to turn off event, in seconds (negative on indef/tie) */ struct insds * nxtolap; /* ptr to next overlapping voice */ /* end of overlap */ float p0; /* Copy of required p-field values for quick access */ float p1; float p2; float p3; } INSDS; TEXT, OPTXT - in Cs.hStorage for parsed orchestra code, for each opcode in an INSTRTXT. typedef struct text { short linenum; /* Line number in orch file (currently buggy!) */ short opnum; /* Opcode index in opcodlst[] */ char *opcod; /* Pointer to opcode name in global pool */ char *strarg; /* (Unquoted) file name if needed by opcode */ ARGLST *inlist; /* Input arguments (pointer to item in name list) */ ARGLST *outlist; ARGOFFS *inoffs; /* Input args (index into list of values) */ ARGOFFS *outoffs; short xincod; /* Rate switch for multi-rate opcode functions */ char intype; /* Type of first input argument (g, k, a, w etc) */ char pftype; /* Type of output argument (k, a etc) */ } TEXT; typedef struct op { struct op * nxtop; TEXT t; } OPTXT; INSTRTXT - in Cs.htypedef struct instr { struct op * nxtop; /* Linked list of instr opcodes */ TEXT t; /* Text of instrument (same as in nxtop) */ short pmax, vmax, pextrab; /* Arg count, size of data for all opcodes in instr */ short mdepends; /* Opcode type (i/k/a) */ short lclkcnt, lcldcnt; /* Storage reqs for this instr */ short lclwcnt, lclacnt; short lclfixed, optxtcount; long localen; long opdstot; /* Total size of opds structs in instr */ long * inslist; /* Only used in parsing (?) */ float * psetdata; /* Used for pset opcode */ struct insds * instance; /* Chain of allocated instances of this instr */ struct instr * nxtinstxt; /* Next instrument in orchestra (numerical order) */ } INSTRTXT; |