Upload files to 'Software'
This commit is contained in:
parent
a088f50d07
commit
566bacc562
|
@ -0,0 +1,135 @@
|
||||||
|
#include <Synth-Clatter.h>
|
||||||
|
#include <Synth-Decay.h>
|
||||||
|
#include <Synth-DrumHeart.h>
|
||||||
|
#include <synth_simple_drum.h>
|
||||||
|
#include <TeensyBoomVoiceLibrary.h>
|
||||||
|
|
||||||
|
#include <Audio.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <SD.h>
|
||||||
|
#include <SerialFlash.h>
|
||||||
|
|
||||||
|
#include "panel-scanner.h"
|
||||||
|
#include "editor.h"
|
||||||
|
#include "pattern.h"
|
||||||
|
#include "player.h"
|
||||||
|
#include "voice.h"
|
||||||
|
#include "teensy_midi.h"
|
||||||
|
|
||||||
|
const int channel = 1;
|
||||||
|
|
||||||
|
// Appp construct singletons
|
||||||
|
PanelScanner theScanner;
|
||||||
|
Editor theEditor;
|
||||||
|
Pattern thePattern; // TBD: multidimensional...
|
||||||
|
Player thePlayer;
|
||||||
|
Teensy_Midi theMidi;
|
||||||
|
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
// put your setup code here, to run once:
|
||||||
|
|
||||||
|
Serial.begin(57600);
|
||||||
|
|
||||||
|
delay(1500);
|
||||||
|
|
||||||
|
Serial.println("Setup");
|
||||||
|
|
||||||
|
pinMode(15, INPUT); // Volume pot pin?
|
||||||
|
|
||||||
|
// SD CARD & general SPI inits
|
||||||
|
// Initialize the SD card
|
||||||
|
SPI.setMOSI(7);
|
||||||
|
SPI.setSCK(14);
|
||||||
|
|
||||||
|
// This sets the chip selects for the panel
|
||||||
|
// to OFF. Gotta do it before SD init, else the panels contend!
|
||||||
|
theScanner.initScanning();
|
||||||
|
|
||||||
|
|
||||||
|
if (!(SD.begin(10)))
|
||||||
|
{
|
||||||
|
Serial.println("Unable to access the SD card");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Serial.println("SD card begin worked");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SD.exists("test.txt"))
|
||||||
|
{
|
||||||
|
Serial.println("found test.txt file");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Serial.println("Didn't find test file?");
|
||||||
|
}
|
||||||
|
|
||||||
|
theMidi.init(); //Midi Initialisieren
|
||||||
|
theEditor.setMode(Editor::eMODE_PATT_SEL);
|
||||||
|
|
||||||
|
// audio library init
|
||||||
|
AudioMemory(20);
|
||||||
|
|
||||||
|
//next = millis() + 1000;
|
||||||
|
|
||||||
|
// read panel before we start to run
|
||||||
|
//paramUpdate();
|
||||||
|
|
||||||
|
voiceInit();
|
||||||
|
|
||||||
|
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
Serial.println("Setup Complete");
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
uint32_t now = millis();
|
||||||
|
static uint32_t then;
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
// put your main code here, to run repeatedly:
|
||||||
|
|
||||||
|
paramUpdate1();// kik,snr,hat
|
||||||
|
paramUpdate2();// toms, shaker
|
||||||
|
paramUpdate3();// master volume & tempo
|
||||||
|
|
||||||
|
if (now > then)
|
||||||
|
{
|
||||||
|
thePlayer.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (now % 5 == 0)
|
||||||
|
{
|
||||||
|
theScanner.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (now % 5000 == 0)
|
||||||
|
{
|
||||||
|
//theScanner.dumpLEDs();
|
||||||
|
|
||||||
|
|
||||||
|
Serial.print("Diagnostics: ");
|
||||||
|
Serial.print(" max, buffs: ");
|
||||||
|
Serial.print(AudioProcessorUsageMax());
|
||||||
|
Serial.print(" ");
|
||||||
|
Serial.println(AudioMemoryUsageMax());
|
||||||
|
AudioProcessorUsageMaxReset();
|
||||||
|
//Test:
|
||||||
|
// triggerKick(true);
|
||||||
|
// int note = 40;
|
||||||
|
// for (note=10; note <= 127; note++) {
|
||||||
|
// MIDI.sendNoteOn(note, 100, channel);
|
||||||
|
// delay(200);
|
||||||
|
// MIDI.sendNoteOff(note, 100, channel);
|
||||||
|
// setBlinkingLED(22, true);
|
||||||
|
//setLEDs(true);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
then = now;
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -0,0 +1,379 @@
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#include "player.h"
|
||||||
|
#include "pattern.h"
|
||||||
|
#include "editor.h"
|
||||||
|
#include "voice.h"
|
||||||
|
#include "teensy_midi.h"
|
||||||
|
|
||||||
|
// Similar, for the pattern...
|
||||||
|
extern Pattern thePattern;
|
||||||
|
extern PanelScanner theScanner;
|
||||||
|
extern Editor theEditor;
|
||||||
|
extern Teensy_Midi theMidi;
|
||||||
|
|
||||||
|
// constructor...
|
||||||
|
Player::Player()
|
||||||
|
{
|
||||||
|
playing = false;
|
||||||
|
swing = false;
|
||||||
|
current_step = 0;
|
||||||
|
|
||||||
|
active_mutes = 0;
|
||||||
|
pending_mutes = 0;
|
||||||
|
|
||||||
|
active_pattern = 0;
|
||||||
|
pending_pattern = -1;
|
||||||
|
|
||||||
|
pause_len = 125;// milliseconds, 125 mS = 120 bpm
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::start()
|
||||||
|
{
|
||||||
|
playing = true;
|
||||||
|
current_step = 0;
|
||||||
|
|
||||||
|
if(chain_active)
|
||||||
|
{
|
||||||
|
chain_play_idx = 0;
|
||||||
|
active_pattern = chain_array[0];
|
||||||
|
thePattern.setCurrentPattern(active_pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
//theScanner.setOverlayLED(0x17);
|
||||||
|
theEditor.forceLEDs();
|
||||||
|
|
||||||
|
theMidi.start();
|
||||||
|
}
|
||||||
|
void Player::stop()
|
||||||
|
{
|
||||||
|
playing = false;
|
||||||
|
theEditor.forceLEDs();
|
||||||
|
theMidi.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Player::isPlaying()
|
||||||
|
{
|
||||||
|
return playing;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::setPause(uint32_t millisec)
|
||||||
|
{
|
||||||
|
pause_len = millisec;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Player::toggleSwing()
|
||||||
|
{
|
||||||
|
swing = !swing;
|
||||||
|
|
||||||
|
Serial.print("Swing is now: ");
|
||||||
|
Serial.println(swing);
|
||||||
|
|
||||||
|
return swing;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Player::getSwing()
|
||||||
|
{
|
||||||
|
return swing;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Player::toggleMuteBit(uint32_t bit)
|
||||||
|
{
|
||||||
|
if(bit > 12)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(playing)
|
||||||
|
{
|
||||||
|
pending_mutes ^= (1 << bit);
|
||||||
|
|
||||||
|
return (pending_mutes & (1 << bit));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
active_mutes ^= (1 << bit);
|
||||||
|
|
||||||
|
return (active_mutes & (1 << bit));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Player::getMuteBit(uint32_t bit)
|
||||||
|
{
|
||||||
|
if(bit > 12)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return (active_mutes & (1 << bit));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Player::getPendingMuteBit(uint32_t bit)
|
||||||
|
{
|
||||||
|
if(bit > 12)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return (pending_mutes & (1 << bit));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool Player::setNextPattern(int32_t next)
|
||||||
|
{
|
||||||
|
if((uint32_t) next > Pattern::NUM_PATTERNS)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(next == active_pattern)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(playing)
|
||||||
|
{
|
||||||
|
pending_pattern = next;
|
||||||
|
|
||||||
|
return true;// (pending_pattern);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
active_pattern = next;
|
||||||
|
thePattern.setCurrentPattern(active_pattern);
|
||||||
|
|
||||||
|
return true; //(active_mutes & (1 << bit));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t Player::getActivePattern()
|
||||||
|
{
|
||||||
|
return active_pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t Player::getPendingPattern()
|
||||||
|
{
|
||||||
|
return pending_pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t Player::getCurrentStep()
|
||||||
|
{
|
||||||
|
return current_step;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Player::getBlinkPhase()
|
||||||
|
{
|
||||||
|
int32_t now = millis();
|
||||||
|
|
||||||
|
if(now < (next_time - (pause_len>>1)))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
// chain stuff
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool Player::chainIsActive()
|
||||||
|
{
|
||||||
|
return chain_active;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::initChain()
|
||||||
|
{
|
||||||
|
chain_active = false;
|
||||||
|
chain_insert_idx = 0;
|
||||||
|
chain_play_idx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::addToChain(int32_t patt_num)
|
||||||
|
{
|
||||||
|
if((uint32_t) patt_num >= Pattern::NUM_PATTERNS)
|
||||||
|
{
|
||||||
|
Serial.println("addToChain patt_num out of bounds!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.print("Adding patt ");
|
||||||
|
Serial.print(patt_num);
|
||||||
|
Serial.print("to chain at idx ");
|
||||||
|
Serial.println(chain_insert_idx);
|
||||||
|
|
||||||
|
if(!chain_active)
|
||||||
|
{
|
||||||
|
// the first piece added to chain
|
||||||
|
chain_active = true;
|
||||||
|
chain_array[0] = patt_num;
|
||||||
|
chain_insert_idx = 1;
|
||||||
|
chain_play_idx = -1;// one before the first step - it'll increment and be at beginning
|
||||||
|
theEditor.forceLEDs();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(chain_insert_idx < (int32_t)CHAIN_LEN)
|
||||||
|
{
|
||||||
|
chain_array[chain_insert_idx] = patt_num;
|
||||||
|
chain_insert_idx++;
|
||||||
|
theEditor.forceLEDs();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t Player::getNextChainVal()
|
||||||
|
{
|
||||||
|
chain_play_idx++;
|
||||||
|
if(chain_play_idx >= chain_insert_idx)
|
||||||
|
{
|
||||||
|
chain_play_idx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
Serial.print("Getting next chain pattern, (idx, val):");
|
||||||
|
Serial.print(chain_play_idx);
|
||||||
|
Serial.print(" ");
|
||||||
|
Serial.println(chain_array[chain_play_idx]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return chain_array[chain_play_idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Player::checkChainMembership(int32_t patt)
|
||||||
|
{
|
||||||
|
// is patt # active within chain?
|
||||||
|
for(int32_t i = 0; i < chain_insert_idx; i++)
|
||||||
|
{
|
||||||
|
if(patt == chain_array[i])
|
||||||
|
{
|
||||||
|
//Serial.println("found chain member");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::tick()
|
||||||
|
{
|
||||||
|
int32_t now = millis();
|
||||||
|
|
||||||
|
if(now < next_time)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!swing)
|
||||||
|
{
|
||||||
|
next_time = now + pause_len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(!(current_step & 0x01))
|
||||||
|
{
|
||||||
|
next_time = now + pause_len + (pause_len/3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
next_time = now + ((2*pause_len)/3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(playing)
|
||||||
|
{
|
||||||
|
uint32_t trigdata = thePattern.getStepData(current_step);
|
||||||
|
|
||||||
|
// Apply mutes
|
||||||
|
trigdata &= (~active_mutes);
|
||||||
|
|
||||||
|
theEditor.forceLEDs();
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
Serial.print("Trigger: step#");
|
||||||
|
Serial.print(current_step);
|
||||||
|
Serial.print(" bitmap:");
|
||||||
|
Serial.println(trigdata, HEX);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
theMidi.clock();
|
||||||
|
|
||||||
|
|
||||||
|
AudioNoInterrupts();
|
||||||
|
|
||||||
|
if (trigdata & 0x01)
|
||||||
|
{
|
||||||
|
triggerKick(trigdata & 0x010000);
|
||||||
|
}
|
||||||
|
if (trigdata & 0x02)
|
||||||
|
{
|
||||||
|
triggerSnare(trigdata & 0x020000);
|
||||||
|
}
|
||||||
|
if (trigdata & 0x04)
|
||||||
|
{
|
||||||
|
// closed hat trumps open hat.
|
||||||
|
triggerHat(false, trigdata & 0x040000);
|
||||||
|
}
|
||||||
|
else if (trigdata & 0x08)
|
||||||
|
{
|
||||||
|
triggerHat(true, trigdata & 0x080000);
|
||||||
|
}
|
||||||
|
if (trigdata & 0x10)
|
||||||
|
{
|
||||||
|
triggerTom(1, trigdata & 0x100000);
|
||||||
|
}
|
||||||
|
else if (trigdata & 0x20)
|
||||||
|
{
|
||||||
|
triggerTom(2, trigdata & 0x200000);
|
||||||
|
}
|
||||||
|
else if (trigdata & 0x40)
|
||||||
|
{
|
||||||
|
triggerTom(3, trigdata & 0x400000);
|
||||||
|
}
|
||||||
|
if (trigdata & 0x80)
|
||||||
|
{
|
||||||
|
triggerBell(trigdata & 0x800000);
|
||||||
|
}
|
||||||
|
if (trigdata & 0x100)
|
||||||
|
{
|
||||||
|
triggerShaker(trigdata & 0x1000000);
|
||||||
|
}
|
||||||
|
if (trigdata & 0x200)
|
||||||
|
{
|
||||||
|
triggerCymbal(trigdata & 0x2000000);
|
||||||
|
}
|
||||||
|
if (trigdata & 0x400)
|
||||||
|
{
|
||||||
|
triggerClap(trigdata & 0x4000000);
|
||||||
|
}
|
||||||
|
AudioInterrupts();
|
||||||
|
}
|
||||||
|
|
||||||
|
current_step++;
|
||||||
|
if(current_step >= 0x10)
|
||||||
|
{
|
||||||
|
// this block of code is setting up the NEXT invocation, so we can change
|
||||||
|
// patterns without overhead before the next set of triggers.
|
||||||
|
// It means that come instenal state is ahead of the actual playback state -
|
||||||
|
// the takeaway: don't call theEditor.forceLEDs(), or the display gets out of sync
|
||||||
|
|
||||||
|
current_step = 0;
|
||||||
|
if(pending_mutes)
|
||||||
|
{
|
||||||
|
active_mutes ^= pending_mutes;
|
||||||
|
pending_mutes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!chain_active)
|
||||||
|
{
|
||||||
|
if(pending_pattern != -1)
|
||||||
|
{
|
||||||
|
active_pattern = pending_pattern;
|
||||||
|
thePattern.setCurrentPattern(pending_pattern);
|
||||||
|
pending_pattern = -1;
|
||||||
|
}
|
||||||
|
//else, just keep current pattern...
|
||||||
|
}
|
||||||
|
else//chain_active
|
||||||
|
{
|
||||||
|
active_pattern = getNextChainVal();
|
||||||
|
thePattern.setCurrentPattern(active_pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
// do this after the LED updates, or they get the wrong current step!
|
||||||
|
current_step = 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
#ifndef _PLAYER_H_
|
||||||
|
#define _PLAYER_H_
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class Player
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Player();
|
||||||
|
|
||||||
|
void start();
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
bool isPlaying();
|
||||||
|
|
||||||
|
void setPause(uint32_t millisec);
|
||||||
|
|
||||||
|
bool toggleSwing();
|
||||||
|
bool getSwing();
|
||||||
|
|
||||||
|
bool toggleMuteBit(uint32_t bit);
|
||||||
|
bool getMuteBit(uint32_t bit);
|
||||||
|
bool getPendingMuteBit(uint32_t bit);
|
||||||
|
|
||||||
|
bool setNextPattern(int32_t next);
|
||||||
|
int32_t getActivePattern();
|
||||||
|
int32_t getPendingPattern();
|
||||||
|
|
||||||
|
int32_t getCurrentStep();
|
||||||
|
bool getBlinkPhase();
|
||||||
|
|
||||||
|
void tick();
|
||||||
|
|
||||||
|
static const uint32_t CHAIN_LEN = 32;
|
||||||
|
|
||||||
|
// Chain Stuff
|
||||||
|
bool chainIsActive();
|
||||||
|
void initChain();
|
||||||
|
void addToChain(int32_t patt_num);
|
||||||
|
int32_t getNextChainVal();
|
||||||
|
bool checkChainMembership(int32_t patt);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
bool playing;
|
||||||
|
bool swing;
|
||||||
|
int32_t current_step;
|
||||||
|
int32_t prev_step;
|
||||||
|
int32_t pause_len;
|
||||||
|
int32_t next_time;
|
||||||
|
|
||||||
|
int32_t active_mutes;
|
||||||
|
int32_t pending_mutes;
|
||||||
|
|
||||||
|
int32_t active_pattern;
|
||||||
|
int32_t pending_pattern;
|
||||||
|
|
||||||
|
bool chain_active;
|
||||||
|
int32_t chain_len;
|
||||||
|
int32_t chain_insert_idx;
|
||||||
|
int32_t chain_play_idx;
|
||||||
|
int8_t chain_array[CHAIN_LEN];
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // keepout
|
|
@ -0,0 +1,40 @@
|
||||||
|
#include <MIDI.h>
|
||||||
|
#include "teensy_midi.h"
|
||||||
|
|
||||||
|
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);
|
||||||
|
int MIDI_Clock = 1;
|
||||||
|
int MIDI_Clock_Master = 1;
|
||||||
|
|
||||||
|
// constructor...
|
||||||
|
Teensy_Midi::Teensy_Midi()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Teensy_Midi::init()
|
||||||
|
{
|
||||||
|
MIDI.begin();
|
||||||
|
Serial.print("Midi Begin: ");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Teensy_Midi::start()
|
||||||
|
{
|
||||||
|
if (MIDI_Clock == 1 && MIDI_Clock_Master == 1) {
|
||||||
|
MIDI.send((midi::MidiType)0xFA, 0, 0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Teensy_Midi::stop()
|
||||||
|
{
|
||||||
|
if (MIDI_Clock == 1 && MIDI_Clock_Master == 1) {
|
||||||
|
MIDI.send((midi::MidiType)0xFC, 0, 0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Teensy_Midi::clock()
|
||||||
|
{
|
||||||
|
//Send midi-CLock
|
||||||
|
if (MIDI_Clock == 1 && MIDI_Clock_Master == 1) {
|
||||||
|
MIDI.send((midi::MidiType)0xF8, 0, 0, 1);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef _TEENSY_MIDI_H_
|
||||||
|
#define _TEENSY_MIDI_H_
|
||||||
|
|
||||||
|
class Teensy_Midi
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Teensy_Midi();
|
||||||
|
|
||||||
|
void init();
|
||||||
|
|
||||||
|
void start();
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
void clock();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue