add octave shifting and other API changes to better support beatbox GUI
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user