Mach1 Spatial SDK
Loading...
Searching...
No Matches
Mach1Decode.h
1// Mach1 Spatial SDK
2// Copyright © 2017 Mach1. All rights reserved.
3
4#ifndef MACH1SPATIALSDK_MACH1DECODE_H
5#define MACH1SPATIALSDK_MACH1DECODE_H
6
7#include "Mach1DecodeCAPI.h"
8#include <cstring>
9#include <string>
10#include <vector>
11
12template <typename PCM>
14 public:
16
18
22 void setPlatformType(Mach1PlatformType type);
23
27 void setDecodeMode(Mach1DecodeMode mode);
28
32 Mach1PlatformType getPlatformType();
33
37 Mach1DecodeMode getDecodeMode();
38
44
50
60 void setRotation(Mach1Point3D newRotationFromMinusOnetoOne);
61
71 void setRotationDegrees(Mach1Point3D newRotationDegrees);
72
82 void setRotationRadians(Mach1Point3D newRotationRadians);
83
94 void setRotationQuat(Mach1Point4D newRotationQuat);
95
100 void setFilterSpeed(float filterSpeed);
101
105 long getCurrentTime();
106
111
131 std::vector<PCM> decode(float Yaw, float Pitch, float Roll, int bufferSize = 0, int sampleIndex = 0);
132
149 std::vector<PCM> decodeCoeffs(int bufferSize = 0, int sampleIndex = 0);
150
168 std::vector<PCM> decodePannedCoeffs(int bufferSize = 0, int sampleIndex = 0, bool applyPanLaw = true);
169
170 std::vector<PCM> decodeCoeffsUsingTranscodeMatrix(std::vector<std::vector<float> > matrix, int channels, int bufferSize = 0, int sampleIndex = 0);
171
172 inline void decodeBuffer(std::vector<std::vector<PCM> > &in, std::vector<std::vector<PCM> > &out, int size);
173
174 inline void decodeBufferInPlace(std::vector<std::vector<PCM> > &buffer, int size);
175
176 inline void decodeBufferRebuffer(std::vector<std::vector<PCM> > &in, std::vector<std::vector<PCM> > &out, int size);
177
178 inline void decodeBufferInPlaceRebuffer(std::vector<std::vector<PCM> > &buffer, int size);
179
180#ifndef __EMSCRIPTEN__
181 void decode(float Yaw, float Pitch, float Roll, float *result, int bufferSize = 0, int sampleIndex = 0);
182 void decodeCoeffs(float *result, int bufferSize = 0, int sampleIndex = 0);
183 void decodePannedCoeffs(float *result, int bufferSize = 0, int sampleIndex = 0, bool applyPanLaw = true);
184
188 char *getLog();
189#else
193 std::string getLog();
194#endif
195
196 private:
197 void *M1obj;
198
199 std::vector<float> old_decode_gains;
200 std::vector<std::vector<float> > intermediary_buffer;
201 int ib_channel_count;
202 size_t ib_buffer_size;
203};
204
205#endif // MACH1SPATIALSDK_MACH1DECODE_H
206
207// Implementation of Mach1Decode<PCM>
208#ifndef MACH1SPATIALSDK_MACH1DECODE_TPP
209#define MACH1SPATIALSDK_MACH1DECODE_TPP
210
211template <typename PCM>
213 M1obj = Mach1DecodeCAPI_create();
214}
215
216template <typename PCM>
218 Mach1DecodeCAPI_delete(M1obj);
219}
220
221template <typename PCM>
222void Mach1Decode<PCM>::setPlatformType(Mach1PlatformType type) {
223 Mach1DecodeCAPI_setPlatformType(M1obj, type);
224}
225
226template <typename PCM>
227void Mach1Decode<PCM>::setDecodeMode(Mach1DecodeMode mode) {
228 Mach1DecodeCAPI_setDecodeMode(M1obj, mode);
229}
230
231template <typename PCM>
233 return Mach1DecodeCAPI_getPlatformType(M1obj);
234}
235
236template <typename PCM>
238 return Mach1DecodeCAPI_getDecodeMode(M1obj);
239}
240
241#ifndef __EMSCRIPTEN__
242template <typename PCM>
243void Mach1Decode<PCM>::decode(float Yaw, float Pitch, float Roll, float *result, int bufferSize, int sampleIndex) {
244 Mach1DecodeCAPI_decode(M1obj, Yaw, Pitch, Roll, result, bufferSize, sampleIndex);
245}
246
247template <typename PCM>
248void Mach1Decode<PCM>::decodeCoeffs(float *result, int bufferSize, int sampleIndex) {
249 Mach1DecodeCAPI_decodeCoeffs(M1obj, result, bufferSize, sampleIndex);
250}
251
252template <typename PCM>
253void Mach1Decode<PCM>::decodePannedCoeffs(float *result, int bufferSize, int sampleIndex, bool applyPanLaw) {
254 Mach1DecodeCAPI_decodePannedCoeffs(M1obj, result, bufferSize, sampleIndex, applyPanLaw);
255}
256#endif
257
258template <typename PCM>
259std::vector<PCM> Mach1Decode<PCM>::decode(float Yaw, float Pitch, float Roll, int bufferSize, int sampleIndex) {
260 std::vector<PCM> vec(getFormatCoeffCount());
261
262 Mach1DecodeCAPI_decode(M1obj, Yaw, Pitch, Roll, vec.data(), bufferSize, sampleIndex);
263
264 return vec;
265}
266
267template <typename PCM>
268std::vector<PCM> Mach1Decode<PCM>::decodeCoeffs(int bufferSize, int sampleIndex) {
269 std::vector<PCM> vec(getFormatCoeffCount());
270
271 Mach1DecodeCAPI_decodeCoeffs(M1obj, vec.data(), bufferSize, sampleIndex);
272
273 return vec;
274}
275
276template <typename PCM>
277std::vector<PCM> Mach1Decode<PCM>::decodePannedCoeffs(int bufferSize, int sampleIndex, bool applyPanLaw) {
278 std::vector<PCM> vec(getFormatCoeffCount());
279
280 Mach1DecodeCAPI_decodePannedCoeffs(M1obj, vec.data(), bufferSize, sampleIndex, applyPanLaw);
281
282 return vec;
283}
284
285template <typename PCM>
286std::vector<PCM> Mach1Decode<PCM>::decodeCoeffsUsingTranscodeMatrix(std::vector<std::vector<float> > matrix, int channels, int bufferSize, int sampleIndex) {
287 std::vector<PCM> vec(2 * channels);
288
289 int inChans = channels;
290 int outChans = getFormatChannelCount();
291
292 float *m = new float[inChans * outChans];
293 for (int i = 0; i < outChans; i++) {
294 for (int j = 0; j < inChans; j++) {
295 m[i * inChans + j] = matrix[i][j];
296 }
297 }
298
299 Mach1DecodeCAPI_decodeCoeffsUsingTranscodeMatrix(M1obj, m, channels, vec.data(), bufferSize, sampleIndex);
300
301 delete[] m;
302 return vec;
303}
304
305template <typename PCM>
307 return Mach1DecodeCAPI_getFormatChannelCount(M1obj);
308}
309
310template <typename PCM>
312 return Mach1DecodeCAPI_getFormatCoeffCount(M1obj);
313}
314
315template <typename PCM>
316void Mach1Decode<PCM>::setRotation(Mach1Point3D newRotationFromMinusOnetoOne) {
317 Mach1DecodeCAPI_setRotation(M1obj, newRotationFromMinusOnetoOne);
318}
319
320template <typename PCM>
322 Mach1DecodeCAPI_setRotationDegrees(M1obj, newRotationDegrees);
323}
324
325template <typename PCM>
327 Mach1DecodeCAPI_setRotationRadians(M1obj, newRotationRadians);
328}
329
330template <typename PCM>
332 Mach1DecodeCAPI_setRotationQuat(M1obj, newRotationQuat);
333}
334
335template <typename PCM>
336void Mach1Decode<PCM>::setFilterSpeed(float filterSpeed) {
337 Mach1DecodeCAPI_setFilterSpeed(M1obj, filterSpeed);
338}
339
340template <typename PCM>
342 return Mach1DecodeCAPI_getCurrentTime(M1obj);
343}
344
345#ifndef __EMSCRIPTEN__
346template <typename PCM>
348 return Mach1DecodeCAPI_getLog(M1obj);
349}
350#else
351template <typename PCM>
352std::string Mach1Decode<PCM>::getLog() {
353 return std::string(Mach1DecodeCAPI_getLog(M1obj));
355}
356#endif
357
358template <typename PCM>
360 return Mach1DecodeCAPI_getCurrentAngle(M1obj);
361}
362
363template <typename PCM>
364void Mach1Decode<PCM>::decodeBuffer(std::vector<std::vector<PCM> > &in, std::vector<std::vector<PCM> > &out, int size) {
365 // get output gain multipliers
366 auto decode_gains = decodeCoeffs(); // TODO: Implement interpolation between coeffs.
367
368 if (old_decode_gains.size() != decode_gains.size()) {
369 old_decode_gains = decode_gains;
370 }
371
372 float size_reciprocal = 1.0f / (float)size;
373
374 // process the samples manually
375 for (int decode_idx = 0, output_idx = 0; decode_idx < decode_gains.size(); decode_idx += 2, output_idx += 1) {
376 auto left_gain = decode_gains[decode_idx + 0];
377 auto right_gain = decode_gains[decode_idx + 1];
378 auto old_left_gain = old_decode_gains[decode_idx + 0];
379 auto old_right_gain = old_decode_gains[decode_idx + 1];
380
381 for (int sample_idx = 0; sample_idx < size; sample_idx++) {
382 auto prc = (float)sample_idx * size_reciprocal;
383 auto left = left_gain * (1.0f - prc) + old_left_gain * prc;
384 auto right = right_gain * (1.0f - prc) + old_right_gain * prc;
385
386 // get the sample in each loop
387 float sample = in[output_idx][sample_idx];
388
389 // clear the output for the new values to come in
390 out[output_idx][sample_idx] = 0;
391 out[0][sample_idx] += sample * left;
392 out[1][sample_idx] += sample * right;
393 }
394 }
395
396 old_decode_gains = decode_gains;
397}
398
399template <typename PCM>
400void Mach1Decode<PCM>::decodeBufferInPlace(std::vector<std::vector<PCM> > &buffer, int size) {
401 decodeBuffer(buffer, buffer, size);
402}
403
404template <typename PCM>
405void Mach1Decode<PCM>::decodeBufferRebuffer(std::vector<std::vector<PCM> > &in, std::vector<std::vector<PCM> > &out, int size) {
406 auto channel_count = 2;
407
408 // restructure intermediary buffer
409 if (ib_channel_count != channel_count || ib_buffer_size != size) {
410 intermediary_buffer.resize(channel_count);
411
412 for (int i = 0; i < channel_count; i++) {
413 intermediary_buffer[i].resize(size);
414 }
415
416 ib_channel_count = channel_count;
417 ib_buffer_size = size;
418 }
419
420 // clear intermediary buffer
421 for (int i = 0; i < ib_channel_count; i++) {
422 memset(intermediary_buffer[i].data(), 0, sizeof(float) * ib_buffer_size);
423 }
424
425 // get output gain multipliers
426 auto decode_gains = decodeCoeffs(); // TODO: Implement interpolation between coeffs.
427
428 if (old_decode_gains.size() != decode_gains.size()) {
429 old_decode_gains = decode_gains;
430 }
431
432 float size_reciprocal = 1.0f / (float)size;
433
434 // process the samples manually
435 for (int decode_idx = 0, output_idx = 0; decode_idx < decode_gains.size(); decode_idx += 2, output_idx += 1) {
436 auto left_gain = decode_gains[decode_idx + 0];
437 auto right_gain = decode_gains[decode_idx + 1];
438 auto old_left_gain = old_decode_gains[decode_idx + 0];
439 auto old_right_gain = old_decode_gains[decode_idx + 1];
440
441 for (int sample_idx = 0; sample_idx < size; sample_idx++) {
442 auto prc = (float)sample_idx * size_reciprocal;
443 auto left = left_gain * (1.0f - prc) + old_left_gain * prc;
444 auto right = right_gain * (1.0f - prc) + old_right_gain * prc;
445
446 // get the sample in each loop
447 float sample = in[output_idx][sample_idx];
448
449 intermediary_buffer[0][sample_idx] += sample * left;
450 intermediary_buffer[1][sample_idx] += sample * right;
451 }
452 }
453
454 // copy over values in intermediary buffer to output buffer
455 for (int output_idx = 0; output_idx < channel_count; output_idx++) {
456 memcpy(out[output_idx].data(), intermediary_buffer[output_idx].data(), sizeof(float) * size);
457 }
458
459 old_decode_gains = decode_gains;
460}
461
462template <typename PCM>
463void Mach1Decode<PCM>::decodeBufferInPlaceRebuffer(std::vector<std::vector<PCM> > &buffer, int size) {
464 decodeBufferRebuffer(buffer, buffer, size);
465}
466
467#endif // MACH1SPATIALSDK_MACH1DECODE_TPP
Definition Mach1Decode.h:13
void setRotation(Mach1Point3D newRotationFromMinusOnetoOne)
Set current buffer/sample intended decoding orientation YPR.
Definition Mach1Decode.h:316
std::vector< PCM > decode(float Yaw, float Pitch, float Roll, int bufferSize=0, int sampleIndex=0)
Definition Mach1Decode.h:259
int getFormatChannelCount()
Get the get amount of channels that this Mach1Decode expects to decode, based on the currently active...
Definition Mach1Decode.h:306
std::vector< PCM > decodePannedCoeffs(int bufferSize=0, int sampleIndex=0, bool applyPanLaw=true)
Definition Mach1Decode.h:277
int getFormatCoeffCount()
Get the get amount of decoding coefficients this Mach1Decode will generate, based on the currently ac...
Definition Mach1Decode.h:311
void setRotationRadians(Mach1Point3D newRotationRadians)
Set current buffer/sample intended decoding orientation YPR.
Definition Mach1Decode.h:326
std::vector< PCM > decodeCoeffs(int bufferSize=0, int sampleIndex=0)
Definition Mach1Decode.h:268
void setFilterSpeed(float filterSpeed)
Set the amount of angle smoothing applied to the orientation angles used for this Mach1Decode.
Definition Mach1Decode.h:336
void setRotationQuat(Mach1Point4D newRotationQuat)
Set current buffer/sample intended decoding orientation YPR.
Definition Mach1Decode.h:331
void setPlatformType(Mach1PlatformType type)
Set the device's angle order and convention if applicable.
Definition Mach1Decode.h:222
char * getLog()
Get the internal log that has been accumulated into this Mach1Decode.
Definition Mach1Decode.h:347
Mach1DecodeMode getDecodeMode()
Get the decoding mode.
Definition Mach1Decode.h:237
void setDecodeMode(Mach1DecodeMode mode)
Set the decoding mode.
Definition Mach1Decode.h:227
Mach1Point3D getCurrentAngle()
Get this Mach1Decode's current 3D angle for feedback design.
Definition Mach1Decode.h:359
void setRotationDegrees(Mach1Point3D newRotationDegrees)
Set current buffer/sample intended decoding orientation YPR.
Definition Mach1Decode.h:321
long getCurrentTime()
Get the current elapsed time in milliseconds (ms) this Mach1Decode has been constructed.
Definition Mach1Decode.h:341
Mach1PlatformType getPlatformType()
Get the device's angle order and convention if applicable.
Definition Mach1Decode.h:232
Definition Mach1Point3D.h:17
Definition Mach1Point4D.h:15