// // wirelessly connected cloud (based on ESP-NOW, a kind of LPWAN?) // // // Conversation about the ROOT @ SEMA storage, Seoul // // // 2021 02 15 // // (part-3) teensy35 : 'client:sampler' (mesh post --> play sounds) // //===================== // // 'USE_EXTERNAL_ANALOG_REFERENCE' // --> this was used probably to make output swing greater Vpp == 3.3v // but, with this + small headphones, i cannot hear anything. // and, this might be dangerous in some case -> this is suspicous of 1 broken teensy 3.6 // so, unless you are so sure, don't enable this. // !WARNING! : teensy36 could be destroyed! don't enable it. // // 'USE_IDLE_NOISE' // --> HACK: let auto-poweroff speakers stay turned ON - (creative muvo mini) // .NOTE. : creative muvo 2 doesn't need this. they just stay on! // // 'USE_LED_INDICATOR' // --> a light indicator for playing/stopped // //===================== #define USE_EXTERNAL_ANALOG_REFERENCE #define USE_IDLE_NOISE #define USE_LED_INDICATOR //======================== // #define IDLE_FREQ 50 #define IDLE_AMP 0.05 // #define GAIN_FACTOR 1.0 // this is a private multiplier for this module. // //======================== //teensy audio #include // #include // #include #include SdFatSdioEX SD; #include // GUItool: begin automatically generated code AudioPlaySdWav playSdWav1; //xy=224,265 AudioSynthWaveformSine sine1; //xy=236,361 AudioMixer4 mixer2; //xy=497,328 AudioMixer4 mixer1; //xy=499,245 AudioAmplifier amp1; //xy=633,245 AudioAmplifier amp2; //xy=634,328 AudioOutputAnalogStereo dacs1; //xy=788,284 AudioConnection patchCord1(playSdWav1, 0, mixer1, 0); AudioConnection patchCord2(playSdWav1, 1, mixer2, 0); AudioConnection patchCord3(sine1, 0, mixer1, 1); AudioConnection patchCord4(sine1, 0, mixer2, 1); AudioConnection patchCord5(mixer2, amp2); AudioConnection patchCord6(mixer1, amp1); AudioConnection patchCord7(amp1, 0, dacs1, 0); AudioConnection patchCord8(amp2, 0, dacs1, 1); // GUItool: end automatically generated code //task #include Scheduler runner; //sample # int sample_now = 0; //0~99 void sample_player_start() { //filename buffer - 8.3 naming convension! 8+1+3+1 = 13 char filename[13] = "NNN.WAV"; //search for the sound file int note = sample_now; int nnn = (note % 1000); // 0~999 int nn = (note % 100); // 0~99 filename[0] = '0' + (nnn / 100); // N__.WAV filename[1] = '0' + (nn / 10); // _N_.WAV filename[2] = '0' + (nn % 10); // __N.WAV //TEST Serial.println(filename); AudioNoInterrupts(); bool test = SD.exists(filename); AudioInterrupts(); if (!test) { Serial.println("... does not exist."); return; } //start the player! playSdWav1.play(filename); #if defined(USE_LED_INDICATOR) //mark the indicator : HIGH: ON digitalWrite(13, HIGH); #endif //to wait a bit for updating isPlaying() delay(10); } void sample_player_stop() { //filename buffer - 8.3 naming convension! 8+1+3+1 = 13 char filename[13] = "NNN.WAV"; //search for the sound file int note = sample_now; int nnn = (note % 1000); // 0~999 int nn = (note % 100); // 0~99 filename[0] = '0' + (nnn / 100); // N__.WAV filename[1] = '0' + (nn / 10); // _N_.WAV filename[2] = '0' + (nn % 10); // __N.WAV //TEST Serial.println(filename); AudioNoInterrupts(); bool test = SD.exists(filename); AudioInterrupts(); if (!test) { Serial.println("... does not exist."); return; } //stop the player. if (playSdWav1.isPlaying() == true) { playSdWav1.stop(); } } void sample_player_check() { if (playSdWav1.isPlaying() == false) { //mark the indicator : LOW: OFF digitalWrite(13, LOW); #if defined(USE_IDLE_NOISE) sine1.amplitude(IDLE_AMP); #endif } else { sine1.amplitude(0); } } // Task sample_player_start_task(0, TASK_ONCE, sample_player_start, &runner, false); Task sample_player_stop_task(0, TASK_ONCE, sample_player_stop, &runner, false); Task sample_player_check_task(0, TASK_FOREVER, sample_player_check, &runner, true); //i2c #include #include "../../post.h" // DISABLED.. due to bi-directional I2C hardship. ==> use UART. // void requestEvent() { // Wire.write(" "); // no letter to send // } void receiveEvent(int numBytes) { //numBytes : how many bytes received(==available) static char letter_intro[POST_BUFF_LEN] = "................................"; // Serial.println("[i2c] on receive!"); int nb = Wire.readBytes(letter_intro, POST_LENGTH); if (POST_LENGTH == nb) { //convert to String String msg = String(letter_intro); Serial.println(msg); //parse letter string. // letter frame ( '[' + 30 bytes + ']' ) // : [123456789012345678901234567890] // 'MIDI' letter frame // : [123456789012345678901234567890] // : [KKKVVVG.......................] // : KKK - Key // .substring(1, 4); // : VVV - Velocity (volume/amp.) // .substring(4, 7); // : G - Gate (note on/off) // .substring(7, 8); String str_key = msg.substring(1, 4); String str_velocity = msg.substring(4, 7); String str_gate = msg.substring(7, 8); // Serial.println(str_key); // Serial.println(str_velocity); // Serial.println(str_gate); // int key = str_key.toInt(); // sample_now = key; // int velocity = str_velocity.toInt(); // 0 ~ 127 float amp_gain = (float)velocity / 127.0; // amp_gain = amp_gain * GAIN_FACTOR; // amp1.gain(amp_gain); amp2.gain(amp_gain); // int gate = str_gate.toInt(); if (gate == 1) { //on 'start' // filter out re-triggering same note while it is playing. if (!playSdWav1.isPlaying() || sample_now != key) { sample_now = key; sample_player_start_task.restart(); Serial.println("sample_player_start_task"); } } else if (gate == 0) { //on 'stop' sample_now = key; sample_player_stop_task.restart(); Serial.println("sample_player_stop_task"); } } } // SD TEST void printDirectory(File dir, int numTabs) { char filename[256] = ""; while(true) { File entry = dir.openNextFile(); if (!entry) { // no more files break; } for (uint8_t i=0; i get killed by watchdog.. :( // // while (!Serial) {} // --> enable this.. to use Serial. otherwise, very jerky/unstable.. //i2c Wire.begin(I2C_ADDR); Wire.onReceive(receiveEvent); // DISABLED.. due to bi-directional I2C hardship. ==> use UART. // Wire.onRequest(requestEvent); //SD - AudioPlaySdWav @ teensy audio library needs SD.begin() first. don't forget/ignore! //+ let's additionally check contents of SD. if (!SD.begin()) { // if (!SD.begin(BUILTIN_SDCARD)) { Serial.println("[sd] initialization failed!"); return; } Serial.println("[sd] initialization done."); root = SD.open("/"); printDirectory(root, 0); //audio AudioMemory(20); #if defined(USE_EXTERNAL_ANALOG_REFERENCE) && !defined(TEENSY36) Serial.println("- ======== 'USE_EXTERNAL_ANALOG_REFERENCE' ========"); dacs1.analogReference(EXTERNAL); // <-- this was used probably to make output swing greater Vpp == 3.3v // but, with this + small headphones, i cannot hear anything. // and, this might be dangerous in some case -> this is suspicous of 1 broken teensy 3.6 // so, unless you are so sure, don't enable this. #endif mixer1.gain(0,1.0); mixer1.gain(1,1.0); mixer1.gain(2,0); mixer1.gain(3,0); mixer2.gain(0,1.0); mixer2.gain(1,1.0); mixer2.gain(2,0); mixer2.gain(3,0); amp1.gain(GAIN_FACTOR); amp2.gain(GAIN_FACTOR); //let auto-poweroff speakers stay turned ON! sine1.frequency(IDLE_FREQ); sine1.amplitude(0); //led pinMode(13, OUTPUT); digitalWrite(13, LOW); // LOW: OFF // Serial.println("[setup] done."); } void loop() { runner.execute(); }