notes.md : Moved DONE notes to archive.md.
Added notes on presets.
This commit is contained in:
parent
171d32f262
commit
d09d4d0311
372
notes.md
372
notes.md
@ -1070,7 +1070,11 @@ It's not clear there is a difference between specifying `_` and the default beh
|
||||
Is there a way to tell it to search the entire network from the root? Isn't that
|
||||
what '_' is supposed to do?
|
||||
|
||||
- cwAudioFile cannot convert float or double input samples to 24 bit output samples
|
||||
See audiofile::writeFloat() and audiofile::writeDouble().
|
||||
|
||||
- If a proc, inside a poly, is given a numeric suffix then that suffix will
|
||||
overwrite the label_sfx_id assigned by the system. This case should be detected.
|
||||
|
||||
Host Environments:
|
||||
------------------
|
||||
@ -1078,129 +1082,6 @@ Host Environments:
|
||||
- CLI, no GUI, w/ I/O and real-time
|
||||
- GUI, with configurable control panels
|
||||
|
||||
Done
|
||||
----
|
||||
- DONE: Remove `preset_label` and `type_src_label` from `_var_channelize()` and report error
|
||||
locations from the point of call.
|
||||
|
||||
- DONE: Move proc_dict.cfg to libcw directory.
|
||||
|
||||
- DONE: The proc inst 'args' should be able to create mult variables. The only way to instantiate
|
||||
new mult variables now is via the 'in' stmt.
|
||||
|
||||
- DONE: The `audio_merge` implementaiton is wrong. It should mimic `audio_mix` where all igain
|
||||
coeff's are instantiated even if they are not referenced.
|
||||
|
||||
- DONE: Add the `caw` examples to the test suite.
|
||||
|
||||
|
||||
- DONE: Remove the multiple 'args' thing and and 'argsLabel'. 'args' should be a simple set of arg's.
|
||||
|
||||
- DONE: Compile presets: at load time the presets should be resolved
|
||||
to the proc and vars to which they will be assigned.
|
||||
|
||||
|
||||
- DONE: (We are not removing the kAnyChIdx)
|
||||
Should the var's with multiple channels remove the 'kAnyChIdx'?
|
||||
This may be a good idea because 'kAnyChIdx' will in general not be used
|
||||
if a var has been channelized - and yet it is possible for another
|
||||
var to connect to it as a source ... which doesn't provoke an error
|
||||
but would almost certainly not do what the user expects.
|
||||
Note that the kAnyChIdx provides an easy way to set all of the channels
|
||||
of a variable to the same value.
|
||||
|
||||
- DONE: verifiy that all proc variables values have a valid type - (i.e. (type & typeMask) != 0)
|
||||
when the proc instance create is complete. This checks that both the type is assigned and
|
||||
a valid value has been assigned - since the type is assigned the first time a value is set.
|
||||
|
||||
- DONE: 'poly' should be implemented as a proc-inst with an internal network - but the
|
||||
elements of the network should be visible outside of it.
|
||||
|
||||
- DONE: 'sub' should be implemented as proc-inst with an internal network, but the
|
||||
elements of the network should not be visible outside of it. Instead it should
|
||||
include the idea of input and output ports which act as proxies to the physical
|
||||
ports of the internal elements.
|
||||
|
||||
- DONE: 'poly' and 'sub' should be arbitrarily nestable.
|
||||
|
||||
- DONE: Allow multiple types on an input.
|
||||
For example 'adder' should have a single input
|
||||
which can by any numeric type.
|
||||
|
||||
|
||||
- DONE: Make a standard way to turn on output printing from any port on any instance
|
||||
This might be a better approach to logging than having a 'printer' object.
|
||||
Add proc instance field: `log:{ var_label_0:0, var_label_1:0 } `
|
||||
|
||||
- Complete user-def-procs:
|
||||
+ User-Def-Procs should have presets written in terms of the user-def-proc vars rather than the network vars
|
||||
or the value application needs to follow the internal variable src_var back to the proxy var.
|
||||
|
||||
+ DONE: write a paragraph in the flow_doc.md about overall approach taken to user-def-proc implementation.
|
||||
|
||||
+ DONE: user-def-proc var desc's should be the same as non+user-def-proc vars but also include the 'proxy' field.
|
||||
In particular they should get default values.
|
||||
If a var desc is part of a user-def-proc then it must have a proxy.
|
||||
The output variables of var desc's must have the 'out' attribute
|
||||
|
||||
|
||||
+ DONE: improve the user-def-proc creating code by using consistent naming + use proxy or wrap but not both
|
||||
|
||||
+ DONE: improve code comments on user-def-proc creation
|
||||
|
||||
|
||||
- DONE: Implement feedback
|
||||
|
||||
- DONE: Implement the ability to set backward connections - from late to early proc's.
|
||||
This can be done by implementing the same process as 'in_stmt' but in a separate
|
||||
'out_stmt'. The difficulty is that it prevents doing some checks until the network
|
||||
is completely specified. For example if audio inputs can accept connections from
|
||||
later proc's then they will not have all of their inputs when they are instantiated.
|
||||
One way around this is to instantiate them with an initial set of inputs but then
|
||||
allow those inputs to be replaced by a later connection.
|
||||
|
||||
BUGS:
|
||||
- DONE: The counter modulo mode is not working as expected.
|
||||
|
||||
|
||||
|
||||
- DONE: Implement 'preset' proc. This will involve implementing the 'cfg' datatype.
|
||||
|
||||
- DONE: Finish the 'poly' frawework. We are making 'mult' var's, but do any of the procs explicitly deal with them?
|
||||
|
||||
- DONE: Turn on variable 'broadcast'. Why was it turned off? ... maybe multiple updates?
|
||||
|
||||
- DONE: There is no way for a proc in a poly context to use it's poly channel number to
|
||||
select a mult variable. For example in an osc in a poly has no way to select
|
||||
the frequency of the osc by conneting to a non-poly proc - like a list.
|
||||
Consider:
|
||||
1. Use a difference 'in' statememt (e.g. 'poly-in' but the
|
||||
same syntax used for connecting 'mult' variables.)
|
||||
2. Include the proc name in the 'in' var to indicate a poly index is being iterated
|
||||
e.g. `lfo: { class:sine_tone, in:{ osc_.dc:list.value_ } }`
|
||||
|
||||
- DONE: Fix up the coding language - change the use of `instance_t` to `proc_t` and `inst` to `proc`, change use of `ctx` in cwFlowProc
|
||||
|
||||
|
||||
|
||||
DONE: After the network is fully instantiated the network and class presets
|
||||
are compiled. At this point all preset values must be resolvable to
|
||||
an actual proc variable. A warning is issued for presets with values
|
||||
that cannot be resolved and they are disabled. The primary reason
|
||||
that a preset might not be resolvable is by targetting a variable
|
||||
channel that does not exist.
|
||||
|
||||
- DONE: All cfg to value conversion should go through `cfg_to_value()`.
|
||||
|
||||
|
||||
Names
|
||||
------
|
||||
ixon -
|
||||
hoot
|
||||
caw, screech, warble, coo, peep, hoot, gobble, quack, honk, whistle, tweet, cheep, chirrup, trill, squawk, seet,
|
||||
cluck,cackle,clack
|
||||
cock-a-dooodle-doo
|
||||
song,tune,aria
|
||||
|
||||
Proc instantiation
|
||||
------------------
|
||||
@ -1282,17 +1163,252 @@ caw w/ UI
|
||||
- get basic information from proc dict
|
||||
- get override information from the network
|
||||
|
||||
3.
|
||||
|
||||
|
||||
|
||||
Network Execution:
|
||||
------------------
|
||||
|
||||
1. During real-time execution the network is executed on callbacks from the audio subsytem.
|
||||
These callbacks occur asynchronously on the IO system audio processing thread.
|
||||
|
||||
2. During real-time processing the MIDI callbacks are also asynchronous.
|
||||
|
||||
|
||||
|
||||
|
||||
Uniform Presets:
|
||||
----------------
|
||||
|
||||
Preset description and application without the presence of 'poly' proc's is very straight forward:
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
example_1:
|
||||
{
|
||||
|
||||
network: {
|
||||
|
||||
procs: {
|
||||
lfo: { class: sine_tone, args:{ hz:3, dc:440, gain:110 }
|
||||
presets:
|
||||
{
|
||||
ps_a:{ hz:2, dc:220, gain:55 },
|
||||
ps_b:{ hz:4, dc:110, gain:220 },
|
||||
}
|
||||
}
|
||||
|
||||
sh: { class: sample_hold, in:{ in:lfo.out } }
|
||||
osc: { class: sine_tone, in:{ hz:sh.out }, args:{ ch_cnt:2 } },
|
||||
gain: { class: audio_gain, in:{ in:osc.out }, args:{ gain:0.3 } },
|
||||
aout: { class: audio_out, in:{ in:gain.out }, args:{ dev_label:"main"} }
|
||||
}
|
||||
|
||||
presets:
|
||||
{
|
||||
a: { gain:{ gain:0.2 } }, // One value sets both channels.
|
||||
b: { gain:{ gain:[0.1,0.3] } }, // Multi-channel preset.
|
||||
c: { osc:a880 } }, // Apply a class preset
|
||||
d: { osc:mono } }, // Apply a class preset with an ignored 'init' variable.
|
||||
f: { osc:a220, lfo:ps_a } }, // Apply a local preset and class preset
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Calling `network_apply_preset(preset_label)` with one of the network preset labels 'a'-'f' will
|
||||
work as expected in all of these cases.
|
||||
|
||||
Notes:
|
||||
|
||||
1. All preset values and proc/var's can be resolved at compile time.
|
||||
|
||||
2. Applying the network can be accomplished by resolving the network preset_label to a network_preset_t
|
||||
in network_t.presetA and calling flow::var_set() on each attached preset_value_t.
|
||||
|
||||
3. Proc preset labels, as used in presets 'c','d','e' in the example, are resolved by first looking
|
||||
for the label in the processor instance configation and then in the processor class description.
|
||||
|
||||
|
||||
---
|
||||
|
||||
The following example shows how the preset processor labels can use underscore notation to address a range of processors.
|
||||
|
||||
```
|
||||
example_2:
|
||||
{
|
||||
network: {
|
||||
procs: {
|
||||
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 ] } },
|
||||
|
||||
// Create three gain controls: g:0,g:1,g:2 using the processor label numeric suffix syntax.
|
||||
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 } },
|
||||
out: { class: audio_out, in:{ in:merge.out }, args:{ dev_label:"main" }}
|
||||
}
|
||||
|
||||
presets: {
|
||||
a: { g_: { gain:0.1 } }, // Use underscore notation to apply a preset value to g0,g1,g2.
|
||||
b: { g0_2: { gain:0.2 } }, // Use underscore notation to apply a preset value to g0 and g1.
|
||||
c: { g2: { gain:0.3 } }, // Apply a preset value to g2 only.
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Todo: This should work now.
|
||||
|
||||
---
|
||||
|
||||
|
||||
example_3: {
|
||||
|
||||
|
||||
|
||||
network: {
|
||||
|
||||
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: {
|
||||
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 }},
|
||||
},
|
||||
|
||||
presets:
|
||||
{
|
||||
a:{ lfo:{ hz:1 } },
|
||||
b:{ lfo:{ hz:2 } },
|
||||
c:{ lfo0_1: { hz:3 }, lfo2:{ hz:4 } },
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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 }},
|
||||
aout: { class: audio_out, in:{ in:merge.out } args:{ dev_label:"main"} }
|
||||
}
|
||||
|
||||
presets: {
|
||||
a:{ osc_poly:a, merge:{ out_gain:0.3 } },
|
||||
b:{ osc_poly:b, merge:{ out_gain:0.2 } },
|
||||
c:{ osc_poly:c, merge:{ out_gain:0.1 } },
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1. If a poly preset processor label does not have a numeric suffix then it is applied to all instances.
|
||||
The alternative to this rule is to use an '_' suffix to imply 'all' processors of the given name.
|
||||
|
||||
2. A preset in an outer network may not directly address a processor in an inner network, however
|
||||
it may select a named preset in an inner network.
|
||||
|
||||
3. Rule 2 can be generalized to: Network presets may only address processors which it contains directly - not nested processors.
|
||||
In the example the outer most presets may therefore address the 'osc_poly' presets by label, but not
|
||||
the processors contained by 'osc_poly'.
|
||||
|
||||
---
|
||||
|
||||
Use 'interface' objects to intercept preset values so that the
|
||||
can be processed before being passed on to a the object that
|
||||
they represent.
|
||||
|
||||
'interface' object have the same interface as the object to which their 'class' argument
|
||||
refers but do nothing other than pass the values to their output ports.
|
||||
|
||||
```
|
||||
example_4:
|
||||
{
|
||||
|
||||
network: {
|
||||
|
||||
procs: {
|
||||
|
||||
lfoIF: { class: interface, args:{ class:sine_tone } },
|
||||
|
||||
// put a modifier here
|
||||
|
||||
lfo: { class: sine_tone, in:{ hz:lfoIF.hz, dc:lfoIF.dc, gain:lfoIF.gain } }
|
||||
sh: { class: sample_hold, in:{ in:lfo.out } }
|
||||
osc: { class: sine_tone, in:{ hz:sh.out }, args:{ ch_cnt:2 } },
|
||||
gain: { class: audio_gain, in:{ in:osc.out }, args:{ gain:0.3 } },
|
||||
aout: { class: audio_out, in:{ in:gain.out }, args:{ dev_label:"main"} }
|
||||
}
|
||||
|
||||
presets:
|
||||
{
|
||||
a: { lfoIF: { hz:1, dc:110, gain:55 } },
|
||||
b: { lfoIF: { hz:2, dc:220, gain:110 } },
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
|
||||
How are presets implemented:
|
||||
|
||||
1. At compile time:
|
||||
|
||||
- Each named preset is stored as a list of value-records and label-records
|
||||
called preset-value-lists.
|
||||
|
||||
- value-records have the form { var, chIdx, value } and are created from each
|
||||
preset value that directly references a variable.
|
||||
|
||||
- label-records are formed from labeled preset references and have the form
|
||||
{ preset-value-list-ptr }. Where the list refers to the list associated with the given label.
|
||||
|
||||
|
||||
- The collection of multiple named presets are then stored as a list of
|
||||
preset-value-lists as part of the network instance in which they were defined.
|
||||
|
||||
2. At runtime the preset is applied by:
|
||||
- Resolving the preset label to a preset-value-list.
|
||||
- Calling var_set(var,chIdx,value) for all value-records
|
||||
- Iterating over all records in the list refered to preset-value-list-ptr of the label-records.
|
||||
|
||||
The notable characteristic of this approach is that it is very fast.
|
||||
With the exception of resolving the initial preset label to the top level preset-value-list
|
||||
no search or address resolution is required to apply the preset.
|
||||
|
||||
|
||||
Final Notes:
|
||||
|
||||
1. External network preset application requests that come from the control application
|
||||
(e.g. caw::main()), or requests that occur from any processor that is not in the top level,
|
||||
must be deferred until the end of the execution cycle when no processors are running.
|
||||
|
||||
Network preset application requests that occur from top level processors (processors running
|
||||
in the outmost network can be applied directly because by definition the top level processors
|
||||
run synchronously.
|
||||
|
||||
One way to handle this is to have a 'apply_preset' at the top level that takes
|
||||
a preset label as input and applies it directly.
|
||||
|
||||
2. Maybe network presets should only be 'label' based and and processor instance
|
||||
presets should only be 'value' based? Does this actually help anything?
|
||||
Given that the system isn't currently limited in this way maybe it doesn't matter.
|
||||
|
||||
3. To Do:
|
||||
|
||||
- Processor instance presets have not been implemented.
|
||||
- Preset application request deferrment has not been implemented.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user