diff --git a/examples/proc_dict.cfg b/examples/proc_dict.cfg deleted file mode 100644 index 53fe709..0000000 --- a/examples/proc_dict.cfg +++ /dev/null @@ -1,630 +0,0 @@ -{ - balance: { - vars: { - in: { type:coeff, value:0.5, doc:"Input vaue" }, - out: { type:coeff, doc:"Ouput value. Same as input value."}, - inv_out: { type:coeff, doc:"1.0 minus output value."} - } - } - - audio_in: { - vars: { - dev_label: { type:string, doc:"Audio device label." }, - out: { type:audio, doc:"Audio output" }, - } - } - - audio_out: { - vars: { - dev_label: { type:string, doc:"Audio device label." }, - in: { type:audio, flags:["src"], doc:"Audio input." } - } - } - - audio_file_in: { - vars: { - fname: { type:string, doc:"Audio file name." }, - out:{ type:audio, doc:"Audio file output" }, - on_off:{ type:bool, value:false, doc:"1=on 0=off" },, - seekSecs:{ type:ftime, value:0.0, doc:"Seek to the specified seconds offset." } - eofFl:{ type:bool, value: true, doc:"Set the system 'halt' flag when the audio is completely read."}, - } - } - - audio_file_out: { - vars: { - fname: { type:string, doc:"Audio file name." }, - bits: { type:uint, value:32u, doc:"Audio file word width. (8,16,24,32,0=float32)."}, - in: { type:audio, flags:["src"], doc:"Audio file input." } - } - } - - audio_gain: { - vars: { - in: { type:audio, flags:["src"], doc:"Audio input." }, - gain: { type:coeff, value:1.0, doc:"Gain coefficient." } - out: { type:audio, doc:"Audio output." }, - } - } - - audio_split: { - vars: { - in: { type:audio, flags:["src"], doc:"Audio input." }, - select: { type:cfg, flags:["init"], doc:"Give a list of integers where each integer selects an output channel for the associated input channel." } - igain: { type:coeff, value:1.0, doc:"Audio gain for each input channel." } - ogain: { type:coeff, value:1.0, doc:"Audio gain for each output channel." } - out: { type:audio, doc:"Audio output." }, - } - - presets: - { - mute_off: { gain:1 }, - mute_on: { gain:0 }, - } - } - - - audio_duplicate: { - vars: { - in: { type:audio, flags:["src"], doc:"Audio input."}, - duplicate: { type: uint, doc:"Count of times to repeat this channel." }, - gain: { type: coeff, value:1.0, doc:"Audio gain." }, - out: { type:audio, doc:"Audio output containing repeat * input channel count channels."} - } - } - - audio_merge: { - vars: { - in: { type:audio, flags:["src", "mult"], doc:"Audio input channel." }, - gain: { type:coeff, value: 1, flags:["src", "mult"], doc:"Input channel gain." }, - out_gain: { type:coeff, value: 1, doc:"Output gain" }, - out: { type:audio, doc:"Audio output. Channel count is the sum of the input channel count." }, - } - } - - audio_mix: { - vars: { - in0: { type:audio, flags:["src"], doc:"First audio input." }, - in1: { type:audio, flags:["src"], doc:"Second audio input." }, - gain0: { type:coeff, value:0.5, doc:"Audio gain for input 0." }, - gain1: { type:coeff, value:0.5, doc:"Audio gain for input 1." }, - out: { type:audio, doc:"Audio output. Channel count is max of the input signal channels." }, - } - } - - audio_delay: { - vars: { - in: { type:audio, flags:["src"], doc:"Audio input." }, - maxDelayMs: { type:ftime, value:1000.0 doc:"Maximum possible delay in milliseconds." }, - delayMs: { type:ftime, doc:"Delay in milliseconds." }, - out: { type:audio, doc:"Audio output." }, - } - } - - - sine_tone: { - vars: { - srate: { type:srate, value:0, doc:"Sine tone sample rate. 0=Use default system sample rate"} - chCnt: { type:uint, value:2, doc:"Output signal channel count."}, - hz: { type:coeff, value:440.0, doc:"Frequency in Hertz."}, - phase: { type:coeff, value:0.0, doc:"Offset phase in radians."}, - dc: { type:coeff, value:0.0, doc:"DC offset applied after gain."}, - gain: { type:coeff, value:0.8, doc:"Signal frequency."}, - out: { type:audio, doc:"Audio output" }, - } - - presets: { - a220 : { hz:220 }, - a440 : { hz:440 }, - a880 : { hz:880 }, - mono: { chCnt:1, gain:0.75 } - } - } - - pv_analysis: { - vars: { - in: { type:audio, flags:["src"], doc:"Audio input." }, - maxWndSmpN: { type:uint, value: 512, doc:"Maximum window sample count." }, - wndSmpN: { type:uint, value: 512, doc:"Window sample count." }, - hopSmpN: { type:uint, value: 128, doc:"Hop sample count." }, - hzFl: { type:bool, value: false, doc:"Calculate frequency via the method of phase changeof each bin." }, - out: { type:spectrum, doc:"Spectrum output." } - } - - presets: { - - dry: { - wndSmpN: 512, - hopSmpN: 128 - } - - kc: { - wndSmpN: 512, - hopSmpN: 128 - } - - a: { - wndSmpN: 512, - hopSmpN: 128 - } - - b: { - wndSmpN: 512, - hopSmpN: 128 - } - - c: { - wndSmpN: 512, - hopSmpN: 128 - } - - d: { - wndSmpN: 512, - hopSmpN: 128 - } - - f_1: { - wndSmpN: 512, - hopSmpN: 128 - } - - f_2: { - wndSmpN: 512, - hopSmpN: 128 - } - - f_3: { - wndSmpN: 512, - hopSmpN: 128 - } - - f_4: { - wndSmpN: 512, - hopSmpN: 128 - } - - g: { - wndSmpN: 512, - hopSmpN: 128 - } - - g_a: { - wndSmpN: 512, - hopSmpN: 128 - } - - g_1_a: { - wndSmpN: 512, - hopSmpN: 128 - } - - g_1_d: { - wndSmpN: 512, - hopSmpN: 128 - } - } - } - - pv_synthesis: { - vars: { - in: { type:spectrum, flags:["src"], doc:"Spectrum input." }, - out: { type:audio, doc:"Audio output." } - } - } - - spec_dist: { - vars: { - in: { type:spectrum, flags:["src"], doc:"Spectrum input." }, - - bypass: { type:bool, value: false, doc:"Copy input to output without transform."}, - ceiling: { type:coeff, value: 30.0, doc:"Ceiling parameter."}, - expo: { type:coeff, value: 2.0, doc:"Exponent parameter."}, - thresh: { type:coeff, value: 54.0, doc:"Threshold parameter."}, - upr: { type:coeff, value: -0.7, doc:"Upper slope parameter."}, - lwr: { type:coeff, value: 2.0, doc:"Lower slope parameter."}, - mix: { type:coeff, value: 0.0, doc:"Basic/Bump Mix parameter."}, - - out: { type:spectrum, doc:"Spectrum output." }, - - } - - presets: { - - dry: { - - } - - kc: { - ceiling: 20.0, - expo: 2.0, - thresh: 65.0, - upr: 0.0, - lwr: 2.0, - mix: 0.0 - } - - a: { - ceiling: 20.0 - expo: 2.0 - thresh: 60.0 - upr: [ -1.1, -0.99], - lwr: 2.0 - mix: 0.0 - } - - b: { - ceiling: 20.0 - expo: 2.0 - thresh: [ 77.0, 74.0 ], - upr: -0.5 - lwr: [ 3.0, 2.0 ], - mix: 0.0 - } - - c: { - ceiling: 20.0 - expo: 2.0 - thresh: 80.0 - upr: -0.5 - lwr: 5.0 - mix: 0.0 - } - - d: { - ceiling: 20.0 - expo: 2.0 - thresh: 70.0 - upr: [ -3.9, 04.5] - lwr: 4.0 - mix: 0.0 - } - - f_1: { - ceiling: 20.0 - expo: 2.0 - thresh: 50.0 - upr: -3.0 - lwr: 1.0 - mix: 0.0 - } - - f_2: { - ceiling: 20.0 - expo: 2.0 - thresh: 60.0 - upr: -3.0 - lwr: 1.0 - mix: 0.0 - } - - f_3: { - ceiling: 20.0 - expo: 2.0 - thresh: 55.0 - upr: -3.0 - lwr: 1.0 - mix: 0.0 - } - - f_4: { - ceiling: 20.0 - expo: 2.0 - thresh: 55.0 - upr: -5.0 - lwr: 1.0 - mix: 0.0 - } - - g: { - ceiling: 40.0 - expo: 8.0 - thresh: [60.0 64.0] - upr: -0.7 - lwr: 8.0 - mix: 1.0 - } - - g_a: { - ceiling: 40.0 - expo: 2.0 - thresh: [50.0 54.0] - upr: -0.7 - lwr: 2.0 - mix: 1.0 - } - - g_1_a: { - ceiling: 20.0 - expo: 2.0 - thresh: [50.0 54.0] - upr: -0.7 - lwr: 8.0 - mix: 1.0 - } - - g_1_d: { - ceiling: [60.0 64.0] - expo: [ 7.0 5.0] - thresh: [40.0 34.0] - upr: [-0.4 -0.3] - lwr: [ 7.0 5.0] - mix: 1.0 - } - } - } - - - compressor: { - vars: { - in: { type:audio, flags:["src"] true, doc:"Audio input." }, - bypass: { type:bool, value: false, doc:"Bypass the compressor."}, - igain: { type:coeff, value: 1.0, doc:"Input gain."}, - thresh: { type:coeff, value: 90.0, doc:"Attack threshold in dB."}, - ratio: { type:coeff, value: 2.0, doc:"Compression ratio."}, - atk_ms: { type:coeff, value: 20.0, doc:"Attack time in milliseconds."}, - rls_ms: { type:coeff, value: 20.0, doc:"Release time in milliseconds."}, - wnd_ms: { type:coeff, value: 200.0, doc:"RMS calc. window length in milliseconds."}, - maxWnd_ms: { type:coeff, value: 1000.0, doc:"Maximim (allocated) window length in milliseconds."}, - ogain: { type:coeff, value: 1.0, doc:"Output gain."}, - out: { type:audio, doc:"Audio output." }, - } - - presets: { - dflt: { - igain: 3.0 - thresh: 60.0 - ratio: 5.0 - atk_ms: 5.0 - rls_ms: 20.0 - wnd_ms:100.0 - ogain: 1.0 - } - - kc: { - bypass: false - igain: 3.0 - thresh: 80.0 - ratio: 2.0 - atk_ms: 20.0 - rls_ms: 1000.0 - wnd_ms: 200.0 - ogain: 1.0 - } - - input: { - bypass: false - igain: 2.0 - thresh: 30.0 - ratio: 12.0 - atk_ms: 5.0 - rls_ms: 20.0 - wnd_ms: 20.0 - ogain: 0.5 - } - - dry: { - - } - - a: { - igain: 6.0 - ogain: 1.0 - } - - b: { - igain: 10.0 - ogain: 1.0 - } - - c: { - igain: 11.0 - ogain: 1.0 - } - - d: { - igain: 9.0 - ogain: 1.0 - } - - f_1: { - igain: 6.0 - ogain: 1.0 - } - - f_2: { - igain: 6.0 - ogain: 1.0 - } - - f_3: { - igain: 6.0 - ogain: 1.0 - } - - f_4: { - igain: 6.0 - ogain: 1.0 - } - - g: { - igain: 10.0 - ogain: 0.75 - } - - g_a: { - igain: 10.0 - ogain: 0.75 - } - - g_1_a: { - igain: 10.0 - ogain: 0.75 - } - - g_1_d: { - igain: 10.0 - ogain: 0.75 - } - - - } - } - - limiter: { - vars: { - in: { type:audio, flags:["src"] true, doc:"Audio input." }, - bypass: { type:bool, value: false, doc:"Bypass the limiter."}, - igain: { type:coeff, value: 1.0, doc:"Input gain."}, - thresh: { type:coeff, value: 0.0, doc:"Linear (0.0-1.0) threshold."}, - ogain: { type:coeff, value: 1.0, doc:"Output gain."}, - out: { type:audio, doc:"Audio output." }, - } - - presets: { - dflt: { - bypass: false, - igain: 1.0 - thresh: 0.9, - ogain: 1.0 - } - - } - } - - dc_filter: { - vars: { - in: { type:audio, flags:["src"], doc:"Audio input." }, - bypass: { type:bool, value: false, doc:"Bypass the DC filter."}, - gain: { type:coeff, value: 1.0, doc:"Output gain."}, - out: { type:audio, doc:"Audio output." }, - } - - presets: { - dflt: { - bypass: false, - gain: 1.0 - } - - } - } - - audio_meter: { - vars: { - in: { type:audio, flags:["src"], doc:"Audio input." }, - dbFl: { type:bool, value: true, doc:"Output in Decibels." }, - wndMs: { type:ftime, value: 100.0, doc:"RMS window length." }, - peakDb: { type:coeff, value: -10.0, doc:"Peak threshold." }, - out: { type:coeff, value: 0.0, doc:"Meter output." }, - peakFl: { type:bool, value: false, doc:"Peak output." } - clipFl: { type:bool, value: false, doc:"Clip indicator output."} - } - } - - subnet: { - vars: { - } - } - - poly: { - vars: { - count: { type:uint, doc:"Count of network duplicates." }, - order: { type:string, value:"net", doc:"Execution order 'net'=net first 'proc'=proc first" } - } - } - - sample_hold: { - vars: { - in: { type:audio, flags:["src"], doc:"Audio input source." }, - period_ms: { type:ftime, value:50, doc:"Sample period in milliseconds." }, - out: { type:sample, value:0.0, doc:"First value in the sample period." }, - mean: { type:sample, value:0.0, doc:"Mean value of samples in period." }, - } - } - - - number: { - vars: { - value: { type:numeric, value:0.0, doc:"Input and output value."}, - store: { type:numeric, value:0.0, doc:"Store but don't emit until the next exec."} - } - } - - timer: { - vars: { - srate: { type:srate, value:0, flags["src"], doc:"Sample rate to use as the time base. 0=Use default system sample rate." }, - period_ms: { type:ftime, value:100, doc:"Timer period in milliseconds." }, - out: { type:bool, value:false, doc:"Output pulse." }, - } - } - - counter: { - vars: { - trigger: { type:bool, flags["src"], doc:"Counter increments with each toggle of trigger." }, - reset: { type:bool, value:false, doc:"Reset the counter to the initial value." }, - init: { type:numeric, value:0.0, doc:"Counter initial value." }, - min: { type:numeric, value:0.0, doc:"Minimum output value." }, - max: { type:numeric, value:10.0, doc:"Maximum output value." }, - inc: { type:numeric, value:1.0, doc:"Incrment value." }, - repeat_fl: { type:bool, value:true, doc:"Repeat on reaching the limits." }, - mode: { type:string, value:"modulo", doc:"limit mode: 'modulo'=wrap, 'reverse'=count in opposite direction, 'clip'=repeat limit value."}, - out_type: { type:string, value:double, flags["init"], doc:"The type of the output value." }, - out: { type:runtime, value:0.0, doc:"Counter output value."}, - } - } - - // All elements of the list must belong to the same of three possible types: - // string,cfg,numeric (uint,int,float,double) - list: { - vars: { - in: { type:uint, flags:["src"], doc:"List selection index." }, - list: { type:cfg, doc:"List as a 'cfg' object." }, - out: { type:runtime, doc:"List output value." }, - value:{ type:runtime, flags["mult"], doc:"List 'mult' output per list value." }, - } - } - - add: { - vars: { - in: { type:numeric, flags:["src","mult"], doc:"Operands" }, - otype: { type:string, value:double, flags:["init"], doc:"The type of the output value." }, - out: { type:runtime, flags:["no_src"], doc:"Result" }, - } - } - - preset: { - vars: { - in: { type:string, flags:["src"], doc:"Preset to select." }, - } - } - - - xfade_ctl: { - - poly_limit_cnt: 1, - - // Notes: - // 1. It would be better to setup the source net-proc as a 'in' variable with type 'net'. - // 2. The only purpose for the 'srateSrc' is to get the sample rate of the system. - - vars: { - net: { type:string, doc:"Proc name of the poly network."}, - netSfxId: { type:uint, value: 0, doc:"Label sfx id of the source poly instance."}, - srateSrc: { type:audio, flags:["src"], doc:"Audio source to derive the sample rate."}, - durMs: { type:uint, value:1000, doc:"Cross-fade duration in milliseconds" }, - trigger: { type:all, doc:"Start cross-fade." }, - preset: { type:string, doc:"Preset to apply to the poly network." }, - - gain: { type:coeff, flags:["mult"], value:0, doc:"Cross-fade gain output." } - } - }, - - print: { - vars: { - in: { type:all, flags:["mult"], doc: "Value to print." }, - eol_fl: { type:all, doc: "Trigger an end-of-line." }, - text: { type:cfg, doc: "List of labels." }, - } - } - - -} diff --git a/examples/subnet_dict.cfg b/examples/subnet_dict.cfg deleted file mode 100644 index c0b236d..0000000 --- a/examples/subnet_dict.cfg +++ /dev/null @@ -1,34 +0,0 @@ -{ - mod_osc: { - - vars: { - hz: { proxy:hz_lfo.dc, doc:"Audio frequency" }, - hz_mod_hz: { proxy:hz_lfo.hz, doc:"Frequency modulator hz" }, - hz_mod_depth: { proxy:hz_lfo.gain, doc:"Frequency modulator depth" }, - amp_mod_hz: { proxy:amp_lfo.hz, doc:"Amplitude modulator hz" }, - amp_mod_depth: { proxy:amp_lfo.gain, doc:"Amplutide modulator depth."}, - mo_out: { proxy:ogain.out flags:[out] doc:"Oscillator output."}, - }, - - network: { - procs: { - hz_lfo: { class: sine_tone, args: { chCnt:1 }} - hz_sh: { class: sample_hold, in:{ in:hz_lfo.out }} - - amp_lfo: { class: sine_tone, args: { chCnt:1 }} - amp_sh: { class: sample_hold, in:{ in:amp_lfo.out }} - - osc: { class: sine_tone, in:{ hz: hz_sh.out }} - ogain: { class: audio_gain, in:{ in:osc.out, gain:amp_sh.out}} - } - - presets: { - net_a: { hz_lfo: { dc:220, gain:55 }, amp_lfo: { gain:0.8 } }, - net_b: { hz_lfo: { dc:110, gain:25 }, amp_lfo: { gain:0.7 } }, - } - } - } - - - -} \ No newline at end of file diff --git a/src/caw/caw_0.cfg b/src/caw/caw_0.cfg new file mode 100644 index 0000000..832f3ac --- /dev/null +++ b/src/caw/caw_0.cfg @@ -0,0 +1,6 @@ +{ + flow: "~/src/caw/src/caw/main.cfg" + io: "~/src/caw/src/caw/cfg/io.cfg" + + +} \ No newline at end of file diff --git a/src/caw/cfg/io.cfg b/src/caw/cfg/io.cfg index 4067f74..03f80bf 100644 --- a/src/caw/cfg/io.cfg +++ b/src/caw/cfg/io.cfg @@ -7,13 +7,15 @@ ui: { enableFl: true, asyncFl: false, - physRootDir: "~/src/cw_io_template/src/proj/html", + physRootDir: "~/src/caw/src/caw/html", dfltPageFn: "index.html", port: 5687, rcvBufByteN: 2048, xmtBufByteN: 2048, fmtBufByteN: 4096, - websockTimeOutMs: 50, // 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 uiCfgFn: "ui.cfg", // default UI resource description }, @@ -38,9 +40,12 @@ }, midi: { - enableFl: false, + enableFl: true, + asyncFl: true, parseBufByteCnt: 1024, - appNameStr: "cwtest", + enableBufFl: true, // Buffer all incoming msgs until RT thread can accept them. + bufferMsgCnt: 4096, // Size of RT msg buffer. + appNameStr: "caw", fileDevName: "file_dev", fileDevReadAheadMicros: 3000, testFileLabel: "file_0", @@ -53,18 +58,17 @@ "enableFl": false }, ] - asyncFl: true, }, audio: { - enableFl: false, + enableFl: true, meterMs: 50, // audio meter filter length and meter callback period threadTimeOutMs: 50, // audio thread cond var time out groupL: [ { - enableFl: false, // (req) + enableFl: true, // (req) asyncFl: true, label: "main", // (req) User label id: 0, // (req) User id (can also be set at runtime) @@ -81,7 +85,7 @@ device: "USB Audio CODEC USB Audio", //device: "HDA Intel PCH CS4208 Analog", - activeFl: false, // (req) + activeFl: true, // (req) meterFl: true, // (opt) label: "main", // (req) User label userId: 0, // (opt) User id (can also be set at runtime) diff --git a/src/caw/main.cfg b/src/caw/main.cfg index 6c057ef..15dae65 100644 --- a/src/caw/main.cfg +++ b/src/caw/main.cfg @@ -1,15 +1,24 @@ { - param: 5, base_dir: "~/src/caw/examples", - proc_dict: "~/src/caw/examples/proc_dict.cfg", - subnet_dict: "~/src/caw/examples/subnet_dict.cfg", - mode: non_real_time, - - + proc_dict: "~/src/caw/src/libcw/flow/proc_dict.cfg", + subnet_dict: "~/src/caw/src/libcw/flow/subnet_dict.cfg", + programs: { + rt_sine_00: { + network: { + + procs: { + osc: { class:sine_tone, args:{ hz:100.0 }}, + aout:{ class:audio_out, in:{ in:osc.out }, args:{ dev_label:"main"} } + } + } + } + + // Demonstrate a simple two processor network. sine_file_01: { + non_real_time_fl:true, durLimitSecs:5.0, network: { @@ -22,8 +31,10 @@ } + // Demonstrate simple signal processing and how to apply a processor class prefix. mod_sine_02: { + non_real_time_fl:true, durLimitSecs:5.0, network: { @@ -37,8 +48,11 @@ } } + + // Demonstrate applying a preset at initialization time. presets_03: { + non_real_time_fl:true, durLimitSecs:5.0, preset: "a", @@ -62,8 +76,10 @@ } } + // Demonstrate the `print` processor and event programming. program_04: { + non_real_time_fl:true, durLimitSecs: 10.0, network { @@ -74,9 +90,11 @@ } } } - + + // Demonstrate 'mult' inputs. mult_inputs_05: { + non_real_time_fl:true, durLimitSecs: 10.0, network: { @@ -85,12 +103,15 @@ 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 } }, - print: { class: print, in: { in0:cnt.out, in1:sum.out, eol_fl:cnt.out }, args:{ text:["cnt","add","count"] }} + print: { class: print, in: { in0:cnt.out, in1:sum.out, eol_fl:sum.out }, args:{ text:["cnt","add","count"] }} } } } + + // Demonstrate different forms of the in-stmt mult_conn_06: { + non_real_time_fl:true, durLimitSecs: 5.0, network: { @@ -114,28 +135,122 @@ } } - proc_suffix_07: { + + // Demonstrate creating processors with explicit sfx-ids and connecting to them with a single in-stmt. + proc_suffix_07: { + non_real_time_fl:true, + durLimitSecs: 5.0, + + network: { + procs: { + osc: { class: sine_tone, args: { chCnt: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 3 audio gain controls with explicit sfx-ids + 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.1} }, + + // Create audio-merge inputs and connect them to 3 consecutive gain controls + // by iterating the in-stmt over the source proc sfx-id. + merge: { class: audio_merge, in:{ in_:g_.out } }, + af: { class: audio_file_out, in:{ in:merge.out }, args:{ fname:"$/out_a.wav" }} + + + } + } + } + + // Demonstrate instantiating 'mult' variables from the an 'args' statement. + mix_08: { + + non_real_time_fl:true, + durLimitSecs:5.0, + + 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 } }, + + // 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] } }, + af: { class: audio_file_out, in: { in:mix.out } args:{ fname:"$/out.wav"} } + } + } + } + + + // Demonstrate a network with a polyphonic subnet. + simple_poly_09: { + + non_real_time_fl:true, durLimitSecs: 5.0, network: { - procs: { - osc: { class: sine_tone, args: { chCnt: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.1} }, - - - merge: { class: audio_merge, in:{ in_:g_.out } }, - af: { class: audio_file_out, in:{ in:merge.out }, args:{ fname:"$/out_a.wav" }} - - - } - } - } + 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: { chCnt: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"} } + } + } + } + + + feedback_10: { + non_real_time_fl:true, + maxCycleCount: 10, + + network: { + procs: { + a: { class: number, log:{value:0}, args:{ value:1 }}, + b: { class: number, log:{value:0}, args:{ value:2 }}, + + add: { class: add, in: { in0:a.value, in1:b.value }, out: { out:b.store }, + log:{out:0}, args:{ otype:int }} + } + } + }, + + feedback_11: { + non_real_time_fl:true, + maxCycleCount: 10, + + network: { + procs: { + a: { class: number, log:{value:0}, args:{ value:1 }}, + b: { class: reg, in:{ in:a.value }, log:{out:0} }, + + add: { class: add, in: { in0:a.value, in1:b.out }, out: { out:b.store }, + log:{out:0}, args:{ otype:int }} + } + } + }, + + + } } \ No newline at end of file diff --git a/src/caw/main.cpp b/src/caw/main.cpp index e028d59..7e8fe8b 100644 --- a/src/caw/main.cpp +++ b/src/caw/main.cpp @@ -6,13 +6,11 @@ #include "cwText.h" #include "cwObject.h" #include "cwFileSys.h" -#include "cwTime.h" -#include "cwMidiDecls.h" -#include "cwFlowDecl.h" -#include "cwFlow.h" - #include "cwIo.h" +#include "cwIoFlowCtl.h" + + using namespace cw; @@ -20,20 +18,15 @@ rc_t test( const object_t* cfg, int argc, char* argv[] ); typedef struct app_str { - object_t* cfg; // complete cfg. + object_t* cfg; // complete cfg. - bool real_time_fl; // Execute in non-real-time mode - const char* pgm_label; // - const object_t* pgm_cfg; // - const char* base_dir; // - char* proj_dir; // Project directory / - object_t* io_cfg; // IO lib cfg. - object_t* proc_class_dict_cfg; // - object_t* subnet_dict_cfg; - - unsigned value; - io::handle_t ioH; + object_t* flow_cfg; // flow program cfg + object_t* io_cfg; // IO lib cfg. + const char* cmd_line_pgm_label; // + io::handle_t ioH; + io_flow_ctl::handle_t ioFlowH; + } app_t; enum @@ -65,6 +58,36 @@ void print( void* arg, const char* text ) printf("%s\n",text); } +rc_t _load_init_pgm( app_t& app, const char* pgm_label, bool& exec_complete_fl_ref ) +{ + rc_t rc = kOkRC; + unsigned pgm_idx; + + exec_complete_fl_ref = false; + + if((pgm_idx = program_index(app.ioFlowH,pgm_label)) == kInvalidIdx ) + { + rc = cwLogError(kInvalidArgRC,"A program named '%s' was not be found.",cwStringNullGuard(pgm_label)); + goto errLabel; + } + + if((rc = program_load(app.ioFlowH,pgm_idx)) != kOkRC ) + { + rc = cwLogError(rc,"Program load failed on '%s'.",cwStringNullGuard(pgm_label)); + goto errLabel; + } + + if( is_program_nrt(app.ioFlowH) ) + { + exec_complete_fl_ref = true; + if((rc = exec_nrt(app.ioFlowH)) != kOkRC ) + goto errLabel; + } + + +errLabel: + return rc; +} rc_t _ui_value_callback(app_t* app, const io::ui_msg_t& m ) { @@ -90,8 +113,8 @@ rc_t _ui_value_callback(app_t* app, const io::ui_msg_t& m ) break; case kValueNumbId: - app->value = m.value->u.u; - cwLogInfo("Setting value:%i",app->value); + //app->value = m.value->u.u; + //cwLogInfo("Setting value:%i",app->value); break; } @@ -104,7 +127,7 @@ rc_t _ui_echo_callback(app_t* app, const io::ui_msg_t& m ) { case kValueNumbId: { - uiSendValue( app->ioH, io::uiFindElementUuId( app->ioH, kValueNumbId ), app->value ); + //uiSendValue( app->ioH, io::uiFindElementUuId( app->ioH, kValueNumbId ), app->value ); } break; @@ -184,6 +207,8 @@ rc_t _io_callback( void* arg, const io::msg_t* m ) break; case io::kAudioTId: + if( app->ioFlowH.isValid() && m != nullptr ) + io_flow_ctl::exec(app->ioFlowH,*m); break; case io::kAudioMeterTId: @@ -209,15 +234,11 @@ rc_t _io_callback( void* arg, const io::msg_t* m ) return kOkRC; } -rc_t _parse_cfg( app_t& app, int argc, char* argv[] ) +rc_t _parse_main_cfg( app_t& app, int argc, char* argv[] ) { rc_t rc = kOkRC; - const char* io_cfg_fn = nullptr; - const char* mode_label = nullptr; - const object_t* pgmL = nullptr; - const char* proc_cfg_fname = nullptr; - const char* subnet_cfg_fname = nullptr; - if( argc < 3 ) + + if( argc < 2 ) { cwLogPrint("Usage: caw "); rc = kInvalidArgRC; @@ -225,124 +246,59 @@ rc_t _parse_cfg( app_t& app, int argc, char* argv[] ) } else { + const char* io_cfg_fn = nullptr; + const char* flow_cfg_fn = nullptr; + + // check for pgm label + if( argc > 2 ) + { + if( textLength(argv[2]) == 0 ) + { + rc = cwLogError(kSyntaxErrorRC,"The command line program label is blank or invalid valid."); + goto errLabel; + } + + app.cmd_line_pgm_label = argv[2]; + } + // parse the cfg. file if((rc = objectFromFile(argv[1],app.cfg)) != kOkRC ) { rc = cwLogError(rc,"Parsing failed on the cfg. file '%s'.",argv[1]); goto errLabel; } - - // parse the cfg parameters - if((rc = app.cfg->readv("param", 0, app.value, - "io_cfg", kOptFl, io_cfg_fn, - "base_dir", 0, app.base_dir, - "proc_dict",0,proc_cfg_fname, - "subnet_dict",0,subnet_cfg_fname, - "mode", 0, mode_label, - "programs", kDictTId, pgmL)) != kOkRC ) + + // read the cfg file + if((rc = app.cfg->readv("flow", kReqFl, flow_cfg_fn, + "io", kReqFl, io_cfg_fn)) != kOkRC ) { - rc = cwLogError(rc,"'caw' system parameter processing failed."); + rc = cwLogError(rc,"Parsing failed on '%s'.",argv[1]); goto errLabel; } - // set the real-time mode flag - app.real_time_fl = !textIsEqual(mode_label,"non_real_time"); - - // if we are in real-time mode then the io_cfg file must be given - if( app.real_time_fl && io_cfg_fn == nullptr ) + // parse the IO cfg file + if((rc = objectFromFile(io_cfg_fn,app.io_cfg)) != kOkRC ) { - rc = cwLogError(kSyntaxErrorRC,"To operation in real-time mode an 'io_cfg' file must be provided."); - goto errLabel; - } - - // parse the 'io_cfg' file - if( app.real_time_fl ) - if((rc = objectFromFile(io_cfg_fn,app.io_cfg)) != kOkRC ) - { - rc = cwLogError(rc,"'caw' IO cfg. file parsing failed on '%s'.",cwStringNullGuard(io_cfg_fn)); - goto errLabel; - } - - - // parse the proc dict. file - if((rc = objectFromFile(proc_cfg_fname,app.proc_class_dict_cfg)) != kOkRC ) - { - rc = cwLogError(rc,"The flow proc dictionary could not be read from '%s'.",cwStringNullGuard(proc_cfg_fname)); + rc = cwLogError(rc,"Parsing failed on '%s'.",cwStringNullGuard(io_cfg_fn)); goto errLabel; } - // parse the subnet dict file - if((rc = objectFromFile(subnet_cfg_fname,app.subnet_dict_cfg)) != kOkRC ) + // parse the flow cfg file + if((rc = objectFromFile(flow_cfg_fn,app.flow_cfg)) != kOkRC ) { - rc = cwLogError(rc,"The flow subnet dictionary could not be read from '%s'.",cwStringNullGuard(subnet_cfg_fname)); + rc = cwLogError(rc,"Parsing failed on '%s'.",cwStringNullGuard(flow_cfg_fn)); goto errLabel; } - - // get the pgm label - if( textLength(argv[2]) == 0 ) - { - rc = cwLogError(kSyntaxErrorRC,"No 'caw' program label was given."); - goto errLabel; - } - - app.pgm_label = argv[2]; - - // find the parameters for the requested program - for(unsigned i=0; ichild_count(); i++) - { - const object_t* pgm = pgmL->child_ele(i); - if( textIsEqual( pgm->pair_label(), app.pgm_label ) ) - { - if( pgm->pair_value() == nullptr || !pgm->pair_value()->is_dict() ) - { - rc = cwLogError(kSyntaxErrorRC,"The parameters for the program '%s' is not a dictionary.",cwStringNullGuard(app.pgm_label)); - goto errLabel; - } - - app.pgm_cfg = pgm->pair_value(); - break; - } - } - - if( app.pgm_cfg == nullptr ) - rc =cwLogError(kEleNotFoundRC,"The program '%s' was not found in the cfg. program list.",cwStringNullGuard(app.pgm_label)); - else - { - if((app.proj_dir = filesys::makeFn(app.base_dir,nullptr,nullptr,app.pgm_label,nullptr)) == nullptr ) - { - rc = cwLogError(kOpFailRC,"An error occurred while forming the the project directory name for '%s' / '%s'.",cwStringNullGuard(app.base_dir),cwStringNullGuard(app.pgm_label)); - goto errLabel; - } - - if( !filesys::isDir(app.proj_dir)) - { - if((rc = filesys::makeDir(app.proj_dir)) != kOkRC ) - { - rc = cwLogError(kOpFailRC,"Project directory create failed."); - goto errLabel; - } - } - } - - } + errLabel: - if( rc != kOkRC ) - rc = cwLogError(rc,"App. cfg. parse failed."); return rc; } -rc_t _main_gui( app_t& app ) +rc_t _io_main( app_t& app ) { rc_t rc = kOkRC; - if((rc = create( app.ioH, app.io_cfg, _io_callback, &app, appIdMapA, appIdMapN ) ) != kOkRC ) - { - rc = cwLogError(rc,"IO create failed."); - goto errLabel; - } - - // start the IO framework instance if((rc = io::start(app.ioH)) != kOkRC ) { @@ -351,7 +307,7 @@ rc_t _main_gui( app_t& app ) } - // execute the io framework + // execute the IO framework while( !io::isShuttingDown(app.ioH)) { // This call will block on the websocket handle @@ -373,60 +329,63 @@ errLabel: } - int main( int argc, char* argv[] ) { rc_t rc = kOkRC; app_t app = {}; - flow::handle_t flowH; + bool exec_complete_fl = false; cw::log::createGlobal(); - - cwLogInfo("caw: args:%i", argc); - if((rc = _parse_cfg(app,argc,argv)) != kOkRC ) + unsigned appIdMapN = sizeof(appIdMapA)/sizeof(appIdMapA[0]); + + if((rc= _parse_main_cfg(app, argc, argv )) != kOkRC ) goto errLabel; - // create the flow object - if((rc = create( flowH, - app.proc_class_dict_cfg, - app.pgm_cfg, - app.subnet_dict_cfg, - app.proj_dir)) != kOkRC ) + // instantiate the IO framework + if((rc = create( app.ioH, app.io_cfg, _io_callback, &app, appIdMapA, appIdMapN, nullptr )) != kOkRC ) { - //rc = cwLogError(rc,"Flow object create failed."); + rc = cwLogError(rc,"IO Framework instantiation failed."); goto errLabel; } - // run the network - if((rc = exec( flowH )) != kOkRC ) - rc = cwLogError(rc,"Execution failed."); - + report(app.ioH); + + // instantiate the IO flow controller + if((rc = create( app.ioFlowH, app.ioH, app.flow_cfg)) != kOkRC ) + { + rc = cwLogError(rc,"IO-Flow instantiation failed."); + goto errLabel; + } + + if( app.cmd_line_pgm_label != nullptr ) + if((rc = _load_init_pgm(app, app.cmd_line_pgm_label, exec_complete_fl )) != kOkRC ) + goto errLabel; + + + if( !exec_complete_fl ) + _io_main(app); + + errLabel: - // destroy the flow object - if((rc = destroy(flowH)) != kOkRC ) - { - rc = cwLogError(rc,"Close the flow object."); - goto errLabel; - } - - destroy(app.ioH); + if((rc = destroy(app.ioFlowH)) != kOkRC ) + rc = cwLogError(rc,"IO Flow destroy failed."); - mem::release(app.proj_dir); + if((rc = destroy(app.ioH)) != kOkRC ) + rc = cwLogError(rc,"IO destroy failed."); - if( app.proc_class_dict_cfg != nullptr ) - app.proc_class_dict_cfg->free(); - - if( app.subnet_dict_cfg != nullptr ) - app.subnet_dict_cfg->free(); - if( app.io_cfg != nullptr ) app.io_cfg->free(); + if( app.flow_cfg != nullptr ) + app.flow_cfg->free(); + if( app.cfg != nullptr ) app.cfg->free(); - - cw::log::destroyGlobal(); - return 0; + cw::log::destroyGlobal(); + + return rc; } + +