SAF
Loading...
Searching...
No Matches
matrixconv.c
Go to the documentation of this file.
1/*
2 * Copyright 2019 Leo McCormack
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
15 */
16
25#include "matrixconv.h"
26#include "matrixconv_internal.h"
27
29(
30 void ** const phMCnv
31)
32{
34 *phMCnv = (void*)pData;
35
36 /* Default user parameters */
37 pData->nInputChannels = 1;
38 pData->enablePartitionedConv = 0;
39
40 /* internal values */
41 pData->hostBlockSize = -1; /* force initialisation */
42 pData->inputFrameTD = NULL;
43 pData->outputFrameTD = NULL;
44 pData->hMatrixConv = NULL;
45 pData->filters = NULL;
46 pData->reInitFilters = 1;
47 pData->nfilters = 0;
48 pData->filter_length = 0;
49 pData->filter_fs = 0;
50 pData->input_wav_length = 0;
51 pData->nOutputChannels = 0;
52
53 /* set FIFO buffers */
54 pData->host_fs = 48000.0f;
55 pData->FIFO_idx = 0;
56 pData->inFIFO = (float**)calloc2d(MAX_NUM_CHANNELS, MAX_FRAME_SIZE, sizeof(float));
57 pData->outFIFO = (float**)calloc2d(MAX_NUM_CHANNELS, MAX_FRAME_SIZE, sizeof(float));
58}
59
61(
62 void ** const phMCnv
63)
64{
65 matrixconv_data *pData = (matrixconv_data*)(*phMCnv);
66
67 if (pData != NULL) {
68 free(pData->inputFrameTD);
69 free(pData->outputFrameTD);
70 free(pData->filters);
72 free(pData->inFIFO);
73 free(pData->outFIFO);
74 free(pData);
75 pData = NULL;
76 *phMCnv = NULL;
77 }
78}
79
81(
82 void * const hMCnv,
83 int sampleRate,
84 int hostBlockSize
85)
86{
87 matrixconv_data *pData = (matrixconv_data*)(hMCnv);
88
89 pData->host_fs = sampleRate;
90
91 if(pData->hostBlockSize != hostBlockSize){
92 pData->hostBlockSize = hostBlockSize;
94 pData->reInitFilters = 1;
95 }
96
98}
99
101(
102 void * const hMCnv,
103 const float *const * inputs,
104 float* const* const outputs,
105 int nInputs,
106 int nOutputs,
107 int nSamples
108)
109{
110 matrixconv_data *pData = (matrixconv_data*)(hMCnv);
111 int s, ch, i;
112 int numInputChannels, numOutputChannels;
113
115
116 /* prep */
117 numInputChannels = pData->nInputChannels;
118 numOutputChannels = pData->nOutputChannels;
119
120 for(s=0; s<nSamples; s++){
121 /* Load input signals into inFIFO buffer */
122 for(ch=0; ch<SAF_MIN(SAF_MIN(nInputs,numInputChannels),MAX_NUM_CHANNELS); ch++)
123 pData->inFIFO[ch][pData->FIFO_idx] = inputs[ch][s];
124 for(; ch<numInputChannels; ch++) /* Zero any channels that were not given */
125 pData->inFIFO[ch][pData->FIFO_idx] = 0.0f;
126
127 /* Pull output signals from outFIFO buffer */
128 for(ch=0; ch<SAF_MIN(SAF_MIN(nOutputs, numOutputChannels),MAX_NUM_CHANNELS); ch++)
129 outputs[ch][s] = pData->outFIFO[ch][pData->FIFO_idx];
130 for(; ch<nOutputs; ch++) /* Zero any extra channels */
131 outputs[ch][s] = 0.0f;
132
133 /* Increment buffer index */
134 pData->FIFO_idx++;
135
136 /* Process frame if inFIFO is full and filters are loaded and saf_matrixConv_apply is ready for it */
137 if (pData->FIFO_idx >= pData->hostBlockSize_clamped && pData->reInitFilters == 0 ) {
138 pData->FIFO_idx = 0;
139
140 /* Load time-domain data */
141 for(i=0; i < numInputChannels; i++)
142 utility_svvcopy(pData->inFIFO[i], pData->hostBlockSize_clamped, pData->inputFrameTD[i]);
143
144 /* Apply matrix convolution */
145 if(pData->hMatrixConv != NULL && pData->filter_length>0)
147 /* if the matrix convolver handle has not been initialised yet (i.e. no filters have been loaded) then zero the output */
148 else
149 memset(FLATTEN2D(pData->outputFrameTD), 0, MAX_NUM_CHANNELS * (pData->hostBlockSize_clamped)*sizeof(float));
150
151 /* copy signals to output buffer */
152 for (i = 0; i < SAF_MIN(numOutputChannels, MAX_NUM_CHANNELS); i++)
153 utility_svvcopy(pData->outputFrameTD[i], pData->hostBlockSize_clamped, pData->outFIFO[i]);
154 }
155 else if(pData->FIFO_idx >= pData->hostBlockSize_clamped){
156 /* clear outFIFO if codec was not ready */
157 pData->FIFO_idx = 0;
158 memset(FLATTEN2D(pData->outFIFO), 0, MAX_NUM_CHANNELS*MAX_FRAME_SIZE*sizeof(float));
159 }
160 }
161}
162
163
164/*sets*/
165
166void matrixconv_refreshParams(void* const hMCnv)
167{
168 matrixconv_data *pData = (matrixconv_data*)(hMCnv);
169 pData->reInitFilters = 1;
170}
171
172void matrixconv_checkReInit(void* const hMCnv)
173{
174 matrixconv_data *pData = (matrixconv_data*)(hMCnv);
175
176 /* reinitialise if needed */
177 if ((pData->reInitFilters == 1) && (pData->filters != NULL)) {
178 pData->reInitFilters = 2;
180 pData->hMatrixConv = NULL;
181
182 /* if length of the loaded wav file was not divisable by the specified number of inputs, then the handle remains NULL,
183 * and no convolution is applied */
185 if(pData->filter_length>0){
187 pData->hostBlockSize_clamped, /*pData->hostBlockSize,*/
188 pData->filters,
189 pData->filter_length,
190 pData->nInputChannels,
191 pData->nOutputChannels,
192 pData->enablePartitionedConv);
193 }
194
195 /* Resize buffers */
196 pData->inputFrameTD = (float**)realloc2d((void**)pData->inputFrameTD, MAX_NUM_CHANNELS, pData->hostBlockSize_clamped, sizeof(float));
197 pData->outputFrameTD = (float**)realloc2d((void**)pData->outputFrameTD, MAX_NUM_CHANNELS, pData->hostBlockSize_clamped, sizeof(float));
198 memset(FLATTEN2D(pData->inputFrameTD), 0, MAX_NUM_CHANNELS*(pData->hostBlockSize_clamped)*sizeof(float));
199
200 /* reset FIFO buffers */
201 pData->FIFO_idx = 0;
202 memset(FLATTEN2D(pData->inFIFO), 0, MAX_NUM_CHANNELS*MAX_FRAME_SIZE*sizeof(float));
203 memset(FLATTEN2D(pData->outFIFO), 0, MAX_NUM_CHANNELS*MAX_FRAME_SIZE*sizeof(float));
204
205 pData->reInitFilters = 0;
206 }
207}
208
210(
211 void* const hMCnv,
212 const float* const* H,
213 int numChannels,
214 int numSamples,
215 int sampleRate
216)
217{
218 matrixconv_data *pData = (matrixconv_data*)(hMCnv);
219 int i;
220 saf_assert(numChannels<=MAX_NUM_CHANNELS_FOR_WAV && numChannels > 0 && numSamples > 0, "WAV is limited to 1024 channels");
221
222 pData->nOutputChannels = SAF_MIN(numChannels, MAX_NUM_CHANNELS);
223 pData->input_wav_length = numSamples;
224 pData->nfilters = (pData->nOutputChannels) * (pData->nInputChannels);
225
226 /* store the loaded filters */
227 pData->filters = realloc1d(pData->filters, numChannels * numSamples * sizeof(float));
228 for(i=0; i<numChannels; i++)
229 memcpy(&(pData->filters[i*numSamples]), H[i], numSamples * sizeof(float));
230 pData->filter_fs = sampleRate;
231
232 /* if the number of samples in loaded data is not divisable by the currently specified number of
233 * inputs, then the filter length is set to 0 and no further processing is conducted. */
234 if(pData->input_wav_length % pData->nInputChannels == 0)
235 pData->filter_length = (pData->input_wav_length) / (pData->nInputChannels);
236 else
237 pData->filter_length = 0;
238
239 pData->reInitFilters = 1;
240}
241
242void matrixconv_setEnablePart(void* const hMCnv, int newState)
243{
244 matrixconv_data *pData = (matrixconv_data*)(hMCnv);
245 if(pData->enablePartitionedConv!=newState){
246 pData->enablePartitionedConv = newState;
247 pData->reInitFilters = 1;
248 }
249}
250
251void matrixconv_setNumInputChannels(void* const hMCnv, int newValue)
252{
253 matrixconv_data *pData = (matrixconv_data*)(hMCnv);
254 pData->nInputChannels = SAF_CLAMP(newValue, 1, MAX_NUM_CHANNELS);
255 pData->nfilters = (pData->nOutputChannels) * (pData->nInputChannels);
256 if((pData->nOutputChannels > 0) && (pData->input_wav_length % pData->nInputChannels == 0))
257 pData->filter_length = (pData->input_wav_length) / (pData->nInputChannels);
258 else
259 pData->filter_length = 0;
260 pData->reInitFilters = 1;
261}
262
263
264/*gets*/
265
266int matrixconv_getEnablePart(void* const hMCnv)
267{
268 matrixconv_data *pData = (matrixconv_data*)(hMCnv);
269 return pData->enablePartitionedConv;
270}
271
272int matrixconv_getNumInputChannels(void* const hMCnv)
273{
274 matrixconv_data *pData = (matrixconv_data*)(hMCnv);
275 return pData->nInputChannels;
276}
277
279{
280 matrixconv_data *pData = (matrixconv_data*)(hMCnv);
281 return pData->nOutputChannels;
282}
283
284int matrixconv_getHostBlockSize(void* const hMCnv)
285{
286 matrixconv_data *pData = (matrixconv_data*)(hMCnv);
287 return pData->hostBlockSize;
288}
289
290int matrixconv_getNfilters(void* const hMCnv)
291{
292 matrixconv_data *pData = (matrixconv_data*)(hMCnv);
293 return pData->nfilters;
294}
295
296int matrixconv_getFilterLength(void* const hMCnv)
297{
298 matrixconv_data *pData = (matrixconv_data*)(hMCnv);
299 return pData->filter_length;
300}
301
302int matrixconv_getFilterFs(void* const hMCnv)
303{
304 matrixconv_data *pData = (matrixconv_data*)(hMCnv);
305 return pData->filter_fs;
306}
307
308int matrixconv_getHostFs(void* const hMCnv)
309{
310 matrixconv_data *pData = (matrixconv_data*)(hMCnv);
311 return pData->host_fs;
312}
313
314int matrixconv_getProcessingDelay(void* const hMCnv)
315{
316 matrixconv_data *pData = (matrixconv_data*)(hMCnv);
317 return pData->hostBlockSize_clamped;
318}
319
#define MAX_NUM_CHANNELS
Maximum number of input/output channels supported.
Definition _common.h:230
void saf_matrixConv_apply(void *const hMC, float *inputSig, float *outputSig)
Performs the matrix convolution.
#define saf_assert(x, message)
Macro to make an assertion, along with a string explaining its purpose.
#define SAF_CLAMP(a, min, max)
Ensures value "a" is clamped between the "min" and "max" values.
void saf_matrixConv_create(void **const phMC, int hopSize, float *H, int length_h, int nCHin, int nCHout, int usePartFLAG)
Creates an instance of matrixConv.
void utility_svvcopy(const float *a, const int len, float *c)
Single-precision, vector-vector copy, i.e.
void saf_matrixConv_destroy(void **const phMC)
Destroys an instance of matrixConv.
#define SAF_MIN(a, b)
Returns the minimum of the two values.
int matrixconv_getNumOutputChannels(void *const hMCnv)
Returns the number of output channels (the same as the number of channels in the loaded wav file)
Definition matrixconv.c:278
void matrixconv_create(void **const phMCnv)
Creates an instance of matrixconv.
Definition matrixconv.c:29
void matrixconv_setNumInputChannels(void *const hMCnv, int newValue)
Sets the number of input channels.
Definition matrixconv.c:251
void matrixconv_destroy(void **const phMCnv)
Destroys an instance of matrixconv.
Definition matrixconv.c:61
void matrixconv_process(void *const hMCnv, const float *const *inputs, float *const *const outputs, int nInputs, int nOutputs, int nSamples)
Performs the matrix convolution processing.
Definition matrixconv.c:101
int matrixconv_getProcessingDelay(void *const hMCnv)
Returns the processing delay in samples (may be used for delay compensation features)
Definition matrixconv.c:314
int matrixconv_getHostFs(void *const hMCnv)
Returns the samperate of the host.
Definition matrixconv.c:308
void matrixconv_setEnablePart(void *const hMCnv, int newState)
Enable (1), disable (0), partitioned convolution.
Definition matrixconv.c:242
int matrixconv_getNfilters(void *const hMCnv)
Returns the number of filters in the loaded wav file (number of outputs multiplied by the number of i...
Definition matrixconv.c:290
int matrixconv_getFilterFs(void *const hMCnv)
Returns the samplerate of the loaded filters.
Definition matrixconv.c:302
int matrixconv_getEnablePart(void *const hMCnv)
Returns a flag indicating whether partitioned convolution is enabled (1) or disabled (0)
Definition matrixconv.c:266
int matrixconv_getHostBlockSize(void *const hMCnv)
Returns the currect host block size.
Definition matrixconv.c:284
void matrixconv_checkReInit(void *const hMCnv)
Checks whether things have to be reinitialised, and does so if it is needed.
Definition matrixconv.c:172
void matrixconv_init(void *const hMCnv, int sampleRate, int hostBlockSize)
Initialises an instance of matrixconv with default settings.
Definition matrixconv.c:81
void matrixconv_refreshParams(void *const hMCnv)
Sets all intialisation flags to 1.
Definition matrixconv.c:166
void matrixconv_setFilters(void *const hMCnv, const float *const *H, int numChannels, int numSamples, int sampleRate)
Loads the matrix of filters, which should have the input filters concatenated for each output.
Definition matrixconv.c:210
int matrixconv_getNumInputChannels(void *const hMCnv)
Returns the number input channels.
Definition matrixconv.c:272
int matrixconv_getFilterLength(void *const hMCnv)
Returns the current filter length, in samples.
Definition matrixconv.c:296
A standard matrix convolver.
A standard matrix convolver.
#define MIN_FRAME_SIZE
Minimum framesize, in time-domain samples.
#define MAX_FRAME_SIZE
Maximum framesize, in time-domain samples.
void ** realloc2d(void **ptr, size_t dim1, size_t dim2, size_t data_size)
2-D realloc which does NOT retain previous data order
Definition md_malloc.c:115
void * malloc1d(size_t dim1_data_size)
1-D malloc (same as malloc, but with error checking)
Definition md_malloc.c:59
void * realloc1d(void *ptr, size_t dim1_data_size)
1-D realloc (same as realloc, but with error checking)
Definition md_malloc.c:79
void ** calloc2d(size_t dim1, size_t dim2, size_t data_size)
2-D calloc (contiguously allocated, so use free() as usual to deallocate)
Definition md_malloc.c:102
#define FLATTEN2D(A)
Use this macro when passing a 2-D dynamic multi-dimensional array to memset, memcpy or any other func...
Definition md_malloc.h:65
Main structure for matrixconv.
float * filters
the matrix of filters; FLAT: nOutputChannels x nInputChannels x filter_length
float ** outputFrameTD
Output buffer; MAX_NUM_CHANNELS x hostBlockSize_clamped.
int nOutputChannels
number of output channels (same as the number of channels in the loaded wav)
int input_wav_length
length of the wav files loaded in samples (inputs are concatenated)
float ** inFIFO
Input FIFO buffer.
int host_fs
current samplerate of the host
int enablePartitionedConv
0: disabled, 1: enabled
float ** inputFrameTD
Input buffer; MAX_NUM_CHANNELS x hostBlockSize_clamped.
void * hMatrixConv
saf_matrixConv handle
int nfilters
the number of filters (nOutputChannels x nInputChannels)
float ** outFIFO
Output FIFO buffer.
int hostBlockSize_clamped
Clamped between MIN_FRAME_SIZE and MAX_FRAME_SIZE.
int hostBlockSize
current host block size
int reInitFilters
FLAG: 0: do not reinit, 1: reinit, 2: reinit in progress.
int filter_length
length of the filters (input_wav_length/nInputChannels)
int nInputChannels
number of input channels
int FIFO_idx
FIFO buffer index.
int filter_fs
current samplerate of the filters