4 #define CTFFT_MAXBITS 8
28 memset(fSampleBuffer,
'\0',
sizeof(fSampleBuffer));
29 memset(fMagnitudeBuffer,
'\0',
sizeof(fMagnitudeBuffer));
33 void writeInput(
const int16_t* samples,
size_t sampleCount)
36 float* dst = &fSampleBuffer[fWriteIndex];
37 for (
size_t i = 0; i < sampleCount; i++)
39 dst[i] = ((float)samples[i*2]) / 32768.0f;
42 fWriteIndex += sampleCount;
49 return (fWriteIndex > 0 && (fWriteIndex %
kFFTSize) == 0);
65 size_t len = std::min(magnitudeBufferLength(), destArraySize);
68 const double minDecibels = fMinDecibels;
69 const double rangeScaleFactor = (fMaxDecibels != minDecibels) ? 1 / (fMaxDecibels - minDecibels) : 1;
71 const float* source = fMagnitudeBuffer;
72 for (
unsigned i = 0; i < len; i++)
74 float linearValue = source[i];
75 double dbMag = (linearValue != 0) ? linearToDecibels(linearValue) : minDecibels;
78 double scaledValue = UCHAR_MAX * (dbMag - minDecibels) * rangeScaleFactor;
83 if (scaledValue > UCHAR_MAX)
84 scaledValue = UCHAR_MAX;
86 destArray[i] = (uint8_t)scaledValue;
95 double fSmoothingTimeConstant;
100 size_t sampleBufferLength()
const
102 return sizeof(fSampleBuffer) /
sizeof(fSampleBuffer[0]);
105 size_t magnitudeBufferLength()
const
107 return sizeof(fMagnitudeBuffer) /
sizeof(fMagnitudeBuffer[0]);
111 static float linearToDecibels(
float linearSample)
113 return 20 * log10f(linearSample);
116 void applyWindow(
float* p,
size_t n)
118 static constexpr
double twoPiDouble = M_PI * 2.0;
122 double a0 = 0.5 * (1 - alpha);
124 double a2 = 0.5 * alpha;
126 for (
unsigned i = 0; i < n; ++i)
128 double x = (double)i / (
double)n;
129 double window = a0 - a1 * cos(twoPiDouble * x) + a2 * cos(twoPiDouble * 2.0 * x);
130 p[i] *= double(window);
137 float* inputBuffer = fSampleBuffer;
138 float* tempP = tempBuffer;
141 unsigned writeIndex = fWriteIndex;
145 memcpy(tempP +
kFFTSize - writeIndex, inputBuffer,
sizeof(*tempP) * writeIndex);
149 memcpy(tempP, inputBuffer + writeIndex -
kFFTSize,
sizeof(*tempP) *
kFFTSize);
162 const double magnitudeScale = 1.0 /
kFFTSize;
165 double k = fSmoothingTimeConstant;
166 k = std::max(0.0, k);
167 k = std::min(1.0, k);
170 float* destination = fMagnitudeBuffer;
171 size_t n = magnitudeBufferLength();
172 for (
size_t i = 0; i < n; ++i)
174 std::complex<double> c(tempP[i*2], tempP[i*2+1]);
175 double scalarMagnitude = abs(c) * magnitudeScale;
176 destination[i] = float(k * destination[i] + (1 - k) * scalarMagnitude);
188 if (pixels !=
nullptr)
189 memset(pixels,
'\0', width * height);
192 void processSamples(
unsigned numBits,
unsigned numChannels,
const int16_t* samples,
int sampleCount)
203 if (sampleCount == 1024)
205 while (sampleCount > 0)
212 else if (sampleCount == 256)
216 else if (sampleCount == 640)
219 while (sampleCount > 0)
226 else if (sampleCount == 1152)
229 while (sampleCount > 0)
236 else if (sampleCount == 0)
239 while (sampleCount > 0)
248 Serial.println(sampleCount);
250 if (analyser.
ready())
253 memmove(&pixels[width], pixels, width * (4*60-1));
254 memcpy(pixels, freq, width);
263 uint8_t
get(
float x,
float y)
265 return (x >= 0.0f && x <= 1.0f && y >= 0.0f && y <= 1.0f) ? pixels[unsigned((3*y) * width + (x*width))] : 0;
267 uint8_t
get(
unsigned x,
unsigned y)
269 return (x < width && y < height) ? pixels[y * width + x] : 0;
285 unsigned height = 4*60;
286 bool updated =
false;
287 uint8_t* pixels = (uint8_t*)malloc(width * height);
288 uint8_t* freq =
new uint8_t[width];