BODYSEQ/Sequencer.cpp

773 lines
15 KiB
C++
Raw Normal View History

2018-12-01 12:22:10 +01:00
/*
Haarnet.h - Friction Music library
Copyright (c) 2014 Science Friction.
All right reserved.
This library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your optionosc1modShape_ptr) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser Public License for more details.
You should have received a copy of the GNU Lesser Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ author: gauthiier
+ contact: d@gauthiier.info
*/
#include "Sequencer.h"
#include "BodyseqSynth.h"
#include <spi4teensy3.h>
#include <Arduino.h>
MSequencer Sequencer;
void MSequencer::init(int bpm)
{
setbpm(bpm);
clockTick = 0;
for(int i = 0; i < MAX_SEQ; i++) {
_sequences[i] = NULL;
}
}
void MSequencer::internalClock()
{
timeNow = micros();
if(timeNow - lastTime >= tickTime) {
clock();
Midi.sendClock();
lastTime = timeNow;
}
}
void MSequencer::update()
{
if(getInternalClock()) internalClock();
for(int i = 0; i < MAX_SEQ; i++) {
seq* s = _sequences[i];
if(s == NULL || s->_stopped) continue;
if(clockTick >= s -> step) {
if(s -> _steps) {
// Serial.println("_steps");
s -> trigger();
// Serial.println("trigger");
} else {
s->_callback();
// Serial.println("callback");
}
s->step += s -> _subdiv;
}
}
}
void MSequencer::setInternalClock(bool i)
{
_internalClock = i;
}
bool MSequencer::getInternalClock()
{
return _internalClock;
}
void MSequencer::clock()
{
clockTick++;
}
void MSequencer::start()
{
clockTick = 0;
for(int i = 0; i < MAX_SEQ; i++) {
startSequence(i);
}
Midi.sendStart();
}
void MSequencer::continues()
{
clockTick = 0; // is this right????
for(int i = 0; i < MAX_SEQ; i++) {
continueSequence(i);
}
Midi.sendContinue();
}
void MSequencer::stop()
{
for(int i = 0; i < MAX_SEQ; i++) {
stopSequence(i);
}
Midi.sendStop();
}
int MSequencer::newSequence(SUBDIV subdiv, func_cb cb)
{
int j = -1;
for(int i = 0; i < MAX_SEQ; i++) {
if(_sequences[i] == NULL) {
j = i;
break;
}
}
if(j >= 0) {
seq* s = new seq(j, subdiv, cb);
_sequences[j] = s;
Serial.print("Created sequence ");
Serial.println(j);
}
return j;
}
int MSequencer::newSequence(SUBDIV subdiv, int steps, SEQ_LOOP_TYPE loop)
{
int j = -1;
for(int i = 0; i < MAX_SEQ; i++) {
if(_sequences[i] == NULL) {
j = i;
break;
}
}
if(j >= 0) {
seq* s = new seq(j, subdiv, steps, loop);
_sequences[j] = s;
Serial.print("Created sequence ");
Serial.println(j);
}
return j;
}
int MSequencer::newSequence(SUBDIV subdiv, int steps, int channel)
{
int j = -1;
for(int i = 0; i < MAX_SEQ; i++) {
if(_sequences[i] == NULL) {
j = i;
break;
}
}
if(j >= 0) {
seq* s = new seq(j, subdiv, steps, channel);
_sequences[j] = s;
Serial.print("Created sequence ");
Serial.println(j);
}
return j;
}
int MSequencer::newSequence(SUBDIV subdiv, int steps, SEQ_LOOP_TYPE loop, bool reverse)
{
int j = -1;
for(int i = 0; i < MAX_SEQ; i++) {
if(_sequences[i] == NULL) {
j = i;
break;
}
}
if(j >= 0) {
seq* s = new seq(j, subdiv, steps, loop, reverse);
_sequences[j] = s;
Serial.print("Created sequence ");
Serial.println(j);
}
return j;
}
bool MSequencer::stopSequence(int index)
{
if(index >= 0 && index < MAX_SEQ && _sequences[index] != NULL) {
_sequences[index]->_stopped = true;
return true;
}
return false;
}
bool MSequencer::startSequence(int index)
{
if(index >= 0 && index < MAX_SEQ && _sequences[index] != NULL) {
_sequences[index] -> _stopped = false;
_sequences[index] -> step = 0;
return true;
}
return false;
}
bool MSequencer::continueSequence(int index)
{
if(index >= 0 && index < MAX_SEQ && _sequences[index] != NULL) {
_sequences[index]->_stopped = false;
return true;
}
return false;
}
void MSequencer::setbpm(int bpm)
{
if(bpm > 0){
_bpm = bpm;
_bpmInClockTicks = _bpm * 24;
tickTime = 60 * 1000000 / _bpmInClockTicks;
}
}
int MSequencer::getbpm()
{
return _bpm;
}
bool MSequencer::setChannel(int index, int channel)
{
if(index >= 0 && index < MAX_SEQ && _sequences[index] != NULL) {
// _sequences[index]->_channel;
_sequences[index]->setchannel(channel);
return true;
}
return false;
}
int MSequencer::getChannel(int index)
{
if(index >= 0 && index < MAX_SEQ && _sequences[index] != NULL) {
return _sequences[index]->_channel;
// return _sequences[index]->getchannel();
}
return -1;
}
bool MSequencer::setSteps(int index, int steps)
{
if(index >= 0 && index < MAX_SEQ && _sequences[index] != NULL) {
_sequences[index]->setsteps(steps);
return true;
}
return false;
}
int MSequencer::getSteps(int index)
{
if(index >= 0 && index < MAX_SEQ && _sequences[index] != NULL) {
return _sequences[index]->getsteps();
}
return -1;
}
bool MSequencer::setPosition(int index, int position)
{
if(index >= 0 && index < MAX_SEQ && _sequences[index] != NULL) {
_sequences[index]->setposition(position);
return true;
}
return false;
}
int MSequencer::getPosition(int index)
{
if(index >= 0 && index < MAX_SEQ && _sequences[index] != NULL) {
return _sequences[index]->getposition();
}
return -1;
}
bool MSequencer::setBegin(int index, int begin)
{
if(index >= 0 && index < MAX_SEQ && _sequences[index] != NULL) {
_sequences[index]->setbegin(begin);
return true;
}
return false;
}
int MSequencer::getBegin(int index)
{
if(index >= 0 && index < MAX_SEQ && _sequences[index] != NULL) {
return _sequences[index]->getbegin();
}
return -1;
}
bool MSequencer::setEnd(int index, int end)
{
if(index >= 0 && index < MAX_SEQ && _sequences[index] != NULL) {
_sequences[index]->setend(end);
return true;
}
return false;
}
int MSequencer::getEnd(int index)
{
if(index >= 0 && index < MAX_SEQ && _sequences[index] != NULL) {
return _sequences[index]->getend();
}
return -1;
}
bool MSequencer::setReverse(int index, bool reverse)
{
if(index >= 0 && index < MAX_SEQ && _sequences[index] != NULL) {
_sequences[index]->setreverse(reverse);
return true;
}
return false;
}
bool MSequencer::getReverse(int index)
{
if(index >= 0 && index < MAX_SEQ && _sequences[index] != NULL) {
return _sequences[index]->getreverse();
}
return -1;
}
bool MSequencer::setInternal(int index, bool internal)
{
if(index >= 0 && index < MAX_SEQ && _sequences[index] != NULL) {
_sequences[index]->setinternal(internal);
return true;
}
return false;
}
bool MSequencer::getInternal(int index)
{
if(index >= 0 && index < MAX_SEQ && _sequences[index] != NULL) {
return _sequences[index]->getinternal();
}
return -1;
}
bool MSequencer::setExternal(int index, bool external)
{
if(index >= 0 && index < MAX_SEQ && _sequences[index] != NULL) {
_sequences[index]->setexternal(external);
return true;
}
return false;
}
bool MSequencer::getExternal(int index)
{
if(index >= 0 && index < MAX_SEQ && _sequences[index] != NULL) {
return _sequences[index]->getexternal();
}
return -1;
}
bool MSequencer::setSubdiv(int index, SUBDIV subdiv)
{
if(index >= 0 && index < MAX_SEQ && _sequences[index] != NULL) {
_sequences[index]->setsubdiv(subdiv);
return true;
}
return false;
}
int MSequencer::getSubdiv(int index)
{
if(index >= 0 && index < MAX_SEQ && _sequences[index] != NULL) {
return _sequences[index]->getsubdiv();
}
return -1;
}
bool MSequencer::setLoopType(int index, SEQ_LOOP_TYPE loop)
{
if(index >= 0 && index < MAX_SEQ && _sequences[index] != NULL) {
_sequences[index]->setlooptype(loop);
return true;
}
return false;
}
int MSequencer::getLoopType(int index)
{
if(index >= 0 && index < MAX_SEQ && _sequences[index] != NULL) {
return _sequences[index]->getlooptype();
}
return -1;
}
bool MSequencer::setCallback(int index, func_cb cb)
{
if(index >= 0 && index < MAX_SEQ && _sequences[index] != NULL) {
_sequences[index]->callback(cb);
return true;
}
return false;
}
func_cb MSequencer::getCallback(int index)
{
if(index >= 0 && index < MAX_SEQ && _sequences[index] != NULL) {
return _sequences[index]->_callback;
}
return NULL;
}
bool MSequencer::insertNotes(int index, int notes[], int numNotes, int newPosition)
{
if(index >= 0 && index < MAX_SEQ && _sequences[index] != NULL) {
_sequences[index]->insertnotes(notes, numNotes, newPosition);
return true;
}
return false;
}
int MSequencer::setSelectedSequence(int s)
{
if(s < 0) s = 0;
if(s > MAX_SEQ) s = MAX_SEQ - 1;
selectedSequence = s;
return selectedSequence;
}
// seq
seq::seq(int id, SUBDIV subdiv, func_cb cb) : _id(id), _stopped(true)
{
setsubdiv(subdiv);
callback(cb);
setcurrentstep(0);
setsteps(0);
}
seq::seq(int id, SUBDIV subdiv, int steps, int channel) : _id(id), _stopped(true)
{
setchannel(channel);
setsubdiv(subdiv);
setsteps(steps);
setlooptype(LOOP);
setreverse(false);
setposition(0);
setbegin(0);
if(steps <= MAX_STEPS) setend(steps-1);
else setend(MAX_STEPS);
for(int i = 0; i < MAX_STEPS; i++) {
_notes[i] = 36 + 3 * i;
_velocity[i] = 127;
}
setinternal(true);
setexternal(true);
_lastposition = 0;
}
seq::seq(int id, SUBDIV subdiv, int steps, SEQ_LOOP_TYPE loop) : _id(id), _stopped(true)
{
setchannel(Midi.midiChannel);
setsubdiv(subdiv);
setsteps(steps);
setlooptype(loop);
setreverse(false);
setposition(0);
setbegin(0);
if(steps <= MAX_STEPS) setend(steps-1);
else setend(MAX_STEPS);
for(int i = 0; i < MAX_STEPS; i++) {
_notes[i] = 36 + 3 * i;
_velocity[i] = 127;
}
setinternal(true);
setexternal(true);
_lastposition = 0;
}
seq::seq(int id, SUBDIV subdiv, int steps, SEQ_LOOP_TYPE loop, bool reverse) : _id(id), _stopped(true)
{
setchannel(Midi.midiChannel);
setsubdiv(subdiv);
setsteps(steps);
setlooptype(loop);
if(reverse) {
setreverse(true);
setposition(steps-1);
} else {
setreverse(false);
setposition(0);
}
setbegin(0);
if(steps <= MAX_STEPS) setend(steps-1);
else setend(MAX_STEPS);
for(int i = 0; i < MAX_STEPS; i++) {
_notes[i] = 36 + 3 * i;
_velocity[i] = 127;
}
setinternal(true);
setexternal(true);
_lastposition = 0;
}
void seq::trigger()
{
if(_begin < 0 ) {
Serial.print("_begin is ");
Serial.println(_begin);
_begin = 0;
}
// Serial.print("_end is ");
// Serial.println(_end);
// Serial.print("_position is ");
// Serial.println(_position);
// Serial.println("enter trigger");
if(_internal) {
// Serial.println("enter conditional");
Midi.noteOff(_channel, _notes[_lastposition], _velocity[_lastposition]);
// Serial.println("internal noteOff");
Midi.noteOn(_channel, _notes[_position], _velocity[_position]);
// Serial.println("internal noteOff");
}
if(_external) {
Midi.sendNoteOff(_channel, _notes[_lastposition], _velocity[_lastposition]);
// Serial.println("external noteOff");
Midi.sendNoteOn(_channel, _notes[_position], _velocity[_position]);
// Serial.println("external noteOff");
}
_lastposition = _position;
if(_reverse) {
if(_position <= _begin) {
_position = _end + 1;
if(!_loop) _stopped = true;
}
_position--;
} else {
if(_position >= _end) {
_position = _begin - 1;
if(!_loop) _stopped = true;
}
_lastposition = _position;
// Serial.print("_last position is ");
// Serial.println(_lastposition);
// Serial.println();
_position++;
// Serial.print("_position is ");
// Serial.println(_position);
// Serial.println();
}
// Serial.println("triggered");
}
void seq::insertnotes(int notes[], int numNotes, int newPosition)
{
for(int i = 0; i < numNotes; i++) {
int pos = newPosition + i;
int note = notes[i];
if(note > 127) note = 127;
else if(note < 0 ) note = 0;
if((pos >= 0) && (pos < MAX_STEPS)) {
_notes[pos] = note;
}
}
}
void seq::setchannel(int c)
{
_channel = c;
}
int seq::getchannel()
{
return _channel;
}
void seq::setsteps(int s)
{
_steps = s;
}
int seq::getsteps()
{
return _steps;
}
void seq::setcurrentstep(int s)
{
step = s;
}
int seq::getcurrentstep()
{
return step;
}
void seq::setposition(int p)
{
_position = p;
}
int seq::getposition()
{
return _position;
}
void seq::setbegin(int b)
{
if(b < 0) b = 0;
if(b > _end) b = _end;
if(b >= _steps) b = _steps - 1;
_begin = b;
}
int seq::getbegin()
{
return _begin;
}
void seq::setend(int e)
{
if(e < 0) e = 0;
if(e >= _steps) e = _steps - 1;
if(e < _begin) e = _begin;
_end = e;
}
int seq::getend()
{
return _end;
}
void seq::setreverse(bool r)
{
_reverse = r;
}
bool seq::getreverse()
{
return _reverse;
}
void seq::setinternal(bool i)
{
_internal = i;
}
bool seq::getinternal()
{
return _internal;
}
void seq::setexternal(bool e)
{
_external = e;
}
bool seq::getexternal()
{
return _external;
}
void seq::setsubdiv(SUBDIV v)
{
_subdiv = v;
}
SUBDIV seq::getsubdiv()
{
return _subdiv;
}
void seq::setlooptype(SEQ_LOOP_TYPE loop)
{
_loop = loop;
}
SEQ_LOOP_TYPE seq::getlooptype()
{
return _loop;
}
void seq::callback(func_cb cb)
{
_callback = cb;
}