examples.cfg/exampled.md : Updates

This commit is contained in:
kevin 2024-09-17 17:35:10 -04:00
parent 99fee3e831
commit ca226a44c7
2 changed files with 176 additions and 56 deletions

View File

@ -1,13 +1,13 @@
{ {
base_dir: "~/src/caw/examples", // Base project directory. See 'sine_file_01' below. base_dir: "~/src/caw/examples/io", // Base project directory. See 'sine_file_01' below.
io_dict: "~/src/caw/src/caw/cfg/io.cfg" // Runtime configuration file. io_dict: "~/src/caw/src/caw/cfg/io.cfg" // Runtime configuration file.
proc_dict: "~/src/caw/src/libcw/flow/proc_dict.cfg", // Processor class definition file. proc_dict: "~/src/caw/src/libcw/flow/proc_dict.cfg", // Processor class definition file.
subnet_dict: "~/src/caw/src/libcw/flow/subnet_dict.cfg", // User written subnet files udp_dict: "~/src/caw/src/libcw/flow/udp_dict.cfg", // User defined proc files
programs: { programs: {
rt_sine_00: { ex_00_rt_sine: {
dur_limit_secs:5.0, dur_limit_secs:5.0,
@ -21,7 +21,7 @@
} }
// Demonstrate a simple two processor network. // Demonstrate a simple two processor network.
sine_file_01: { ex_01_sine_file: {
non_real_time_fl:true, non_real_time_fl:true,
dur_limit_secs:5.0, dur_limit_secs:5.0,
@ -37,7 +37,7 @@
// Demonstrate a simple signal processing network // Demonstrate a simple signal processing network
mod_sine_02: { ex_02_mod_sine: {
non_real_time_fl:true, non_real_time_fl:true,
dur_limit_secs:5.0, dur_limit_secs:5.0,
@ -55,7 +55,7 @@
// Demonstrate applying a preset at initialization time. // Demonstrate applying a preset at initialization time.
presets_03: { ex_03_presets: {
non_real_time_fl:true, non_real_time_fl:true,
dur_limit_secs:5.0, dur_limit_secs:5.0,
@ -82,7 +82,7 @@
} }
// Demonstrate the `print` processor and event programming. // Demonstrate the `print` processor and event programming.
program_04: { ex_04_program: {
non_real_time_fl:true, non_real_time_fl:true,
dur_limit_secs: 10.0, dur_limit_secs: 10.0,
@ -97,7 +97,7 @@
} }
// Demonstrate 'mult' inputs. // Demonstrate 'mult' inputs.
mult_inputs_05: { ex_05_mult_inputs: {
non_real_time_fl:true, non_real_time_fl:true,
dur_limit_secs: 10.0, dur_limit_secs: 10.0,
@ -115,7 +115,7 @@
// Demonstrate different forms of the in-stmt // Demonstrate different forms of the in-stmt
mult_conn_06: { ex_06_mult_conn: {
non_real_time_fl:true, non_real_time_fl:true,
dur_limit_secs: 5.0, dur_limit_secs: 5.0,
@ -147,7 +147,7 @@
// Demonstrate creating processors with explicit sfx-ids and connecting to them with a single in-stmt. // Demonstrate creating processors with explicit sfx-ids and connecting to them with a single in-stmt.
proc_suffix_07: { ex_07_proc_suffix: {
non_real_time_fl:true, non_real_time_fl:true,
dur_limit_secs: 5.0, dur_limit_secs: 5.0,
@ -172,7 +172,7 @@
} }
// Demonstrate instantiating 'mult' variables from the an 'args' statement. // Demonstrate instantiating 'mult' variables from the an 'args' statement.
mix_08: { ex_08_mix: {
non_real_time_fl:true, non_real_time_fl:true,
dur_limit_secs:5.0, dur_limit_secs:5.0,
@ -193,7 +193,7 @@
// Demonstrate a network with a polyphonic subnet. // Demonstrate a network with a polyphonic subnet.
simple_poly_09: { ex_09_homog_poly: {
non_real_time_fl:true, non_real_time_fl:true,
dur_limit_secs: 5.0, dur_limit_secs: 5.0,
@ -207,7 +207,9 @@
osc_poly: { osc_poly: {
class: poly, class: poly,
args: { count:3 }, // Create 3 instances of 'network'.
// Create 3 instances of 'network' and run them in concurrently.
args: { count:3, parallel_fl:true },
network: { network: {
procs: { procs: {
@ -226,8 +228,54 @@
} }
} }
// Demonstrate a network with poly network with different subnets.
ex_10_hetero_poly: {
non_real_time_fl:true,
dur_limit_secs: 5.0,
feedback_10: { network: {
procs: {
g_list: { class: list, args: { in:0, list:[ 110f,220f,440f ]}},
dc_list: { class: list, args: { in:0, list:[ 220f,440f,880f ]}},
osc_poly: {
class: poly,
args: { parallel_fl:true },
network: [
// network 0
{
procs: {
lfo: { class: sine_tone, in:{ _.dc:_.dc_list.value_, _.gain:_.g_list.value_ } args: { ch_cnt:1, hz:3 }},
sh: { class: sample_hold, in:{ in:lfo.out }},
osc: { class: sine_tone, in:{ hz: sh.out }},
}
},
// network 1
{
procs: {
oscil: { class: sine_tone, args:{ hz:55 }},
}
}
]
}
// Iterate over the instances of `osc_poly.osc_.out` to create one `audio_merge`
// input for every output from the polyphonic network.
merge: { class: audio_merge, in:{ in0:osc_poly.osc.out, in1:osc_poly.oscil1.out}, args:{ gain:1, out_gain:0.5 }},
af: { class: audio_file_out, in:{ in:merge.out } args:{ fname:"$/out.wav"} }
}
}
}
ex_11_feedback: {
non_real_time_fl:true, non_real_time_fl:true,
max_cycle_count: 10, max_cycle_count: 10,
@ -243,7 +291,7 @@
}, },
feedback_11: { ex_11a_feedback: {
non_real_time_fl:true, non_real_time_fl:true,
max_cycle_count: 10, max_cycle_count: 10,
print_network_fl: true, print_network_fl: true,
@ -259,7 +307,7 @@
} }
}, },
subnet_12 : { ex_12_user_defined_proc : {
non_real_time_fl: true, non_real_time_fl: true,
dur_limit_secs: 5, dur_limit_secs: 5,

View File

@ -8,13 +8,13 @@ system parameters that the program needs to compile and run the program.
``` javascript ``` javascript
{ {
base_dir: "~/src/caw/examples", base_dir: "~/src/caw/examples/io",
proc_dict: "~/src/caw/examples/proc_dict.cfg", proc_dict: "~/src/caw/examples/proc_dict.cfg",
mode: non_real_time, mode: non_real_time,
programs: { programs: {
sine_file_01: { ex_01_sine_file: {
dur_limit_secs:5.0, // Run the network for 5 seconds dur_limit_secs:5.0, // Run the network for 5 seconds
@ -33,7 +33,7 @@ system parameters that the program needs to compile and run the program.
} }
``` ```
![Example 0](svg/00_osc_af.svg "`sine_file_01` processing network") ![Example 0](svg/00_osc_af.svg "`ex_01_sine_file` processing network")
When executed this program will write a five second sine signal to an audio file When executed this program will write a five second sine signal to an audio file
named `~/src/caw/examples/sine_file_01/out.wav`. The output file name named `~/src/caw/examples/sine_file_01/out.wav`. The output file name
@ -103,7 +103,7 @@ audio_file_out: {
``` ```
The class definitions specify the names, types and default values for The class definitions specify the names, types and default values for
each variable. Since the `sine_tone` instance in `sine_file_00` each variable. Since the `sine_tone` instance in `ex_01_sine_file`
doesn't override any of the the variable default values the generated doesn't override any of the the variable default values the generated
audio file must be a stereo (`ch_cnt`=2), 440 Hertz signal with an audio file must be a stereo (`ch_cnt`=2), 440 Hertz signal with an
amplitude of 0.8. amplitude of 0.8.
@ -124,7 +124,7 @@ Attribute | Description
src | This variable must be connected to a source variable or the processor instantiation will fail. src | This variable must be connected to a source variable or the processor instantiation will fail.
no_src | This variable cannot be connected to a source variable (it is write-only, or output only). no_src | This variable cannot be connected to a source variable (it is write-only, or output only).
init | This variable is only read at processer instantiation time, changes during runtime will be ignored. init | This variable is only read at processer instantiation time, changes during runtime will be ignored.
mult | This variable may be instantiated multiple times. See `mult_input_05` below. mult | This variable may be instantiated multiple times. See `ex_05_mult_input` below.
out | This is a subnet output variable. out | This is a subnet output variable.
__caw__ uses types and does it's best at converting between types where the conversion will __caw__ uses types and does it's best at converting between types where the conversion will
@ -161,13 +161,13 @@ ftime | double | Fractional time in seconds or milliseconds.
Also notice that the processor class has named presets. During Also notice that the processor class has named presets. During
processor instantiaion these presets can be used to set the processor instantiaion these presets can be used to set the
initial state of the processor. See `mod_sine_02` below for initial state of the processor. See `ex_02_mod_sine` below for
an example of a class preset used this way. an example of a class preset used this way.
### Example 02: Modulated Sine Signal ### Example 02: Modulated Sine Signal
This example is an extended version of `sine_file_01` where a low frequency oscillator (LFO) This example is an extended version of `ex_01_sine_file` where a low frequency oscillator (LFO)
is formed using a second `sine_tone` processor and a sample and hold unit. The output is formed using a second `sine_tone` processor and a sample and hold unit. The output
of the sample and hold unit is then used to modulate the frequency of an audio of the sample and hold unit is then used to modulate the frequency of an audio
frequency `sine_tone` oscillator. frequency `sine_tone` oscillator.
@ -178,7 +178,7 @@ of 440. The LFO output signal is therefore sweeping an amplitude
between 330 and 550 which will be treated as frequency values by `osc`. between 330 and 550 which will be treated as frequency values by `osc`.
``` json ``` json
mod_sine_02: { ex_02_mod_sine: {
dur_limit_secs:5.0, dur_limit_secs:5.0,
@ -194,7 +194,7 @@ mod_sine_02: {
} }
``` ```
![Example 2](svg/02_mod_sine.svg "`mod_sine_02` processing network") ![Example 2](svg/02_mod_sine.svg "`ex_02_mod_sine` processing network")
The `osc` instance in this example uses a `preset` statement. This will have The `osc` instance in this example uses a `preset` statement. This will have
the effect of applying the class preset `mono` to the `osc` when it is the effect of applying the class preset `mono` to the `osc` when it is
@ -226,8 +226,8 @@ value from the buffer, and 'mean' is the average of all the values in the buffer
One of the fundamental features of __caw__ is the ability to build One of the fundamental features of __caw__ is the ability to build
presets which can set the network, or a given processor, to a particular state. presets which can set the network, or a given processor, to a particular state.
`mod_sine_02` showed the use of a class preset to set the number of `ex_02_mod_sine` showed the use of a class preset to set the number of
audio channels generated by the audio oscillator. `presets_03` shows audio channels generated by the audio oscillator. `ex_03_presets` shows
how presets can be specified and applied for the entire network. how presets can be specified and applied for the entire network.
In this example four network presets are specified in the `presets` statement In this example four network presets are specified in the `presets` statement
@ -238,7 +238,7 @@ If this example was run in real-time it would also be possible to apply
the the presets while the network was running. the the presets while the network was running.
``` JSON ``` JSON
presets_03: { ex_03_presets: {
dur_limit_secs:5.0, dur_limit_secs:5.0,
preset: "a", preset: "a",
@ -276,7 +276,7 @@ independently.
One of the simplest ways to address the individual channels of a One of the simplest ways to address the individual channels of a
processor is by providing a list of values in a preset specification. processor is by providing a list of values in a preset specification.
Several examples of this are shown in the presets contained in then network Several examples of this are shown in the presets contained in then network
`presets` dictionary in `presets_03`. For example the preset `presets` dictionary in `ex_03_presets`. For example the preset
`a.lfo.dc` specifies that the DC offset of first channel of the LFO `a.lfo.dc` specifies that the DC offset of first channel of the LFO
should be 880 and the second channel should be 770. should be 880 and the second channel should be 770.
@ -285,7 +285,7 @@ list of values. If only a single value is given (e.g. `b.lfo.dc`) then
the same value is applied to all channels. the same value is applied to all channels.
Note that if a processor specifies a class preset with a `preset` Note that if a processor specifies a class preset with a `preset`
statement, as in the `osc` processor in `mod_sine_02`, or sets statement, as in the `osc` processor in `ex_02_mod_sine`, or sets
initial values with an `args` statement, these initial values with an `args` statement, these
values will be applied to the processor when it is instantiated, but values will be applied to the processor when it is instantiated, but
may be overwritten when the network preset is applied. For example, may be overwritten when the network preset is applied. For example,
@ -319,7 +319,7 @@ TODO: Check that this accurately describes preset interpolation.
### Example 04 : Event Programming ### Example 04 : Event Programming
``` ```
program_04: { ex_04_program: {
dur_limit_secs: 10.0, dur_limit_secs: 10.0,
@ -333,7 +333,7 @@ program_04: {
} }
``` ```
![Example 4](svg/04_program.svg "`program_04` processing network") ![Example 4](svg/04_program.svg "`ex_04_program` processing network")
This program demonstrates how __caw__ passes messages between processors. This program demonstrates how __caw__ passes messages between processors.
@ -369,13 +369,13 @@ always print after the value received by `log.in`.
### Example 05: Processors with expandable numbers of inputs ### Example 05: Processors with expandable numbers of inputs
`mult_inputs_05` extends `program_04` by including a __number__ and __add__ processor. `ex_05_mult_inputs` extends `ex_04_program` by including a __number__ and __add__ processor.
The __number__ processor acts like a register than can hold a single value. The __number__ processor acts like a register than can hold a single value.
As used here the __number__ processor simply holds the constant value '3'. As used here the __number__ processor simply holds the constant value '3'.
The __add__ processor then sums the output of _cnt_ and _numb_. The __add__ processor then sums the output of _cnt_ and _numb_.
``` ```
mult_inputs_05: { ex_05_mult_inputs: {
dur_limit_secs: 10.0, dur_limit_secs: 10.0,
@ -391,7 +391,7 @@ mult_inputs_05: {
} }
``` ```
![Example 5](svg/05_mult_inputs.svg "`mult_inputs_05` processing network") ![Example 5](svg/05_mult_inputs.svg "`ex_05_mult_inputs` processing network")
The notable new concept introduced by this program is the concept of The notable new concept introduced by this program is the concept of
__mult__ variables. These are variables which can be instantiated __mult__ variables. These are variables which can be instantiated
@ -416,7 +416,7 @@ to easily create and connect many `mult` variables in a single
connection expression. connection expression.
``` ```
mult_conn_06: { ex_06_mult_conn: {
dur_limit_secs: 5.0, dur_limit_secs: 5.0,
@ -443,7 +443,7 @@ mult_conn_06: {
} }
``` ```
![Example 6](svg/06_mult_conn.svg "`mult_conn_06` processing network") ![Example 6](svg/06_mult_conn.svg "`ex_-6_mult_conn` processing network")
The audio source for this network is a six channel signal generator, The audio source for this network is a six channel signal generator,
where the frequency is each channel is incremented by an octave. where the frequency is each channel is incremented by an octave.
@ -455,7 +455,7 @@ variables `out0`,`out1` and `out2`.
The __audio_split__ class takes a single signal and splits it into multiple signals. The __audio_split__ class takes a single signal and splits it into multiple signals.
The __audio_merge__ class takes multple signals and concatenates them into a single signal. The __audio_merge__ class takes multple signals and concatenates them into a single signal.
Each of the three merge processor (merge_a,merge_b,merge_c) in `mult_conn_06` Each of the three merge processor (merge_a,merge_b,merge_c) in `ex_06_mult_conn`
demonstrates three different ways of selecting multiple signals to merge demonstrates three different ways of selecting multiple signals to merge
in with a single `in:{...}` statement expression. in with a single `in:{...}` statement expression.
@ -520,7 +520,7 @@ An error should be generated.
### Example 07: Processor suffix notiation ### Example 07: Processor suffix notiation
As demonstrated in `mult_conn_06` variables are identified by their label As demonstrated in `ex_-6_mult_conn` variables are identified by their label
and an integer suffix id. By default, for non __mult__ variables, the suffix id is set to 0. and an integer suffix id. By default, for non __mult__ variables, the suffix id is set to 0.
Using the `in:{...}` statement however variables that have the 'mult' attribute Using the `in:{...}` statement however variables that have the 'mult' attribute
can be instantiated multiple times with each instance having a different suffix id. can be instantiated multiple times with each instance having a different suffix id.
@ -529,7 +529,7 @@ Processors instances use a similar naming scheme; they have both a text label
and a suffix id. and a suffix id.
``` ```
proc_suffix_07: { ex_07_proc_suffix: {
dur_limit_secs: 5.0, dur_limit_secs: 5.0,
network: { network: {
@ -549,14 +549,14 @@ proc_suffix_07: {
``` ```
![Example 7](svg/07_proc_suffix.svg "`proc_suffix_07` processing network") ![Example 7](svg/07_proc_suffix.svg "`ex_07_proc_suffix` processing network")
In this example three __audio_gain__ processors are instantiated with In this example three __audio_gain__ processors are instantiated with
the same label 'g' and are then differentiated by their suffix id's: the same label 'g' and are then differentiated by their suffix id's:
0,1, and 2. The merge processor is then able to connect to them using 0,1, and 2. The merge processor is then able to connect to them using
a single `in:{...}` expression, `in_:g_.out` which iterates over the a single `in:{...}` expression, `in_:g_.out` which iterates over the
gain processors suffix id. This expression is very similar to the gain processors suffix id. This expression is very similar to the
`merge_a` connection expression in `mult_conn_06`: `in_:split.out_` `merge_a` connection expression in `ex_06_mult_conn`: `in_:split.out_`
which iterated over the label suffix id's of the `split.out`. In this which iterated over the label suffix id's of the `split.out`. In this
case the connection is iterating over the label suffix id's of the case the connection is iterating over the label suffix id's of the
networks processors rather than over a processors variables. networks processors rather than over a processors variables.
@ -596,7 +596,7 @@ The slight complication however is that every input also has a gain coefficient
associated with it that the user may want to set. associated with it that the user may want to set.
``` ```
mix_08: { ex_08_mix: {
non_real_time_fl:true, non_real_time_fl:true,
dur_limit_secs:5.0, dur_limit_secs:5.0,
@ -614,9 +614,9 @@ mix_08: {
} }
``` ```
![Example 8](svg/08_mix.svg "`mix_08` processing network") ![Example 8](svg/08_mix.svg "`ex_08_mix` processing network")
Notice that the `mix` processor instantiates two stereo input channels in the `in:{...}` statement Notice that the `mix` processor instantiates two stereo input channels in the `in:{...}` statement
and then assigns initial gain values to each individual channel. If a scalar value was given instead of a and then assigns initial gain values to each individual channel. If a scalar value was given instead of a
list (e.g. `igain0:0.8`) then the scalar value would be assigned to all channels list (e.g. `igain0:0.8`) then the scalar value would be assigned to all channels
@ -625,11 +625,10 @@ list (e.g. `igain0:0.8`) then the scalar value would be assigned to all channels
This example introduces the __poly__ construct. In previous examples when the This example introduces the __poly__ construct. In previous examples when the
network used multiple copies of the same processor they were manually constructed - each with network used multiple copies of the same processor they were manually constructed - each with
a unique suffix id. The __poly__ construct allows whole sub-networks to be duplicated a unique suffix id. The __poly__ construct allows whole sub-networks to be duplicated
and automatically assigned unique suffix id's. and automatically assigned unique suffix id's.
``` ```
simple_poly_09: { ex_09_simple_poly: {
non_real_time_fl:true, non_real_time_fl:true,
dur_limit_secs: 5.0, dur_limit_secs: 5.0,
@ -638,7 +637,10 @@ simple_poly_09: {
procs: { procs: {
// LFO gain parameters - one per poly voice
g_list: { class: list, args: { in:0, list:[ 110f,220f,440f ]}}, g_list: { class: list, args: { in:0, list:[ 110f,220f,440f ]}},
// LFO DC offset parameters - one per poly voice
dc_list: { class: list, args: { in:0, list:[ 220f,440f,880f ]}}, dc_list: { class: list, args: { in:0, list:[ 220f,440f,880f ]}},
osc_poly: { osc_poly: {
@ -663,7 +665,9 @@ simple_poly_09: {
} }
``` ```
![Example 9](svg/09_simple_poly.svg "`simple_poly_09` processing network") ![Example 9](svg/09_simple_poly.svg "`ex_09_simple_poly` processing network")
This program instantiates three modulated sine tones each with a different set of parameters.
Notice the _lfo_ `in:{...}` statement for the `dc` variable Notice the _lfo_ `in:{...}` statement for the `dc` variable
connection. The statement contains three underscores. The first connection. The statement contains three underscores. The first
@ -683,15 +687,83 @@ and desination processors share the same id. This allows the
suffix id to be dropped from the source processor and thereby to simplify suffix id to be dropped from the source processor and thereby to simplify
the syntax for connecting sub-network processors. the syntax for connecting sub-network processors.
Finally note that _poly_ to external connections are simply made Also note that _poly_ to external connections are simply made
by referring to the poly source by name to locate the source processor. by referring to the poly source by name to locate the source processor.
This is shown in the `merge` input statement `in:{ in_:osc_poly.osc_.out}`. This is shown in the `merge` input statement `in:{ in_:osc_poly.osc_.out}`.
The final characteristic to note about the poly construct
is the use of the 'parallel_fl' attribute. When this flag is
set the subnets will run concurrently in separate threads.
Since no connections between subnets is possible, and no other
processors can run, while the subnets are running this is
always safe.
### Example 10: Feedback ### Example 10: Heterogeneous polyphonic subnet
In the previous example each of the three voices shared the same network
structure. In this example there are two voice with different
networks.
``` ```
feedback_10: { ex_10_hetero_poly: {
non_real_time_fl:true,
dur_limit_secs: 5.0,
network: {
procs: {
g_list: { class: list, args: { in:0, list:[ 110f,220f,440f ]}},
dc_list: { class: list, args: { in:0, list:[ 220f,440f,880f ]}},
osc_poly: {
class: poly,
args: { parallel_fl:true },
network: [
// network 0
{
procs: {
lfo: { class: sine_tone, in:{ _.dc:_.dc_list.value_, _.gain:_.g_list.value_ } args: { ch_cnt:1, hz:3 }},
sh: { class: sample_hold, in:{ in:lfo.out }},
osc_a: { class: sine_tone, in:{ hz: sh.out }},
}
},
// network 1
{
procs: {
osc_b: { class: sine_tone, args:{ hz:55 }},
}
}
]
}
// Iterate over the instances of `osc_poly.osc_.out` to create one `audio_merge`
// input for every output from the polyphonic network.
merge: { class: audio_merge, in:{ in0:osc_poly.osc_a.out, in1:osc_poly.osc_b.out}, args:{ gain:1, out_gain:0.5 }},
af: { class: audio_file_out, in:{ in:merge.out } args:{ fname:"$/out.wav"} }
}
}
}
```
Since the structure of the two subnets is different the very compact
`in:{...}` statements used to connect the `merge` processor to
the output of each of the `osc` processors is no longer possible.
However, this example demonstrates how `caw`can be used to
run heterogeneous networks concurrently thereby makeing better
use of available hardware cores.
### Example 11: Feedback
```
ex_11_feedback: {
non_real_time_fl:true, non_real_time_fl:true,
max_cycle_count: 10, max_cycle_count: 10,
@ -705,7 +777,7 @@ feedback_10: {
} }
} }
``` ```
![Example 10](svg/10_feedback.svg "`feedback_10` processing network") ![Example 11](svg/11_feedback.svg "`ex_11_feedback` processing network")
This example demonstrates how to achieve a feedback connection using This example demonstrates how to achieve a feedback connection using
the `out:{...}` statement. Until now all the examples have been the `out:{...}` statement. Until now all the examples have been
@ -816,7 +888,7 @@ shown in the `mo_out` port.
The `mod_osc` user defined processor is instantiated and used just like a built-in processor. The `mod_osc` user defined processor is instantiated and used just like a built-in processor.
``` ```
user_defined_subnet_12 : { user_defined_proc_12 : {
non_real_time_fl: true, non_real_time_fl: true,
dur_limit_secs: 5, dur_limit_secs: 5,