diff --git a/src/jack.cpp b/src/jack.cpp index bc7a465..8098e8b 100644 --- a/src/jack.cpp +++ b/src/jack.cpp @@ -15,6 +15,7 @@ Jack::Jack() m_connected = false; m_recording = false; m_buffer = new RingBuffer(2048); + m_notecache.Reset(); } Jack::~Jack() @@ -93,6 +94,8 @@ int Jack::ProcessCallback(jack_nframes_t nframes) while (ev.time == frame) { jack_midi_event_write(output, ev.time, ev.buffer, ev.size); + m_notecache.HandleEvent(ev); + if (m_recording) { /* Don't add the event to the buffer if it will become full. * This includes the case where the event would actually fit, @@ -211,8 +214,10 @@ void Jack::Run() if (m_recording) { m_recording = false; m_loops[m_recording_loop].SetLength(m_recording_time); + m_loops[m_recording_loop].EndFromNoteCache(m_notecache); printf("Finished recording loop %d\n", m_recording_loop); } else { + m_loops[m_recording_loop].StartFromNoteCache(m_notecache); m_recording_time = 0; m_recording = true; printf("Started recording loop %d\n", m_recording_loop); diff --git a/src/jack.h b/src/jack.h index 42cd8b8..1151477 100644 --- a/src/jack.h +++ b/src/jack.h @@ -6,6 +6,7 @@ #include #include "loop.h" #include "ringbuffer.h" +#include "notecache.h" #define NUM_LOOPS 9 @@ -24,6 +25,8 @@ private: int m_recording_loop; jack_nframes_t m_recording_time; + NoteCache m_notecache; + static void ShutdownCallbackHandler(void *arg) { ((Jack *)arg)->ShutdownCallback(); diff --git a/src/loop.cpp b/src/loop.cpp index 9534888..a69889e 100644 --- a/src/loop.cpp +++ b/src/loop.cpp @@ -29,7 +29,7 @@ void Loop::PlayFrame(void *port_buffer, jack_nframes_t frame) jack_nframes_t position = (*m_iterator).second; if (event.time + position > m_position) break; - jack_midi_event_write(port_buffer, event.time, event.buffer, event.size); + jack_midi_event_write(port_buffer, frame, event.buffer, event.size); } m_position++; @@ -73,6 +73,51 @@ void Loop::Stop() m_state = LS_STOPPING; } +void Loop::StartFromNoteCache(NoteCache &cache) +{ + for (uint8_t c = 0; c < 16; c++) { + for (uint8_t n = 0; n < 128; n++) { + int8_t v = cache.GetNote(c, n); + + if (v > 0) { + uint8_t *buffer = (uint8_t *)malloc(3); + buffer[0] = 0x90 + c; + buffer[1] = n; + buffer[2] = v; + + jack_midi_event_t event; + event.time = 0; + event.buffer = buffer; + event.size = 3; + + AddEvent(0, &event); + } + } + } +} + +void Loop::EndFromNoteCache(NoteCache &cache) +{ + for (uint8_t c = 0; c < 16; c++) { + for (uint8_t n = 0; n < 128; n++) { + int8_t v = cache.GetNote(c, n); + + if (v > 0) { + uint8_t *buffer = (uint8_t *)malloc(3); + buffer[0] = 0x80 + c; + buffer[1] = n; + buffer[2] = 0; + + jack_midi_event_t event; + event.time = 0; + event.buffer = buffer; + event.size = 3; + + AddEvent(m_length - 1, &event); + } + } + } +} /* void Loop::Reset() diff --git a/src/loop.h b/src/loop.h index cc5c4e6..55607d0 100644 --- a/src/loop.h +++ b/src/loop.h @@ -7,6 +7,7 @@ #include #include #include +#include "notecache.h" enum LoopState { LS_IDLE, @@ -34,6 +35,9 @@ public: void SetLength(jack_nframes_t length); void Start(bool loop); void Stop(); + + void StartFromNoteCache(NoteCache &cache); + void EndFromNoteCache(NoteCache &cache); }; #endif /* LOOP_H */ diff --git a/src/notecache.h b/src/notecache.h new file mode 100644 index 0000000..1ded8e1 --- /dev/null +++ b/src/notecache.h @@ -0,0 +1,52 @@ +/* $Id$ */ + +#ifndef NOTECACHE_H +#define NOTECACHE_H + +#include +#include + +class NoteCache { +private: + int8_t m_notes[16][128]; + +public: + NoteCache() + { + memset(m_notes, 0, sizeof m_notes); + } + + ~NoteCache() + { + } + + void Reset() + { + memset(m_notes, 0, sizeof m_notes); + } + + int8_t GetNote(int8_t channel, int8_t note) const + { + return m_notes[channel][note]; + } + + void HandleEvent(jack_midi_event_t &event) + { + uint8_t *buffer = event.buffer; + uint8_t cmd = buffer[0]; + + /* Note on or off event */ + if ((cmd & 0xE0) == 0x80) { + int8_t channel = cmd & 0x0F; + + for (uint i = 1; i < event.size; i += 2) { + int8_t note = buffer[i] & 0x7F; + int8_t velocity = buffer[i] & 0x7F; + if ((cmd & 0xF0) == 0x80) velocity = 0; + m_notes[channel][note] = velocity; + } + } + } +}; + +#endif /* NOTECACHE_H */