Skip to content

Commit

Permalink
ADSR: Improve resolution, Capt MIDI: Add beat clock in
Browse files Browse the repository at this point in the history
  • Loading branch information
Chysn committed Aug 23, 2018
1 parent 92fcb2b commit ae7d5a7
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 38 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ Release
.cproject
.gitignore.swp
.settings/
*.ino
sloeber.ino.cpp
.gitignore
bin
Expand Down
2 changes: 1 addition & 1 deletion software/APP_Boilerplate.ino.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
// SOFTWARE.

#include "HSApplication.h"
#include "SystemExclusiveHandler.h"
#include "HSMIDI.h"

class ClassName : public HSApplication, public SystemExclusiveHandler {
public:
Expand Down
2 changes: 1 addition & 1 deletion software/o_c_REV/APP_HEMISPHERE.ino
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace menu = OC::menu;

#include "hemisphere_config.h"
#include "HemisphereApplet.h"
#include "SystemExclusiveHandler.h"
#include "HSMIDI.h"

#define DECLARE_APPLET(id, categories, class_name) \
{ id, categories, class_name ## _Start, class_name ## _Controller, class_name ## _View, class_name ## _Screensaver, \
Expand Down
79 changes: 60 additions & 19 deletions software/o_c_REV/APP_MIDI.ino
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,31 @@
// See https://www.pjrc.com/teensy/td_midi.html

#include "HSApplication.h"
#include "SystemExclusiveHandler.h"
#include "HSMIDI.h"

const uint16_t MIDI_INDICATOR_COUNTDOWN = 2000;
const int MIDI_PARAMETER_COUNT = 40;
const int MIDI_CURRENT_SETUP = MIDI_PARAMETER_COUNT * 4;
const int MIDI_SETTING_LAST = MIDI_CURRENT_SETUP + 1;
const int MIDI_LOG_MAX_SIZE = 101;

const char* const midi_in_functions[13] = {
"--", "Note", "Gate", "Trig", "Veloc", "Mod", "Aft", "Bend", "Expr", "Pan", "Hold", "Brth", "yAxis"
// Icons that are used next to the menu items
const uint8_t MIDI_midi_icon[8] = {0x3c, 0x42, 0x91, 0x45, 0x45, 0x91, 0x42, 0x3c};
const uint8_t MIDI_note_icon[8] = {0xc0, 0xe0, 0xe0, 0xe0, 0x7f, 0x02, 0x14, 0x08};
const uint8_t MIDI_clock_icon[8] = {0x9c, 0xa2, 0xc1, 0xcf, 0xc9, 0xa2, 0x9c, 0x00};

const char* const midi_in_functions[17] = {
"--", "Note", "Gate", "Trig", "Veloc", "Mod", "Aft", "Bend", "Expr", "Pan", "Hold", "Brth", "yAxis", "Qtr", "8th", "16th", "24ppq"
};
const char* const midi_out_functions[12] = {
"--", "Note", "Leg.", "Veloc", "Mod", "Aft", "Bend", "Expr", "Pan", "Hold", "Brth", "yAxis"
};

#define MIDI_SETUP_PARAMETER_LIST \
{ 0, 0, 12, "MIDI > A", midi_in_functions, settings::STORAGE_TYPE_U8 },\
{ 0, 0, 12, "MIDI > B", midi_in_functions, settings::STORAGE_TYPE_U8 },\
{ 0, 0, 12, "MIDI > C", midi_in_functions, settings::STORAGE_TYPE_U8 },\
{ 0, 0, 12, "MIDI > D", midi_in_functions, settings::STORAGE_TYPE_U8 },\
{ 0, 0, 16, "MIDI > A", midi_in_functions, settings::STORAGE_TYPE_U8 },\
{ 0, 0, 16, "MIDI > B", midi_in_functions, settings::STORAGE_TYPE_U8 },\
{ 0, 0, 16, "MIDI > C", midi_in_functions, settings::STORAGE_TYPE_U8 },\
{ 0, 0, 16, "MIDI > D", midi_in_functions, settings::STORAGE_TYPE_U8 },\
{ 0, 0, 11, "1 > MIDI", midi_out_functions, settings::STORAGE_TYPE_U8 },\
{ 0, 0, 11, "2 > MIDI", midi_out_functions, settings::STORAGE_TYPE_U8 },\
{ 0, 0, 11, "3 > MIDI", midi_out_functions, settings::STORAGE_TYPE_U8 },\
Expand Down Expand Up @@ -93,7 +98,11 @@ enum MIDI_IN_FUNCTION {
MIDI_IN_PAN,
MIDI_IN_HOLD,
MIDI_IN_BREATH,
MIDI_IN_Y_AXIS
MIDI_IN_Y_AXIS,
MIDI_IN_CLOCK_4TH,
MIDI_IN_CLOCK_8TH,
MIDI_IN_CLOCK_16TH,
MIDI_IN_CLOCK_24PPQN,
};

enum MIDI_OUT_FUNCTION {
Expand All @@ -111,13 +120,13 @@ enum MIDI_OUT_FUNCTION {
MIDI_OUT_Y_AXIS,
};

const char* const midi_messages[6] = {
"Note", "Off", "CC#", "Aft", "Bend", "SysEx"
const char* const midi_messages[7] = {
"Note", "Off", "CC#", "Aft", "Bend", "SysEx", "Clock"
};
struct CaptainMIDILog {
bool midi_in; // 0 = out, 1 = in
char io; // 1, 2, 3, 4, A, B, C, D
uint8_t message; // 0 = Note On, 1 = Note Off, 2 = CC, 3 = Aftertouch, 4 = Bend, 5 = SysEx
uint8_t message; // 0 = Note On, 1 = Note Off, 2 = CC, 3 = Aftertouch, 4 = Bend, 5 = SysEx, 6 = Clock
uint8_t channel; // MIDI channel
int16_t data1;
int16_t data2;
Expand Down Expand Up @@ -164,6 +173,12 @@ struct CaptainMIDILog {
if (data2 > 0) graphics.print("+");
graphics.print(data2); // Aftertouch or bend value
}

if (message == 6) {
graphics.print(data1);
graphics.print("/");
graphics.print(data2);
}
}
}
};
Expand Down Expand Up @@ -269,6 +284,7 @@ public:
indicator_out[ch] = 0;
Out(ch, 0);
}
clock_count = 0;
}

void Panic() {
Expand Down Expand Up @@ -378,6 +394,7 @@ private:
// MIDI In
int note_in[4]; // Up to four notes at a time are kept track of with MIDI In
uint16_t indicator_in[4]; // A MIDI indicator will display next to MIDI In assignment
uint8_t clock_count; // MIDI clock counter (24ppqn)

// MIDI Out
bool gated[4]; // Current gated status of each input
Expand All @@ -388,10 +405,6 @@ private:
uint16_t indicator_out[4]; // A MIDI indicator will display next to MIDI Out assignment

void DrawSetupScreens() {
// Icons that are used next to the menu items
const uint8_t midi_icon[8] = {0x3c, 0x42, 0x91, 0x45, 0x45, 0x91, 0x42, 0x3c};
const uint8_t note_icon[8] = {0xc0, 0xe0, 0xe0, 0xe0, 0x7f, 0x02, 0x14, 0x08};

// Create the header, showing the current Setup and Screen name
gfxHeader("Setup ");
graphics.print(get_setup_number() + 1);
Expand Down Expand Up @@ -419,13 +432,21 @@ private:
graphics.setPrintPos(70, list_item.y + 2);
graphics.print(midi_note_numbers[note_in[p]]);
}
} else graphics.drawBitmap8(70, list_item.y + 2, 8, midi_icon);
} else graphics.drawBitmap8(70, list_item.y + 2, 8, MIDI_midi_icon);
}

// Indicate if the assignment is a note type
if (get_in_channel(p) > 0 && get_in_assign(p) == MIDI_IN_NOTE)
graphics.drawBitmap8(56, list_item.y + 1, 8, note_icon);
graphics.drawBitmap8(56, list_item.y + 1, 8, MIDI_note_icon);
else if (screen > 1) suppress = 1;

// Indicate if the assignment is a clock
if (get_in_assign(p) >= MIDI_IN_CLOCK_4TH) {
uint8_t o_x = (clock_count < 12) ? 2 : 0;
graphics.drawBitmap8(80 + o_x, list_item.y + 1, 8, MIDI_clock_icon);
if (screen > 0) suppress = 1;
}

} else { // It's a MIDI Out assignment
p -= 4;
if (indicator_out[p] > 0 || note_out[p] > -1) {
Expand All @@ -434,12 +455,12 @@ private:
graphics.setPrintPos(70, list_item.y + 2);
graphics.print(midi_note_numbers[note_out[p]]);
}
} else graphics.drawBitmap8(70, list_item.y + 2, 8, midi_icon);
} else graphics.drawBitmap8(70, list_item.y + 2, 8, MIDI_midi_icon);
}

// Indicate if the assignment is a note type
if (get_out_channel(p) > 0 && (get_out_assign(p) == MIDI_OUT_NOTE || get_out_assign(p) == MIDI_OUT_LEGATO))
graphics.drawBitmap8(56, list_item.y + 1, 8, note_icon);
graphics.drawBitmap8(56, list_item.y + 1, 8, MIDI_note_icon);
else if (screen > 1) suppress = 1;
}

Expand Down Expand Up @@ -618,6 +639,12 @@ private:
// Handle system exclusive dump for Setup data
if (message == MIDI_MSG_SYSEX) OnReceiveSysEx();

// Listen for incoming clock
if (message == MIDI_MSG_REALTIME && data1 == 0) {
if (++clock_count >= 24) clock_count = 0;
}


bool note_captured = 0; // A note or gate should only be captured by
bool gate_captured = 0; // one assignment, to allow polyphony in the interface

Expand Down Expand Up @@ -716,11 +743,25 @@ private:
indicator = 1;
}

if (in_fn >= MIDI_IN_CLOCK_4TH) {
// Clock is unlogged because there can be a lot of it
uint8_t mod = get_clock_mod(in_fn);
if (clock_count % mod == 0) ClockOut(ch);
}

if (indicator) indicator_in[ch] = MIDI_INDICATOR_COUNTDOWN;
}
}
}

uint8_t get_clock_mod(int fn) {
uint8_t mod = 1;
if (fn == MIDI_IN_CLOCK_4TH) mod = 24;
if (fn == MIDI_IN_CLOCK_8TH) mod = 12;
if (fn == MIDI_IN_CLOCK_16TH) mod = 6;
return mod;
}

int get_in_assign(int ch) {
int setup_offset = get_setup_number() * MIDI_PARAMETER_COUNT;
return values_[ch + setup_offset];
Expand Down
2 changes: 1 addition & 1 deletion software/o_c_REV/APP_SCALEEDITOR.ino
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#include "braids_quantizer_scales.h"
#include "OC_scales.h"
#include "HSApplication.h"
#include "SystemExclusiveHandler.h"
#include "HSMIDI.h"
#include "SegmentDisplay.h"

class ScaleEditor : public HSApplication, public SystemExclusiveHandler {
Expand Down
2 changes: 1 addition & 1 deletion software/o_c_REV/APP_THEDARKESTTIMELINE.ino
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
#include "braids_quantizer_scales.h"
#include "OC_scales.h"
#include "HSApplication.h"
#include "SystemExclusiveHandler.h"
#include "HSMIDI.h"

const bool DT_CV_TIMELINE = 0;
const bool DT_PROBABILITY_TIMELINE = 1;
Expand Down
2 changes: 1 addition & 1 deletion software/o_c_REV/HEM_ADEG.ino
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
// SOFTWARE.

#define HEM_ADEG_MAX_VALUE 255
#define HEM_ADEG_MAX_TICKS 32000
#define HEM_ADEG_MAX_TICKS 33333

class ADEG : public HemisphereApplet {
public:
Expand Down
16 changes: 8 additions & 8 deletions software/o_c_REV/HEM_ADSREG.ino
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@
#define HEM_EG_SUSTAIN 2
#define HEM_EG_RELEASE 3
#define HEM_EG_NO_STAGE -1
#define HEM_EG_MAX_VALUE 200
#define HEM_EG_MAX_VALUE 255

#define HEM_SUSTAIN_CONST 35
#define HEM_EG_DISPLAY_HEIGHT 30

// About four seconds
#define HEM_EG_MAX_TICKS_AD 66667
#define HEM_EG_MAX_TICKS_AD 33333

// About eight seconds
#define HEM_EG_MAX_TICKS_R 133333
Expand Down Expand Up @@ -145,10 +145,10 @@ protected:

private:
int edit_stage;
int attack; // Attack rate from 1-200 where 1 is fast
int decay; // Decay rate from 1-200 where 1 is fast
int sustain; // Sustain level from 1-200 where 1 is low
int release; // Release rate from 1-200 where 1 is fast
int attack; // Attack rate from 1-255 where 1 is fast
int decay; // Decay rate from 1-255 where 1 is fast
int sustain; // Sustain level from 1-255 where 1 is low
int release; // Release rate from 1-255 where 1 is fast
int attack_mod; // Modification to attack from CV1
int release_mod; // Modification to release from CV2

Expand Down Expand Up @@ -245,10 +245,10 @@ private:
}

void ReleaseAmplitude(int ch) {
int effective_release = constrain(release + release_mod, 1, HEM_EG_MAX_VALUE);
int effective_release = constrain(release + release_mod, 1, HEM_EG_MAX_VALUE) - 1;
int total_stage_ticks = Proportion(effective_release, HEM_EG_MAX_VALUE, HEM_EG_MAX_TICKS_R);
int ticks_remaining = total_stage_ticks - stage_ticks[ch];
if (effective_release == 1) ticks_remaining = 0;
if (effective_release == 0) ticks_remaining = 0;
if (ticks_remaining <= 0 || amplitude[ch] <= 0) { // End of release; turn off envelope
stage[ch] = HEM_EG_NO_STAGE;
stage_ticks[ch] = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,18 @@
// * MIDI note/CV quantizer functions
//////////////////////////////////////////////////////////////////////////

#ifndef SYSEX_HANDLER_H_
#define SYSEX_HANDLER_H_
#ifndef HSMIDI_H
#define HSMIDI_H

// Teensyduino USB MIDI Library message numbers
// See https://www.pjrc.com/teensy/td_midi.html
const uint8_t MIDI_MSG_NOTE_ON = 1;
const uint8_t MIDI_MSG_NOTE_OFF = 0;
const uint8_t MIDI_MSG_MIDI_CC = 3;
const uint8_t MIDI_MSG_AFTERTOUCH = 5;
const uint8_t MIDI_MSG_PITCHBEND = 6;
const uint8_t MIDI_MSG_SYSEX = 7;
const uint8_t MIDI_MSG_REALTIME = 8;

const char* const midi_note_numbers[128] = {
"C-1","C#-1","D-1","D#-1","E-1","F-1","F#-1","G-1","G#-1","A-1","A#-1","B-1",
Expand All @@ -53,8 +55,8 @@ const char* const midi_note_numbers[128] = {
};

const char* const midi_channels[17] = {
"Off", " 1", " 2", " 3", " 4", " 5", " 6", " 7", " 8",
" 9", " 10", " 11", " 12", " 13", " 14", " 15", " 16"
"Off", " 1", " 2", " 3", " 4", " 5", " 6", " 7", " 8",
" 9", "10", "11", "12", "13", "14", "15", "16"
};


Expand Down Expand Up @@ -315,4 +317,4 @@ class MIDIQuantizer {
}
};

#endif /* SYSEX_HANDLER_H_ */
#endif /* HSMIDI_H */

0 comments on commit ae7d5a7

Please sign in to comment.