File: LPCAnalysis.h

package info (click to toggle)
supercollider-sc3-plugins 3.13.0~repack-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 20,104 kB
  • sloc: cpp: 303,352; lisp: 9,589; ansic: 3,547; sh: 96; makefile: 87; haskell: 21
file content (211 lines) | stat: -rw-r--r-- 4,821 bytes parent folder | download | duplicates (5)
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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
/*
 *  LPCAnalysis.h
 *
 *  Created by Nicholas Collins on 10/09/2009.
 *  Copyright 2009 Nicholas M Collins. All rights reserved.
 *
 */

//overloading operator_new for this class http://herosys.net/w/?p=143
//way to call RTFree/RTAlloc or new and delete via intermediate function call, to preserve implementation independence?
//no because need to call new if another class; only want variable functionality if creating array of floats, etc
//so create own classes for templates? Note that stl code already used via new anyway!
//really do just need global replacement of new and delete...
//or function calls for new and delete if creating primitives? or #ifdef SCMEMORYALLOC



//define above this header file if compiling inside SuperCollider
#define SCMEMORYALLOC 1
//

#ifdef SCMEMORYALLOC
#include "SC_PlugIn.h"
#endif

//swap to double later if necessary for greater resolution of autocorrelation calculations for numerical stability
typedef double LPCfloat;


class LPCAnalysis {

public:

	int windowsize;
	float * windowfunction; //can add later if start cross fading consecutive windows with hop
	int windowtype; //0 is rectangular, 1 is triangular, 2 is squared cosine, 3 is custom passed in buffer?

	float * input;
	//float * output;
	//int blocksize;
	int numpoles;
	int pos;
	float * coeff;
	float * last;


	int testdelta;
	LPCfloat delta;
	LPCfloat latesterror;
	float G; //gain;

	//matrix calculations at double resolution to help avoid errors?
	//storage for Levinson-Durbin iteration to calculate coefficients
	LPCfloat * R;
	LPCfloat * preva;
	LPCfloat * a;

#ifdef SCMEMORYALLOC
	struct World * world;
	InterfaceTable *ft;

	//int _blocksize, blocksize(_blocksize),
	//
	LPCAnalysis(int _windowsize, int _windowtype=0, int offset=0, World * _world=0, InterfaceTable * it=0): windowsize(_windowsize), windowtype(_windowtype), world(_world), ft(it) {

		input= (float *)RTAlloc(world, windowsize*sizeof(float));
		windowfunction= (float *)RTAlloc(world, windowsize*sizeof(float));
		//output= RTAlloc(world, blocksize*sizeof(float));
		coeff= (float *)RTAlloc(world, windowsize*sizeof(float));

		last= (float *)RTAlloc(world, windowsize*sizeof(float));
		R= (LPCfloat *)RTAlloc(world, (windowsize+1)*sizeof(LPCfloat));
		preva= (LPCfloat *)RTAlloc(world, (windowsize+1)*sizeof(LPCfloat));
		a= (LPCfloat *)RTAlloc(world, (windowsize+1)*sizeof(LPCfloat));

		zeroAll();

		pos=offset;
	}


	~LPCAnalysis() {
		RTFree(world, input);
		RTFree(world, windowfunction);
		//RTFree(world, output);
		RTFree(world, coeff);
		RTFree(world, last);
		RTFree(world, R);
		RTFree(world, preva);
		RTFree(world, a);
	}


	//must pass in world since not stored yet
	void* operator new(size_t sz, World* wd, InterfaceTable * ft) {
		return RTAlloc(wd, sizeof(LPCAnalysis));
	}

	//use stored world to sort this
	void operator delete(void* pObject) {

		LPCAnalysis * lpc = (LPCAnalysis*)pObject;
		InterfaceTable * ft= lpc->ft;

		RTFree(lpc->world, (LPCAnalysis*)pObject);
	}

#else
	//, int _blocksize ,blocksize(_blocksize)
	LPCAnalysis(int _windowsize, int _windowtype=0, int offset=0): windowsize(_windowsize), windowtype(_windowtype) {
		//need to know about stupid unit->mWorld
		input= new float[windowsize];
		windowfunction= new float[windowsize];
		//output= new float[blocksize];
		coeff= new float[windowsize];
		last= new float[windowsize];

		R= new LPCfloat[windowsize+1];
		preva= new LPCfloat[windowsize+1];
		a= new LPCfloat[windowsize+1];

		zeroAll();

		pos=offset;
	};


	~LPCAnalysis() {
		delete [] input;
		//delete [] output;
		delete [] windowfunction;
		delete [] coeff;
		delete [] last;
		delete [] R;
		delete [] preva;
		delete [] a;

	}



#endif

	void zeroAll() {

		int i;

		numpoles=10;

		pos=0;

		for (i=0; i<windowsize;++i) {
			input[i]= 0.0;
			coeff[i]=0.0;
			last[i]=0.0;
		}

		int half= windowsize>>1;

		switch(windowtype) {

		default:
		case 0:
			//rectangular window
			for (i=0; i<windowsize;++i) {
				windowfunction[i]= 1.0;
			}
			break;

		case 1:
				//triangular window
				float mult= 1.0/(float)half;
				for (i=0; i<half;++i) {
					float value= mult*((float)i);
					windowfunction[i]= value;
					windowfunction[half+i]=1.0-value;
				}


			break;
		//
//		case 2:
//
//
//			break;
//
		}


		//for (i=0; i<blocksize;++i) {
//			output[i]= 0.0;
//		}

		testdelta=0;
		delta= 0.999;
		latesterror=0.0;

		G=0.0; //gain starts at zero;
	}


	//latest value of p is number of poles for fitting; if -1 adapt using criteria
	//assess if tonal or transient via error?
	//source is driver signal for filtering, newinput is data arriving for analysis
	void update(float * newinput, float * newsource, float * output, int numSamples, int p);

	void calculateOutput(float * source, float * target, int startpos, int num);

	void calculatePoles();

};