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