-Add notecache to allow seamless loops.
git-svn-id: http://svn.fuzzle.org/mloop/mloop/trunk@2 ba049829-c6ef-42ef-81ac-908dd8d2e907remotes/git-svn@10
parent
90e082d82b
commit
4569a323ee
|
@ -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);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <jack/jack.h>
|
||||
#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();
|
||||
|
|
47
src/loop.cpp
47
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()
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <list>
|
||||
#include <jack/jack.h>
|
||||
#include <jack/midiport.h>
|
||||
#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 */
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/* $Id$ */
|
||||
|
||||
#ifndef NOTECACHE_H
|
||||
#define NOTECACHE_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
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 */
|
Loading…
Reference in New Issue