Commit | Line | Data |
---|---|---|
f6f4142a TM |
1 | #include <nekobee.h> |
2 | #include <nekobee_voice.h> | |
3 | //#include <nekobee_voice_render.h> | |
4 | #include <nekobee_synth.h> | |
5 | #include <nekobee_types.h> | |
6 | #include <esp_task_wdt.h> | |
7 | #include "driver/i2s.h" | |
8 | #include "freertos/queue.h" | |
9 | ||
10 | ||
11 | #include <BLEMidi.h> | |
12 | //void connected(); | |
13 | //void disconnected(); | |
14 | ||
15 | ||
16 | nekobee_synth_t fSynth; | |
17 | ||
18 | #define SAMPLE_RATE 30000 | |
19 | #define BUF_LEN XSYNTH_NUGGET_SIZE //512 | |
20 | ||
21 | void nekobee_handle_raw_event(nekobee_synth_t* const synth, const uint8_t size, const uint8_t* const data) | |
22 | { | |
23 | if (size != 3) | |
24 | return; | |
25 | ||
26 | switch (data[0] & 0xf0) | |
27 | { | |
28 | case 0x80: | |
29 | nekobee_synth_note_off(synth, data[1], data[2]); | |
30 | break; | |
31 | case 0x90: | |
32 | if (data[2] > 0) | |
33 | nekobee_synth_note_on(synth, data[1], data[2]); | |
34 | else | |
35 | nekobee_synth_note_off(synth, data[1], 64); /* shouldn't happen, but... */ | |
36 | break; | |
37 | case 0xB0: | |
38 | nekobee_synth_control_change(synth, data[1], data[2]); | |
39 | break; | |
40 | default: | |
41 | break; | |
42 | } | |
43 | } | |
44 | ||
45 | ||
46 | static const i2s_port_t i2s_num = I2S_NUM_0; // i2s port number | |
47 | ||
48 | ||
49 | static const i2s_config_t i2s_config = { | |
50 | .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX /*| I2S_MODE_DAC_BUILT_IN*/ ), | |
51 | .sample_rate = SAMPLE_RATE, | |
52 | .bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT, // only the top 8 bits will actually be used by the internal DAC, but using 8 bits stra> | |
53 | .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, // always use stereo output. mono seems to be buggy, and the overhead is insignifcant o> | |
54 | .communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_LSB), // this appears to be the correct setting> | |
55 | .intr_alloc_flags = 0, // default interrupt priority | |
56 | .dma_buf_count = 4, // 8*128 bytes of buffer corresponds to 256 samples (2 channels, see above, 2 bytes per sample per channel) | |
57 | .dma_buf_len = BUF_LEN, | |
58 | .use_apll = false | |
59 | }; | |
60 | ||
61 | static const i2s_pin_config_t pin_config = { | |
62 | .bck_io_num = 26, | |
63 | .ws_io_num = 25, | |
64 | .data_out_num = 17, | |
65 | .data_in_num = I2S_PIN_NO_CHANGE | |
66 | }; | |
67 | ||
68 | uint8_t midii=0, midichar, mididata[8]; | |
69 | ||
70 | ||
71 | void synth_task( void * pvParameters ) { | |
72 | ||
73 | ||
74 | ||
75 | i2s_driver_install(i2s_num, &i2s_config, 0, NULL); //install and start i2s driver | |
76 | ||
77 | //i2s_set_pin(i2s_num, NULL); //for internal DAC, this will enable both of the internal channels | |
78 | i2s_set_pin(i2s_num, &pin_config); | |
79 | ||
80 | //You can call i2s_set_dac_mode to set built-in DAC output mode. | |
81 | //i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN); | |
82 | ||
83 | //i2s_set_sample_rates(i2s_num, SAMPLE_RATE); //set sample rates | |
84 | ||
85 | //i2s_driver_uninstall(i2s_num); //stop & destroy i2s driver | |
86 | ||
87 | //i2s_adc_disable(i2s_num); | |
88 | ||
89 | ||
90 | ||
91 | ||
92 | ||
93 | ||
94 | float *out; | |
95 | out = (float*)malloc(sizeof(float)*BUF_LEN); | |
96 | int32_t *outdma; | |
97 | outdma = (int32_t*)malloc(sizeof(int32_t)*BUF_LEN*8); | |
98 | ||
99 | int i = 0, n=60, v=60; | |
100 | //nekobee_synth_note_on(&fSynth, n , v); | |
101 | while(1) { | |
102 | if(i==0) { | |
103 | esp_task_wdt_reset(); | |
104 | //nekobee_synth_note_off(&fSynth, n , v); | |
105 | n = 16+rand()%63; | |
106 | v = 16+rand()%63; | |
107 | n = rand()%127; | |
108 | v = rand()%127; | |
109 | //nekobee_synth_note_on(&fSynth, n , v); | |
110 | } | |
111 | ||
112 | ||
113 | ||
114 | ||
115 | while(Serial.available()) { | |
116 | ||
117 | midichar = Serial.read(); | |
118 | if(midichar & 0b10000000) { | |
119 | midii = 0; | |
120 | } else if(midii == 0) continue; | |
121 | mididata[midii] = midichar; | |
122 | midii++; | |
123 | ||
124 | if(midii >= 3) { | |
125 | nekobee_handle_raw_event(&fSynth, midii, mididata); | |
126 | midii = 0; | |
127 | } | |
128 | } | |
129 | ||
130 | nekobee_synth_render_voices(&fSynth, out, BUF_LEN, 1); | |
131 | for(int i = 0; i < BUF_LEN; i++) { | |
132 | outdma[i*2] = outdma[(i*2)+1] = lrintf(out[i] * 2147483647); //((127)+round((out[i]*120.0)))*255; | |
133 | } | |
134 | ||
135 | size_t bytes_written; | |
136 | i2s_write(i2s_num, outdma, BUF_LEN*4*2, &bytes_written, portMAX_DELAY); | |
137 | ||
138 | //printf("%d\t%f\n", outdma[0], out[0]); | |
139 | //fwrite (out, sizeof(float)*BUF_LEN, 1, stdout); | |
140 | //Serial.println(out[0]); | |
141 | //Serial.println(uxTaskGetStackHighWaterMark(NULL)); | |
142 | //Serial.printf("%d\n", outdma[0]); | |
143 | //mgos_msleep(30); | |
144 | //delay(1); | |
145 | i++; if(i>400) i=0; | |
146 | } | |
147 | ||
148 | } | |
149 | ||
150 | ||
151 | uint8_t bn=0, bv=0; | |
152 | ||
153 | void onNoteOn(uint8_t channel, uint8_t note, uint8_t velocity) | |
154 | { | |
155 | nekobee_synth_note_off(&fSynth, bn , bv); | |
156 | nekobee_synth_note_on(&fSynth, note , velocity); | |
157 | bn = note, bv = velocity; | |
158 | Serial.print("on"); | |
159 | Serial.println(note); | |
160 | } | |
161 | ||
162 | void onNoteOff(uint8_t channel, uint8_t note, uint8_t velocity) | |
163 | { | |
164 | nekobee_synth_note_off(&fSynth, note , velocity); | |
165 | Serial.print("off"); | |
166 | Serial.println(note); | |
167 | } | |
168 | ||
169 | ||
170 | ||
171 | ||
172 | void setup() { | |
173 | Serial.begin(115200); | |
174 | ||
175 | nekobee_init_tables(); | |
176 | ||
177 | // init synth | |
178 | fSynth.sample_rate = SAMPLE_RATE; | |
179 | fSynth.deltat = 1.0f / (float)SAMPLE_RATE; | |
180 | fSynth.nugget_remains = 0; | |
181 | ||
182 | fSynth.note_id = 0; | |
183 | fSynth.polyphony = XSYNTH_DEFAULT_POLYPHONY; | |
184 | fSynth.voices = XSYNTH_DEFAULT_POLYPHONY; | |
185 | fSynth.monophonic = XSYNTH_MONO_MODE_ONCE; | |
186 | fSynth.glide = 0; | |
187 | fSynth.last_noteon_pitch = 0.0f; | |
188 | fSynth.vcf_accent = 0.0f; | |
189 | fSynth.vca_accent = 0.0f; | |
190 | ||
191 | for (int i=0; i<8; ++i) | |
192 | fSynth.held_keys[i] = -1; | |
193 | ||
194 | fSynth.voice = nekobee_voice_new(); | |
195 | fSynth.voicelist_mutex_grab_failed = 0; | |
196 | //pthread_mutex_init(&fSynth.voicelist_mutex, nullptr); | |
197 | ||
198 | fSynth.channel_pressure = 0; | |
199 | fSynth.pitch_wheel_sensitivity = 0; | |
200 | fSynth.pitch_wheel = 0; | |
201 | ||
202 | for (int i=0; i<128; ++i) | |
203 | { | |
204 | fSynth.key_pressure[i] = 0; | |
205 | fSynth.cc[i] = 0; | |
206 | } | |
207 | fSynth.cc[7] = 127; // full volume | |
208 | ||
209 | fSynth.mod_wheel = 1.0f; | |
210 | fSynth.pitch_bend = 1.0f; | |
211 | fSynth.cc_volume = 1.0f; | |
212 | ||
213 | // Default values | |
214 | /* | |
215 | fParams.waveform = 0.0f; | |
216 | fParams.tuning = 0.0f; | |
217 | fParams.cutoff = 25.0f; | |
218 | fParams.resonance = 25.0f; | |
219 | fParams.envMod = 50.0f; | |
220 | fParams.decay = 75.0f; | |
221 | fParams.accent = 25.0f; | |
222 | fParams.volume = 75.0f; | |
223 | fParams.bypass = false; | |
224 | */ | |
225 | ||
226 | // Internal stuff | |
227 | fSynth.waveform = 0.0f; | |
228 | fSynth.tuning = 1.0f; | |
229 | fSynth.cutoff = 5.0f; | |
230 | fSynth.resonance = 0.8f; | |
231 | fSynth.envmod = 0.3f; | |
232 | fSynth.decay = 0.0002f; | |
233 | fSynth.accent = 0.3f; | |
234 | fSynth.volume = 0.75f; | |
235 | ||
236 | //nekobee_synth_render_voices(&fSynth, NULL, 0, 1); //Update controls | |
237 | nekobee_synth_init_controls(&fSynth); | |
238 | //nekobee_synth_note_on(&fSynth, 80, 128); | |
239 | ||
240 | Serial.println("READY"); | |
241 | ||
242 | xTaskCreate(&synth_task, "blinking_led", 5*configMINIMAL_STACK_SIZE, NULL, 0, NULL); | |
243 | ||
244 | ||
245 | ||
246 | BLEMidiServer.begin("NekoMIDI"); | |
247 | BLEMidiServer.setOnConnectCallback([](){ // To show how to make a callback with a lambda function | |
248 | Serial.println("Connected"); | |
249 | }); | |
250 | BLEMidiServer.setOnDisconnectCallback([](){ // To show how to make a callback with a lambda function | |
251 | Serial.println("Disconnected"); | |
252 | }); | |
253 | BLEMidiServer.setNoteOnCallback(onNoteOn); | |
254 | BLEMidiServer.setNoteOffCallback(onNoteOff); | |
255 | //BLEMidiServer.setControlChangeCallback(onControlChange); | |
256 | //BLEMidiServer.enableDebugging(); | |
257 | ||
258 | } | |
259 | ||
260 | ||
261 | ||
262 | int i=0; | |
263 | void loop() { | |
264 | /* | |
265 | void | |
266 | nekobee_voice_render(nekobee_synth_t *synth, nekobee_voice_t *voice, | |
267 | float *out, unsigned long sample_count, | |
268 | int do_control_update) | |
269 | ||
270 | void nekobee_synth_render_voices(nekobee_synth_t *synth, float *out, | |
271 | unsigned long sample_count, | |
272 | int do_control_update); | |
273 | */ | |
274 | ||
275 | //nekobee_synth_render_voices(&fSynth, outbuffer, len, update_controls); | |
276 | ||
277 | //float out; | |
278 | ||
279 | //nekobee_synth_render_voices(&fSynth, &out, 1, 0); | |
280 | ||
281 | //Serial.println(out); | |
282 | //Serial.println(i++); | |
283 | delay(30); | |
284 | ||
285 | ||
286 | ||
287 | //fSynth.waveform = 0.0f; | |
288 | //fSynth.tuning = 1.0f; | |
289 | ||
290 | int adc2 = 0; | |
291 | if(adc2_get_raw(ADC2_CHANNEL_2, ADC_WIDTH_12Bit, &adc2) == ESP_OK) | |
292 | fSynth.cutoff = ((float)adc2)/(4095.0f/40.0f); | |
293 | if(adc2_get_raw(ADC2_CHANNEL_0, ADC_WIDTH_12Bit, &adc2) == ESP_OK) | |
294 | fSynth.resonance = ((float)adc2)/(4095.0f); | |
295 | ||
296 | fSynth.envmod = ((float)analogRead(35))/4095.0f; | |
297 | ||
298 | //fSynth.decay = 0.0002f; | |
299 | fSynth.decay = ((float)analogRead(34))/(4095.0f/0.0004f); | |
300 | fSynth.accent = ((float)analogRead(36))/4095.0f; | |
301 | fSynth.volume = ((float)analogRead(39))/4095.0f; | |
302 | ||
303 | /* | |
304 | Serial.print("SYNTH:"); | |
305 | Serial.print("\tCUT:"); Serial.print(fSynth.cutoff); | |
306 | Serial.print("\tRES:"); Serial.print(fSynth.resonance); | |
307 | Serial.print("\tENV:"); Serial.print(fSynth.envmod); | |
308 | Serial.print("\tDEC:"); Serial.printf("%.7f", fSynth.decay); | |
309 | Serial.print("\tACC:"); Serial.print(fSynth.accent); | |
310 | Serial.print("\tVOL:"); Serial.print(fSynth.volume); | |
311 | Serial.println(); | |
312 | */ | |
313 | ||
314 | } |