add octave shifting and other API changes to better support beatbox GUI

This commit is contained in:
Paul Davis
2018-11-07 13:46:11 -05:00
parent 1320af9b86
commit b9c26ee4c4
2 changed files with 76 additions and 13 deletions

View File

@@ -53,19 +53,22 @@ class Step : public PBD::Stateful {
Step (StepSequence&, Temporal::Beats const & beat);
~Step ();
void set_note (double note, double velocity = 0.5, int32_t duration = 1, int n = 0);
void set_note (double note, double velocity = 0.5, int n = 0);
void set_chord (size_t note_cnt, double* notes);
void set_parameter (int number, double value, int n = 0);
void adjust_velocity (int amt);
void adjust_pitch (int amt);
void adjust_octave (int amt);
Mode mode() const { return _mode; }
void set_mode (Mode m);
double note (size_t n = 0) const { return _notes[n].number; }
double velocity (size_t n = 0) const { return _notes[n].velocity; }
int32_t duration (size_t n = 0) const { return _notes[n].duration; }
double duration () const { return _duration; }
void set_duration (double duration);
void set_offset (Temporal::Beats const &, size_t n = 0);
Temporal::Beats offset (size_t n = 0) const { return _notes[n].offset; }
@@ -105,7 +108,8 @@ class Step : public PBD::Stateful {
bool _skipped;
Mode _mode;
int _octave_shift;
double _duration;
struct ParameterValue {
int parameter;
double value;
@@ -117,14 +121,13 @@ class Step : public PBD::Stateful {
double interval; /* semitones */
};
double velocity;
int32_t duration;
Temporal::Beats offset;
bool on;
Temporal::Beats off_at;
MIDI::byte off_msg[3];
Note () : number (-1), velocity (0.5), duration (1), on (false) {}
Note (double n, double v, double d, Temporal::Beats const & o) : number (n), velocity (v), duration (d), offset (o), on (false) {}
Note () : number (-1), velocity (0.5), on (false) {}
Note (double n, double v,Temporal::Beats const & o) : number (n), velocity (v), offset (o), on (false) {}
};
static const int _notes_per_step = 5;
@@ -137,11 +140,10 @@ class Step : public PBD::Stateful {
void check_note (size_t n, MidiBuffer& buf, bool, samplepos_t, samplepos_t, MidiStateTracker&);
void check_parameter (size_t n, MidiBuffer& buf, bool, samplepos_t, samplepos_t);
StepSequencer& sequencer() const;
};
class StepSequence
class StepSequence : public PBD::Stateful
{
public:
enum Direction {
@@ -189,6 +191,9 @@ class StepSequence
StepSequencer& sequencer() const { return _sequencer; }
XMLNode& get_state();
int set_state (XMLNode const &, int);
private:
StepSequencer& _sequencer;
mutable Glib::Threads::Mutex _step_lock;
@@ -207,7 +212,8 @@ class StepSequence
MusicalMode _mode;
};
class StepSequencer {
class StepSequencer : public PBD::Stateful
{
public:
StepSequencer (TempoMap&, size_t nseqs, size_t nsteps, Temporal::Beats const & step_size, Temporal::Beats const & bar_size);
~StepSequencer ();
@@ -235,6 +241,9 @@ class StepSequencer {
TempoMap& tempo_map() const { return _tempo_map; }
XMLNode& get_state();
int set_state (XMLNode const &, int);
private:
mutable Glib::Threads::Mutex _sequence_lock;

View File

@@ -38,6 +38,8 @@ Step::Step (StepSequence &s, Temporal::Beats const & b)
, _nominal_beat (b)
, _skipped (false)
, _mode (AbsolutePitch)
, _octave_shift (0)
, _duration (1.0)
{
std::cerr << "step @ " << b << std::endl;
@@ -76,12 +78,11 @@ Step::set_beat (Temporal::Beats const & b)
}
void
Step::set_note (double note, double velocity, int32_t duration, int n)
Step::set_note (double note, double velocity, int n)
{
assert (n < _notes_per_step);
_notes[n].number = note;
_notes[n].velocity = velocity;
_notes[n].duration = duration;
}
void
@@ -141,6 +142,22 @@ Step::adjust_velocity (int amt)
PropertyChanged (pc);
}
void
Step::adjust_octave (int amt)
{
/* this is applied to all notes at once */
_octave_shift += amt;
if (_octave_shift > 4) {
_octave_shift = 4;
} else if (_octave_shift < -4) {
_octave_shift = -4;
}
PropertyChange pc;
PropertyChanged (pc);
}
bool
Step::run (MidiBuffer& buf, bool running, samplepos_t start_sample, samplepos_t end_sample, MidiStateTracker& tracker)
{
@@ -240,6 +257,18 @@ Step::check_note (size_t n, MidiBuffer& buf, bool running, samplepos_t start_sam
break;
}
if (_octave_shift) {
const int t = mbuf[1] + (12 * _octave_shift);
if (t > 127 || t < 0) {
/* Out of range */
return;
}
mbuf[1] = t;
}
mbuf[2] = (uint8_t) floor (note.velocity * 127.0);
note.off_msg[0] = 0x80 | _sequence.channel();
@@ -258,10 +287,10 @@ Step::check_note (size_t n, MidiBuffer& buf, bool running, samplepos_t start_sam
note.off_at = note_on_time;
if (note.duration == 1) {
if (_duration == 1.0) {
note.off_at += Temporal::Beats (0, _sequence.step_size().to_ticks() - 1);
} else {
note.off_at += Temporal::Beats (0, _sequence.step_size().to_ticks() / note.duration);
note.off_at += Temporal::Beats (0, _sequence.step_size().to_ticks() * _duration);
}
}
}
@@ -392,6 +421,19 @@ StepSequence::step (size_t n) const
return *_steps[n];
}
XMLNode&
StepSequence::get_state()
{
return *new XMLNode (X_("StepSequence"));
}
int
StepSequence::set_state (XMLNode const &, int)
{
return 0;
}
/**/
StepSequencer::StepSequencer (TempoMap& tmap, size_t nseqs, size_t nsteps, Temporal::Beats const & step_size, Temporal::Beats const & bar_size)
@@ -464,3 +506,15 @@ StepSequencer::sequence (size_t n) const
assert (n < _sequences.size());
return *_sequences[n];
}
XMLNode&
StepSequencer::get_state()
{
return *new XMLNode (X_("StepSequencer"));
}
int
StepSequencer::set_state (XMLNode const &, int)
{
return 0;
}