1. Updates to examples.cfg and example.md and associated SVG's

2. Turned off websock LLL_NOTICE logs with 'extraLogsFl' in io.cfg.
This commit is contained in:
kevin 2024-09-12 17:20:29 -04:00
parent 4425693233
commit 6aea3e1ea7
5 changed files with 247 additions and 45 deletions

View File

@ -106,8 +106,8 @@
procs: {
tmr: { class: timer, args:{ period_ms:1000.0 }},
cnt: { class: counter, in: { trigger:tmr.out }, args:{ min:0, max:3, inc:1, init:0, mode:modulo } },
numb: { class: number, args:{ value:3 }},
sum: { class: add, in: { in0:cnt.out, in1:numb.value } },
numb: { class: number, args:{ in:3 }},
sum: { class: add, in: { in0:cnt.out, in1:numb.out } },
print: { class: print, in: { in0:cnt.out, in1:sum.out, eol_fl:sum.out }, args:{ text:["cnt","add","count"] }}
}
}
@ -180,12 +180,12 @@
network: {
procs: {
osc_a: { class: sine_tone, args: { hz:110 } },
osc_b: { class: sine_tone, args: { hz:220 } },
gain: { class: number, args: { value:0.5f } },
osc0: { class: sine_tone, args: { hz:110 } },
osc1: { class: sine_tone, args: { hz:220 } },
gain: { class: number, args: { in:0.5f } },
// Instantiate gain:0 and gain:1 to control the input gain of in:0 and in:1.
mix: { class: audio_mix, in: { in0:osc_a.out, in1:osc_b.out }, args:{ igain0:[0.8, 0], igain1:[0, 0.2] } },
mix: { class: audio_mix, in: { in_:osc_.out }, args:{ igain0:[0.8, 0], igain1:[0, 0.2] } },
af: { class: audio_file_out, in: { in:mix.out } args:{ fname:"$/out.wav"} }
}
}
@ -233,11 +233,11 @@
network: {
procs: {
a: { class: number, log:{value:0}, args:{ value:1 }},
b: { class: number, log:{value:0}, args:{ value:2 }},
a: { class: number, log:{out:0}, args:{ in:1 }},
b: { class: number, log:{out:0 }, args:{ in:2 }},
add: { class: add, in: { in0:a.value, in1:b.value }, out: { out:b.store },
log:{out:0}, args:{ otype:int }}
add: { class: add, in: { in0:a.out, in1:b.out }, out: { out:b.in },
log:{out:0} }
}
}
},
@ -245,13 +245,14 @@
feedback_11: {
non_real_time_fl:true,
max_cycle_count: 10,
print_network_fl: true,
network: {
procs: {
a: { class: number, log:{value:0}, args:{ value:1 }},
b: { class: reg, in:{ in:a.value }, log:{out:0} },
a: { class: number, log:{out:0}, args:{ in:1 }},
b: { class: reg, in:{ in:a.in }, log:{out:0} },
add: { class: add, in: { in0:a.value, in1:b.out }, out: { out:b.store },
add: { class: add, in: { in0:a.out, in1:b.out }, out: { out:b.in },
log:{out:0}, args:{ otype:int }}
}
}

View File

@ -21,10 +21,10 @@ system parameters that the program needs to compile and run the program.
network: {
procs: {
// Create a 'sine_tone' oscillator.
// Create a 'sine_tone' oscillator.
osc: { class: sine_tone },
// Create an audio output file and fill it with the output of the oscillator.
// Create an audio output file and fill it with the output of the oscillator.
af: { class: audio_file_out, in: { in:osc.out } args:{ fname:"$/out.wav"} }
}
}
@ -253,10 +253,10 @@ presets_03: {
}
presets: {
a: { lfo: { hz:1.0, dc:[880 770] }, osc: { gain:[0.95,0.8] } },
b: { lfo: { hz:[2.0 2.5], dc:220 }, osc: { gain:0.75 } },
c: { lfo: a880 },
d: [ a,b,0.5 ]
a: { lfo: { hz:1.0, dc:[880 770] }, osc: { gain:[0.95,0.8] } },
b: { lfo: { hz:[2.0 2.5], dc:220 }, osc: { gain:0.75 } },
c: { lfo: a880 },
d: [ a,b,0.5 ]
}
}
}
@ -322,13 +322,13 @@ TODO: Check that this accurately describes preset interpolation.
program_04: {
dur_limit_secs: 10.0,
network {
procs: {
tmr: { class: timer, args:{ period_ms:1000.0 }},
cnt: { class: counter, in: { trigger:tmr.out }, args:{ min:0, max:3, inc:1, init:0, mode:modulo } },
log: { class: print, in: { in:cnt.out, eol_fl:cnt.out }, args:{ text:["my","count"] }}
}
tmr: { class: timer, args:{ period_ms:1000.0 }},
cnt: { class: counter, in: { trigger:tmr.out }, args:{ min:0, max:3, inc:1, init:0, mode:modulo } },
log: { class: print, in: { in:cnt.out, eol_fl:cnt.out }, args:{ text:["my","count"] }}
}
}
}
```
@ -378,7 +378,7 @@ The __add__ processor then sums the output of _cnt_ and _numb_.
mult_inputs_05: {
dur_limit_secs: 10.0,
network {
procs: {
tmr: { class: timer, args:{ period_ms:1000.0 }},
@ -537,10 +537,10 @@ proc_suffix_07: {
osc: { class: sine_tone, args: { ch_cnt:6, hz:[110,220,440,880,1760, 3520] }},
split: { class: audio_split, in:{ in:osc.out }, args: { select:[ 0,0, 1,1, 2,2 ] } },
g0: { class:audio_gain, in:{ in:split0.out0 }, args:{ gain:0.9} },
g1: { class:audio_gain, in:{ in:split0.out1 }, args:{ gain:0.5} },
g2: { class:audio_gain, in:{ in:split0.out2 }, args:{ gain:0.2} },
g0: { class:audio_gain, in:{ in:split0.out0 }, args:{ gain:0.9} },
g1: { class:audio_gain, in:{ in:split0.out1 }, args:{ gain:0.5} },
g2: { class:audio_gain, in:{ in:split0.out2 }, args:{ gain:0.2} },
merge: { class: audio_merge, in:{ in_:g_.out } },
af: { class: audio_file_out, in:{ in:merge.out }, args:{ fname:"$/out_a.wav" }}
}
@ -549,7 +549,7 @@ proc_suffix_07: {
```
![Example 7](svg/07_proc_suffix.svg "`proc_suffix_06` processing network")
![Example 7](svg/07_proc_suffix.svg "`proc_suffix_07` 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:
@ -585,6 +585,206 @@ TODO:
used simultaneously on both the processor and the variable?
### Example 08: Instantiating variables from the `args:{...}` statement.
Previous examples showed how to instantiate __mult__ variables in the `in:{...}` statement.
This example shows how to instantiate __mult__ variables from the `args:{...}` statement.
An `audio_mix` processor is the perfect motivator for this feature.
A mixer is a natural example of a processor that requires a context dependent number of inputs.
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: {
non_real_time_fl:true,
dur_limit_secs:5.0,
network: {
procs: {
osc0: { class: sine_tone, args: { hz:110 } },
osc1: { class: sine_tone, args: { hz:220 } },
// Instantiate gain:0 and gain:1 to control the input gain of in:0 and in:1.
mix: { class: audio_mix, in: { in_:osc_.out }, args:{ igain0:[0.8, 0], igain1:[0, 0.2] } },
af: { class: audio_file_out, in: { in:mix.out } args:{ fname:"$/out.wav"} }
}
}
}
```
![Example 8](svg/08_mix.svg "`mix_08` processing network")
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
### Example 09: Polyphonic subnet
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.
```
simple_poly_09: {
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: { count:3 }, // Create 3 instances of 'network'.
network: {
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 }},
}
}
}
// 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:{ in_:osc_poly.osc_.out}, args:{ gain:1, out_gain:0.5 }},
af: { class: audio_file_out, in:{ in:merge.out } args:{ fname:"$/out.wav"} }
}
}
}
```
![Example 9](svg/09_simple_poly.svg "`simple_poly_09` processing network")
Notice the _lfo_ `in:{...}` statement for the `dc` variable
connection. The statement contains three underscores. The first
underscore indicates that the connection should be made to all of the
_lfo_ processors in the subnet (i.e. `lfo0`,`lfo1`,`lfo2`). The second
underscore indicates that the source is located outside the subnet.
The compiler will iterate through the network, in execution order,
looking for a processor named `dc_list` as the source. The last
underscore indicates that that the connections should begin with
`g_list.value0` and iterate forward to locate `glist.value1` and
`glist.value2` to locate the other source variables.
One subtle characteristic of the the _poly_ subnet is that the
internal connections (`lfo->sh->osc`) do not specifiy processor
id's. By default the `in:{...}` assumes that source processors
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
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}`.
### Example 10: Feedback
```
feedback_10: {
non_real_time_fl:true,
max_cycle_count: 10,
network: {
procs: {
a: { class: number, log:{out:0}, args:{ in:1 }},
b: { class: number, log:{out:0}, args:{ in:2 }},
sum: { class: add, in: { in0:a.out, in1:b.out }, out: {out:b.in }, log:{out:0} }
}
}
}
```
![Example 10](svg/10_feedback.svg "`feedback_10` processing network")
This example demonstrates how to achieve a feedback connection using
the `out:{...}` statement. Until now all the examples have been
forward connections. That is processors outputs act as sources to
processes that execute later. The `out:{...}` statement allows
connections to processes that occur earlier. The trick to making this
work is to be sure that the destination processor does not depend on
the variable receiving the feedback having a valid value on the
very first cycle of network execution - prior to the source processor
executing. One way to achieve this is to set the value of the
variable receiving the feedback to a default value in the `args:{...}`
statement. This approach is used here with the `b.in` variable.
The `log:{...}` statement is also introduced in this example.
This statement has the form `log:{ <var>:<suffix_id>, <var>:<suffix_id> ... }`.
Any variables included in the statement will be logged to the console
whenever the variable changes value. This is often a more convenient
way to monitor the changing state of the network then using calls to `print`.
The output is somewhat cryptic but it still
gives most of the necassary information to debug a program.
```
: exe cycle: process: id: variable: id vid ch : : : type:value : destination
: ---------- ----------- ----- --------------- -- --- ----- ------------: -------------
: 0 : a: 0: out: 0 vid: 2 ch: -1 : : : <invalid>:
: 0 : a: 0: out: 0 vid: 2 ch: -1 : : : i:1 :
: 0 : b: 0: out: 0 vid: 2 ch: -1 : : : <invalid>:
: 0 : b: 0: out: 0 vid: 2 ch: -1 : : : i:2 :
: 0 : add: 0: out: 0 vid: 0 ch: -1 : : : d:3.000000 : dst:b:0.in:0:
info: : Entering runtime.
: 0 : a: 0: out: 0 vid: 2 ch: -1 : : : i:1 : dst:add:0.in:0:
: 0 : b: 0: out: 0 vid: 2 ch: -1 : : : i:2 : dst:add:0.in:1:
: 0 : add: 0: out: 0 vid: 0 ch: -1 : : : d:3.000000 : dst:b:0.in:0:
: 1 : b: 0: out: 0 vid: 2 ch: -1 : : : i:3 : dst:add:0.in:1:
: 1 : add: 0: out: 0 vid: 0 ch: -1 : : : d:4.000000 : dst:b:0.in:0:
: 2 : b: 0: out: 0 vid: 2 ch: -1 : : : i:4 : dst:add:0.in:1:
: 2 : add: 0: out: 0 vid: 0 ch: -1 : : : d:5.000000 : dst:b:0.in:0:
: 3 : b: 0: out: 0 vid: 2 ch: -1 : : : i:5 : dst:add:0.in:1:
```
The `exe cycle` value give the execution cycle index. Each time the network completes
a cycle this index advances. The process and variable 'id' column gives thethe integer suffix
id's of the associated process and variable. The 'vid' column gives the variable id
for the given variable. Every variable instance is given a unique integer identifier which
allows it to be located quickly by the system. The 'ch' column indicates the channel value
of the variable, or -1 if the variable is not channelized. Recall that variables may be
channelized if the audio signal they are applied to have multiple channels. The 'type:value'
column give the data type and current value of the variable.
The data types are:
Type | Description
-----|-------------
b | bool
u | unsigned
i | int
f | float
d | double
s | string
t | time
c | cfg
abuf | audio
fbuf | spectrum
mbuf | MIDI
### Appendix:
#### Network Parameters:
Label | Description
----------------------|------------------------------------------------------------------------
`non_real_time_fl` | Run the program in non-real-time for `max_cycle_count` cycles.
`frames_per_cycle` | Count of audio sample frames per network execution cycle.
`sample_rate` | Default system audio sample rate.
`max_cycle_count` | Maximum count of network cycles to execute in non-real-time mode.
`dur_limit_secs` | Set `max_cycle_count` as (`sample_rate` * `dur_limit_secs`)/`frames_per_cycle`.
`print_class_dict_fl` |
`print_network_fl` |
### Some Invariants

View File

@ -8,7 +8,7 @@
version="1.1"
id="svg4975"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
sodipodi:docname="mult_inputs_05.svg"
sodipodi:docname="05_mult_inputs.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
@ -25,8 +25,8 @@
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="0.914906"
inkscape:cx="514.26048"
inkscape:cy="25.685699"
inkscape:cx="508.24893"
inkscape:cy="26.778707"
inkscape:window-width="1444"
inkscape:window-height="1236"
inkscape:window-x="1768"
@ -271,16 +271,16 @@
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.35759px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-dasharray:none;stroke-opacity:1"
x="70.084045"
x="72.200714"
y="101.89201"
id="text1846-1-6"><tspan
sodipodi:role="line"
id="tspan2038-46"
x="70.084045"
y="101.89201">value</tspan><tspan
x="72.200714"
y="101.89201"
id="tspan1251">out</tspan><tspan
sodipodi:role="line"
id="tspan2040-2"
x="70.084045"
x="72.200714"
y="109.839" /></text>
<rect
style="fill:#ffe6d5;stroke:#000000;stroke-width:0.3;stroke-dasharray:none;stroke-opacity:1"
@ -516,7 +516,7 @@
sodipodi:nodetypes="csc" />
<path
style="fill:none;stroke:#000000;stroke-width:0.499999;marker-end:url(#marker6190)"
d="m 79.375864,70.660447 c 0,0 16.250131,-26.542293 42.606456,-19.629019 l 36.92007,9.684148"
d="m 79.375864,70.660447 c 0,0 27.997896,-28.514648 53.632036,-19.276672 l 25.89449,9.331801"
id="path6186"
sodipodi:nodetypes="csc" />
</g>

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -25,8 +25,8 @@
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="1.829812"
inkscape:cx="-8.4708155"
inkscape:cy="127.60874"
inkscape:cx="120.23093"
inkscape:cy="61.481726"
inkscape:window-width="1444"
inkscape:window-height="1236"
inkscape:window-x="1297"
@ -120,7 +120,7 @@
id="tspan1166"
x="17.768917"
y="36.995285"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:6.35759px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.530632">osc_a</tspan></text>
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:6.35759px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.530632">osc0</tspan></text>
<rect
style="fill:#ffe6d5;stroke:#000000;stroke-width:0.3;stroke-dasharray:none;stroke-opacity:1"
id="rect1009"
@ -162,7 +162,7 @@
id="tspan1166-1"
x="18.376963"
y="64.089928"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:6.35759px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.530632">osc_b</tspan></text>
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:6.35759px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.530632">osc1</tspan></text>
<rect
style="fill:#ffe6d5;stroke:#000000;stroke-width:0.3;stroke-dasharray:none;stroke-opacity:1"
id="rect1009-2"

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -13,10 +13,11 @@
rcvBufByteN: 2048,
xmtBufByteN: 2048,
fmtBufByteN: 4096,
websockTimeOutMs: 25, // max time out while blocking for a websock event
//websockTimeOutMs: 25, // max time out while blocking for a websock event
queueBlkCnt: 8, // Initial count of websocket queue memory blocks See:cwNbMpScQueue.h
queueBlkByteCnt: 32768, // Size of each websocket queue memory block
idleMsgPeriodMs: 50, // period without messages before an idle message is generated
extraLogsFl:false, // enable the websock LLL_NOTICE logs
uiCfgFn: "ui.cfg", // default UI resource description
},