forked from zhujisheng/audio-reactive-led-strip
-
Notifications
You must be signed in to change notification settings - Fork 0
/
music_leds_esphome.h
123 lines (99 loc) · 3.96 KB
/
music_leds_esphome.h
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
114
115
116
117
118
119
120
121
122
123
#include "esphome.h"
using namespace esphome;
#include "driver/i2s.h"
#include <FastLED.h>
#include "FFT.h"
#include "VisualEffect.h"
enum PLAYMODE {MODE_SCROLL, MODE_ENERGY, MODE_SPECTRUM};
class MusicLeds{
private:
//N_PIXELS: The number of the LEDS on the led strip, must be even.
static const uint16_t N_PIXELS = 256;
//MIN_VOLUME_THRESHOLD: If the audio's volume is less than this number, the signal will not be processed.
static constexpr float MIN_VOLUME_THRESHOLD = 0.0003;
//Microphone(type of PDM)'s WS Pin and DATA_IN Pin, connecting to GPIO
static const int CK_IO_PIN = 19;
static const int WS_IO_PIN = 18;
static const int DATA_IN_PIN = 21;
static const uint16_t BUFFER_SIZE = 512;
static const uint8_t N_ROLLING_HISTORY = 2;
static const uint16_t SAMPLE_RATE = 44100;
static const uint16_t N_MEL_BIN = 18;
static constexpr float MIN_FREQUENCY = 200;
static constexpr float MAX_FREQUENCY = 12000;
float y_data[BUFFER_SIZE * N_ROLLING_HISTORY];
class FFT *fft;
class VisualEffect * effect;
CRGB physic_leds[N_PIXELS];
i2s_port_t i2s_num = I2S_NUM_0; // i2s port number
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = SAMPLE_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT,
.communication_format = I2S_COMM_FORMAT_PCM,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // high interrupt priority
.dma_buf_count = 32,
.dma_buf_len = 32
};
i2s_pin_config_t pin_config = {
.bck_io_num = CK_IO_PIN,
.ws_io_num = WS_IO_PIN,
.data_out_num = -1,
.data_in_num = DATA_IN_PIN
};
PLAYMODE CurrentMode = MODE_SCROLL;
public:
MusicLeds();
~MusicLeds();
void ShowFrame( PLAYMODE CurrentMode, light::AddressableLight *p_it);
};
MusicLeds::MusicLeds(){
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
i2s_set_pin(I2S_NUM_0, &pin_config);
i2s_stop(I2S_NUM_0);
i2s_start(I2S_NUM_0);
fft = new FFT(BUFFER_SIZE*N_ROLLING_HISTORY, N_MEL_BIN, MIN_FREQUENCY, MAX_FREQUENCY, SAMPLE_RATE, MIN_VOLUME_THRESHOLD);
effect = new VisualEffect(N_MEL_BIN,N_PIXELS);
}
MusicLeds::~MusicLeds(){
i2s_stop(I2S_NUM_0);
delete fft;
delete effect;
}
void MusicLeds::ShowFrame( PLAYMODE CurrentMode, light::AddressableLight *p_it){
static float mel_data[N_MEL_BIN];
for (int i = 0; i < N_ROLLING_HISTORY - 1; i++)
memcpy(y_data + i * BUFFER_SIZE, y_data + (i + 1)*BUFFER_SIZE, sizeof(float)*BUFFER_SIZE);
int16_t l[BUFFER_SIZE];
unsigned int read_num;
i2s_read(I2S_NUM_0, l, BUFFER_SIZE * 2, &read_num, portMAX_DELAY);
for(int i = 0; i < BUFFER_SIZE; i++) {
y_data[BUFFER_SIZE * (N_ROLLING_HISTORY - 1) + i] = l[i] / 32768.0;
static int ii=0;
ii++;
if(ii%SAMPLE_RATE==0)
ESP_LOGD("custom","%lu\t%d\n",millis(),ii);
}
fft->t2mel( y_data, mel_data );
switch(CurrentMode){
case MODE_SCROLL:
effect->visualize_scroll(mel_data, physic_leds);
break;
case MODE_ENERGY:
effect->visualize_energy(mel_data, physic_leds);
break;
case MODE_SPECTRUM:
effect->visualize_spectrum(mel_data, physic_leds);
break;
}
for (int i = 0; i < p_it->size(); i++) {
light::ESPColor c;
c.r = physic_leds[i].r;
c.g = physic_leds[i].g;
c.b = physic_leds[i].b;
c.w = 0;
(*p_it)[i] = c;
}
}
class MusicLeds music_leds;