SAF
Loading...
Searching...
No Matches
multiconv.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 "multiconv.h"
26#include "multiconv_internal.h"
27
29(
30 void ** const phMCnv
31)
32{
34 *phMCnv = (void*)pData;
35
36 /* Default user parameters */
37 pData->nChannels = 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->hMultiConv = NULL;
45 pData->filters = NULL;
46 pData->reInitFilters = 1;
47 pData->nfilters = 0;
48 pData->filter_length = 0;
49 pData->filter_fs = 0;
50
51 /* set FIFO buffers */
52 pData->host_fs = 48000.0f;
53 pData->FIFO_idx = 0;
54 pData->inFIFO = (float**)calloc2d(MAX_NUM_CHANNELS, MAX_FRAME_SIZE, sizeof(float));
55 pData->outFIFO = (float**)calloc2d(MAX_NUM_CHANNELS, MAX_FRAME_SIZE, sizeof(float));
56// memset(FLATTEN2D(pData->inFIFO), 0, MAX_NUM_CHANNELS*MAX_FRAME_SIZE*sizeof(float));
57// memset(FLATTEN2D(pData->outFIFO), 0, MAX_NUM_CHANNELS*MAX_FRAME_SIZE*sizeof(float));
58}
59
61(
62 void ** const phMCnv
63)
64{
65 multiconv_data *pData = (multiconv_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 multiconv_data *pData = (multiconv_data*)(hMCnv);
88
89 pData->host_fs = sampleRate;
90 if(pData->hostBlockSize != hostBlockSize){
91 pData->hostBlockSize = hostBlockSize;
93 pData->reInitFilters = 1;
94 }
95
97}
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 multiconv_data *pData = (multiconv_data*)(hMCnv);
111 int s, ch, i;
112 int numChannels;
113
115
116 /* prep */
117 numChannels = SAF_MIN(pData->nChannels, pData->nfilters);
118
119 for(s=0; s<nSamples; s++){
120 /* Load input signals into inFIFO buffer */
121 for(ch=0; ch<SAF_MIN(SAF_MIN(nInputs,numChannels),MAX_NUM_CHANNELS); ch++)
122 pData->inFIFO[ch][pData->FIFO_idx] = inputs[ch][s];
123 for(; ch<numChannels; ch++) /* Zero any channels that were not given */
124 pData->inFIFO[ch][pData->FIFO_idx] = 0.0f;
125
126 /* Pull output signals from outFIFO buffer */
127 for(ch=0; ch<SAF_MIN(SAF_MIN(nOutputs, numChannels),MAX_NUM_CHANNELS); ch++)
128 outputs[ch][s] = pData->outFIFO[ch][pData->FIFO_idx];
129 for(; ch<nOutputs; ch++) /* Zero any extra channels */
130 outputs[ch][s] = 0.0f;
131
132 /* Increment buffer index */
133 pData->FIFO_idx++;
134
135 /* Process frame if inFIFO is full and filters are loaded and saf_matrixConv_apply is ready for it */
136 if (pData->FIFO_idx >= pData->hostBlockSize_clamped && pData->reInitFilters == 0 ) {
137 pData->FIFO_idx = 0;
138
139 /* Load time-domain data */
140 for(i=0; i < numChannels; i++)
141 utility_svvcopy(pData->inFIFO[i], pData->hostBlockSize_clamped, pData->inputFrameTD[i]);
142
143 /* Apply convolution */
144 if(pData->hMultiConv != NULL)
146 else
147 memset(FLATTEN2D(pData->outputFrameTD), 0, MAX_NUM_CHANNELS * (pData->hostBlockSize_clamped)*sizeof(float));
148
149 /* copy signals to output buffer */
150 for (i = 0; i < SAF_MIN(numChannels, MAX_NUM_CHANNELS); i++)
151 utility_svvcopy(pData->outputFrameTD[i], pData->hostBlockSize_clamped, pData->outFIFO[i]);
152 }
153 else if(pData->FIFO_idx >= pData->hostBlockSize_clamped){
154 /* clear outFIFO if codec was not ready */
155 pData->FIFO_idx = 0;
156 memset(FLATTEN2D(pData->outFIFO), 0, MAX_NUM_CHANNELS*MAX_FRAME_SIZE*sizeof(float));
157 }
158 }
159}
160
161
162/*sets*/
163
164void multiconv_refreshParams(void* const hMCnv)
165{
166 multiconv_data *pData = (multiconv_data*)(hMCnv);
167 pData->reInitFilters = 1;
168}
169
170void multiconv_checkReInit(void* const hMCnv)
171{
172 multiconv_data *pData = (multiconv_data*)(hMCnv);
173
174 /* reinitialise if needed */
175 if ((pData->reInitFilters == 1) && (pData->filters !=NULL)) {
176 pData->reInitFilters = 2;
181 pData->filters,
182 pData->filter_length,
183 pData->nfilters,
184 pData->enablePartitionedConv);
185
186 /* Resize buffers */
187 pData->inputFrameTD = (float**)realloc2d((void**)pData->inputFrameTD, MAX_NUM_CHANNELS, pData->hostBlockSize_clamped, sizeof(float));
188 pData->outputFrameTD = (float**)realloc2d((void**)pData->outputFrameTD, MAX_NUM_CHANNELS, pData->hostBlockSize_clamped, sizeof(float));
189 memset(FLATTEN2D(pData->inputFrameTD), 0, MAX_NUM_CHANNELS*(pData->hostBlockSize_clamped)*sizeof(float));
190
191 /* reset FIFO buffers */
192 pData->FIFO_idx = 0;
193 memset(FLATTEN2D(pData->inFIFO), 0, MAX_NUM_CHANNELS*MAX_FRAME_SIZE*sizeof(float));
194 memset(FLATTEN2D(pData->outFIFO), 0, MAX_NUM_CHANNELS*MAX_FRAME_SIZE*sizeof(float));
195
196 pData->reInitFilters = 0;
197 }
198}
199
201(
202 void* const hMCnv,
203 const float* const* H,
204 int numChannels,
205 int numSamples,
206 int sampleRate
207)
208{
209 multiconv_data *pData = (multiconv_data*)(hMCnv);
210 int i;
211
212 pData->filters = realloc1d(pData->filters, numChannels*numSamples*sizeof(float));
213 pData->nfilters = numChannels;
214 pData->filter_length = numSamples;
215 for(i=0; i<numChannels; i++)
216 memcpy(&(pData->filters[i*numSamples]), H[i], numSamples*sizeof(float));
217 pData->filter_fs = sampleRate;
218 pData->reInitFilters = 1;
219}
220
221void multiconv_setEnablePart(void* const hMCnv, int newState)
222{
223 multiconv_data *pData = (multiconv_data*)(hMCnv);
224 if(pData->enablePartitionedConv!=newState){
225 pData->enablePartitionedConv = newState;
226 pData->reInitFilters = 1;
227 }
228}
229
230void multiconv_setNumChannels(void* const hMCnv, int newValue)
231{
232 multiconv_data *pData = (multiconv_data*)(hMCnv);
233 pData->nChannels = SAF_CLAMP(newValue, 1, MAX_NUM_CHANNELS);
234}
235
236/*gets*/
237
238int multiconv_getEnablePart(void* const hMCnv)
239{
240 multiconv_data *pData = (multiconv_data*)(hMCnv);
241 return pData->enablePartitionedConv;
242}
243
244int multiconv_getNumChannels(void* const hMCnv)
245{
246 multiconv_data *pData = (multiconv_data*)(hMCnv);
247 return pData->nChannels;
248}
249
250int multiconv_getHostBlockSize(void* const hMCnv)
251{
252 multiconv_data *pData = (multiconv_data*)(hMCnv);
253 return pData->hostBlockSize;
254}
255
256int multiconv_getNfilters(void* const hMCnv)
257{
258 multiconv_data *pData = (multiconv_data*)(hMCnv);
259 return pData->nfilters;
260}
261
262int multiconv_getFilterLength(void* const hMCnv)
263{
264 multiconv_data *pData = (multiconv_data*)(hMCnv);
265 return pData->filter_length;
266}
267
268int multiconv_getFilterFs(void* const hMCnv)
269{
270 multiconv_data *pData = (multiconv_data*)(hMCnv);
271 return pData->filter_fs;
272}
273
274int multiconv_getHostFs(void* const hMCnv)
275{
276 multiconv_data *pData = (multiconv_data*)(hMCnv);
277 return pData->host_fs;
278}
279
280int multiconv_getProcessingDelay(void* const hMCnv)
281{
282 multiconv_data *pData = (multiconv_data*)(hMCnv);
283 return pData->hostBlockSize_clamped;
284}
#define MAX_NUM_CHANNELS
Maximum number of input/output channels supported.
Definition _common.h:230
void saf_multiConv_destroy(void **const phMC)
Destroys an instance of multiConv.
#define SAF_CLAMP(a, min, max)
Ensures value "a" is clamped between the "min" and "max" values.
void saf_multiConv_apply(void *const hMC, float *inputSig, float *outputSig)
Performs the multi-channel convolution.
void utility_svvcopy(const float *a, const int len, float *c)
Single-precision, vector-vector copy, i.e.
void saf_multiConv_create(void **const phMC, int hopSize, float *H, int length_h, int nCH, int usePartFLAG)
Creates an instance of multiConv.
#define SAF_MIN(a, b)
Returns the minimum of the two values.
#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
int multiconv_getFilterLength(void *const hMCnv)
Returns the current filter length, in samples.
Definition multiconv.c:262
void multiconv_create(void **const phMCnv)
Creates an instance of multiconv.
Definition multiconv.c:29
void multiconv_init(void *const hMCnv, int sampleRate, int hostBlockSize)
Initialises an instance of multiconv with default settings.
Definition multiconv.c:81
int multiconv_getNfilters(void *const hMCnv)
Returns the number of filters in the loaded wav file.
Definition multiconv.c:256
int multiconv_getHostBlockSize(void *const hMCnv)
Returns the currect host block size.
Definition multiconv.c:250
int multiconv_getEnablePart(void *const hMCnv)
Returns a flag indicating whether partitioned convolution is enabled (1) or disabled (0)
Definition multiconv.c:238
int multiconv_getFilterFs(void *const hMCnv)
Returns the samplerate of the loaded filters.
Definition multiconv.c:268
int multiconv_getNumChannels(void *const hMCnv)
Returns the number input/output channels.
Definition multiconv.c:244
void multiconv_checkReInit(void *const hMCnv)
Checks whether things have to be reinitialised, and does so if it is needed.
Definition multiconv.c:170
void multiconv_setEnablePart(void *const hMCnv, int newState)
Enable (1), disable (0), partitioned convolution.
Definition multiconv.c:221
void multiconv_setNumChannels(void *const hMCnv, int newValue)
Sets the number of input/output channels.
Definition multiconv.c:230
void multiconv_refreshParams(void *const hMCnv)
Sets all intialisation flags to 1.
Definition multiconv.c:164
int multiconv_getProcessingDelay(void *const hMCnv)
Returns the processing delay in samples (may be used for delay compensation features)
Definition multiconv.c:280
int multiconv_getHostFs(void *const hMCnv)
Returns the samperate of the host.
Definition multiconv.c:274
void multiconv_destroy(void **const phMCnv)
Destroys an instance of multiconv.
Definition multiconv.c:61
void multiconv_process(void *const hMCnv, const float *const *inputs, float *const *const outputs, int nInputs, int nOutputs, int nSamples)
Performs the multuchannel convolution processing.
Definition multiconv.c:101
void multiconv_setFilters(void *const hMCnv, const float *const *H, int numChannels, int numSamples, int sampleRate)
Loads the multichannel of filters.
Definition multiconv.c:201
A multi-channel convolver.
A multi-channel convolver.
Main structure for multiconv.
int hostBlockSize_clamped
Clamped between MIN_FRAME_SIZE and MAX_FRAME_SIZE.
int nfilters
Current number of FIR filters.
void * hMultiConv
convolver handle
float ** outFIFO
Output FIFO buffer.
int nChannels
Current number of input/output channels.
int filter_length
length of the filters (input_wav_length/nInputChannels)
int host_fs
current samplerate of the host
int filter_fs
current samplerate of the filters
int FIFO_idx
FIFO buffer index.
int hostBlockSize
current host block size
float * filters
FLAT: nfilters x filter_length.
float ** inputFrameTD
Input buffer; MAX_NUM_CHANNELS x hostBlockSize_clamped.
float ** outputFrameTD
Output buffer; MAX_NUM_CHANNELS x hostBlockSize_clamped.
float ** inFIFO
Input FIFO buffer.
int enablePartitionedConv
1: enable partitioned convolution, 0: regular convolution (fft over the length of the filter)
int reInitFilters
FLAG: 0: do not reinit, 1: reinit, 2: reinit in progress.