-Updated engine to record / playback loop
parent
40724e3bca
commit
a94ac55fbd
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
#ifndef LUPPP_BUFFERS_H
|
||||||
|
#define LUPPP_BUFFERS_H
|
||||||
|
|
||||||
|
class Buffers
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Buffers()
|
||||||
|
{
|
||||||
|
memset( audio, 0, sizeof(float*)*2);
|
||||||
|
}
|
||||||
|
float* audio[2];
|
||||||
|
|
||||||
|
enum BUFFER {
|
||||||
|
MASTER_OUTPUT = 0,
|
||||||
|
MASTER_INPUT,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LUPPP_BUFFERS_H
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "looper.hxx"
|
||||||
|
|
||||||
namespace Event
|
namespace Event
|
||||||
{
|
{
|
||||||
enum {
|
enum {
|
||||||
|
@ -18,6 +20,8 @@ namespace Event
|
||||||
PLAY_SAMPLE,
|
PLAY_SAMPLE,
|
||||||
MASTER_VOL,
|
MASTER_VOL,
|
||||||
RECORD,
|
RECORD,
|
||||||
|
|
||||||
|
LOOPER_STATE,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -47,6 +51,17 @@ class EventMasterVol : public EventBase
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class EventLooperState : public EventBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int type() { return int(LOOPER_STATE); }
|
||||||
|
uint32_t size() { return sizeof(EventLooperState); }
|
||||||
|
|
||||||
|
Looper::State state;
|
||||||
|
EventLooperState(){}
|
||||||
|
EventLooperState(Looper::State s) : state(s){}
|
||||||
|
};
|
||||||
|
|
||||||
class EventLoadSample : public EventBase
|
class EventLoadSample : public EventBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -56,6 +56,12 @@ void handleDspEvents()
|
||||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventRecord) );
|
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventRecord) );
|
||||||
//jack->setRecord( ev.track, ev.record );
|
//jack->setRecord( ev.track, ev.record );
|
||||||
} break; }
|
} break; }
|
||||||
|
case Event::LOOPER_STATE: {
|
||||||
|
if ( availableRead >= sizeof(EventLooperState) ) {
|
||||||
|
EventLooperState ev;
|
||||||
|
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventLooperState) );
|
||||||
|
jack->setLooperState( 0, ev.state );
|
||||||
|
} break; }
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
// just do nothing
|
// just do nothing
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
#ifndef LUPPP_G_TRACK_H
|
#ifndef LUPPP_G_TRACK_H
|
||||||
#define LUPPP_G_TRACK_H
|
#define LUPPP_G_TRACK_H
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include <FL/Fl.H>
|
#include <FL/Fl.H>
|
||||||
#include <FL/Fl_Group.H>
|
#include <FL/Fl_Group.H>
|
||||||
#include <FL/Fl_Slider.H>
|
#include <FL/Fl_Slider.H>
|
||||||
|
@ -10,6 +12,26 @@
|
||||||
#include "avtk/avtk_button.h"
|
#include "avtk/avtk_button.h"
|
||||||
#include "avtk/avtk_background.h"
|
#include "avtk/avtk_background.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "eventhandler.hxx"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
static void button_callback(Fl_Widget *w, void *data) {
|
||||||
|
cout << "Button " << w->label() << " clicked" << endl;
|
||||||
|
|
||||||
|
if ( strcmp( w->label() , "Rec" ) == 0 )
|
||||||
|
{
|
||||||
|
EventLooperState e = EventLooperState(Looper::STATE_RECORDING);
|
||||||
|
writeToDspRingbuffer( &e );
|
||||||
|
}
|
||||||
|
else if ( strcmp( w->label() , "Play" ) == 0 )
|
||||||
|
{
|
||||||
|
EventLooperState e = EventLooperState(Looper::STATE_PLAYING);
|
||||||
|
writeToDspRingbuffer( &e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class GTrack : public Fl_Group
|
class GTrack : public Fl_Group
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -18,8 +40,8 @@ class GTrack : public Fl_Group
|
||||||
title( strdup(l) ),
|
title( strdup(l) ),
|
||||||
bg( x, y , w, h, title ),
|
bg( x, y , w, h, title ),
|
||||||
|
|
||||||
button1(x + 5, y + 24, 18, 18,"1"),
|
button1(x + 5, y + 24, 100, 18,"Rec"),
|
||||||
button2(x + 5, y + 44, 18, 18,"2"),
|
button2(x + 5, y + 44, 100, 18,"Play"),
|
||||||
button3(x + 5, y + 64, 18, 18,"3"),
|
button3(x + 5, y + 64, 18, 18,"3"),
|
||||||
button4(x + 5, y + 84, 18, 18,"4"),
|
button4(x + 5, y + 84, 18, 18,"4"),
|
||||||
button5(x + 5, y +104, 18, 18,"5"),
|
button5(x + 5, y +104, 18, 18,"5"),
|
||||||
|
@ -29,6 +51,9 @@ class GTrack : public Fl_Group
|
||||||
dial2(x+45, y +155, 24, 24, "B"),
|
dial2(x+45, y +155, 24, 24, "B"),
|
||||||
dial3(x+75, y +155, 24, 24, "C")
|
dial3(x+75, y +155, 24, 24, "C")
|
||||||
{
|
{
|
||||||
|
button1.callback( button_callback, 0 );
|
||||||
|
button2.callback( button_callback, 0 );
|
||||||
|
|
||||||
end(); // close the group
|
end(); // close the group
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,8 @@ Jack::Jack()
|
||||||
{
|
{
|
||||||
cerr << "Jack() error setting process callback" << endl;
|
cerr << "Jack() error setting process callback" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loopers.push_back( new Looper() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,6 +61,9 @@ int Jack::process (jack_nframes_t nframes)
|
||||||
// pre-zero output buffers
|
// pre-zero output buffers
|
||||||
memset( buffers.audio[Buffers::MASTER_OUTPUT], 0, sizeof(float) * nframes );
|
memset( buffers.audio[Buffers::MASTER_OUTPUT], 0, sizeof(float) * nframes );
|
||||||
|
|
||||||
|
loopers.at(0)->process(nframes, &buffers );
|
||||||
|
|
||||||
|
/*
|
||||||
float* input = buffers.audio[Buffers::MASTER_INPUT];
|
float* input = buffers.audio[Buffers::MASTER_INPUT];
|
||||||
float* output = buffers.audio[Buffers::MASTER_OUTPUT];
|
float* output = buffers.audio[Buffers::MASTER_OUTPUT];
|
||||||
|
|
||||||
|
@ -66,6 +71,7 @@ int Jack::process (jack_nframes_t nframes)
|
||||||
{
|
{
|
||||||
*output++ = *input++;
|
*output++ = *input++;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
23
src/jack.hxx
23
src/jack.hxx
|
@ -11,24 +11,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Library
|
// Library
|
||||||
|
#include <vector>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <jack/jack.h>
|
#include <jack/jack.h>
|
||||||
#include <jack/midiport.h>
|
#include <jack/midiport.h>
|
||||||
|
|
||||||
class Buffers
|
#include "looper.hxx"
|
||||||
{
|
|
||||||
public:
|
|
||||||
Buffers()
|
|
||||||
{
|
|
||||||
memset( audio, 0, sizeof(float*)*2);
|
|
||||||
}
|
|
||||||
float* audio[2];
|
|
||||||
|
|
||||||
enum BUFFER {
|
using namespace std;
|
||||||
MASTER_OUTPUT = 0,
|
|
||||||
MASTER_INPUT,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
class Jack
|
class Jack
|
||||||
{
|
{
|
||||||
|
@ -39,9 +29,16 @@ class Jack
|
||||||
int getBuffersize();
|
int getBuffersize();
|
||||||
int getSamplerate();
|
int getSamplerate();
|
||||||
|
|
||||||
|
void setLooperState(int, Looper::State s)
|
||||||
|
{
|
||||||
|
loopers.at(0)->setState(s);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Buffers buffers;
|
Buffers buffers;
|
||||||
|
|
||||||
|
vector<Looper*> loopers;
|
||||||
|
|
||||||
int nframes;
|
int nframes;
|
||||||
int samplerate;
|
int samplerate;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
|
||||||
|
#ifndef LUPPP_LOOPER_H
|
||||||
|
#define LUPPP_LOOPER_H
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "buffers.hxx"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class Looper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum State {
|
||||||
|
STATE_PLAYING = 0,
|
||||||
|
STATE_RECORDING,
|
||||||
|
};
|
||||||
|
|
||||||
|
Looper() :
|
||||||
|
state(STATE_PLAYING),
|
||||||
|
endPoint (0),
|
||||||
|
playPoint (0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void setState(State s)
|
||||||
|
{
|
||||||
|
// quantize?!
|
||||||
|
state = s;
|
||||||
|
|
||||||
|
if ( state == STATE_PLAYING ) // setup PLAY
|
||||||
|
{
|
||||||
|
endPoint = lastWrittenSampleIndex;
|
||||||
|
playPoint = 0;
|
||||||
|
cout << "State = PLAYING, endPoint = " << endPoint << endl;
|
||||||
|
}
|
||||||
|
else if ( state == STATE_RECORDING ) // setup REC
|
||||||
|
{
|
||||||
|
cout << "State = RECORDING" << endl;
|
||||||
|
playPoint = 0;
|
||||||
|
endPoint = 0;
|
||||||
|
lastWrittenSampleIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void process(int nframes, Buffers* buffers)
|
||||||
|
{
|
||||||
|
float* in = buffers->audio[Buffers::MASTER_INPUT];
|
||||||
|
float* out = buffers->audio[Buffers::MASTER_OUTPUT];
|
||||||
|
|
||||||
|
if ( state == STATE_PLAYING )
|
||||||
|
{
|
||||||
|
for(int i = 0; i < nframes; i++)
|
||||||
|
{
|
||||||
|
if ( playPoint >= endPoint )
|
||||||
|
{
|
||||||
|
playPoint = 0;
|
||||||
|
}
|
||||||
|
out[i] += sample[playPoint++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if ( state == STATE_RECORDING )
|
||||||
|
{
|
||||||
|
for(int i = 0; i < nframes; i++)
|
||||||
|
{
|
||||||
|
if ( lastWrittenSampleIndex < 44100 * 60 )
|
||||||
|
{
|
||||||
|
sample[lastWrittenSampleIndex++] = in[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
State state;
|
||||||
|
|
||||||
|
int endPoint, playPoint, lastWrittenSampleIndex;
|
||||||
|
float sample[44100*60];
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LUPPP_LOOPER_H
|
Loading…
Reference in New Issue