Code:
// constantes, variables y ajustes
#define bitSet64(value, bit) ((value) |= (1ULL << (bit)))
#define bitClear64(value, bit) ((value) &= ~(1ULL << (bit)))
#define bitWrite64(value, bit, bitvalue) (bitvalue ? bitSet64(value, bit) : bitClear64(value, bit))
#define sonido
//#define debug
#define midi_
//#define midiSync
//#define SAMPLER
#define DRUM
#define DRUMS
#include <math.h>
#include <SD.h>
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SerialFlash.h>
#ifdef sonido
//------------------AUDIO DESIGN TOOL----------------
// GUItool: begin automatically generated code
#ifdef SAMPLER
String muestra[64] = { "1.raw", "2.raw", "3.raw", "4.raw", "5.raw", "6.raw", "7.raw", "8.raw", "9.raw", "10.raw",
"11.raw", "12.raw", "13.raw", "14.raw", "15.raw", "16.raw", "17.raw", "18.raw", "19.raw", "20.raw",
"21.raw", "22.raw", "23.raw", "24.raw", "25.raw", "26.raw", "27.raw", "28.raw", "29.raw", "30.raw",
"31.raw", "32.raw", "33.raw", "34.raw", "35.raw", "36.raw", "37.raw", "38.raw", "39.raw", "40.raw",
"41.raw", "42.raw", "43.raw", "44.raw", "45.raw", "46.raw", "47.raw", "48.raw", "49.raw", "50.raw",
"51.raw", "52.raw", "53.raw", "54.raw", "55.raw", "56.raw", "57.raw", "58.raw", "59.raw", "60.raw",
"61.raw", "62.raw", "63.raw", "64.raw"
};
AudioPlaySdRaw sample0; //xy=220,122
AudioPlaySdRaw sample1; //xy=220,242
AudioPlaySdRaw sample2; //xy=220,362
AudioPlaySdRaw sample3; //xy=220,482
AudioPlaySdRaw sample4; //xy=220,602
AudioPlaySdRaw sample5; //xy=220,722
AudioPlaySdRaw sample6; //xy=220,842
AudioPlaySdRaw sample7; //xy=220,962
AudioConnection patchCord12(sample0, 0, mixer0, 2);
AudioConnection patchCord14(sample1, 0, mixer1, 2);
AudioConnection patchCord16(sample2, 0, mixer2, 2);
AudioConnection patchCord18(sample3, 0, mixer3, 2);
AudioConnection patchCord20(sample4, 0, mixer4, 2);
AudioConnection patchCord22(sample5, 0, mixer5, 2);
AudioConnection patchCord23(sample6, 0, mixer6, 2);
AudioConnection patchCord24(sample7, 0, mixer7, 2);
#endif
AudioSynthNoiseWhite noise1; //xy=57,331.2500047683716
AudioMixer4 mixer1; //xy=379,202
AudioMixer4 mixer2; //xy=379,322
AudioMixer4 mixer3; //xy=379,442
AudioMixer4 mixer4; //xy=379,562
AudioMixer4 mixer0; //xy=381,94.75
AudioMixer4 mixer5; //xy=379,682
AudioMixer4 mixer6; //xy=379,802
AudioMixer4 mixer7; //xy=379,922
#ifdef DRUMS
AudioSynthSimpleDrum drum1; //xy=219,162
AudioSynthSimpleDrum drum2; //xy=219,282
AudioSynthSimpleDrum drum0; //xy=220,35
AudioSynthSimpleDrum drum3; //xy=219,402
AudioSynthSimpleDrum drum4; //xy=219,522
AudioSynthSimpleDrum drum5; //xy=219,642
AudioSynthSimpleDrum drum6; //xy=219,762
AudioSynthSimpleDrum drum7; //xy=219,882
AudioConnection patchCord9(drum1, 0, mixer1, 0);
AudioConnection patchCord10(drum2, 0, mixer2, 0);
AudioConnection patchCord11(drum0, 0, mixer0, 0);
AudioConnection patchCord13(drum3, 0, mixer3, 0);
AudioConnection patchCord15(drum4, 0, mixer4, 0);
AudioConnection patchCord17(drum5, 0, mixer5, 0);
AudioConnection patchCord19(drum6, 0, mixer6, 0);
AudioConnection patchCord21(drum7, 0, mixer7, 0);
#endif
AudioEffectEnvelope envelope0; //xy=229.75,76.75
AudioEffectEnvelope envelope1; //xy=230,202
AudioEffectEnvelope envelope2; //xy=230,322
AudioEffectEnvelope envelope3; //xy=230,442
AudioEffectEnvelope envelope4; //xy=230,562
AudioEffectEnvelope envelope5; //xy=230,682
AudioEffectEnvelope envelope6; //xy=230,802
AudioEffectEnvelope envelope7; //xy=230,922
AudioFilterBiquad biquad1; //xy=522,202
AudioFilterBiquad biquad2; //xy=522,322
AudioFilterBiquad biquad0; //xy=523.2500076293945,109.50000095367432
AudioFilterBiquad biquad3; //xy=522,442
AudioFilterBiquad biquad4; //xy=522,562
AudioFilterBiquad biquad5; //xy=522,682
//AudioFilterStateVariable filter1; //xy=525,33.75
AudioFilterBiquad biquad6; //xy=522,802
AudioFilterBiquad biquad7; //xy=522,922
AudioMixer4 mixer10; //xy=707,710
AudioMixer4 mixer11; //xy=709,845
AudioMixer4 mixer13; //xy=710,598
AudioMixer4 mixer12; //xy=714,384
AudioMixer4 mixer9; //xy=719,276
AudioMixer4 mixer8; //xy=721,150
AudioMixer4 mixer16; //xy=808,483
//AudioEffectFreeverb freeverb1; //xy=950,487
AudioMixer4 mixer15; //xy=1086,599
AudioMixer4 mixer14; //xy=1090,371
AudioOutputI2S i2s1; //xy=1216,481
AudioConnection patchCord1(noise1, envelope1);
AudioConnection patchCord2(noise1, envelope2);
AudioConnection patchCord3(noise1, envelope3);
AudioConnection patchCord4(noise1, envelope4);
AudioConnection patchCord5(noise1, envelope5);
AudioConnection patchCord6(noise1, envelope6);
AudioConnection patchCord7(noise1, envelope7);
AudioConnection patchCord8(noise1, envelope0);
AudioConnection patchCord25(envelope0, 0, mixer0, 1);
AudioConnection patchCord26(envelope1, 0, mixer1, 1);
AudioConnection patchCord27(envelope2, 0, mixer2, 1);
AudioConnection patchCord28(envelope3, 0, mixer3, 1);
AudioConnection patchCord29(envelope4, 0, mixer4, 1);
AudioConnection patchCord30(envelope5, 0, mixer5, 1);
AudioConnection patchCord31(envelope6, 0, mixer6, 1);
AudioConnection patchCord32(envelope7, 0, mixer7, 1);
AudioConnection patchCord33(mixer1, biquad1);
AudioConnection patchCord34(mixer2, biquad2);
AudioConnection patchCord35(mixer3, biquad3);
AudioConnection patchCord36(mixer4, biquad4);
//AudioConnection patchCord37(mixer0, 0, filter1, 0);
AudioConnection patchCord37(mixer0, biquad0);
AudioConnection patchCord38(mixer5, biquad5);
AudioConnection patchCord39(mixer6, biquad6);
AudioConnection patchCord40(mixer7, biquad7);
AudioConnection patchCord41(biquad1, 0, mixer8, 1);
AudioConnection patchCord42(biquad1, 0, mixer9, 1);
AudioConnection patchCord43(biquad1, 0, mixer12, 1);
AudioConnection patchCord44(biquad2, 0, mixer8, 2);
AudioConnection patchCord45(biquad2, 0, mixer9, 2);
AudioConnection patchCord46(biquad2, 0, mixer12, 2);
AudioConnection patchCord47(biquad3, 0, mixer8, 3);
AudioConnection patchCord48(biquad3, 0, mixer9, 3);
AudioConnection patchCord49(biquad3, 0, mixer12, 3);
AudioConnection patchCord50(biquad4, 0, mixer10, 0);
AudioConnection patchCord51(biquad4, 0, mixer11, 0);
AudioConnection patchCord52(biquad4, 0, mixer13, 0);
AudioConnection patchCord53(biquad5, 0, mixer10, 1);
AudioConnection patchCord54(biquad5, 0, mixer11, 1);
AudioConnection patchCord55(biquad5, 0, mixer13, 1);
//AudioConnection patchCord56(filter1, 0, mixer8, 0);
//AudioConnection patchCord57(filter1, 0, mixer9, 0);
//AudioConnection patchCord58(filter1, 0, mixer12, 0);
AudioConnection patchCord56(biquad0, 0, mixer8, 0);
AudioConnection patchCord57(biquad0, 0, mixer9, 0);
AudioConnection patchCord58(biquad0, 0, mixer12, 0);
AudioConnection patchCord59(biquad6, 0, mixer10, 2);
AudioConnection patchCord60(biquad6, 0, mixer11, 2);
AudioConnection patchCord61(biquad6, 0, mixer13, 2);
AudioConnection patchCord62(biquad7, 0, mixer10, 3);
AudioConnection patchCord63(biquad7, 0, mixer11, 3);
AudioConnection patchCord64(biquad7, 0, mixer13, 3);
AudioConnection patchCord65(mixer10, 0, mixer14, 1);
AudioConnection patchCord66(mixer11, 0, mixer15, 1);
AudioConnection patchCord67(mixer13, 0, mixer16, 1);
AudioConnection patchCord68(mixer12, 0, mixer16, 0);
AudioConnection patchCord69(mixer9, 0, mixer15, 0);
AudioConnection patchCord70(mixer8, 0, mixer14, 0);
//AudioConnection patchCord71(mixer16, freeverb1);
//AudioConnection patchCord72(freeverb1, 0, mixer14, 2);
//AudioConnection patchCord73(freeverb1, 0, mixer15, 2);
AudioConnection patchCord74(mixer15, 0, i2s1, 1);
AudioConnection patchCord75(mixer14, 0, i2s1, 0);
// GUItool: end automatically generated code
//------------------AUDIO DESIGN TOOL----------------
#ifdef DRUMS
AudioSynthSimpleDrum *drum[8] =
{
&drum0, &drum1, &drum2, &drum3, &drum4, &drum5, &drum6, &drum7
};
#endif
#ifdef SAMPLER
AudioPlaySdRaw *sample[8] =
{
&sample0, &sample1, &sample2, &sample3, &sample4, &sample5, &sample6, &sample7
};
#endif
AudioEffectEnvelope *envelope[8] =
{
&envelope0, &envelope1, &envelope2, &envelope3, &envelope4, &envelope5, &envelope6, &envelope7
};
AudioFilterBiquad *biquad[8] =
{
&biquad0, &biquad1, &biquad2, &biquad3, &biquad4, &biquad5, &biquad6, &biquad7
};
AudioMixer4 *mixer[17] =
{
&mixer0, &mixer1, &mixer2, &mixer3, &mixer4, &mixer5, &mixer6, &mixer7,
&mixer8, &mixer9, &mixer10, &mixer11, &mixer12, &mixer13, &mixer14, &mixer15,
&mixer16
};
#endif
/*
AudioPlayMemory sample[8];
#include "AudioSampleHat01wavv.h"
#include "AudioSampleHat02wavv.h"
#include "AudioSampleKick02wavq.h"
#include "AudioSampleKickwavq.h"
#include "AudioSampleSnarewavq.h"
#include "AudioSampleSnare01wavq.h"
#include "AudioSampleSnare02wavq.h"
*/
#ifdef midi_
#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();
#endif
#ifdef midiSync
byte counter;
byte CLOCK = 248;
byte START = 250;
byte CONTINUE = 251;
byte STOP = 252;
#endif
#include <EEPROM.h>
//int eeAddress; //Location we want the data to be put.
// L E D S
#include <WS2812Serial.h>
#define numled 72
#define PIN0 17
byte BRIGHTNESS = 30;
byte drawingMemory[numled * 3]; // 3 bytes per LED
DMAMEM byte displayMemory[numled * 12]; // 12 bytes per LED
WS2812Serial leds(numled, displayMemory, drawingMemory, PIN0, WS2812_GRB);
int ledRef = 0; // contador para refresco de los leds
// numero de ciclos del loop necesarios para la escritura de los leds
#define ledRefMini 40 //50 // reloj perfecto pero mucha latencia?
int ledRef_ = ( ledRefMini * 81 ) - 1; // los 80 ciclos del grid y el pico final!!
// E N C O D E R :
//#define ENCODER_OPTIMIZE_INTERRUPTS
#define ENCODER_DO_NOT_USE_INTERRUPTS
#include <Encoder.h>
#define encA 14
#define encB 15
#define encClick 16
Encoder myEnc( encA, encB );
byte enc4;
byte _enc4;
int enc;
int _enc;
byte encPos;
byte actRow;
byte actCol;
bool encButt;
bool _encButt;
bool encButt_;
bool shuttle;
#define row0 30 // pins for 4051 row
#define row1 31
#define row2 8
#define col0 12 // pins for column
#define col1 13
#define col2 27
#define col3 26
#define pad 33 // COLUMN, pin de lectura del los pad del panel
#define triggIn 19 // entrada de relog
#define resetInput 18
bool butt[8][10]; // lectura de los pads,
bool _butt[8][10]; // comparador
bool butt_[8][8]; // estado del boton, las dos ultimas columnas no se estanb utilizando
bool recModulation;
bool recMode = true; //'true' sería insert note,false sería delete, muy guapo para performance
const byte triggOut[] = {2, 3, 4, 5, 6, 9, 10, 11};// pines de salida para las 8 pistas de triggers
bool resetIn;
bool _resetIn;
bool trigg; // entrada del clock
bool _trigg;
#define maxSteps 63 // longitud maxima de la secuencia ( quitandole -1 )
// VARIABLES PARA ALMACENAR COMO PRESET:
uint64_t dot[64][8];
uint64_t roll[64][8];
byte prob[64][8][(maxSteps + 1)];
byte val[64][8][maxSteps + 1]; // esta variablepodríamos usarlapara la velocidad midi x ejemplo
byte steps[64][8]; // duracion de cada linea
byte pMode[64][8]; // 0 normal, 1 reverse, 2 pendulum
byte clockDiv[64][8]; // division de reloj del row -1 ( 0 para clock divison = 1 ),
byte euclNum[64][8];
uint64_t noInitPatt;
uint64_t masterTrack;
uint64_t noInitProject;
byte part[65][64];
uint64_t noInitPart; // incluir en los presets
//--------GLOBAL SETTINGS---------
bool playSample[8] = { false, false, false, false, false, false, false, false };
bool playDrum[8] = { true, true, true, true, true, true, true, true };
byte midiNote[8];
uint8_t raw[8] = { 2, 3, 4, 5, 6, 7, 8, 9 }; // archivo que reproducira cada sampler/pista
bool resetSeq_;
byte actPatt;
byte nextPatt;
byte pattCounter;
byte loopSize[65];
byte actPart = 64;
byte multButtMax = 0;
byte multButtMin = 63;
int multButt = -1; // esto nos sirve para saber el ultimo botón pulsado y si se ha pulsado algo
byte multButt_ = 64; // esto es para ajustar con el primer loop
bool liveRecord_;
// otras variables relativas a las secuencias:
int pos[8]; // posicion del puntero de reproducción
int count[8]; // contador para el clock divider
byte page[8]; // contador de paginas para del display d cada pista
bool dir[8] = { true, true, true, true, true, true, true, true }; // direccion de la reproduccion para el modo pendulum
//int numeroClave; // variable para mi script de random, calculado a partir del contador de espera de los leds.
// implementaciones avanzadas
//byte ramification; // ciclo acumulativo de remates
/* tipose de rwamidficacion
proprcional
aritmetica */
//byte alg; // algoritmo de remates
/* nothing
inverse
reverse
re-order 3.3.2.3.3.2. -> 3.3.3.3.2.2. */
//bool logic; // para las pistas lógicas
//byte logicType; // quizasa no hace falta bool, solo el tipo > 0
bool mute[8];
int8_t sculpt[8]; // random offset
int i; // loop helpers
byte x;
byte y;
byte suma;
// control de tempo:
bool intTempo = false; // tempo interno, false seria externo (clock input)
int tempo = 120; // 120/min = 2/seg = 500 milis; tempo en la medida tradicional,
elapsedMicros temp;
uint32_t temp_ = 125000; // deducido a partir de tempo o viceversa, lo q debe durar temp
unsigned int t32 = temp_ / 2;
int stepCount; // byte es poco para un contador de pulsos
byte beatCount; // este es para los trsillos y el swing
byte swingAmount; // de 0 a 100
unsigned int swingTemp_; //el tiempo de retraso que lleva el golpe de swing, máximo 1/3 del pulso
bool t32_; // esto no me mola, usaremos algo distinto para el contador del relog
//bool t64;
#define triggLength 1000 //duracion de los triggers en microsegundos
byte editMode; // probando con tempo
byte lastEditMode;
// 0 - normal
// 1 - length -> azul
// 2 - play mode -> no deberia ser un menu, encoder y selector de pistas
// 3 - clock div -> verde
// 4 - probabilidad
// 5 - roll
// 6 - rotate
// 7 - euclidean -> no deberia ser un menu, encoder y selector de pistas
// 8 - tempo -> no deberia ser un menu, encoder
// 9 - midi -> no deberia ser un menu, encoder y selector de pistas
// 10 - val
// 11 - audio
// 12 - brillo y settings?
// 13 - swing -> no deberia ser un menu, encoder
// 14 - modulacion
// 15 - pattern
// 16 - drum settings
// 17 - mute
// 18 - invert
// 19 - editPart
// 20 - part grid
// 21 - song editor
// 22 - shuttle
// 23 - escoger muestra
bool edit; // esto se usa para que el encoder no se mueva,
//comprobar en que menus haria falta movimiento
// M E N U - H O R I Z O N T A L
bool menu2 = false;
// M E N U V E R T I C A L
bool menuVertical; // activa la vision de menu horizontal
byte menuIndex; // 0 audio, 1 mezcla, 2 modulacion
byte menuParam; // parámtros del 1 al 8
int menuVar[3][8][8]; // [menuIndex][actTrack][menuParam]
//drum synth
#define drumVol 0
#define drumDecay 1
#define drumFreq 2
#define drumMod 3
#define drumSecond 4
#define noiseVol 5
#define noiseDecay 6
//---------------
#define volumen 0
#define panoramica 1
#define revAmount 2
#define filterFreq 3
#define resonancia 4
#define filterType 5
//channel mixer
//reverb settings
#define revSize 0
#define revDamp 1
#define revL 2
#define revR 3
/*
Mix(1, 2, 3):
-vol
-pan
-reverb
Mod:
*/
// P U S H B U T T O N S - en principio no estoy usando los 'bool' excepto en el encoder
// pasa por lo modos de edicion
#define playStopButt 0
#define tempoButt 0
#define homeButt 1
#define settingsButt 1
#define lengthButt 2
#define divButt 2
#define pattButt 3
#define saveAllButt 3 // esto deberia ser save project?
#define playModeButt 4
#define masterTrackButt 4
#define fillButt 5
#define euclButt 5
#define muteButt 6
// mute all
#define provButt 7
// prob roll
#define invButt 8 // tambien invert all
// inv all
#define rollButt 9
#define midiButt 9
#define rotateButt 10 //tambien rotate all
//rotate all
#define valButt 11
#define modButt 11
#define trippButt 12 //tresillos
#define swingButt 12
#define audioButt 13 // drumSynth
#define shiftButt 14
#define zoomButt 15
#define brightButt 15
// botones de funcion del grid:
// D R U M S Y T N H - linea 7
#define drumSynthVol 49
#define drumSynthDecay 50
#define drumSynthFreq 51
#define drumSynthMod 52
#define drumSynthSecond 53
#define noiseSynthVol 54
#define noiseSynthDecay 55
// M I X E R - ultima linea
#define mixerVol 57
#define mixerPan 58
#define mixerReverbSend 59
#define mixerFilterFreq 60
#define mixerFilterRes 61
#define mixerFilterType 62
bool shiftButt_; // para las egundas funsiones de cada boton, tambien como track select?
bool zoom; //estado del zoom
byte zoomTrack;
// ENTRADAS DE CV Y MATRIZ DE MODULACIÓN:
const byte cvIn[4] = { 22 , 22 , 22 , 22 };// 22, 23, 24, 25
int cvRead[4]; //lectura de CV
int8_t modMatrix[3][8][7]; // cuatro canales de CV, de -100 a 100%
byte modSource[3][8][7]; // [menuIndex][actTrack][menuParam]
long rndNumber = random(16);
Code:
//
// T U K R A trigger sequencer
//
// Tesseract Modular
//
// Mangu Díaz 2020
// unsigned const int * samples[] = {AudioSampleSnare, AudioSampleHihat};
#include "ini.h"
void setup()
{
#ifdef sonido
AudioMemory(60); //120
for (i = 0; i < 8; i++)
{
envelope[i]->attack(0.0);
envelope[i]->hold(0.0);
envelope[i]->sustain(0.0);
envelope[i]->release(0.0);
envelope[i]->releaseNoteOn(0.0);
}
noise1.amplitude(0.5);
SD.begin(BUILTIN_SDCARD);
#endif
#ifdef midi_
MIDI.begin();
#endif
#ifdef midiSync
MIDI.setHandleRealTimeSystem(RealTimeSystem);
#endif
#ifdef debug
while (!Serial)
;
Serial.print("T U K R A Firmware Debug Mode\n");
Serial.print("ledRef_ : ");
Serial.print(ledRef_);
Serial.print("\n");
intTempo = false;
#endif
for (i = 0; i < 8; i++)
{
pinMode(triggOut[i], OUTPUT);
}
// setting pins for buttons etc:
pinMode(triggIn, INPUT);
pinMode(encClick, INPUT_PULLUP);
pinMode(resetInput, INPUT);
// multiplexer:
pinMode(row0, OUTPUT);
pinMode(row1, OUTPUT);
pinMode(row2, OUTPUT);
pinMode(col0, OUTPUT);
pinMode(col1, OUTPUT);
pinMode(col2, OUTPUT);
pinMode(col3, OUTPUT);
pinMode(pad, INPUT_PULLUP);
// ENTRADAS DE CV
analogReadResolution(10);
pinMode(cvIn[0], INPUT); //empezamos jugando solo con una entrada
//pinMode(cvIn[1], INPUT);
//pinMode(cvIn[2], INPUT);
//pinMode(cvIn[3], INPUT);
// LEDS:
leds.setBrightness(BRIGHTNESS);
leds.begin();
//inicializar el projecto
for (i = 0; i < 64; i++)
{
actPatt = i;
initPatt();
}
actPatt = 0;
part[64][0] = 0;
loopSize[64] = 0;
loadAll();
// readPreset();
#include "bootSeq.h"
}
void loop()
{
#ifdef midiSync
MIDI.read();
#endif
// byte menuParam;
ledRef++;
// M A T R I X B U T T O N R E A D:
if ((ledRef % ledRefMini) == 0)
{
butt[x][y] = digitalRead(pad);
if (y == 9)
{
x++;
if (x > 7)
{
x = 0;
}
uint8_t r0 = bitRead(x, 0);
uint8_t r1 = bitRead(x, 1);
uint8_t r2 = bitRead(x, 2);
digitalWrite(row0, r0);
digitalWrite(row1, r1);
digitalWrite(row2, r2);
}
y++;
if (y > 9)
{
y = 0;
}
uint8_t c0 = bitRead(y, 0);
uint8_t c1 = bitRead(y, 1);
uint8_t c2 = bitRead(y, 2);
uint8_t c3 = bitRead(y, 3);
digitalWrite(col0, c0);
digitalWrite(col1, c1);
digitalWrite(col2, c2);
digitalWrite(col3, c3);
// G R I D 8 X 8
if (y < 8)
{
//reseteamos los valores para empezar
uint32_t redVal = 0;
uint32_t blueVal = 0;
uint32_t greenVal = 0;
byte x_;
byte y_;
suma = (x * 8) + y;
if (butt[x][y] != _butt[x][y])
{
if (butt[x][y] == LOW)
{
multButt_++;
if ((shiftButt_) && (y == 0) && (editMode != 15)) // selección de pista
{
actRow = x;
zoomTrack = x;
}
else
{
butt_[x][y] = true;
if ((!menuVertical) && (editMode != 14)) // hay conflicto aqui con el menu horizontal y el menu modulacion
{
encPos = suma;
actRow = x;
actPos();
}
}
}
else
{
multButt_--;
/*
#ifdef debug
Serial.print("botones pulsados..."); Serial.print(multButt_); Serial.print("\n");
#endif
*/
}
_butt[x][y] = butt[x][y];
}
if (menuVertical) // MENU VERTICAL
{
if ((y > 0) && ((menuVar[menuIndex][actRow][y - 1] / 128) >= (7 - x)))
{
redVal = (7 - x) * 10;
greenVal = 70 - ((7 - x) * 10);
}
if (((y == menuParam + 1) && (x == 7))) // esto nos indica el parametro seleccionado
{
blueVal = 30;
}
if ((y == 0) && (x == actRow)) // selección de pista
{
blueVal = 100;
}
if (butt_[x][y] == true)
{
if (y == 0)
{
actRow = x;
}
else
{
menuVar[menuIndex][actRow][y - 1] = (128 * (7 - x));
menuParam = y - 1;
}
}
}
// nuevo Menu Horizontal
// falta por implementar el encoder!
else if (menu2)
{
if ((menuVar[menuIndex][x][menuParam] / 128) >= y)
{
redVal = y * 10;
blueVal = 70 - (y * 10);
}
if (butt_[x][y] == true)
{
menuVar[menuIndex][x][menuParam] = (128 * y);
}
}
else // si no hay menu horizontal o vertical procesamos todo lo demas,
{
if (zoom == false)
{
page[x] = (pos[x] / 8);
y_ = (y + (page[x] * 8));
x_ = x;
}
else
{
x_ = zoomTrack;
y_ = (suma);
}
if (bitRead(dot[actPatt][x_], y_) == true) // hay un golpe ahi
{
blueVal = 50;
}
if ((pos[x_] == y_)) // posicion de reproduccion
{
redVal = 50;
}
if (encPos == suma) //posicion del encoder
{
greenVal = 50;
if (encButt_ == true) // E N C O D E R . B U T T O N
{
switch (editMode)
{
case 0:
bitWrite64(dot[actPatt][x_], y_, !bitRead(dot[actPatt][x_], y_));
bitSet64(noInitPatt, actPatt); // el patron tiene contenido
break;
case 5: //roll
if (bitRead(dot[actPatt][x_], y_) == true)
{
if (bitRead(roll[actPatt][x_], y_) == true)
{
bitClear64(roll[actPatt][x_], y_);
}
else
{
bitSet64(roll[actPatt][x_], y_);
}
}
break;
default:
edit = !edit;
if (edit == false)
{
actPos();
}
break;
}
encButt_ = false;
}
}
switch (editMode) // B U T T O N G R I D M O D E
{
case 0: // H O M E
if (butt_[x][y] == true)
{
if (shiftButt_)
{
switch (suma)
{
case 1: // R E C M O D E
liveRecord_ = !liveRecord_;
break;
case 2: // P A R T E D I T O R
editMode = 19;
break;
case 9: // S H U T T L E
shuttle = true;
break;
case 17: // INVERTIR DIRECCIÓN
invertDir();
break;
case 18: // I N I T P A R T
initPatt();
break;
case 10: // part grid
editMode = 20;
break;
case 25: // S E L E C T R A W
editMode = 23;
edit = true;
break;
//----------MENU HORIZONTAL-----------
case mixerVol: // MIXER -> VOLUMEN
menu2 = true;
edit = true;
menuIndex = 1;
menuParam = 0;
break;
case mixerPan: // MIXER -> PAN
menu2 = true;
edit = true;
menuIndex = 1;
menuParam = 1;
break;
case mixerReverbSend: // MIXER -> REVERB SEND
menu2 = true;
edit = true;
menuIndex = 1;
menuParam = 2;
break;
case mixerFilterFreq: // MIXER -> FILTER CUTOFF
menu2 = true;
edit = true;
menuIndex = 1;
menuParam = 3;
break;
case mixerFilterRes: // MIXER -> FILTER RES
menu2 = true;
edit = true;
menuIndex = 1;
menuParam = 4;
break;
case mixerFilterType: // MIXER -> FILTER TYPE
menu2 = true;
edit = true;
menuIndex = 1;
menuParam = 5;
break;
case drumSynthVol: // DRUM -> VOLUMEN
menu2 = true;
edit = true;
menuIndex = 0;
menuParam = 0;
break;
case drumSynthDecay: // DRUM -> DECAY
menu2 = true;
edit = true;
menuIndex = 0;
menuParam = 1;
break;
case drumSynthFreq: // DRUM -> PITCH
menu2 = true;
edit = true;
menuIndex = 0;
menuParam = 2;
break;
case drumSynthMod: // DRUM -> PITCH ENV
menu2 = true;
edit = true;
menuIndex = 0;
menuParam = 3;
break;
case drumSynthSecond: // DRUM -> 5º
menu2 = true;
edit = true;
menuIndex = 0;
menuParam = 4;
break;
case noiseSynthVol: // NOISE -> VOL
menu2 = true;
edit = true;
menuIndex = 0;
menuParam = 5;
break;
case noiseSynthDecay: // NOISE -> DECAY
menu2 = true;
edit = true;
menuIndex = 0;
menuParam = 6;
break;
}
}
else if (liveRecord_)
{
liveRecord();
}
else
{
bitWrite64(dot[actPatt][x_], y_, !bitRead(dot[actPatt][x_], y_));
bitSet64(noInitPatt, actPatt);
}
}
break;
case 1: // S T E P S
if (steps[actPatt][x_] >= (zoom * x * 8) + y)
{
blueVal += 10;
}
if (butt_[x][y] == true)
{
steps[actPatt][x_] = y_;
}
break;
case 2: // P L A Y M O D E
break;
case 3: // div, step repeat
if (clockDiv[actPatt][x_] >= y)
{
greenVal += 10;
}
if (butt_[x][y] == true)
{
clockDiv[actPatt][x_] = y_;
}
break;
case 4: // prob
if (bitRead(dot[actPatt][x_], y_) == true)
{
redVal = (225 / (prob[actPatt][x_][y_] + 1));
blueVal = (prob[actPatt][x_][y_] * 14);
}
break;
case 5: // roll
if (bitRead(roll[actPatt][x_], y_) == true)
{
redVal += 40;
}
if (butt_[x][y] == true)
{
bitWrite64(roll[actPatt][x_], y_, !bitRead(roll[actPatt][x_], y_));
}
break;
case 10: // VAL,
//quitamos el condicional ...solo sirve para jugar con la modulacion cruzada!
//if ( bitRead(dot[actPatt][x_], y_) == true ) // hay un golpe ahi
//{
redVal = val[actPatt][x_][y_] / 2;
blueVal = 127 - val[actPatt][x_][y_];
//}
if (butt_[x][y] == true)
{
multButt = suma;
if (multButt > multButtMax)
{
multButtMax = multButt;
}
if (multButt < multButtMin)
{
multButtMin = multButt;
}
}
else
{
if ((multButt != -1) && (multButt_ == 0)) // esto nos indica que nigun boton esta pulsado pero no se ha reseteado
{
// reset:
multButtMin = 63;
multButtMax = 0;
multButt = -1;
}
}
break;
case 14: // M O D M A T R I X
if (y > 0) // grid de puntos de modulacion, offset 'y-1'
{
if (modMatrix[menuIndex][x][y - 1] > 0) // colores para modulación positiva
{
redVal = 30 + (modMatrix[menuIndex][x][y - 1] * 2);
greenVal = (100 - modMatrix[menuIndex][x][y - 1]) / 2;
}
else if (modMatrix[menuIndex][x][y - 1] < 0) // modulación negativa
{
blueVal = 30 + (modMatrix[menuIndex][x][y - 1] * -2);
redVal = (100 + modMatrix[menuIndex][x][y - 1]) / 2;
greenVal = 0;
}
else
{
redVal = 0;
blueVal = 0;
}
if (butt_[x][y] == true)
{
encPos = suma;
edit = true;
actRow = x;
actCol = y;
}
}
else // primera columna, seleccion de CV del parametro seleccionado
{
redVal = 0;
blueVal = 0;
greenVal = 0;
if (x == modSource[menuIndex][actRow][actCol - 1])
{
greenVal = 100;
}
if (menuIndex == x - 6)
{
blueVal = 100;
}
if (butt_[x][y] == true)
{
if (x < 5) // seleccion del cv de 1 a 4, luego ya veremos
{
modSource[menuIndex][actRow][actCol - 1] = x;
}
// seleccion del menuIndex, de momento 0 o 1 (drumSynth y audio)
else if (x > 5)
{
menuIndex = x - 6;
}
}
}
break;
case 15: // P A T T E R N
redVal = 0;
blueVal = 0;
if (actPatt == suma) // patron en reproduccion
{
greenVal = 50;
}
else if ((suma >= part[64][0]) && (suma <= part[64][loopSize[64]])) // rango de patrones del loop
{
redVal = 100;
}
else // fuera del loop
{
blueVal = 20;
redVal = bitRead(noInitPatt, suma) * 50;
}
if (butt_[x][y] == true)
{
multButt = suma;
if (multButt > multButtMax)
{
multButtMax = multButt;
}
if (multButt < multButtMin)
{
multButtMin = multButt;
}
if (shiftButt_ == true)
{
copyPatt();
actPatt = suma;
}
}
else
{
if ((multButt != -1) && (multButt_ == 0)) // esto nos indica que nigun boton esta pulsado en este ciclo pero que hay un loop por procesar!
{
makeLoop();
// reset:
multButtMin = 63;
multButtMax = 0;
multButt = -1;
}
}
break;
case 18: // invert sequence
if (butt_[x][y] == true)
{
invertSeq(actRow);
}
break;
case 17: // M U T E
if (mute[x_] == true)
{
redVal += 15;
greenVal += 10;
}
if (butt_[x][y] == true)
{
mute[actRow] = !mute[actRow];
}
break;
case 19: // p a t t e r n
if (suma > loopSize[actPart])
{
redVal = 0;
greenVal = 0;
blueVal = 0;
}
else
{
redVal = part[actPart][suma] * 2;
greenVal = (part[actPart][suma] % 3) * 30;
blueVal = 63 - (part[actPart][suma]);
}
if (butt_[x][y] == true)
{
if (shiftButt_ == true)
{
//hacer algo
part[actPart][suma] = actPatt;
}
else
{
//abrir o guardar parte
actPatt = part[actPart][suma];
}
}
break;
case 20: // P A T T E R N G R I D
blueVal = 20 * bitRead(noInitPart, suma);
if (suma == actPart)
{
redVal = 80;
}
else
{
redVal = 40;
greenVal += 20;
}
if (butt_[x][y] == true)
{
if (shiftButt_ == true)
{
//guardar la parte actual en ese slot
for (i = 0; i < 64; i++)
{
part[suma][i] = part[actPart][i];
}
loopSize[suma] = loopSize[actPart];
bitSet64(noInitPart, suma);
}
else
{
//abrir parte
actPart = suma;
}
}
break;
} // end of GRID
} // final del condicional 'no horizontal menu'
leds.setPixelColor((suma), leds.Color(redVal, greenVal, blueVal));
butt_[x][y] = false;
} // fin de si y < 8
if (y > 7) // F U N C T I O N B U T T O N S
{
byte buttCount = (x * 2) + y - 8;
if (butt[x][y] != _butt[x][y])
{
if (butt[x][y] == LOW)
{
if (shiftButt_)
{
switch (buttCount) // f u n c i o n e s s e c u n d a r i a s
{
case euclButt:
if (editMode == 7)
{
editMode = lastEditMode;
lastEditMode = 7;
}
else
{
lastEditMode = editMode;
editMode = 7;
}
break;
case brightButt: // edit BRIGHTNESS
editMode = 12;
edit = true;
break;
case tempoButt: // edit tempo
editMode = 8;
edit = true;
break;
case modButt: // mod settings
editMode = 14;
edit = false;
menuVertical = false;
leds.setPixelColor(64, leds.Color((1023 - cvRead[0]) / 10, cvRead[0] / 10, 0));
leds.setPixelColor(65, leds.Color((1023 - cvRead[1]) / 10, cvRead[1] / 10, 0));
leds.setPixelColor(66, leds.Color((1023 - cvRead[2]) / 10, cvRead[2] / 10, 0));
leds.setPixelColor(67, leds.Color((1023 - cvRead[3]) / 10, cvRead[3] / 10, 0));
break;
case midiButt:
editMode = 9;
break;
case swingButt: // swing control
editMode = 13;
edit = true;
break;
case divButt:
editMode = 3;
edit = true;
menuVertical = false;
break;
case saveAllButt: // save project
saveAll();
break;
case masterTrackButt: // el track 1 resetea a los demas
bitWrite64(masterTrack, actPatt, !bitRead(masterTrack, actPatt));
break;
case audioButt: // M I X E R settings
lastEditMode = editMode;
// editMode = 11; 16 ??
menuIndex = 1; // corresponde all array de audio
menuVertical = true;
break;
}
}
else
{
switch (buttCount)
{
case homeButt: // H O M E
if ((editMode == 0) && (zoom == true))
{
zoom = false;
}
else
{
lastEditMode = editMode;
editMode = 0;
menuVertical = false;
menu2 = false;
edit = false; //igual esta la tenemos q sacar de aqui
}
break;
case playStopButt:
intTempo = !intTempo;
if (intTempo)
{
temp_ = 15000000 / tempo;
t32 = temp_ / 2;
swingCalculator();
resetSeq();
writeTrigg();
temp = 0;
beatCount = 1;
}
break;
case zoomButt:
zoom = !zoom;
if (zoom == true)
{
zoomTrack = actRow;
}
break;
case lengthButt:
if (editMode == 1)
{
editMode = lastEditMode;
lastEditMode = 1;
}
else
{
lastEditMode = editMode;
editMode = 1;
edit = true;
menuVertical = false;
}
break;
case playModeButt:
if (editMode == 2)
{
editMode = lastEditMode;
lastEditMode = 2;
}
else
{
lastEditMode = editMode;
editMode = 2;
}
break;
case provButt:
if (editMode == 4)
{
editMode = lastEditMode;
lastEditMode = 4;
}
else
{
lastEditMode = editMode;
editMode = 4;
}
break;
case rollButt:
if (editMode == 5)
{
editMode = lastEditMode;
lastEditMode = 5;
}
else
{
lastEditMode = editMode;
editMode = 5;
}
break;
case valButt: // val edit
if (editMode == 10)
{
editMode = lastEditMode;
lastEditMode = 10;
}
else
{
lastEditMode = editMode;
editMode = 10;
}
break;
case rotateButt:
if (editMode == 6)
{
editMode = lastEditMode;
lastEditMode = 6;
}
else
{
lastEditMode = editMode;
editMode = 6;
}
break;
case audioButt: // drum settings
if (editMode == 16)
{
editMode = lastEditMode;
lastEditMode = 16;
menuVertical = false;
}
else
{
lastEditMode = editMode;
editMode = 16;
menuIndex = 0; // corresponde all array de DRUM SETTING
menuVertical = true;
}
break;
case shiftButt: // trackSelect
shiftButt_ = true;
break;
case muteButt: // M U T E
if (editMode == 17)
{
editMode = lastEditMode;
lastEditMode = 17;
}
else
{
lastEditMode = editMode;
editMode = 17;
menuVertical = false;
//edit = true;
}
break;
case pattButt:
if (editMode == 15)
{
editMode = lastEditMode;
lastEditMode = 15;
}
else
{
lastEditMode = editMode;
editMode = 15;
menuVertical = false;
edit = false;
encPos = actPatt;
actPos();
}
break;
case invButt: // invertir los golpes
if (editMode == 18)
{
editMode = lastEditMode;
lastEditMode = 18;
}
else
{
lastEditMode = editMode;
editMode = 18;
}
break;
}
}
}
else if (buttCount == shiftButt) // release
{
shiftButt_ = false;
}
_butt[x][y] = butt[x][y];
}
} // fin si x> 8
} // fin ledref
if (ledRef == ledRef_)
{
cvRead[0] = 1023 - analogRead(cvIn[0]);
cvRead[1] = 1023 - analogRead(cvIn[1]);
cvRead[2] = 1023 - analogRead(cvIn[2]);
cvRead[3] = 1023 - analogRead(cvIn[3]);
// tolerancia:
// cvRead[cvSelect] = constrain( cvRead[cvSelect], 0, 1023 );
// borrar esto luego:
leds.setPixelColor(64, leds.Color(cvRead[0] / 5, cvRead[0] / 10, 0));
leds.setPixelColor(65, leds.Color(cvRead[1] / 5, cvRead[1] / 10, 0));
leds.setPixelColor(66, leds.Color(cvRead[2] / 5, cvRead[2] / 10, 0));
leds.setPixelColor(67, leds.Color(cvRead[3] / 5, cvRead[3] / 10, 0));
#include "enc.h"
// lectura de encoder click:
encButt = digitalRead(encClick);
if (encButt != _encButt)
{
if (encButt == LOW)
{
encButt_ = true;
}
_encButt = encButt;
}
if (edit == true) // avisador del encoder!!
{
leds.setPixelColor(71, leds.Color(100 - enc, enc, 0));
}
else
{
leds.setPixelColor(71, leds.Color(0, 0, 0));
}
leds.show();
ledRef = 0;
}
// escritura de los pulsos etc:
// R E L O G I N T E R N O
if (intTempo == true)
{
if ((((beatCount == 0) || (beatCount == 2)) && (temp >= (temp_ - swingTemp_))) || (temp >= (temp_ + swingTemp_)))
{
temp = 0;
t32_ = true;
if ((beatCount == 0) || (beatCount == 2))
{
t32 = (temp_ + swingTemp_) / 2; // remainder 0
}
else
{
t32 = (temp_ - swingTemp_) / 2; // remainder 1 de 'beatCount % 2'
}
go();
writeTrigg();
beatCount++;
rndNumber = random(16);
if (beatCount > 3)
{
beatCount = 0;
}
}
}
else // el tempo no es interno, se lee la entrada del relog
{
// R E S E T
resetIn = digitalRead(resetInput);
if (_resetIn != resetIn)
{
if (resetIn == LOW) //podriamos poner un condicional!
{
//resetSeq();
resetSeq_ = true;
}
_resetIn = resetIn;
}
trigg = digitalRead(triggIn);
if (trigg != _trigg)
{
if (trigg == LOW)
{
temp_ = temp;
if (temp_ > 1500000)
{
temp_ = 1500000;
}
if (temp_ < 60000)
{
temp_ = 60000;
}
swingCalculator();
if ((beatCount == 0) || (beatCount == 2))
{
#ifdef debug
//yy = temp / xx;
//zz = AudioMemoryUsageMax();
//Serial.print("\n temp..."); Serial.print(temp); Serial.print(" - temp_..."); Serial.print(temp_);
// Serial.print(" ciclos..."); Serial.print(xx);
// Serial.print(" promedio(microsegundos)..."); Serial.print(yy); Serial.print(" audio memory "); Serial.print(zz);
//xx = 0;
#endif
temp = 0;
t32_ = true;
t32 = (temp_ + swingTemp_) / 2;
go();
writeTrigg();
beatCount++;
rndNumber = random(16);
if (beatCount > 3)
{
beatCount = 0;
}
}
else // calculamos el roll del offbeat
{
t32 = (temp_ - swingTemp_) / 2;
}
}
_trigg = trigg;
}
if (((beatCount == 1) || (beatCount == 3)) && (temp >= (temp_ - swingTemp_)))
{
temp = 0;
t32_ = true;
go();
writeTrigg();
beatCount++;
rndNumber = random(16);
if (beatCount > 3)
{
beatCount = 0;
}
}
} // fin tempo externo
if (temp >= triggLength)
{
clearTrigg();
}
if ((t32_ == true) && (temp >= t32))
{
rollOn();
t32_ = false;
}
}
void go() // avanzar en la secuencia
{
for (i = 0; i < 8; i++)
{
count[i]--;
if (count[i] < 0)
{
count[i] = clockDiv[actPatt][i];
switch (pMode[actPatt][i])
{
case 0:
pos[i]++;
if (pos[i] > steps[actPatt][i])
{
pos[i] = 0;
}
break;
case 1:
pos[i]--;
if (pos[i] < 0)
{
pos[i] = steps[actPatt][i];
}
break;
case 2: // pendulum
if (dir[i] == true)
{
pos[i]++;
if (pos[i] > steps[actPatt][i])
{
pos[i] = steps[actPatt][i];
dir[i] = false;
}
}
else
{
pos[i]--;
if (pos[i] < 0)
{
pos[i] = 0;
dir[i] = true;
}
}
break;
case 3: // 4 random
// do the random shit
break;
}
}
}
if (((pMode[actPatt][0] == 0) && (pos[0] == 0)) || ((pMode[actPatt][0] == 1) && (pos[0] == steps[actPatt][0])))
{
// lectura del la cadena PARTE
if (loopSize > 0) //loppsiz podria eliminarse
{
pattCounter++;
if (pattCounter > loopSize[actPart])
{
pattCounter = 0;
}
if (pattCounter == loopSize[actPart])
{
nextPatt = part[actPart][0];
}
else
{
nextPatt = part[actPart][pattCounter + 1];
}
}
actPatt = part[actPart][pattCounter];
//actPatt = nextPatt; // pasamos al siguiente patron
if (bitRead(masterTrack, actPatt) == true)
{
resetSeq();
}
}
stepCount++; // esto es para 'ramifications'
}
void rollOn() // rehacer todo esto, de momento es solo un tipo de redoble
{
for (i = 0; i < 8; i++)
{
if ((bitRead(roll[actPatt][i], (pos[i])) == true) && (bitRead(dot[actPatt][i], pos[i]) == true) && (count[i] == clockDiv[actPatt][i]) && (mute[i] == false) && (rndNumber + sculpt[i] >= prob[actPatt][i][pos[i]]))
{
digitalWrite(triggOut[i], HIGH);
#ifdef sonido
drumSynth();
#endif
#ifdef midi_
MIDI.sendNoteOn(midiNote[i], val[actPatt][i][pos[i]], 1);
#endif
}
}
}
void writeTrigg()
{ // si estos parametros no vamos a automatizarlos podemos quitarlos de aqui
// reasignar estos parametros...
/*
tempFloat = fscale( 0, 1023, 0.00, 1.00, menuVar[1][0][revSize], 0.3 , 0);
freeverb1.roomsize(tempFloat);
tempFloat = fscale( 0, 1023, 0.00, 1.00, menuVar[1][0][revDamp], 0.3 , 0);
freeverb1.damping(tempFloat);
tempFloat = fscale( 0, 1023, 0.00, 1.00, menuVar[1][0][revL], 0.3 , 0);
mixer[14]->gain(3, tempFloat);
tempFloat = fscale( 0, 1023, 0.00, 1.00, menuVar[1][0][revR], 0.3 , 0);
mixer[15]->gain(3, tempFloat);
*/
for (i = 0; i < 8; i++)
{
if ((count[i] == clockDiv[actPatt][i]) && (bitRead(dot[actPatt][i], pos[i]) == true) && (mute[i] == false) && (rndNumber + sculpt[i] >= prob[actPatt][i][pos[i]]))
{
digitalWrite(triggOut[i], LOW);
#ifdef midi_
MIDI.sendNoteOn(midiNote[i], val[actPatt][i][pos[i]], 1);
#endif
#ifdef sonido
drumSynth();
#endif
}
}
}
void clearTrigg()
{
for (i = 0; i < 8; i++)
{
digitalWrite(triggOut[i], HIGH);
#ifdef sonido
// envelope1.noteOff();
#endif
}
#ifdef midi_
MIDI.sendControlChange(123,0,0);
// all note off
#endif
}
void resetSeq()
{
for (i = 0; i < 8; i++)
{
if (pMode[actPatt][i] == 1)
{
pos[i] = steps[actPatt][i];
}
else
{
pos[i] = 0;
}
}
beatCount = 0;
}
void actPos()
{
enc4 = encPos;
_enc4 = enc4;
enc = (enc4 * 4);
_enc = enc;
myEnc.write(enc);
}
void preset() // preset write
{
uint32_t eeAddress = 0;
EEPROM.put(eeAddress, midiNote);
eeAddress += sizeof(midiNote);
EEPROM.put(eeAddress, menuVar);
eeAddress += sizeof(menuVar);
EEPROM.put(eeAddress, modMatrix);
eeAddress += sizeof(modMatrix);
EEPROM.put(eeAddress, modSource);
eeAddress += sizeof(modSource);
}
void readPreset()
{
uint32_t eeAddress = 0;
EEPROM.get(eeAddress, midiNote);
eeAddress += sizeof(midiNote);
EEPROM.get(eeAddress, menuVar);
eeAddress += sizeof(menuVar);
EEPROM.get(eeAddress, modMatrix);
eeAddress += sizeof(modMatrix);
EEPROM.get(eeAddress, modSource);
eeAddress += sizeof(modSource);
}
void euclFunct(int track) // cuclidean caculator
{
int bucket = 0;
for (i = 0; i <= steps[actPatt][track]; i++)
{
bucket += euclNum[actPatt][track];
if (bucket > steps[actPatt][track])
{
bucket -= (steps[actPatt][track] + 1);
bitSet64(dot[actPatt][track], i);
}
else
{
bitClear64(dot[actPatt][track], i);
}
}
rotateSeq(track);
}
// atencion, la rotacion no esta afectando a los otros parametros! pero esto podría implementarse facilmente
// pero tendríamos que declarar funciones diferentes para no rotar la secuencia cada vez que hagamos un euclidiano!
// void rotateAll rotateAllNeg
void rotateSeq(uint32_t track) // rotate a sequence
{
bool h = bitRead(dot[actPatt][track], steps[actPatt][track]);
for (i = steps[actPatt][track]; i > 0; i--)
{
bitWrite64(dot[actPatt][track], i, bitRead(dot[actPatt][track], i - 1));
}
bitWrite64(dot[actPatt][track], 0, h);
}
void rotateSeqNeg(uint32_t track)
{
bool h = bitRead(dot[actPatt][track], 0);
for (i = 0; i < steps[actPatt][track]; i++)
{
bitWrite64(dot[actPatt][track], i, bitRead(dot[actPatt][track], i + 1));
}
bitWrite64(dot[actPatt][track], steps[actPatt][track], h);
}
void liveRecord()
{
// para cuatizar los golpes,
if (temp < t32)
{
digitalWrite(triggOut[x], LOW);
#ifdef midi_
MIDI.sendNoteOn(midiNote[x], (y * 16), 1);
#endif
#ifdef sonido
i = x;
drumSynth();
#endif
bitWrite64(dot[actPatt][x], pos[x], recMode);
if (recModulation)
{
val[actPatt][x][pos[x]] = (y * 16) - 1; // en caso de que el rango sea 0-127
}
}
else
{
bitWrite64(dot[actPatt][x], pos[x] + 1, recMode);
if (recModulation)
{
val[actPatt][x][pos[x] + 1] = (y * 16) - 1; // en caso de que el rango sea 0-127
}
}
// escribimos o borramos el golpe, recMode 'insert'(true) o 'clear'(false)
}
float fscale(float originalMin, float originalMax, float newBegin, float newEnd, float inputValue, float curve)
{
//version recortada, la curva debe ser de -1.0 a 1.0 y los valores sin invertir
float OriginalRange = 0;
float NewRange = 0;
float zeroRefCurVal = 0;
float normalizedCurVal = 0;
float rangedValue = 0;
curve = pow(10, curve); // convert linear scale into lograthimic exponent for other pow function
OriginalRange = originalMax - originalMin;
NewRange = newEnd - newBegin;
zeroRefCurVal = inputValue - originalMin;
normalizedCurVal = zeroRefCurVal / OriginalRange; // normalize to 0 - 1 float
rangedValue = (pow(normalizedCurVal, curve) * NewRange) + newBegin;
return rangedValue;
}
void swingCalculator()
{
swingTemp_ = (swingAmount * (temp_ / 3) / 100);
}
void saveAll()
{
/*
if (!SD.exists("1"))
{
//crear directorio
SD.mkdir("1");
}
else
{
//borrar archivos antes de escribir los nuevos
}
*/
File dataFile;
SD.remove("val.dat");
dataFile = SD.open("val.dat", FILE_WRITE);
dataFile.write((uint8_t *)&val, sizeof(val));
dataFile.close();
SD.remove("prob.dat");
dataFile = SD.open("prob.dat", FILE_WRITE);
dataFile.write((uint8_t *)&prob, sizeof(prob));
dataFile.close();
SD.remove("steps.dat");
dataFile = SD.open("steps.dat", FILE_WRITE);
dataFile.write((uint8_t *)&steps, sizeof(steps));
dataFile.close();
SD.remove("pMode.dat");
dataFile = SD.open("pMode.dat", FILE_WRITE);
dataFile.write((uint8_t *)&pMode, sizeof(pMode));
dataFile.close();
SD.remove("clockDiv.dat");
dataFile = SD.open("clockDiv.dat", FILE_WRITE);
dataFile.write((uint8_t *)&clockDiv, sizeof(clockDiv));
dataFile.close();
SD.remove("euclNum.dat");
dataFile = SD.open("euclNum.dat", FILE_WRITE);
dataFile.write((uint8_t *)&euclNum, sizeof(euclNum));
dataFile.close();
SD.remove("dot.dat");
dataFile = SD.open("dot.dat", FILE_WRITE);
dataFile.write((uint8_t *)&dot, sizeof(dot));
dataFile.close();
SD.remove("roll.dat");
dataFile = SD.open("roll.dat", FILE_WRITE);
dataFile.write((uint8_t *)&roll, sizeof(roll));
dataFile.close();
SD.remove("midiNote.dat");
dataFile = SD.open("midiNote.dat", FILE_WRITE);
dataFile.write((uint8_t *)&midiNote, sizeof(midiNote));
dataFile.close();
SD.remove("menuVar.dat");
dataFile = SD.open("menuVar.dat", FILE_WRITE);
dataFile.write((uint8_t *)&menuVar, sizeof(menuVar));
dataFile.close();
SD.remove("noInitPatt.dat");
dataFile = SD.open("noInitPatt.dat", FILE_WRITE);
dataFile.write((uint8_t *)&noInitPatt, sizeof(noInitPatt));
dataFile.close();
SD.remove("raw.dat");
dataFile = SD.open("raw.dat", FILE_WRITE);
dataFile.write((uint8_t *)&raw, sizeof(raw));
dataFile.close();
}
void loadAll()
{
File dataFile;
dataFile = SD.open("val.dat", FILE_READ);
dataFile.read((uint8_t *)&val, sizeof(val));
dataFile = SD.open("prob.dat", FILE_READ);
dataFile.read((uint8_t *)&prob, sizeof(prob));
dataFile = SD.open("steps.dat", FILE_READ);
dataFile.read((uint8_t *)&steps, sizeof(steps));
dataFile = SD.open("pMode.dat", FILE_READ);
dataFile.read((uint8_t *)&pMode, sizeof(pMode));
dataFile = SD.open("clockDiv.dat", FILE_READ);
dataFile.read((uint8_t *)&clockDiv, sizeof(clockDiv));
dataFile = SD.open("euclNum.dat", FILE_READ);
dataFile.read((uint8_t *)&euclNum, sizeof(euclNum));
dataFile = SD.open("dot.dat", FILE_READ);
dataFile.read((uint8_t *)&dot, sizeof(dot));
dataFile = SD.open("roll.dat", FILE_READ);
dataFile.read((uint8_t *)&roll, sizeof(roll));
dataFile = SD.open("midiNote.dat", FILE_READ);
dataFile.read((uint8_t *)&midiNote, sizeof(midiNote));
dataFile = SD.open("menuVar.dat", FILE_READ);
dataFile.read((uint8_t *)&menuVar, sizeof(menuVar));
dataFile = SD.open("noInitPatt.dat", FILE_READ);
dataFile.read((uint8_t *)&noInitPatt, sizeof(noInitPatt));
dataFile = SD.open("raw.dat", FILE_READ);
dataFile.read((uint8_t *)&raw, sizeof(raw));
dataFile.close();
}
void initPatt()
{
// inicializacion de las variables, patron inicial
byte a;
byte b;
for (a = 0; a < 8; a++)
{
steps[actPatt][a] = 7;
pMode[actPatt][a] = 0;
clockDiv[actPatt][a] = 0;
euclNum[actPatt][a] = 0;
midiNote[a] = a * 2;
roll[actPatt][a] = 0;
dot[actPatt][a] = 0;
// default settings for filter & volume
menuVar[0][a][drumMod] = 512;
menuVar[1][a][filterFreq] = 896;
menuVar[1][a][volumen] = 896;
menuVar[1][a][panoramica] = 512;
for (b = 0; b <= maxSteps; b++)
{
prob[actPatt][a][b] = 0;
val[actPatt][a][b] = 120;
}
}
}
void invertSeq(byte track)
{
dot[actPatt][track] = ~dot[actPatt][track];
}
void copyPatt()
{
for (i = 0; i < 8; i++)
{
dot[suma][i] = dot[actPatt][i];
roll[suma][i] = roll[actPatt][i];
steps[suma][i] = steps[actPatt][i];
pMode[suma][i] = pMode[actPatt][i];
clockDiv[suma][i] = clockDiv[actPatt][i];
euclNum[suma][i] = euclNum[actPatt][i];
for (byte n = 0; n < 64; n++)
{
prob[suma][i][n] = prob[actPatt][i][n];
val[suma][i][n] = val[actPatt][i][n];
}
}
bitSet64(noInitPatt, suma);
}
void drumSynth() // i es el track!
{
#ifdef sonido
// VOLUMEN Y PANORAMICA
// calculamos este valor combinando los valores de 'volumen' y 'panorámica'
// L:
float tempFloat2 = (calcMod(1, i, volumen) * (constrain((1023 - calcMod(1, i, panoramica)) * 2, 0, 1023))) / 1023;
float tempFloat = fscale(0, 1024, 0.0, 1.0, tempFloat2, 0.3);
mixer[(8 + ((i / 4) * 2))]->gain((i % 4), tempFloat);
// R:
tempFloat2 = (calcMod(1, i, volumen) * (constrain(calcMod(1, i, panoramica) * 2, 0, 1023))) / 1023;
tempFloat = fscale(0, 1024, 0.0, 1.0, tempFloat2, 0.3);
mixer[(9 + ((i / 4) * 2))]->gain((i % 4), tempFloat);
// R E V E R B
//tempFloat = fscale(0, 1024, 0.0, 1.0, calcMod(1, i, revAmount), 0.3);
//mixer[(12 + ((i / 4) * 2))]->gain((i % 4), tempFloat);
// F I L T R O
// resonancia:
tempFloat2 = fscale(0, 1024, 0.7, 5.0, calcMod(1, i, resonancia), 0);
//cutOff:
tempFloat = fscale(0, 1024, 20, 20000, calcMod(1, i, filterFreq), 0.4);
if (menuVar[1][i][filterType] < 333)
{
biquad[i]->setLowpass(0, tempFloat, tempFloat2);
}
else if (menuVar[1][i][filterType] > 666)
{
biquad[i]->setHighpass(0, tempFloat, tempFloat2);
}
else
{
biquad[i]->setBandpass(0, tempFloat, tempFloat2);
}
/*
// esto es para el otro filtro, ya veremos si lo usamos!
tempFloat = fscale(0, 1024, 20, 20000, calcMod(1, i, filterFreq), 0.4);
filter1.frequency(tempFloat);
tempFloat = fscale(0, 1024, 0.7, 5.0, calcMod(1, i, resonancia), 0);
filter1.resonance(tempFloat);
*/
#ifdef DRUM
if (playDrum[i] == true)
{
// D R U M
#ifdef DRUMS
tempFloat = fscale(0, 1023, 0.00, 1.00, calcMod(0, i, drumVol), 0.3);
mixer[i]->gain(0, tempFloat);
tempFloat = fscale(0, 1023, 40, 2000, calcMod(0, i, drumFreq), 0.4);
drum[i]->frequency(tempFloat);
tempFloat = fscale(0, 1023, 10, 2000, calcMod(0, i, drumDecay), 0.4);
drum[i]->length(tempFloat);
tempFloat = fscale(0, 1023, 0.0, 1.0, calcMod(0, i, drumMod), 0);
drum[i]->pitchMod(tempFloat);
tempFloat = fscale(0, 1023, 0.0, 1.0, calcMod(0, i, drumSecond), 0);
drum[i]->secondMix(tempFloat);
#endif
// N O I S E
tempFloat = fscale(0, 1023, 0.00, 0.50, calcMod(0, i, noiseVol), 0.3);
mixer[i]->gain(1, tempFloat);
tempFloat = fscale(0, 1023, 1, 2000, calcMod(0, i, noiseDecay), 0.4);
envelope[i]->decay(tempFloat);
#ifdef DRUMS
drum[i]->noteOn();
#endif
envelope[i]->noteOn();
}
#endif
#ifdef SAMPLER
if (playSample[i] == true)
{
sample[i]->play(muestra[raw[i]].c_str());
}
// sample[i].play(AudioSampleKickwavq);
#endif
#endif
}
void makeLoop()
{
if (multButtMax != multButtMin)
{
loopSize[64] = multButtMax - multButtMin; // el array de partes va a tener un contador también,
for (i = 0; i <= loopSize[64]; i++)
{
part[64][i] = i + multButtMin;
}
actPart = 64; // parte temporal
}
else
{
actPatt = multButtMax;
}
/*
if (intTempo)
{
nextPatt = part[64][0]; //esperamos al siguiente ciclo si esta andando
}
else
{
actPatt = part[64][0];
nextPatt = part[64][0];
}
*/
/*
#ifdef debug
Serial.print("\n actPatt..."); Serial.print(actPatt); Serial.print(" - nextPatt..."); Serial.print(nextPatt); //Serial.print("\n");
#endif
*/
}
void invertDir()
{
for (i = 0; i < 8; i++)
{
switch (pMode[actPatt][i])
{
case 0:
pMode[actPatt][i] = 1;
break;
case 1:
pMode[actPatt][i] = 0;
break;
case 2:
dir[i] = !dir[i];
break;
}
}
}
// M I D I S Y N C H
#ifdef midiSync
/*
void RealTimeSystem(byte realtimebyte) {
if (realtimebyte == 248) {
//Serial1.write(248);
counter++;
if (counter == 24)
{
counter = 0;
// CORCHEA
}
if (counter == 12)
{
//ROLL
}
}
if (realtimebyte == START || realtimebyte == CONTINUE) {
counter = 0;
// PLAY
}
if (realtimebyte == STOP) {
// STOP
}
}
*/
#endif
void checkDir()
{ /*
for (i = 0; i < 64; i++ )
{
// folder = String(i);
if ( SD.exists("1") )
{
bitSet64(noInitProject, i);
}
} */
}
int calcMod(byte menuIndex2, byte track2, byte menuParam2)
{
int result;
int inputValue2 = menuVar[menuIndex2][track2][menuParam2];
if (modMatrix[menuIndex2][track2][menuParam2] == 0)
{
result = inputValue2;
}
else
{
if (modSource[menuIndex2][track2][menuParam2] != 4)
{
result = constrain((inputValue2 + (cvRead[modSource[menuIndex2][track2][menuParam2]] * modMatrix[menuIndex2][track2][menuParam2] / 100)), 0, 1023);
}
else if (modSource[menuIndex2][track2][menuParam2] == 4) // cvSource 4 -> calculamos con VAL
{
result = constrain((inputValue2 + ((val[actPatt][track2][pos[track2]] * 8) * modMatrix[menuIndex2][track2][menuParam2] / 100)), 0, 1023);
}
}
return result;
}