forked from W4D/soundcube-firmware
almost a complete sequencer... almost
This commit is contained in:
@ -95,6 +95,25 @@ struct Config {
|
|||||||
|
|
||||||
Config config;
|
Config config;
|
||||||
|
|
||||||
|
struct Sample{
|
||||||
|
float volume = 1.0;
|
||||||
|
WaveStream *file;
|
||||||
|
};
|
||||||
|
|
||||||
|
Sample samples[NSTREAMS];
|
||||||
|
|
||||||
|
struct SequenceStep{
|
||||||
|
int len = 0;
|
||||||
|
Sample *samples[4];
|
||||||
|
void trigger(){
|
||||||
|
for(int i = 0; i < len; i++){
|
||||||
|
samples[i]->file->play(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SequenceStep steps[16];
|
||||||
|
|
||||||
void loadConfiguration(Config& config) {
|
void loadConfiguration(Config& config) {
|
||||||
File file = SD.open("/config.txt");
|
File file = SD.open("/config.txt");
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
@ -116,7 +135,7 @@ void loadConfiguration(Config& config) {
|
|||||||
config.ring_color.g_active = doc["ring"]["color"]["active"]["g"] | 80;
|
config.ring_color.g_active = doc["ring"]["color"]["active"]["g"] | 80;
|
||||||
config.ring_color.b_active = doc["ring"]["color"]["active"]["b"] | 50;
|
config.ring_color.b_active = doc["ring"]["color"]["active"]["b"] | 50;
|
||||||
|
|
||||||
JsonArray _sampleFiles = doc["sampleFiles"];
|
JsonArray _sampleFiles = doc["samples"];
|
||||||
config.boxid = doc["boxid"].as<String>();
|
config.boxid = doc["boxid"].as<String>();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for(JsonVariant item : _sampleFiles){
|
for(JsonVariant item : _sampleFiles){
|
||||||
@ -208,9 +227,10 @@ bool load_samples(){
|
|||||||
stream[i].begin();
|
stream[i].begin();
|
||||||
char filename[64];
|
char filename[64];
|
||||||
sprintf(filename, "/sound/%s/%s", config.boxid.c_str(), config.sampleFiles[i].c_str());
|
sprintf(filename, "/sound/%s/%s", config.boxid.c_str(), config.sampleFiles[i].c_str());
|
||||||
|
Serial.println(filename);
|
||||||
|
|
||||||
if(SD.exists(filename)){
|
if(SD.exists(filename)){
|
||||||
bool loaded = stream[i].load(SD.open(filename));
|
bool loaded = stream[i].load(SD.open(filename));
|
||||||
|
|
||||||
if(loaded) {
|
if(loaded) {
|
||||||
Serial.print("file read: ");
|
Serial.print("file read: ");
|
||||||
Serial.print(stream[i].wavefile.length);
|
Serial.print(stream[i].wavefile.length);
|
||||||
@ -230,9 +250,9 @@ bool load_samples(){
|
|||||||
} else {
|
} else {
|
||||||
for(int k = 0; k < 3; k++){
|
for(int k = 0; k < 3; k++){
|
||||||
digitalWrite(6, HIGH);
|
digitalWrite(6, HIGH);
|
||||||
delay(100);
|
delay(20);
|
||||||
digitalWrite(6, LOW);
|
digitalWrite(6, LOW);
|
||||||
delay(50);
|
delay(25);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -303,7 +323,7 @@ void setup() {
|
|||||||
|
|
||||||
// Rotary Encoder
|
// Rotary Encoder
|
||||||
ENC.begin(); // set direction pin.
|
ENC.begin(); // set direction pin.
|
||||||
ENC.setDirection(AS5600_COUNTERCLOCK_WISE);
|
ENC.setDirection(AS5600_CLOCK_WISE);
|
||||||
ENC.resetCumulativePosition();
|
ENC.resetCumulativePosition();
|
||||||
|
|
||||||
pinMode(6, OUTPUT); // Vibration Motor
|
pinMode(6, OUTPUT); // Vibration Motor
|
||||||
@ -345,6 +365,12 @@ void setup() {
|
|||||||
streams_loaded = load_samples();
|
streams_loaded = load_samples();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(streams_loaded) {
|
||||||
|
for(int i = 0; i < NSTREAMS; i++){
|
||||||
|
samples[i].file = &stream[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
digitalWrite(6, HIGH);
|
digitalWrite(6, HIGH);
|
||||||
delay(25);
|
delay(25);
|
||||||
digitalWrite(6, LOW);
|
digitalWrite(6, LOW);
|
||||||
@ -352,13 +378,13 @@ void setup() {
|
|||||||
digitalWrite(6, HIGH);
|
digitalWrite(6, HIGH);
|
||||||
delay(25);
|
delay(25);
|
||||||
digitalWrite(6, LOW);
|
digitalWrite(6, LOW);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dactest = false;
|
bool dactest = false;
|
||||||
uint32_t last = 0;
|
uint32_t last = 0;
|
||||||
bool tick = false;
|
bool tick = false;
|
||||||
int bar = 0;
|
int bar = 0;
|
||||||
|
int bar_old = -1;
|
||||||
int set_bar = 0;
|
int set_bar = 0;
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
@ -429,10 +455,8 @@ void loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set bar
|
// Set bar
|
||||||
if(buttons[BACK]) set_bar++;
|
// if(buttons[BACK]) set_bar++;
|
||||||
if(buttons[POWER]) set_bar--;
|
// if(buttons[POWER]) set_bar--;
|
||||||
if(set_bar == 16) set_bar = 0;
|
|
||||||
if(set_bar == -1) set_bar = 15;
|
|
||||||
|
|
||||||
if(buttons[DEBUG1]) {
|
if(buttons[DEBUG1]) {
|
||||||
Serial.println("vol down");
|
Serial.println("vol down");
|
||||||
@ -450,8 +474,12 @@ void loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(buttons[SELECT]){
|
if(buttons[SELECT]){
|
||||||
stream[active % NSTREAMS].toggle();
|
//stream[active % NSTREAMS].toggle();
|
||||||
ui_beep = true;
|
//ui_beep = true;
|
||||||
|
|
||||||
|
int n = steps[set_bar].len;
|
||||||
|
steps[set_bar].samples[n] = &samples[0];
|
||||||
|
steps[set_bar].len = (steps[set_bar].len + 1) % 4;
|
||||||
|
|
||||||
// Flash encoder leds
|
// Flash encoder leds
|
||||||
ui_leds[0] = CRGB(0, 100, 50);
|
ui_leds[0] = CRGB(0, 100, 50);
|
||||||
@ -464,6 +492,12 @@ void loop() {
|
|||||||
buttonChanged = false;
|
buttonChanged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(position < 0) position += 4096;
|
||||||
|
set_bar = (position / 256) % 16;
|
||||||
|
|
||||||
|
// if(set_bar == 16) set_bar = 0;
|
||||||
|
// if(set_bar == -1) set_bar = 15;
|
||||||
|
|
||||||
//dac.setValue(0, dactest ? 0 : sin((float)millis() / 100.0f) * 32768 + 32768);
|
//dac.setValue(0, dactest ? 0 : sin((float)millis() / 100.0f) * 32768 + 32768);
|
||||||
|
|
||||||
// empty LED matrix
|
// empty LED matrix
|
||||||
@ -477,16 +511,27 @@ void loop() {
|
|||||||
|
|
||||||
|
|
||||||
for(int i = 0; i < 48; i++){
|
for(int i = 0; i < 48; i++){
|
||||||
if(floor(i/3) == set_bar){
|
int step = floor(i/3);
|
||||||
|
if(step == set_bar){
|
||||||
ui_leds[lut_ring_cw[i]] = CRGB(config.ring_color.r_active, config.ring_color.g_active, config.ring_color.b_active);
|
ui_leds[lut_ring_cw[i]] = CRGB(config.ring_color.r_active, config.ring_color.g_active, config.ring_color.b_active);
|
||||||
}
|
}
|
||||||
if(floor(i/3) == bar){
|
if(step == bar){
|
||||||
ui_leds[lut_ring_cw[i]] = CRGB(config.ring_color.r, config.ring_color.g, config.ring_color.b);
|
ui_leds[lut_ring_cw[i]] = CRGB(config.ring_color.r, config.ring_color.g, config.ring_color.b);
|
||||||
}
|
}
|
||||||
|
if(steps[step].len > 0) {
|
||||||
|
ui_leds[lut_ring_cw[i]] = CRGB(0, 10, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bar != bar_old){
|
||||||
|
if(steps[bar].len > 0) {
|
||||||
|
steps[bar].trigger();
|
||||||
|
Serial.print("trigger ");
|
||||||
|
Serial.println(bar);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if(position < 0) position += 4096;
|
|
||||||
// active_led_ring = (position / 32) % 48;
|
|
||||||
|
|
||||||
// // set active LED ring LED
|
// // set active LED ring LED
|
||||||
// for(int i = 0; i < active_led_ring; i++){
|
// for(int i = 0; i < active_led_ring; i++){
|
||||||
@ -504,5 +549,5 @@ void loop() {
|
|||||||
if(i2s.getUnderflow()) Serial.println("underflow");
|
if(i2s.getUnderflow()) Serial.println("underflow");
|
||||||
|
|
||||||
//delay(20); // wait 1ms
|
//delay(20); // wait 1ms
|
||||||
|
bar_old = bar;
|
||||||
}
|
}
|
||||||
@ -74,16 +74,21 @@ struct WaveFile{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void readblock(){
|
bool readblock(){
|
||||||
uint8_t samplebyte[blockalign];
|
uint8_t samplebyte[blockalign];
|
||||||
|
|
||||||
file.read(samplebyte, blockalign);
|
file.read(samplebyte, blockalign);
|
||||||
if(!file.available() && loop) file.seek(44, SeekSet);
|
if(!file.available() && loop) file.seek(44, SeekSet);
|
||||||
|
if(!file.available() && !loop) {
|
||||||
|
file.seek(44, SeekSet);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for(int i = 0; i < blockalign; i+=2){
|
for(int i = 0; i < blockalign; i+=2){
|
||||||
int16_t sample = (samplebyte[i+1] << 8) + samplebyte[i];
|
int16_t sample = (samplebyte[i+1] << 8) + samplebyte[i];
|
||||||
buffer.push(sample);
|
buffer.push(sample);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t get(){
|
int16_t get(){
|
||||||
@ -94,6 +99,10 @@ struct WaveFile{
|
|||||||
file.seek(44, SeekSet);
|
file.seek(44, SeekSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void reset(){
|
||||||
|
file.seek(44, SeekSet);
|
||||||
|
}
|
||||||
|
|
||||||
bool loop = false;
|
bool loop = false;
|
||||||
uint16_t format = 0;
|
uint16_t format = 0;
|
||||||
uint32_t length = 0;
|
uint32_t length = 0;
|
||||||
@ -121,7 +130,10 @@ class WaveStream{
|
|||||||
|
|
||||||
void toggle(){playing = !playing;}
|
void toggle(){playing = !playing;}
|
||||||
|
|
||||||
void play(){playing = true;}
|
void play(bool reset = false){
|
||||||
|
if(reset) wavefile.reset();
|
||||||
|
playing = true;
|
||||||
|
}
|
||||||
|
|
||||||
void stop(){
|
void stop(){
|
||||||
playing = false;
|
playing = false;
|
||||||
@ -134,7 +146,8 @@ class WaveStream{
|
|||||||
if(!wavefile.buffer.isFull() && playing){
|
if(!wavefile.buffer.isFull() && playing){
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
while (!wavefile.buffer.isFull() && cnt < 6000) {
|
while (!wavefile.buffer.isFull() && cnt < 6000) {
|
||||||
wavefile.readblock();
|
bool ok = wavefile.readblock();
|
||||||
|
if(!ok) playing = false;
|
||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user