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.
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.
subnet_dict: "~/src/caw/src/libcw/flow/subnet_dict.cfg", // User written subnet files
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.
proc_dict: "~/src/caw/src/libcw/flow/proc_dict.cfg", // Processor class definition file.
udp_dict: "~/src/caw/src/libcw/flow/udp_dict.cfg", // User defined proc files
programs: {
rt_sine_00: {
ex_00_rt_sine: {
dur_limit_secs:5.0,
@ -21,7 +21,7 @@
}
// Demonstrate a simple two processor network.
sine_file_01: {
ex_01_sine_file: {
non_real_time_fl:true,
dur_limit_secs:5.0,
@ -37,7 +37,7 @@
// Demonstrate a simple signal processing network
mod_sine_02: {
ex_02_mod_sine: {
non_real_time_fl:true,
dur_limit_secs:5.0,
@ -55,7 +55,7 @@
// Demonstrate applying a preset at initialization time.
presets_03: {
ex_03_presets: {
non_real_time_fl:true,
dur_limit_secs:5.0,
@ -82,7 +82,7 @@
}
// Demonstrate the `print` processor and event programming.
program_04: {
ex_04_program: {
non_real_time_fl:true,
dur_limit_secs: 10.0,
@ -97,7 +97,7 @@
}
// Demonstrate 'mult' inputs.
mult_inputs_05: {
ex_05_mult_inputs: {
non_real_time_fl:true,
dur_limit_secs: 10.0,
@ -115,7 +115,7 @@
// Demonstrate different forms of the in-stmt
mult_conn_06: {
ex_06_mult_conn: {
non_real_time_fl:true,
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.
proc_suffix_07: {
ex_07_proc_suffix: {
non_real_time_fl:true,
dur_limit_secs: 5.0,
@ -172,7 +172,7 @@
}
// Demonstrate instantiating 'mult' variables from the an 'args' statement.
mix_08: {
ex_08_mix: {
non_real_time_fl:true,
dur_limit_secs:5.0,
@ -193,7 +193,7 @@
// Demonstrate a network with a polyphonic subnet.
simple_poly_09: {
ex_09_homog_poly: {
non_real_time_fl:true,
dur_limit_secs: 5.0,
@ -207,7 +207,9 @@
osc_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: {
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,
max_cycle_count: 10,
@ -243,7 +291,7 @@
},
feedback_11: {
ex_11a_feedback: {
non_real_time_fl:true,
max_cycle_count: 10,
print_network_fl: true,
@ -259,7 +307,7 @@
}
},
subnet_12 : {
ex_12_user_defined_proc : {
non_real_time_fl: true,
dur_limit_secs: 5,

View File

@ -8,13 +8,13 @@ system parameters that the program needs to compile and run the program.
``` javascript
{
base_dir: "~/src/caw/examples",
base_dir: "~/src/caw/examples/io",
proc_dict: "~/src/caw/examples/proc_dict.cfg",
mode: non_real_time,
programs: {
sine_file_01: {
ex_01_sine_file: {
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
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
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
audio file must be a stereo (`ch_cnt`=2), 440 Hertz signal with an
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.
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.
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.
__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
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.
### 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
of the sample and hold unit is then used to modulate the frequency of an audio
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`.
``` json
mod_sine_02: {
ex_02_mod_sine: {
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 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
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
audio channels generated by the audio oscillator. `presets_03` shows
`ex_02_mod_sine` showed the use of a class preset to set the number of
audio channels generated by the audio oscillator. `ex_03_presets` shows
how presets can be specified and applied for the entire network.
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.
``` JSON
presets_03: {
ex_03_presets: {
dur_limit_secs:5.0,
preset: "a",
@ -276,7 +276,7 @@ independently.
One of the simplest ways to address the individual channels of a
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
`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
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.
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
values will be applied to the processor when it is instantiated, but
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
```
program_04: {
ex_04_program: {
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.
@ -369,13 +369,13 @@ always print after the value received by `log.in`.
### 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.
As used here the __number__ processor simply holds the constant value '3'.
The __add__ processor then sums the output of _cnt_ and _numb_.
```
mult_inputs_05: {
ex_05_mult_inputs: {
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
__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.
```
mult_conn_06: {
ex_06_mult_conn: {
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,
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_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
in with a single `in:{...}` statement expression.
@ -520,7 +520,7 @@ An error should be generated.
### 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.
Using the `in:{...}` statement however variables that have the 'mult' attribute
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.
```
proc_suffix_07: {
ex_07_proc_suffix: {
dur_limit_secs: 5.0,
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
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
a single `in:{...}` expression, `in_:g_.out` which iterates over 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
case the connection is iterating over the label suffix id's of the
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.
```
mix_08: {
ex_08_mix: {
non_real_time_fl:true,
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
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
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
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,
dur_limit_secs: 5.0,
@ -638,7 +637,10 @@ simple_poly_09: {
procs: {
// LFO gain parameters - one per poly voice
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 ]}},
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
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
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.
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,
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
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.
```
user_defined_subnet_12 : {
user_defined_proc_12 : {
non_real_time_fl: true,
dur_limit_secs: 5,