-Add notecache to allow seamless loops.

git-svn-id: http://svn.fuzzle.org/mloop/mloop/trunk@2 ba049829-c6ef-42ef-81ac-908dd8d2e907
remotes/git-svn@10
petern 2009-07-21 21:33:51 +00:00
parent 90e082d82b
commit 4569a323ee
5 changed files with 110 additions and 1 deletions

View File

@ -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);

View File

@ -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();

View File

@ -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()

View File

@ -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 */

52
src/notecache.h 100644
View File

@ -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 */