-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaudio_utils.cpp
113 lines (105 loc) · 3.42 KB
/
audio_utils.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include <application.h>
#include "arm_math.h"
#include "audio.h"
////////////////////////////////////////////////////////////////////////////////
// UTILITY FUNCTIONS
////////////////////////////////////////////////////////////////////////////////
// Compute the average magnitude of a target frequency window vs. all other frequencies.
void windowMean(float* magnitudes, int lowBin, int highBin, float* windowMean, float* otherMean) {
*windowMean = 0;
*otherMean = 0;
// Notice the first magnitude bin is skipped because it represents the
// average power of the signal.
for (int i = 1; i < FFT_SIZE/2; ++i) {
if (i >= lowBin && i <= highBin) {
*windowMean += magnitudes[i];
}
else {
*otherMean += magnitudes[i];
}
}
*windowMean /= (highBin - lowBin) + 1;
*otherMean /= (FFT_SIZE / 2 - (highBin - lowBin));
}
// Convert a frequency to the appropriate FFT bin it will fall within.
int frequencyToBin(float frequency) {
float binFrequency = float(SAMPLE_RATE_HZ) / float(FFT_SIZE);
return int(frequency / binFrequency);
}
// Convert from HSV values (in floating point 0 to 1.0) to RGB colors usable
// by neo pixel functions.
uint32_t pixelHSVtoRGBColor(float hue, float saturation, float value) {
// Implemented from algorithm at http://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV
float chroma = value * saturation;
float h1 = float(hue)/60.0;
float x = chroma*(1.0-fabs(fmod(h1, 2.0)-1.0));
float r = 0;
float g = 0;
float b = 0;
if (h1 < 1.0) {
r = chroma;
g = x;
}
else if (h1 < 2.0) {
r = x;
g = chroma;
}
else if (h1 < 3.0) {
g = chroma;
b = x;
}
else if (h1 < 4.0) {
g = x;
b = chroma;
}
else if (h1 < 5.0) {
r = x;
b = chroma;
}
else // h1 <= 6.0
{
r = chroma;
b = x;
}
float m = value - chroma;
r += m;
g += m;
b += m;
return (int(255*r) & 0xff) << 16 | (int(255*g) & 0xff) << 8 | (int(255*b) & 0xff); // pixels.Color(int(255*r), int(255*g), int(255*b));
}
////////////////////////////////////////////////////////////////////////////////
// SPECTRUM DISPLAY FUNCTIONS
///////////////////////////////////////////////////////////////////////////////
void spectrumSetup() {
// Set the frequency window values by evenly dividing the possible frequency
// spectrum across the number of neo pixels.
float windowSize = (SAMPLE_RATE_HZ / 2.0) / float(NEO_PIXEL_COUNT);
for (int i = 0; i < NEO_PIXEL_COUNT+1; ++i) {
frequencyWindow[i] = i*windowSize;
}
// Evenly spread hues across all pixels.
for (int i = 0; i < NEO_PIXEL_COUNT; ++i) {
hues[i] = 360.0*(float(i)/float(NEO_PIXEL_COUNT-1));
}
}
void spectrumLoop() {
// Update each LED based on the intensity of the audio
// in the associated frequency window.
float intensity, otherMean;
for (int i = 0; i < NEO_PIXEL_COUNT; ++i) {
windowMean(magnitudes,
frequencyToBin(frequencyWindow[i]),
frequencyToBin(frequencyWindow[i+1]),
&intensity,
&otherMean);
// Convert intensity to decibels.
intensity = 20.0*log10(intensity);
// Scale the intensity and clamp between 0 and 1.0.
intensity -= SPECTRUM_MIN_DB;
intensity = intensity < 0.0 ? 0.0 : intensity;
intensity /= (SPECTRUM_MAX_DB-SPECTRUM_MIN_DB);
intensity = intensity > 1.0 ? 1.0 : intensity;
// pixels.setPixelColor(i, pixelHSVtoRGBColor(hues[i], 1.0, intensity));
}
// pixels.show();
}