11 |
#include <time.h> |
#include <time.h> |
12 |
#include <stdio.h> |
#include <stdio.h> |
13 |
|
|
14 |
|
#include "../src/engines/common/LFOTriangleIntMath.h" |
15 |
|
#include "../src/engines/common/LFOTriangleDiHarmonic.h" |
16 |
|
|
17 |
// whether we should not show any messages on the console |
// whether we should not show any messages on the console |
18 |
#ifndef SILENT |
#ifndef SILENT |
19 |
# define SILENT 0 |
# define SILENT 0 |
41 |
# define SIGNED 1 |
# define SIGNED 1 |
42 |
#endif |
#endif |
43 |
|
|
44 |
|
// maximum value of the LFO output (also depends on SIGNED above) |
45 |
|
#ifndef MAX |
46 |
|
# define MAX 1.0f |
47 |
|
#endif |
48 |
|
|
49 |
// pro forma |
// pro forma |
50 |
#ifndef SAMPLING_RATE |
#ifndef SAMPLING_RATE |
51 |
# define SAMPLING_RATE 44100.0f |
# define SAMPLING_RATE 44100.0f |
61 |
// we use 32 bit single precision floating point as sample point format |
// we use 32 bit single precision floating point as sample point format |
62 |
typedef float sample_t; |
typedef float sample_t; |
63 |
|
|
64 |
|
using namespace LinuxSampler; |
65 |
|
|
66 |
|
#if SIGNED |
67 |
|
LFOTriangleIntMath<range_signed>* pIntLFO = NULL; |
68 |
|
LFOTriangleDiHarmonic<range_signed>* pDiHarmonicLFO = NULL; |
69 |
|
#else // unsigned |
70 |
|
LFOTriangleIntMath<range_unsigned>* pIntLFO = NULL; |
71 |
|
LFOTriangleDiHarmonic<range_unsigned>* pDiHarmonicLFO = NULL; |
72 |
|
#endif |
73 |
|
|
74 |
// integer math solution |
// integer math solution |
75 |
float int_math(sample_t* pDestinationBuffer, float* pAmp, const int steps, const float frequency) { |
float int_math(sample_t* pDestinationBuffer, float* pAmp, const int steps, const float frequency) { |
76 |
// pro forma |
// pro forma |
77 |
const float r = frequency / SAMPLING_RATE; // frequency alteration quotient |
pIntLFO->trigger(frequency, start_level_max, 1200 /* max. internal depth */, 0, false, (unsigned int) SAMPLING_RATE); |
|
unsigned int maxvalue = (unsigned int) -1; // all 0xFFFF... |
|
|
#if SIGNED |
|
|
const float normalizer = 1.0f / ((float) maxvalue / 4.0f); |
|
|
#else // unsigned |
|
|
const float normalizer = 1.0f / ((float) maxvalue / 2.0f); |
|
|
#endif |
|
|
const int c = (int) (maxvalue * r); |
|
|
const int signshifts = (sizeof(int) * 8) - 1; |
|
|
|
|
|
int iSign; |
|
78 |
|
|
79 |
clock_t stop_time; |
clock_t stop_time; |
80 |
clock_t start_time = clock(); |
clock_t start_time = clock(); |
81 |
|
|
82 |
for (int run = 0; run < RUNS; run++) { |
for (int run = 0; run < RUNS; run++) { |
83 |
int iLevel = 0; |
pIntLFO->update(0); // pro forma |
84 |
for (int i = 0; i < steps; ++i) { |
for (int i = 0; i < steps; ++i) { |
85 |
iLevel += c; |
pDestinationBuffer[i] = pIntLFO->render() * pAmp[i]; // * pAmp[i] just to simulate some memory load |
|
iSign = (iLevel >> signshifts) | 1; |
|
|
#if SIGNED |
|
|
pDestinationBuffer[i] = (normalizer * (float) (iSign * iLevel) - 1.0f) * pAmp[i]; // * pAmp[i] just to simulate some memory load |
|
|
#else // unsigned |
|
|
pDestinationBuffer[i] = normalizer * (float) (iSign * iLevel) * pAmp[i]; // * pAmp[i] just to simulate some memory load |
|
|
#endif |
|
86 |
} |
} |
87 |
} |
} |
88 |
|
|
167 |
|
|
168 |
// numeric, di-harmonic solution |
// numeric, di-harmonic solution |
169 |
float numeric_di_harmonic_solution(sample_t* pDestinationBuffer, float* pAmp, const int steps, const float frequency) { |
float numeric_di_harmonic_solution(sample_t* pDestinationBuffer, float* pAmp, const int steps, const float frequency) { |
170 |
// we approximate the triangular wave by adding 2 harmonics |
// pro forma |
171 |
const float c1 = 2.0f * M_PI * frequency / SAMPLING_RATE; |
pDiHarmonicLFO->trigger(frequency, start_level_max, 1200 /* max. internal depth */, 0, false, (unsigned int) SAMPLING_RATE); |
|
const float phi1 = 0.0f; // phase displacement |
|
|
const float c2 = 2.0f * M_PI * frequency / SAMPLING_RATE * 3.0f; |
|
|
const float phi2 = 0.0f; // phase displacement |
|
|
|
|
|
// amplitue for the 2nd harmonic (to approximate the triangular wave) |
|
|
const float amp2 = 0.1f; |
|
|
|
|
|
// initial values for real and imaginary part |
|
|
float real1 = cos(phi1); |
|
|
float imag1 = sin(phi1); |
|
|
float real2 = cos(phi2); |
|
|
float imag2 = sin(phi2); |
|
172 |
|
|
173 |
clock_t stop_time; |
clock_t stop_time; |
174 |
clock_t start_time = clock(); |
clock_t start_time = clock(); |
175 |
|
|
176 |
for (int run = 0; run < RUNS; run++) { |
for (int run = 0; run < RUNS; run++) { |
177 |
for (int i = 0; i < steps; i++) { |
pDiHarmonicLFO->update(0); // pro forma |
178 |
#if SIGNED |
for (int i = 0; i < steps; ++i) { |
179 |
pDestinationBuffer[i] = (real1 + real2 * amp2) * pAmp[i]; // * pAmp[i] just to simulate some memory load |
pDestinationBuffer[i] = pDiHarmonicLFO->render() * pAmp[i]; // * pAmp[i] just to simulate some memory load |
|
#else // unsigned |
|
|
pDestinationBuffer[i] = ((real1 + real2 * amp2) * 0.5f + 0.5f) * pAmp[i]; // * pAmp[i] just to simulate some memory load |
|
|
#endif |
|
|
real1 -= c1 * imag1; |
|
|
imag1 += c1 * real1; |
|
|
real2 -= c2 * imag2; |
|
|
imag2 += c2 * real2; |
|
180 |
} |
} |
181 |
} |
} |
182 |
|
|
214 |
# endif |
# endif |
215 |
#endif |
#endif |
216 |
|
|
217 |
|
#if SIGNED |
218 |
|
pIntLFO = new LFOTriangleIntMath<range_signed>(MAX); |
219 |
|
pDiHarmonicLFO = new LFOTriangleDiHarmonic<range_signed>(MAX); |
220 |
|
#else // unsigned |
221 |
|
pIntLFO = new LFOTriangleIntMath<range_unsigned>(MAX); |
222 |
|
pDiHarmonicLFO = new LFOTriangleDiHarmonic<range_unsigned>(MAX); |
223 |
|
#endif |
224 |
|
|
225 |
// output buffer for the calculated sinusoid wave |
// output buffer for the calculated sinusoid wave |
226 |
sample_t* pOutputBuffer = new sample_t[steps]; |
sample_t* pOutputBuffer = new sample_t[steps]; |
227 |
// just an arbitrary amplitude envelope to simulate a bit higher memory bandwidth |
// just an arbitrary amplitude envelope to simulate a bit higher memory bandwidth |
258 |
if (pAmplitude) delete[] pAmplitude; |
if (pAmplitude) delete[] pAmplitude; |
259 |
if (pOutputBuffer) delete[] pOutputBuffer; |
if (pOutputBuffer) delete[] pOutputBuffer; |
260 |
|
|
261 |
|
if (pIntLFO) delete pIntLFO; |
262 |
|
if (pDiHarmonicLFO) delete pDiHarmonicLFO; |
263 |
|
|
264 |
if (/*int_math_result <= table_lookup_result &&*/ int_math_result <= numeric_di_harmonic_result) return INT_MATH_SOLUTION; |
if (/*int_math_result <= table_lookup_result &&*/ int_math_result <= numeric_di_harmonic_result) return INT_MATH_SOLUTION; |
265 |
if (/*numeric_di_harmonic_result <= table_lookup_result &&*/ numeric_di_harmonic_result <= int_math_result) return DI_HARMONIC_SOLUTION; |
if (/*numeric_di_harmonic_result <= table_lookup_result &&*/ numeric_di_harmonic_result <= int_math_result) return DI_HARMONIC_SOLUTION; |
266 |
//if (table_lookup_result <= int_math_result && table_lookup_result <= numeric_di_harmonic_result) return TABLE_LOOKUP_SOLUTION; |
//if (table_lookup_result <= int_math_result && table_lookup_result <= numeric_di_harmonic_result) return TABLE_LOOKUP_SOLUTION; |