diff --git a/sampler/platformio.ini b/sampler/platformio.ini
index 3e51ed2..0d45977 100644
--- a/sampler/platformio.ini
+++ b/sampler/platformio.ini
@@ -14,44 +14,19 @@ default_envs = teensy35
[common]
lib_ignore = Audio, SD
lib_deps =
- 721 ; TaskScheduler
- 322 ; SdFat
- 401 ; Adafruit SleepyDog Library
+ 721@3.0.2 ; TaskScheduler
+ 322@1.0.7 ; SdFat
[env:teensy35]
-platform = teensy
+platform = teensy@3.6.0
board = teensy35
framework = arduino
lib_deps = ${common.lib_deps}
lib_ignore = ${common.lib_ignore}
[env:teensy36]
-platform = teensy
+platform = teensy@3.6.0
board = teensy36
framework = arduino
lib_deps = ${common.lib_deps}
lib_ignore = ${common.lib_ignore}
-
-
-; [platformio]
-; env_default = teensy35
-;
-; [common]
-; lib_ignore = Audio, SD
-; lib_deps =
-; 721@3.0.2 ; TaskScheduler
-; 322@1.0.7 ; SdFat
-;
-; [env:teensy35]
-; platform = teensy@3.6.0
-; board = teensy35
-; framework = arduino
-; lib_deps = ${common.lib_deps}
-; lib_ignore = ${common.lib_ignore}
-;
-; [env:teensy36]
-; platform = teensy@3.6.0
-; board = teensy36
-; framework = arduino
-; lib_deps = ${common.lib_deps}
-; lib_ignore = ${common.lib_ignore}
diff --git a/sampler/src/main.cpp b/sampler/src/main.cpp
index 33cb76c..7f0dc1a 100644
--- a/sampler/src/main.cpp
+++ b/sampler/src/main.cpp
@@ -16,33 +16,14 @@
// (part-3) teensy35 : 'client:sampler' (mesh post --> play sounds)
//
-//
-// 2019 12 29
-//
-// multiple sound playback -> 4 voices -- TESTING
-//
-
-//--------------------
-//
-// 'ANALOG_REF_EXTERNAL_3P3V'
-// --> this will output 3.3v-pp from dacs pins of the board.
-// outdoor or big space. you will need this.
-// but, teensy36 board dacs pins once might have burned off cause of this?
-// teensy35 was okay since they are stronger (5V compatible I/O)
-//
-// #define ANALOG_REF_EXTERNAL_3P3V
-//
-// 'LED_INDICATOR'
-// --> this will enable red LED on/off according to the file playback status.
-//
-#define LED_INDICATOR
-//--------------------
-
-//watchdog
-#include
+//HACK: let auto-poweroff speakers stay turned ON! - (creative muvo mini)
+#define IDLE_FREQ 22000
+#define IDLE_AMP 0 // --> creative muvo 2 doesn't need this. they just stay on!
//teensy audio
#include
+// #include
+// #include
#include
SdFatSdioEX SD;
#include
@@ -53,285 +34,98 @@ SdFatSdioEX SD;
#define SDCARD_SCK_PIN 13 // not actually used
// GUItool: begin automatically generated code
-AudioPlaySdWav playSdWav1; //xy=183,90
-AudioPlaySdWav playSdWav2; //xy=185,253
-AudioPlaySdWav playSdWav3; //xy=187,411
-AudioPlaySdWav playSdWav4; //xy=188,579
-AudioAmplifier amp1; //xy=374,49
-AudioAmplifier amp2; //xy=375,132
-AudioAmplifier amp3; //xy=377,219
-AudioAmplifier amp4; //xy=378,302
-AudioAmplifier amp5; //xy=378,370
-AudioAmplifier amp6; //xy=379,453
-AudioAmplifier amp7; //xy=381,540
-AudioAmplifier amp8; //xy=382,623
-AudioMixer4 mixer2; //xy=620,413
-AudioMixer4 mixer1; //xy=621,210
-AudioOutputAnalogStereo dacs1; //xy=812,318
-AudioConnection patchCord1(playSdWav1, 0, amp1, 0);
-AudioConnection patchCord2(playSdWav1, 1, amp2, 0);
-AudioConnection patchCord3(playSdWav2, 0, amp3, 0);
-AudioConnection patchCord4(playSdWav2, 1, amp4, 0);
-AudioConnection patchCord5(playSdWav3, 0, amp5, 0);
-AudioConnection patchCord6(playSdWav3, 1, amp6, 0);
-AudioConnection patchCord7(playSdWav4, 0, amp7, 0);
-AudioConnection patchCord8(playSdWav4, 1, amp8, 0);
-AudioConnection patchCord9(amp1, 0, mixer1, 0);
-AudioConnection patchCord10(amp2, 0, mixer2, 0);
-AudioConnection patchCord11(amp3, 0, mixer1, 1);
-AudioConnection patchCord12(amp4, 0, mixer2, 1);
-AudioConnection patchCord13(amp5, 0, mixer1, 2);
-AudioConnection patchCord14(amp6, 0, mixer2, 2);
-AudioConnection patchCord15(amp7, 0, mixer1, 3);
-AudioConnection patchCord16(amp8, 0, mixer2, 3);
-AudioConnection patchCord17(mixer2, 0, dacs1, 1);
-AudioConnection patchCord18(mixer1, 0, dacs1, 0);
+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
-//
-class Voice {
- //private
-
- //teensy audio
- AudioPlaySdWav& player;
- AudioAmplifier& ampL;
- AudioAmplifier& ampR;
-
- // a filename buffer
- char filename[13];
-
-public:
-
- //
- int note_now;
- int velocity_now;
-
- //
- Voice(AudioPlaySdWav& player_, AudioAmplifier& ampL_, AudioAmplifier& ampR_)
- : player(player_)
- , ampL(ampL_)
- , ampR(ampR_)
- {
- //initializations
- note_now = 0;
- velocity_now = 0;
- strcpy(filename, "NNN.WAV");
- }
-
- //
- void noteOn(int note) {
- // present my 'note' -> 'occupied'.
- note_now = note;
- // set filename to play...
- 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
- // the filename to play is...
- Serial.println(filename);
- // go! (re-triggering)
- // if (player.isPlaying()) player.stop();
- player.play(filename);
- // --> we just believe that this 'file' is existing & available. NO additional checking.
- delay(10);
- // --> let's wait a bit before exit, to give more room to work for background workers(==filesystem|audio-interrupts)
- // --> if we get too fast 'player.play' twice, then the system might get broken/stalled. ?
- }
- //
- void noteOff() {
- player.stop();
- delay(10); // wait to close file?
- // present my 'note' -> 'free'.
- note_now = 0;
- }
- //
- void setVelocity(int val) {
- if (val < 0) val = 0;
- float vv = (float)val / 127; // allowing +gain for values over 127.
- ampL.gain(vv);
- ampR.gain(vv);
- }
- //
- bool isPlaying() {
- return player.isPlaying();
- }
-};
-
-// voice banks
-#include
-#include
-static Voice __voice_1(playSdWav1, amp1, amp2);
-static Voice __voice_2(playSdWav2, amp3, amp4);
-static Voice __voice_3(playSdWav3, amp5, amp6);
-static Voice __voice_4(playSdWav4, amp7, amp8);
-static std::vector poly_bank;
-static std::deque< std::pair > poly_queue;
-
//task
#include
Scheduler runner;
-// polyphonics
-static int note_sched = 0;
-static int velocity_sched = 0;
-void scheduleNoteOn()
+//sample #
+int sample_now = 0; //0~99
+void sample_player_start()
{
//filename buffer - 8.3 naming convension! 8+1+3+1 = 13
- char fname[13] = "NNN.WAV";
+ char filename[13] = "NNN.WAV";
//search for the sound file
- int note = note_sched;
+ int note = sample_now;
int nnn = (note % 1000); // 0~999
int nn = (note % 100); // 0~99
- fname[0] = '0' + (nnn / 100); // N__.WAV
- fname[1] = '0' + (nn / 10); // _N_.WAV
- fname[2] = '0' + (nn % 10); // __N.WAV
+ filename[0] = '0' + (nnn / 100); // N__.WAV
+ filename[1] = '0' + (nn / 10); // _N_.WAV
+ filename[2] = '0' + (nn % 10); // __N.WAV
//TEST
- Serial.println(fname);
+ Serial.println(filename);
AudioNoInterrupts();
- bool test = SD.exists(fname);
+ bool test = SD.exists(filename);
AudioInterrupts();
if (!test) {
Serial.println("... does not exist.");
return;
}
- //ok, let's schedule a voice
- //btw, is it already playing?
- // --> entry : (# of voice bank, playing note #)
- bool is_already = false;
- for (uint32_t idx = 0; idx < poly_queue.size(); idx++) {
- if (poly_queue[idx].second == note) {
- //oh, it is alreay playing
- // --> what to do?
- // (1) re-trigger (stop-and-restart)
- // is_already = true;
- // Voice& v = poly_bank[poly_queue[idx].first];
- // v.noteOff();
- // v.noteOn(note);
- // v.setVelocity(velocity_sched);
- // break;
- // (2) do nothing (just let it play till end)
- // is_already = true;
- // break;
- // (3) trigger a new one? (schedule a new one overlapping)
- // --> then you just ignore the fact.
- // i.e. do not tick 'is_already = true',
- // then a new one will be automatically assigned.
- break;
- }
- }
- //it's sth. new..
- if (is_already == false) {
- //fine, is there idle voice?
- bool is_found_idle = false;
- for (uint32_t idx = 0; idx < poly_bank.size(); idx++) {
- if (poly_bank[idx].note_now == 0) {
- //cool, got one.
- is_found_idle = true;
- //play start-up
- Voice& v = poly_bank[idx];
- v.noteOn(note);
- v.setVelocity(velocity_sched);
- //leave a record : (# of voice bank, playing note #)
- poly_queue.push_back(std::pair(idx, note));
- break;
- }
- }
- //oh, no idle one!
- if (is_found_idle == false) {
- //then, who's the oldest?
- int oldest = poly_queue.front().first;
- poly_bank[oldest].noteOff();
- poly_queue.pop_front();
- //
- int newentry = oldest;
- //
- Voice& v = poly_bank[newentry];
- v.noteOn(note);
- v.setVelocity(velocity_sched);
- //leave a record : (# of voice bank, playing note #)
- poly_queue.push_back(std::pair(newentry, note));
- }
- }
- //small waiting time for 'isPlaying' update?
- // delay(10);
- //monitoring the queue
- Serial.println("--notoOn:poly_queue---");
- Serial.println("(voice#, note#)");
- for (uint32_t idx = 0; idx < poly_queue.size(); idx++) {
- Serial.print("(");
- Serial.print(poly_queue[idx].first);
- Serial.print(", ");
- Serial.print(poly_queue[idx].second);
- Serial.println(")");
- }
- Serial.println();
+ //start the player!
+ //NOTE: block out 're-triggering'
+ // if (playSdWav1.isPlaying() == false) {
+ playSdWav1.play(filename);
+ // }
+ //mark the indicator : HIGH: ON
+ digitalWrite(13, HIGH);
+ //to wait a bit for updating isPlaying()
+ delay(10);
}
-//
-Task scheduleNoteOn_task(0, TASK_ONCE, scheduleNoteOn);
-//
-void scheduleNoteOff() {
- for (auto it = poly_queue.begin(); it != poly_queue.end(); ++it) {
- //is this meaningful, btw?
- if ((*it).second == note_sched) {
- //okay. we've got that.
- Serial.println("okay. we've got that.");
- //a record : (# of voice bank, playing note #)
- poly_bank[(*it).first].noteOff(); // stop the bank
- poly_queue.erase(it); // remove the record
- break;
- }
+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;
}
- //monitoring the queue
- Serial.println("--notoOff:poly_queue---");
- Serial.println("(voice#, note#)");
- for (uint32_t idx = 0; idx < poly_queue.size(); idx++) {
- Serial.print("(");
- Serial.print(poly_queue[idx].first);
- Serial.print(", ");
- Serial.print(poly_queue[idx].second);
- Serial.println(")");
+ //stop the player.
+ if (playSdWav1.isPlaying() == true) {
+ playSdWav1.stop();
}
- Serial.println();
}
-//
-Task scheduleNoteOff_task(0, TASK_ONCE, scheduleNoteOff);
-
-//
-extern Task playcheck_task;
-void playcheck() {
- //
- if (playcheck_task.isFirstIteration()) {
- //watchdog
- Watchdog.enable(1000);
- }
- //
-#if defined(LED_INDICATOR)
- //
- bool is_nosound = true;
- for (uint32_t idx = 0; idx < poly_bank.size(); idx++) {
- if (poly_bank[idx].isPlaying()) {
- is_nosound = false;
- }
- }
- if (is_nosound) {
+void sample_player_check() {
+ if (playSdWav1.isPlaying() == false) {
//mark the indicator : LOW: OFF
digitalWrite(13, LOW);
- } else {
- //mark the indicator : HIGH: ON
- digitalWrite(13, HIGH);
+ //let speaker leave turned ON!
+ sine1.amplitude(IDLE_AMP);
+ }
+ else {
+ //let speaker leave turned ON!
+ sine1.amplitude(0);
}
-#endif
-
- // //
- // Serial.print("AM_max:");
- // Serial.println(AudioMemoryUsageMax());
-
- //watchdog
- Watchdog.reset();
- // Serial.println("Watchdog.reset");
}
//
-Task playcheck_task(200, TASK_FOREVER, playcheck);
+Task sample_player_start_task(0, TASK_ONCE, sample_player_start);
+Task sample_player_stop_task(0, TASK_ONCE, sample_player_stop);
+Task sample_player_check_task(0, TASK_FOREVER, sample_player_check, &runner, true);
//i2c
#include
@@ -377,17 +171,20 @@ void receiveEvent(int numBytes) {
//
int key = str_key.toInt();
- int velocity = str_velocity.toInt(); // 0 ~ 127
- int gate = str_gate.toInt();
-
+ sample_now = key;
//
+ int velocity = str_velocity.toInt(); // 0 ~ 127
+ float amp_gain = (float)velocity / 127.0;
+ amp1.gain(amp_gain);
+ amp2.gain(amp_gain);
+ //
+ int gate = str_gate.toInt();
if (gate == 0) {
- note_sched = key;
- scheduleNoteOff_task.restart();
+ sample_player_stop_task.restart();
+ Serial.println("sample_player_stop_task");
} else {
- note_sched = key;
- velocity_sched = velocity;
- scheduleNoteOn_task.restart();
+ sample_player_start_task.restart();
+ Serial.println("sample_player_start_task");
}
}
}
@@ -439,8 +236,10 @@ void setup() {
// DISABLED.. due to bi-directional I2C hardship. ==> use UART.
// Wire.onRequest(requestEvent);
- //SD
+ //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;
}
@@ -448,51 +247,34 @@ void setup() {
root = SD.open("/");
printDirectory(root, 0);
- //polyphonics - 4 voices
- poly_bank.push_back(__voice_1);
- poly_bank.push_back(__voice_2);
- poly_bank.push_back(__voice_3);
- poly_bank.push_back(__voice_4);
-
//audio
- AudioMemory(20); // <-- used AudioMemoryUsageMax() to check out!
+ AudioMemory(20);
#if !defined(TEENSY36)
- //NOTE!! teensy36 board..
- // output broken? ..
- // so disable this for teensy36..
- // this is the cause??
-#if defined(ANALOG_REF_EXTERNAL_3P3V)
+ //NOTE!! teensy36 board.. output broken? .. so disable this for teensy36.. this is the cause??
dacs1.analogReference(EXTERNAL);
-#endif
#endif
mixer1.gain(0,1.0);
mixer1.gain(1,1.0);
- mixer1.gain(2,1.0);
- mixer1.gain(3,1.0);
+ mixer1.gain(2,0);
+ mixer1.gain(3,0);
mixer2.gain(0,1.0);
mixer2.gain(1,1.0);
- mixer2.gain(2,1.0);
- mixer2.gain(3,1.0);
+ mixer2.gain(2,0);
+ mixer2.gain(3,0);
amp1.gain(1.0);
amp2.gain(1.0);
- amp3.gain(1.0);
- amp4.gain(1.0);
- amp5.gain(1.0);
- amp6.gain(1.0);
- amp7.gain(1.0);
- amp8.gain(1.0);
- //tasks
- runner.addTask(playcheck_task);
- playcheck_task.restartDelayed(60000); // watchdog start after 60 sec. waiting task scheduling system stabilizing takes that so much time!
- //
- runner.addTask(scheduleNoteOn_task);
- runner.addTask(scheduleNoteOff_task);
+ //let auto-poweroff speakers stay turned ON!
+ sine1.frequency(IDLE_FREQ);
//led
pinMode(13, OUTPUT);
digitalWrite(13, LOW); // LOW: OFF
+ //player task
+ runner.addTask(sample_player_start_task);
+ runner.addTask(sample_player_stop_task);
+
//
Serial.println("[setup] done.");
}
diff --git a/src/main.cpp b/src/main.cpp
index 6edb1c0..cd587f8 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -64,7 +64,7 @@
//=====================
// (1) the backbone AP
-#if 1
+#if 0
#define DISABLE_I2C_REQ
#define SET_CONTAINSROOT
// (2) osc client (the ROOT)
@@ -72,7 +72,7 @@
#define SET_ROOT
#define SET_CONTAINSROOT
// (3) sampler client
-#elif 0
+#elif 1
#define DISABLE_AP
#define DISABLE_I2C_REQ
//