File: matrix_spatialiser_1422.xml

package info (click to toggle)
swh-plugins 0.4.17-3
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 3,264 kB
  • sloc: ansic: 23,551; xml: 12,633; perl: 1,114; sh: 964; makefile: 218
file content (172 lines) | stat: -rw-r--r-- 5,587 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
<?xml version="1.0"?>
<!DOCTYPE ladspa SYSTEM "ladspa-swh.dtd">
<?xml-stylesheet href="ladspa.css" type="text/css"?>

<ladspa>
  <global>
    <meta name="maker" value="Joern Nettingsmeier &lt;nettings@folkwang-hochschule.de&gt;"/>
    <meta name="copyright" value="GPL"/>
    <meta name="properties" value="HARD_RT_CAPABLE"/>
    <code><![CDATA[
	/*
	   thanks to Steve Harris for walking me through my first plugin !
	*/

	#include "ladspa-util.h"

        /* we use sin/cos panning and start at pi/4. this is the correction factor
	   to bring the signal back to unity gain in neutral position.
	   it should be 1/x : sin(x) = cos(x) (~1.41421...). but since we are using an
	   approximation of sin/cos, we take its equal gain point, which leads to 1.3333...
	*/
	#define EQUALGAINPOINT_OFFSET 128.0f
	#define EQUALGAINPOINT_TO_UNITY 4.0f / 3.0f

	#define BITSPERCYCLE 10                 /* resolution of the width parameter for */
	#define BITSPERQUARTER (BITSPERCYCLE-2) /* one cycle (0-2pi) */

	/* borrowed code: http://www.dspguru.com/comp.dsp/tricks/alg/sincos.htm
	   i'm using a constant of 0.75, which makes the calculations simpler and does
	   not yield discontinuities.
	   author: Olli Niemitalo (oniemita@mail.student.oulu.fi)
	*/
	static inline void sin_cos_approx(int phasein, float *vsin, float *vcos) {
		// Modulo phase into quarter, convert to float 0..1
		float modphase = (phasein & ((1<<BITSPERQUARTER) - 1))
		* 1.0f / (1<<BITSPERQUARTER);
		// Extract quarter bits
		int quarter = phasein & (3<<BITSPERQUARTER);
		// Recognize quarter
		if (!quarter) {
			// First quarter, angle = 0 .. pi/2
			float x = modphase - 0.5f;
			float temp = 0.75f - x * x;
			*vsin = temp + x;
			*vcos = temp - x;
		} else if (quarter == 1<<BITSPERQUARTER) {
			// Second quarter, angle = pi/2 .. pi
			float x = 0.5f - modphase;
			float temp = 0.75f - x*x;
			*vsin = x + temp;
			*vcos = x - temp;
		} else if (quarter == 2<<BITSPERQUARTER) {
			// Third quarter, angle = pi .. 1.5pi
			float x = modphase - 0.5f;
			float temp = x*x - 0.75f;
			*vsin = temp - x;
			*vcos = temp + x;
		} else {
			// Fourth quarter, angle = 1.5pi..2pi
			float x = modphase - 0.5f;
			float temp = 0.75f - x*x;
			*vsin = x - temp;
			*vcos = x + temp;
		}
	}
    ]]></code>
  </global>

  <plugin label="matrixSpatialiser" id="1422" class="UtilityPlugin">
    <name>Matrix Spatialiser</name>
    <p><![CDATA[
      A simple spatializer that lets you control the width of a stereo signal.

      We convert it into a MS (mid/side) signal, manipulate the gain coefficients
      with a constant-power panning function, and reconvert to left/right stereo.

      $mid = (i_left + i_right) / 2$

      $side = (i_left - i_right) / 2$

      $width = (-pi/4)..0..(pi/4)$

      $o_left = mid * cos(width + pi/4)$
      $o_right = side * sin(width + pi/4)$

      {\small shifted by pi/4, so that 0 is neutral.}
    ]]></p>
    <callback event="instantiate"><![CDATA[
	current_m_gain = 0.0f;
	current_s_gain = 0.0f;
    ]]></callback>

    <callback event="activate"><![CDATA[
	sin_cos_approx(EQUALGAINPOINT_OFFSET, &current_s_gain, &current_m_gain);
	current_m_gain *= EQUALGAINPOINT_TO_UNITY; /* normalize the neutral  */
	current_s_gain *= EQUALGAINPOINT_TO_UNITY; /* setting to unity gain. */
    ]]></callback>

    <callback event="run"><![CDATA[
	unsigned long pos;
	LADSPA_Data mid, side;
	LADSPA_Data m_gain, s_gain;
	int width_ = f_round(width + EQUALGAINPOINT_OFFSET);

	/* smoothen the gain changes. to spread the curve over the entire
	   buffer length (i.e.#sample_count samples), make lp dependent on
	   sample_count.
	*/
	const float lp = 7.0f / (float) sample_count; /* value found by experiment */
	const float lp_i = 1.0f - lp;

	/* do approximately the same as
	   s_gain = sin(width); m_gain = cos(width);
	   but a lot faster:
	*/
	sin_cos_approx(width_, &s_gain, &m_gain);

	m_gain *= EQUALGAINPOINT_TO_UNITY; /* normalize the neutral  */
	s_gain *= EQUALGAINPOINT_TO_UNITY; /* setting to unity gain. */

	#ifdef DEBUG
	/* do a "hardware bypass" if width == 0 */
	/* no smoothing here                    */
	if (width_ == 128) {
		for (pos = 0; pos < sample_count; pos++) {
		buffer_write(o_left[pos], i_left[pos]);
		buffer_write(o_right[pos], i_right[pos]);
		}
	} else
	#endif

	for (pos = 0; pos < sample_count; pos++) {
		current_m_gain = current_m_gain * lp_i + m_gain * lp;
		current_s_gain = current_s_gain * lp_i + s_gain * lp;
		mid = (i_left[pos] + i_right[pos]) * 0.5f * current_m_gain;
		side = (i_left[pos] - i_right[pos]) * 0.5f * current_s_gain;
		buffer_write(o_left[pos], mid + side);
		buffer_write(o_right[pos], mid - side);
	}

	plugin_data->current_m_gain = current_m_gain;
	plugin_data->current_s_gain = current_s_gain;
    ]]></callback>

    <port label="i_left" dir="input" type="audio">
      <name>Input L</name>
    </port>
    <port label="i_right" dir="input" type="audio">
      <name>Input R</name>
    </port>
    <port label="width" dir="input" type="control" hint="integer,default_0">
      <name>Width</name>
      <range min="-512" max="512"/>
      <p><![CDATA[
         0 is neutral (unmodified signal)
	 + 128 is side only (=very wide)
	 - 128 is mid only (=mono)
       ]]></p>
     </port>

    <port label="o_left" dir="output" type="audio">
      <name>Output L</name>
    </port>
    <port label="o_right" dir="output" type="audio">
      <name>Output R</name>
    </port>

    <instance-data label="current_m_gain" type="LADSPA_Data" />
    <instance-data label="current_s_gain" type="LADSPA_Data" />
  </plugin>
</ladspa>