Ardour  9.0-rc2-184-gc50547f0a6
midi_state_tracker.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008-2015 David Robillard <d@drobilla.net>
3  * Copyright (C) 2009-2017 Paul Davis <paul@linuxaudiosystems.com>
4  * Copyright (C) 2010-2011 Carl Hetherington <carl@carlh.net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
21 #pragma once
22 
23 #include <glibmm/threads.h>
24 
25 #include "temporal/beats.h"
26 
27 #include "ardour/debug.h"
28 #include "ardour/midi_buffer.h"
29 #include "ardour/source.h"
30 
31 namespace Evoral {
32 template <typename T> class EventSink;
33 template <typename T> class EventList;
34 }
35 
36 namespace ARDOUR {
37 
38 class MidiSource;
39 
44 {
45 public:
47  virtual ~MidiNoteTracker() {}
48 
49  virtual void track (const uint8_t* evbuf);
50  virtual void dump (std::ostream&) const;
51  virtual void reset ();
52 
54  void add (uint8_t note, uint8_t chn);
55  void remove (uint8_t note, uint8_t chn);
56  void resolve_notes (MidiBuffer& buffer, samplepos_t time, bool reset = true);
59 
60  void flush_notes (MidiBuffer& buffer, samplepos_t time, bool reset = true);
61 
62  template<typename Time>
63  void flush_notes (Evoral::EventSink<Time> &sink, Time time, bool reset = true) {
64  push_notes<Time> (sink, time, reset, MIDI_CMD_NOTE_ON, 64);
65  }
66 
67  bool empty() const { return _on == 0; }
68  uint16_t on() const { return _on; }
69  bool active (uint8_t note, uint8_t channel) const {
70  return _active_notes[(channel*128)+note] > 0;
71  }
72 
73  template<typename Time>
74  void track (const Evoral::Event<Time>& ev) {
75  track (ev.buffer());
76  }
77 
78 private:
79  uint8_t _active_notes[128*16];
80  uint16_t _on;
81 
82  void push_notes (MidiBuffer &dst, samplepos_t time, bool reset, int cmd, int velocity);
83 
84  template<typename Time>
85  void push_notes (Evoral::EventSink<Time> &dst, Time time, bool reset, int cmd, int velocity) {
86  DEBUG_TRACE (PBD::DEBUG::MidiTrackers, string_compose ("%1 ES::push_notes @ %2 on = %3\n", this, time, _on));
87 
88  if (!_on) {
89  return;
90  }
91 
92  for (int channel = 0; channel < 16; ++channel) {
93  const int coff = channel << 7;
94  for (int note = 0; note < 128; ++note) {
95  uint8_t cnt = _active_notes[note + coff];
96  while (cnt) {
97  uint8_t buffer[3] = { ((uint8_t) (cmd | channel)), uint8_t (note), (uint8_t) velocity };
98  /* note that we do not care about failure from
99  write() ... should we warn someone ?
100  */
101  dst.write (time, Evoral::MIDI_EVENT, 3, buffer);
102  cnt--;
103  DEBUG_TRACE (PBD::DEBUG::MidiTrackers, string_compose ("%1: MB-push note %2/%3 at %4\n", this, (int) note, (int) channel, time));
104  }
105  if (reset) {
106  _active_notes [note + coff] = 0;
107  }
108  }
109  }
110  if (reset) {
111  _on = 0;
112  }
113  }
114 };
115 
117 {
118  public:
121 
122  void track (const uint8_t* evbuf);
123  void dump (std::ostream&) const;
124  void reset ();
125 
129 
130  private:
131  uint8_t program[16];
132  uint16_t bender[16];
133  uint16_t pressure[16];
134  uint8_t control[16][127];
135 };
136 
137 } // namespace ARDOUR
138 
void track(const Evoral::Event< Time > &ev)
void resolve_notes(MidiSource &src, const Source::WriterLock &lock, Temporal::Beats time)
void track(const MidiBuffer::const_iterator &from, const MidiBuffer::const_iterator &to)
virtual void dump(std::ostream &) const
bool active(uint8_t note, uint8_t channel) const
virtual void reset()
void push_notes(MidiBuffer &dst, samplepos_t time, bool reset, int cmd, int velocity)
void resolve_notes(MidiBuffer &buffer, samplepos_t time, bool reset=true)
void flush_notes(Evoral::EventSink< Time > &sink, Time time, bool reset=true)
void flush_notes(MidiBuffer &buffer, samplepos_t time, bool reset=true)
void push_notes(Evoral::EventSink< Time > &dst, Time time, bool reset, int cmd, int velocity)
void resolve_notes(Evoral::EventSink< samplepos_t > &buffer, samplepos_t time)
void remove(uint8_t note, uint8_t chn)
virtual void track(const uint8_t *evbuf)
void add(uint8_t note, uint8_t chn)
void resolve_state(Evoral::EventSink< samplepos_t > &, Evoral::EventList< samplepos_t > const &, samplepos_t time, bool reset=true)
void track(const uint8_t *evbuf)
void resolve_diff(MidiStateTracker const &other, Evoral::EventSink< samplepos_t > &, samplepos_t time, bool reset=true)
void dump(std::ostream &) const
void flush(MidiBuffer &, samplepos_t, bool reset)
Glib::Threads::RWLock::WriterLock WriterLock
virtual uint32_t write(Time time, EventType type, uint32_t size, const uint8_t *buf)=0
const uint8_t * buffer() const
Definition: Event.h:125
std::string string_compose(const std::string &fmt, const T1 &o1)
Definition: compose.h:246
#define MIDI_CMD_NOTE_ON
Definition: midi_events.h:107
#define LIBARDOUR_API
#define DEBUG_TRACE(bits, str)
Temporal::samplepos_t samplepos_t
Definition: editor.h:87
DebugBits MidiTrackers