Csound Csound-dev Csound-tekno Search About

[Csnd] MIDI hardware/computer keyboard interface to VST plugins: basic concept

Date2017-12-29 13:27
From"Jeanette C."
Subject[Csnd] MIDI hardware/computer keyboard interface to VST plugins: basic concept
Hey hey,
I am using Csound to design an interface to VST plugins using a hardware MIDI 
device and the computer keyboard (for some advanced features). This should be 
adaptable to many MIDI hardwar devices in the end.

I'd like to introduce the concept with some implementation details below and 
would appreciate any input on efficiency, improvements, reasonable ranges and 
boundaries of parameters. Never mind yet how the required tables will be 
filled.

Thanks to anyone who cares to comment!

Best wishes,

Jeanette
Task description
Using Csound as VST host, create an interface to a loaded VST plugin using
a hardware MIDI control device, by mapping MIDI CCs and NRPNs to VST parameters.

Problems
1. All VST parameters go from 0.0-1.0, while MIDI CCs go from 0-127 and NRPNs
 	can go from 0-16384
 	Scaling is necessary
2. A VST plugin might have many more parameters than a MIDI hardware device
 	has control elements
 	Some hardware control elements (knobs, switches/sliders) must be dedicated
 	as group switches (or page switches) to allow other control elements
 	to effect multiple VST parameters.
 	Example: switch for oscillator1, oscillator2 (which have [nearly] the
 	same parameters.
3. Connected to group switches: when a group switch is turned, the hardware
 	control elements in that group, retain their old values
 	The hardware control elements of such a "switch group" must be adjusted
 	according to the current position of the switch itself and the connected
 	VST parameter values.

Basic implementation concept
Use table lookup (through multiple stages, in case of "switch groups") to map
and scale the MIDI parameters to the VST parameters.

----------------------------------------
Implementation details:

Total size of involved ftables and arrays:
 	512 + 16512 + 128 + 16512 + 32768 + 32768 + 32768 + 32768
 	644KB (1024bytes)
 	659KB (1000bytes)

MIDI input:
 	A special UDO has been written to read MIDI input. It behaves like
 	midiin, with one exception:
 	it parses NRPNs and outputs a completed NRPN as 128 + NRPN, it also output
 	a full NRPN value (works only if all four MIDI CCs are send: 99, 98, 38 and
 	6, for 14BIT NRPN and 14BIT value)

Extra management features:
Features like save/load user presets (specific to Csound), recall original
patch, compare and possibly others will be accessible through simple computer
keyboard interface.

Switch (or switch group):
 	switch config table has 4 * 128 (max number of switch groups) = 512
 	switch_global_map: table of 16512 elements:
 		map index MIDI CC/NRPN to switch group number
 	switch_value: kArray[] of length 128, holding the actual values of the
 		switches for the groups
 	switch_config table (values are grouped in four tuples):
 		CC/NRPN (MIDI CC or NRPN used as the group switch)
 			0-16512: MIDI CC/NRPN
 			-1: no more switches, stop reading here!
 		upper bound (number of switch positions, counted from 0)
 		group size (how many elements the "switch group" has)
 		offset (offset into the auxtable where "switch group" starts)

MIDI CC/NRPN to VST param mapping
global map table (16512 elements = 128 CCs + 16384 NRPNs):
 	0: no mapping
 	0-16513: map to VST param of that number
 	-1.x-128.x: map to switch-group 1-128, element x
 		(aux tables can be premade, since they are addressed by reference numbers
 		from global table and so don't need linear I/O mapping by MIDI CC/NRPN)
 		multiply x by 100 to get element x of switch group
 	-130: pass MIDI straight to VST MIDI in
 	-129: Do nothing, no mapping
auxtable of switch groups (allocate 32768, actual elements depend on config):
 	0-16512: map to VST param of that number
 	size calculation:
 		for all siwtch groups
 			size += number of switch positions * number of group elements
scaling (allocate 32768, filled elements depend on number of VST params):
 	VST-param number as index to get scaling value

Reverse map VST-param to MIDI CC/NRPN
global table value-ranges (32768, filled elements depend on number of VST params)
 	0-16512: map to MIDI CC or NRPN-128
 	-1.x-128.x: map to switch group 1-128, element x (multiply x by 100
 		to get actual element x of switch group)
 	-129: map to nothing
auxtable value range (32768, filled elements depend on configuration):
 	0-16512: map to MIDI CC or NRPN-128
 	-129: map to nothing?

Setting VST parameters from MIDI input:
read midi:
 	status: as in midiin
 	channel: as in midiin
 	MIDI CN: 0-127 = MIDI CC, 128-16512 = NRPN + 128
 	data: value of MIDI CC or NRPN
if status == 176 (controller)
 	switch_value = query switch_map indexed by MIDI CN
 	if switch_value >0
 		turn switch
 	else
 		query MIDI global map with index MIDI CN:
 		switch globalvalue
 			0-16512:
 				VST param = globalvalue
 				scale_value = query scaletable indexed by VST-param
 				VST_value = MIDI DATA * scale_value
 				set VST parameter to VST_value
 			-1.0-128.999: query switch 1-128
 				group_element = frac(abs(globalvalue) * 100
 				offset = switch_group_offset
 				auxindex = offset + cur_switchvalue * number_of_group_elements
 				VST-param = query auxtable at auxindex
 				scale_value = query scaletable indexed by VST-param
 				VST_value = MIDI DATA * scale_value
 				set VST parameter to VST_value
 			-129:
 				do nothing
 			-130: pass MIDI CC through
 				vstmidiout status, channel, MIDI CC, DATA (doesn't work for NRPN)
 		endswitch
 	endif ; switch or VST_param

Turning a switch:
 	; We must set the connected MIDI CCs/NRPNs to the correct value, otherwise
 	; they will reflect the parameter value of the last witch position,
 	; i.e. the next adjustment of oscillator 2 coarse tune, will set it one unit
 	; from the value of oscillator1 coarse tune, since it's the same MIDI
 	; controller
 	index = 1
 	base_offset = switch_offset + switch_pos * number of group elements
 	while index <= number of switch group elements
 		readindex = base_offset + index
 		VST_param = query MIDI auxtable at readindex
 		MIDI CN = query VST auxtable at readindex
 		VST_value vstparamget VST_param
 		scale_factor = query scale table indexed by VST_param
 		if MIDI CN < 128
 			midiout 176, channel, MIDI CN, VST_value / scale_factor
 		else ; NRPN
 			nrpn MIDI CN, VST_value / scale_factor
 		endif
 		index++
 	done
*** END ***

--------
* website: http://juliencoder.de - for summer is a state of sound
* SoundCloud: https://soundcloud.com/jeanette_c

We still move to a rhythm just like this
We still dream of sharing our first kiss <3
(Britney Spears)

Csound mailing list
Csound@listserv.heanet.ie
https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND
Send bugs reports to
        https://github.com/csound/csound/issues
Discussions of bugs and features can be posted here