Re: [Csnd] Instrument Static Variables, Completely encapsulated instruments
Date | 2005-09-09 21:42 |
From | Michael Gogins |
Subject | Re: [Csnd] Instrument Static Variables, Completely encapsulated instruments |
I think Istvan's suggestion is very sensible, especially for hosts that drive csound by performing ksmps at a time. In that case the host always knows Csound isn't doing anything when the host changes the value of a variable, and Csound knows the host isn't going to monkey with a variable while Csound is computing. Regards, Mike -----Original Message----- From: Istvan Varga |
Date | 2005-09-10 20:40 |
From | Istvan Varga |
Subject | Re: [Csnd] Instrument Static Variables, Completely encapsulated instruments |
Michael Gogins wrote: > I think Istvan's suggestion is very sensible, especially for hosts > that drive csound by performing ksmps at a time. In that case the host > always knows Csound isn't doing anything when the host changes the value > of a variable, and Csound knows the host isn't going to monkey with a > variable while Csound is computing. So, should it be implemented as documented below, or does anyone suggest changes (even if something simple like different names etc.) ? ---------------------------------------------------------------------- API FUNCTIONS PUBLIC int csoundGetChannelPtr(CSOUND *csound, MYFLT **p, const char *name, int type); Stores a pointer to the specified channel in *p. The channel is automatically created and initialized to zero if it does not exist yet. 'name' must be a non-NULL, non-empty string composed of letters, digits, and the underscore character, and the first character must be a letter. 'type' should be one of the following: 1: k-rate (single MYFLT value) 2: a-rate (vector of csoundGetKsmps(csound) MYFLT values) 3: S-rate (vector of MYFLT values with enough space for storing csoundGetStrVarMaxLen(csound) - 1 characters) Note: types 2 and 3 should only be used after the orchestra is successfully compiled with csoundCompile(), otherwise the vector sizes are undefined. Returns zero on success, or one of the following error codes: CSOUND_ERROR invalid parameters CSOUND_MEMORY memory allocation failure any positive value the channel already exists with a different type that is returned as the error code PUBLIC int csoundListChannels(CSOUND *csound, char ***names, int **types); Creates an alphabetically sorted list of all available channels, storing names in *names, and types (see above) in *types; (*types)[n] corresponds to (*names)[n]. If not NULL, both arrays should be freed when no longer needed with free(). Returns the number of channels, possibly zero if there are none, or a negative error code. OPCODES chn_k Sname chn_a Sname chn_S Sname Allocate a k-, a-, or S-rate channel with the specified name. If it already exists with the same type, the opcode is ignored, however, an init error occurs if the channel exists with a different type. ival getchn Sname kval getchn Sname aval getchn Sname Sval getchn Sname Read from a channel (allocated if does not exist yet); the type must be compatible. setchn Sname, ival setchn Sname, kval setchn Sname, aval setchn Sname, Sval -- Send bugs reports to this list. To unsubscribe, send email to csound-unsubscribe@lists.bath.ac.uk |
Date | 2005-09-11 01:32 |
From | Steven Yi |
Subject | Re: [Csnd] Instrument Static Variables, Completely encapsulated instruments |
Attachments | None |
Date | 2005-09-11 11:32 |
From | Istvan Varga |
Subject | Re: [Csnd] Instrument Static Variables, Completely encapsulated instruments |
Steven Yi wrote: > I the functionality sounds good. As for names, could we perhaps use a > common prefix so that the opcodes stay together in terms of manual and > my own memory? i.e. > > chnget > chnset > chn_k Yes, this is a good idea. > Also, just to get it straight in my head, will it be possible to > initialize a channel with chn_a and then setchn with an ival, as well > as read from a chn_k channel into an irate variable? It may be possible for the opcodes to "cast" values in cases where doing so makes sense. Also, there are no separate types for 'k' and 'i', because these are both just single MYFLT values. > chn seems a little short to remember, maybe it would be alright to > just use setchannel and getchannel? And are these too close in name > to chani/chano? Well, in fact the functionality is also very close, the only difference is that chani/chano are indexed by a number and are very similar to ZAK. I have chosen 'chn' to make the names short and save typing, but this can be changed. Any comments on the API functions ? -- Send bugs reports to this list. To unsubscribe, send email to csound-unsubscribe@lists.bath.ac.uk |
Date | 2005-09-12 04:56 |
From | Steven Yi |
Subject | Re: [Csnd] Instrument Static Variables, Completely encapsulated instruments |
Attachments | None |
Date | 2005-09-15 13:12 |
From | Istvan Varga |
Subject | Re: [Csnd] Instrument Static Variables, Completely encapsulated instruments |
Steven Yi wrote: > -ZAK - redo opcodes to use named bus on backend with fixed names like > "ZAK_CHANNEL_" + channel number given, deprecate zakinit as it'd be > unnecessary, but leave it in as a stub opcode for compatibility > > -chani/chano - perhaps the same measure as above > > I don't know how big the performance hit would be moving from an > indexed array lookup of the channel (zak/chan) to string based map > lookup in the named channels. Is it worth having one set of opcodes > that can take either an integer or a string name, and the lookup would > be against two different data structures holding channels? I do not think that replacing the ZAK system with the named bus is a particularly good idea: ZAK is intended for local use by the orchestra, and having a separate name space is useful; also, it would be much less efficient, particularly with k-rate indexes, not only because of the name lookup, but as a result of significantly increased number of names as well that make the name lookup itself slower, and uses more memory (a separate structure with name and parameters allocated with malloc() for every single ZAK location) potentially making cache usage less efficient. I cannot comment on the chani/chano system because I am not sure how that is intended to be used in practice, but I think it would need a new API function so that the host can actually access the bus. By the way, I also have an idea of a new opcode that "exports" a global orchestra variable as a channel of the named bus, something like (no opcode name yet): gafoo OpcodeName "Output" this is intended to be used in the orchestra header, and then if the host queries the "Output" channel after calling csoundCompile() it would get a direct pointer to gafoo. Is this useful ? -- Send bugs reports to this list. To unsubscribe, send email to csound-unsubscribe@lists.bath.ac.uk |
Date | 2005-09-23 18:06 |
From | Istvan Varga |
Subject | Re: [Csnd] Instrument Static Variables, Completely encapsulated instruments |
There is an implementation of the opcodes and API functions in the CVS sources now, so you can try it and suggest changes (probably many are needed, but at least there is something to get started with). The "casting" of types by opcodes, as requested by Steven Yi, is not (yet) supported, however, it is possible to create channels from actual orchestra variables, making it easier and more efficient to implement communication between the orchestra and the host application. Also, there is some "metadata" such as input/output direction, and optional parameters for control channels (integer/linear/exponential type, default, minimum, and maximum value); these probably need to be changed too, or may be removed if not found to be useful. OPCODES ival chnget Sname kval chnget Sname aval chnget Sname Sval chnget Sname Read value from a channel (created if does not exist yet, with an initial value of zero; otherwise, it must be of a compatible type). chnset ival, Sname chnset kval, Sname chnset aval, Sname chnset Sval, Sname Write to a channel (created if does not exist yet; otherwise, it must be of a compatible type). chn_k Sname, imode[, itype, idflt, imin, imax] Declare control channel. imode is a sum of 1 for input and 2 for output. For more information on input/output mode and the optional arguments, see the API function below. chn_a Sname, imode chn_S Sname, imode Declare audio or string channel. gival chnexport Sname, imode[, itype, idflt, imin, imax] gkval chnexport Sname, imode[, itype, idflt, imin, imax] gaval chnexport Sname, imode gSval chnexport Sname, imode Export a global variable as a channel of the bus that should not exist before calling the opcode. Allows the host application to read or write orchestra variables directly. The parameters are the same as in the case of chn_k/chn_a/chn_S. itype, imode, ictltype, idflt, imin, imax chnparams Query parameters of a channel (if it does not exist, all returned values are zero): itype: channel data type (1: control, 2: audio, 3: string) imode: sum of 1 for input and 2 for output ictltype, idflt, imin, imax: special parameters for control channel only; if not available, all are set to zero API FUNCTIONS /** * Stores a pointer to the specified channel of the bus in *p, * creating the channel first if it does not exist yet. * 'type' must be the bitwise OR of exactly one of the following values, * CSOUND_CONTROL_CHANNEL * control data (one MYFLT value) * CSOUND_AUDIO_CHANNEL * audio data (csoundGetKsmps(csound) MYFLT values) * CSOUND_STRING_CHANNEL * string data (MYFLT values with enough space to store * csoundGetStrVarMaxLen(csound) characters, including the * NULL character at the end of the string) * and at least one of these: * CSOUND_INPUT_CHANNEL * CSOUND_OUTPUT_CHANNEL * If the channel already exists, it must match the data type (control, * audio, or string), however, the input/output bits are OR'd with the * new value. Note that audio and string channels can only be created * after calling csoundCompile(), because the storage size is not known * until then. * Return value is zero on success, or a negative error code, * CSOUND_MEMORY there is not enough memory for allocating the channel * CSOUND_ERROR the specified name or type is invalid * or, if a channel with the same name but incompatible type already exists, * the type of the existing channel. In the case of any non-zero return * value, *p is set to NULL. * Note: to find out the type of a channel without actually creating or * changing it, set 'type' to zero, so that the return value will be either * the type of the channel, or CSOUND_ERROR if it does not exist. */ PUBLIC int csoundGetChannelPtr(CSOUND *, MYFLT **p, const char *name, int type); /** * Returns a list of allocated channels, storing a pointer to an array * of channel names in *names, and a pointer to an array of channel types * in *types. (*types)[n] corresponds to (*names)[n], and has the same * format as the 'type' parameter of csoundGetChannelPtr(). * The return value is the number of channels, which may be zero if there * are none, or CSOUND_MEMORY if there is not enough memory for allocating * the lists. In the case of no channels or an error, *names and *types are * set to NULL. * Note: the caller is responsible for freeing the lists returned in *names * and *types with free(), however, the actual channel names should not be * changed or freed. Also, the name pointers may become invalid after calling * csoundReset(). */ PUBLIC int csoundListChannels(CSOUND *, char ***names, int **types); /** * Sets special parameters for a control channel. The parameters are: * type: must be one of CSOUND_CONTROL_CHANNEL_INT, * CSOUND_CONTROL_CHANNEL_LIN, or CSOUND_CONTROL_CHANNEL_EXP for * integer, linear, or exponential channel data, respectively, * or zero to delete any previously assigned parameter information * dflt: the control value that is assumed to be the default, should be * greater than or equal to 'min', and less than or equal to 'max' * min: the minimum value expected; if the control type is exponential, * it must be non-zero * max: the maximum value expected, should be greater than 'min'; * if the control type is exponential, it must be non-zero and * match the sign of 'min' * Returns zero on success, or a non-zero error code on failure: * CSOUND_ERROR: the channel does not exist, is not a control channel, * or the specified parameters are invalid * CSOUND_MEMORY: could not allocate memory */ PUBLIC int csoundSetControlChannelParams(CSOUND *, const char *name, int type, MYFLT dflt, MYFLT min, MYFLT max); /** * Returns special parameters (assuming there are any) of a control channel, * previously set with csoundSetControlChannelParams(). * If the channel exists, is a control channel, and has the special parameters * assigned, then the default, minimum, and maximum value is stored in *dflt, * *min, and *max, respectively, and a positive value that is one of * CSOUND_CONTROL_CHANNEL_INT, CSOUND_CONTROL_CHANNEL_LIN, and * CSOUND_CONTROL_CHANNEL_EXP is returned. * In any other case, *dflt, *min, and *max are not changed, and the return * value is zero if the channel exists, is a control channel, but has no * special parameters set; otherwise, a negative error code is returned. */ PUBLIC int csoundGetControlChannelParams(CSOUND *, const char *name, MYFLT *dflt, MYFLT *min, MYFLT *max); -- Send bugs reports to this list. To unsubscribe, send email to csound-unsubscribe@lists.bath.ac.uk |
Date | 2005-09-23 21:24 |
From | Istvan Varga |
Subject | [Cs-dev] Re: [Csnd] Instrument Static Variables, Completely encapsulated instruments |
There is an implementation of the opcodes and API functions in the CVS sources now, so you can try it and suggest changes (probably many are needed, but at least there is something to get started with). The "casting" of types by opcodes, as requested by Steven Yi, is not (yet) supported, however, it is possible to create channels from actual orchestra variables, making it easier and more efficient to implement communication between the orchestra and the host application. Also, there is some "metadata" such as input/output direction, and optional parameters for control channels (integer/linear/exponential type, default, minimum, and maximum value); these probably need to be changed too, or may be removed if not found to be useful. OPCODES ival chnget Sname kval chnget Sname aval chnget Sname Sval chnget Sname Read value from a channel (created if does not exist yet, with an initial value of zero; otherwise, it must be of a compatible type). chnset ival, Sname chnset kval, Sname chnset aval, Sname chnset Sval, Sname Write to a channel (created if does not exist yet; otherwise, it must be of a compatible type). chn_k Sname, imode[, itype, idflt, imin, imax] Declare control channel. imode is a sum of 1 for input and 2 for output. For more information on input/output mode and the optional arguments, see the API function below. chn_a Sname, imode chn_S Sname, imode Declare audio or string channel. gival chnexport Sname, imode[, itype, idflt, imin, imax] gkval chnexport Sname, imode[, itype, idflt, imin, imax] gaval chnexport Sname, imode gSval chnexport Sname, imode Export a global variable as a channel of the bus that should not exist before calling the opcode. Allows the host application to read or write orchestra variables directly. The parameters are the same as in the case of chn_k/chn_a/chn_S. itype, imode, ictltype, idflt, imin, imax chnparams Query parameters of a channel (if it does not exist, all returned values are zero): itype: channel data type (1: control, 2: audio, 3: string) imode: sum of 1 for input and 2 for output ictltype, idflt, imin, imax: special parameters for control channel only; if not available, all are set to zero API FUNCTIONS /** * Stores a pointer to the specified channel of the bus in *p, * creating the channel first if it does not exist yet. * 'type' must be the bitwise OR of exactly one of the following values, * CSOUND_CONTROL_CHANNEL * control data (one MYFLT value) * CSOUND_AUDIO_CHANNEL * audio data (csoundGetKsmps(csound) MYFLT values) * CSOUND_STRING_CHANNEL * string data (MYFLT values with enough space to store * csoundGetStrVarMaxLen(csound) characters, including the * NULL character at the end of the string) * and at least one of these: * CSOUND_INPUT_CHANNEL * CSOUND_OUTPUT_CHANNEL * If the channel already exists, it must match the data type (control, * audio, or string), however, the input/output bits are OR'd with the * new value. Note that audio and string channels can only be created * after calling csoundCompile(), because the storage size is not known * until then. * Return value is zero on success, or a negative error code, * CSOUND_MEMORY there is not enough memory for allocating the channel * CSOUND_ERROR the specified name or type is invalid * or, if a channel with the same name but incompatible type already exists, * the type of the existing channel. In the case of any non-zero return * value, *p is set to NULL. * Note: to find out the type of a channel without actually creating or * changing it, set 'type' to zero, so that the return value will be either * the type of the channel, or CSOUND_ERROR if it does not exist. */ PUBLIC int csoundGetChannelPtr(CSOUND *, MYFLT **p, const char *name, int type); /** * Returns a list of allocated channels, storing a pointer to an array * of channel names in *names, and a pointer to an array of channel types * in *types. (*types)[n] corresponds to (*names)[n], and has the same * format as the 'type' parameter of csoundGetChannelPtr(). * The return value is the number of channels, which may be zero if there * are none, or CSOUND_MEMORY if there is not enough memory for allocating * the lists. In the case of no channels or an error, *names and *types are * set to NULL. * Note: the caller is responsible for freeing the lists returned in *names * and *types with free(), however, the actual channel names should not be * changed or freed. Also, the name pointers may become invalid after calling * csoundReset(). */ PUBLIC int csoundListChannels(CSOUND *, char ***names, int **types); /** * Sets special parameters for a control channel. The parameters are: * type: must be one of CSOUND_CONTROL_CHANNEL_INT, * CSOUND_CONTROL_CHANNEL_LIN, or CSOUND_CONTROL_CHANNEL_EXP for * integer, linear, or exponential channel data, respectively, * or zero to delete any previously assigned parameter information * dflt: the control value that is assumed to be the default, should be * greater than or equal to 'min', and less than or equal to 'max' * min: the minimum value expected; if the control type is exponential, * it must be non-zero * max: the maximum value expected, should be greater than 'min'; * if the control type is exponential, it must be non-zero and * match the sign of 'min' * Returns zero on success, or a non-zero error code on failure: * CSOUND_ERROR: the channel does not exist, is not a control channel, * or the specified parameters are invalid * CSOUND_MEMORY: could not allocate memory */ PUBLIC int csoundSetControlChannelParams(CSOUND *, const char *name, int type, MYFLT dflt, MYFLT min, MYFLT max); /** * Returns special parameters (assuming there are any) of a control channel, * previously set with csoundSetControlChannelParams(). * If the channel exists, is a control channel, and has the special parameters * assigned, then the default, minimum, and maximum value is stored in *dflt, * *min, and *max, respectively, and a positive value that is one of * CSOUND_CONTROL_CHANNEL_INT, CSOUND_CONTROL_CHANNEL_LIN, and * CSOUND_CONTROL_CHANNEL_EXP is returned. * In any other case, *dflt, *min, and *max are not changed, and the return * value is zero if the channel exists, is a control channel, but has no * special parameters set; otherwise, a negative error code is returned. */ PUBLIC int csoundGetControlChannelParams(CSOUND *, const char *name, MYFLT *dflt, MYFLT *min, MYFLT *max); ------------------------------------------------------- SF.Net email is sponsored by: Tame your development challenges with Apache's Geronimo App Server. Download it for free - -and be entered to win a 42" plasma tv or your very own Sony(tm)PSP. Click here to play: http://sourceforge.net/geronimo.php _______________________________________________ Csound-devel mailing list Csound-devel@lists.sourceforge.net |
Date | 2005-09-23 21:55 |
From | Steven Yi |
Subject | Re: [Csnd] Instrument Static Variables, Completely encapsulated instruments |
Attachments | None |
Date | 2005-09-23 23:15 |
From | Steven Yi |
Subject | Re: [Csnd] Instrument Static Variables, Completely encapsulated instruments |
Attachments | None 2005_09_23_encapsulated_instrument.csd |
Date | 2005-09-23 23:17 |
From | Steven Yi |
Subject | Re: [Csnd] Instrument Static Variables, Completely encapsulated instruments |
Attachments | None |
Date | 2005-09-24 11:56 |
From | Istvan Varga |
Subject | Re: [Csnd] Instrument Static Variables, Completely encapsulated instruments |
Steven Yi wrote: > Oh, one note, in the example, you can get rid of the second chnget > line as it isn't necessary and was leftover from testing. Thanks! Actually, you do not need the chn_k either, because the first chnget already declares the channel as k-rate: itableNum chnget "instr1_sineTable" if (itableNum == 0) then itableNum ftgen 0, 0, 65537, 10, 1 chnset itableNum, "instr1_sineTable" prints "Created Sine Table %d for instrument 1\n", itableNum endif -- Send bugs reports to this list. To unsubscribe, send email to csound-unsubscribe@lists.bath.ac.uk |
Date | 2005-09-24 12:47 |
From | Istvan Varga |
Subject | Re: [Csnd] Instrument Static Variables, Completely encapsulated instruments |
Steven Yi wrote: > I am a little confused about all the modes and why you might want all > those options, but I only read enough of the email to do a test of the > encapsulated instrument, and will look into it a bit more. > > As for linear/exponential, etc., those seem like things that should be > handled by the code before and after going through the channels, yes? > Seems like it might limit the purpose of the bus. As I already mentioned, I am not sure about the channel metadata, so it may be changed significantly if requested, or it may even be removed completely. Generally, the information on input/output direction, unknown/integer/linear/exponential control type, default, minimum, and maximum control value are only hints that can be used by the host application to allow the user to connect channels of the bus to some external ports. For example, knowing that a control channel named "FilterFrequency" is expected to receive input, has an exponential scale, should be in the range 100 to 10000 with a default "normal" setting of 1000, is useful for attaching a knob to that channel. Basically, there are two types of metadata: the input/output bitmask is always present, and if a new query of the channel is made with an inconsistent bitmask, it is simply updated using bitwise OR: asig chnget "foo" ; creates channel, with input bit set chnset asig, "foo" ; this will set output too, so mode is now 3 The other type of metadata is optional and is for control channels only, it provides information on the expected range of the control data; the parameters included are "type" (unknown, integer, linear, exponential), "default value", "minimum value", and "maximum value". All these additional parameters are only relevant if you intend to use this system for implementing communication between the orchestra and the host application (as an alternative to invalue/outvalue). If all you need is "named ZAK", accessed only from the orchestra, then using only chnset and chnget should be fine, without caring about the rest of the opcodes or the various special parameters (they do make the channel lookup somewhat slower, though, so that may be one reason to remove all support for metadata). > As for chn_k, I'm a little confused on itype for that opcode, as it > would seem to me by its nature it's going to be a control signal. itype for chn_k selects an optional "sub-type" for the control channel, which can also be changed by a later chn_k call. itype = 0 generic control channel (idflt, imin, and imax are ignored), with no information on the range of the data itype = 1 the channel data is expected to be limited to integer values itype = 2 the channel data is expected to have a linear scale itype = 3 the channel data is expected to have an exponential scale example (declarations in the orchestra header): ; name mode type default min max gkamp chnexport "Amplitude", 1, 3, 0.5, 0.001, 1 gkampDB chnexport "Amplitude_DB", 1, 2, -6, -60, 0 gkfreq chnexport "Frequency", 1, 3, 440, 20, 20000 gknote chnexport "Note_Number", 1, 1, 60, 1, 127 Note again that all the parameters are only hints, and have no effect at all on the actual use of the channel. >>On 9/23/05, Istvan Varga |
Date | 2005-09-25 11:38 |
From | Istvan Varga |
Subject | Re: [Csnd] Instrument Static Variables, Completely encapsulated instruments |
Well, I think for now it is safest to remove the API functions, and keep only the two opcodes chnget and chnset for use as a named ZAK system that is private to the orchestra. Istvan Varga wrote: > Steven Yi wrote: > >> I am a little confused about all the modes and why you might want all >> those options, but I only read enough of the email to do a test of the >> encapsulated instrument, and will look into it a bit more. > > > > >> As for linear/exponential, etc., those seem like things that should be >> handled by the code before and after going through the channels, yes? >> Seems like it might limit the purpose of the bus. > > > As I already mentioned, I am not sure about the channel metadata, > so it may be changed significantly if requested, or it may even be > removed completely. Generally, the information on input/output direction, > unknown/integer/linear/exponential control type, default, minimum, > and maximum control value are only hints that can be used by the host > application to allow the user to connect channels of the bus to some > external ports. For example, knowing that a control channel named > "FilterFrequency" is expected to receive input, has an exponential > scale, should be in the range 100 to 10000 with a default "normal" > setting of 1000, is useful for attaching a knob to that channel. > Basically, there are two types of metadata: the input/output bitmask > is always present, and if a new query of the channel is made with an > inconsistent bitmask, it is simply updated using bitwise OR: > > asig chnget "foo" ; creates channel, with input bit set > chnset asig, "foo" ; this will set output too, so mode is now 3 > > The other type of metadata is optional and is for control channels only, > it provides information on the expected range of the control data; the > parameters included are "type" (unknown, integer, linear, exponential), > "default value", "minimum value", and "maximum value". > > All these additional parameters are only relevant if you intend to use > this system for implementing communication between the orchestra and > the host application (as an alternative to invalue/outvalue). > If all you need is "named ZAK", accessed only from the orchestra, then > using only chnset and chnget should be fine, without caring about the > rest of the opcodes or the various special parameters (they do make > the channel lookup somewhat slower, though, so that may be one reason > to remove all support for metadata). > >> As for chn_k, I'm a little confused on itype for that opcode, as it >> would seem to me by its nature it's going to be a control signal. > > > itype for chn_k selects an optional "sub-type" for the control channel, > which can also be changed by a later chn_k call. > > itype = 0 > > generic control channel (idflt, imin, and imax are ignored), > with no information on the range of the data > > itype = 1 > > the channel data is expected to be limited to integer values > > itype = 2 > > the channel data is expected to have a linear scale > > itype = 3 > > the channel data is expected to have an exponential scale > > example (declarations in the orchestra header): > > ; name mode type default min max > gkamp chnexport "Amplitude", 1, 3, 0.5, 0.001, 1 > gkampDB chnexport "Amplitude_DB", 1, 2, -6, -60, 0 > gkfreq chnexport "Frequency", 1, 3, 440, 20, 20000 > gknote chnexport "Note_Number", 1, 1, 60, 1, 127 > > Note again that all the parameters are only hints, and have no effect > at all on the actual use of the channel. > >>> On 9/23/05, Istvan Varga |
Date | 2005-09-25 17:34 |
From | Steven Yi |
Subject | Re: [Csnd] Instrument Static Variables, Completely encapsulated instruments |
Attachments | None |