mirror of
https://github.com/vale981/openAV-Luppp
synced 2025-03-04 16:51:37 -05:00
-Added Controller subfolder, working on MIDI mapping / binding and feedback functionality
This commit is contained in:
parent
6e861dd4c1
commit
370815e7aa
8 changed files with 123 additions and 20 deletions
|
@ -12,13 +12,15 @@ class Buffers
|
|||
{
|
||||
memset( audio, 0, sizeof(float*)*2);
|
||||
}
|
||||
float* audio[2];
|
||||
char* midi [1];
|
||||
float* audio[32];
|
||||
unsigned char* midi [32];
|
||||
|
||||
enum BUFFER {
|
||||
MASTER_OUTPUT = 0,
|
||||
MASTER_INPUT,
|
||||
MASTER_MIDI_INPUT,
|
||||
APC_INPUT,
|
||||
APC_OUTPUT,
|
||||
};
|
||||
|
||||
// Jack details
|
||||
|
|
0
src/controller/apc.cxx
Normal file
0
src/controller/apc.cxx
Normal file
22
src/controller/apc.hxx
Normal file
22
src/controller/apc.hxx
Normal file
|
@ -0,0 +1,22 @@
|
|||
|
||||
|
||||
#ifndef LUPPP_APC_H
|
||||
#define LUPPP_APC_H
|
||||
|
||||
#include "controller.hxx"
|
||||
|
||||
class AkaiAPC : public Controller
|
||||
{
|
||||
public:
|
||||
AkaiAPC();
|
||||
|
||||
void mute(int t, bool b);
|
||||
void clip(int t, bool b);
|
||||
|
||||
void record(int t, bool b);
|
||||
|
||||
void volume(int t, float f);
|
||||
};
|
||||
|
||||
#endif // LUPPP_APC_H
|
||||
|
21
src/controller/controller.hxx
Normal file
21
src/controller/controller.hxx
Normal file
|
@ -0,0 +1,21 @@
|
|||
|
||||
|
||||
#ifndef LUPPP_CONTROLLER_H
|
||||
#define LUPPP_CONTROLLER_H
|
||||
|
||||
class Controller
|
||||
{
|
||||
public:
|
||||
Controller();
|
||||
virtual ~Controller();
|
||||
|
||||
virtual void mute(int t, bool b);
|
||||
virtual void clip(int t, bool b);
|
||||
|
||||
virtual void record(int t, bool b);
|
||||
|
||||
virtual void volume(int t, float f);
|
||||
};
|
||||
|
||||
#endif // LUPPP_CONTROLLER_H
|
||||
|
41
src/jack.cxx
41
src/jack.cxx
|
@ -38,6 +38,18 @@ Jack::Jack()
|
|||
JackPortIsInput,
|
||||
0 );
|
||||
|
||||
apcMidiInput = jack_port_register( client,
|
||||
"apc_in",
|
||||
JACK_DEFAULT_MIDI_TYPE,
|
||||
JackPortIsInput,
|
||||
0 );
|
||||
|
||||
apcMidiOutput = jack_port_register( client,
|
||||
"apc_out",
|
||||
JACK_DEFAULT_MIDI_TYPE,
|
||||
JackPortIsOutput,
|
||||
0 );
|
||||
|
||||
if ( jack_set_process_callback( client,
|
||||
static_process,
|
||||
static_cast<void*>(this)) )
|
||||
|
@ -79,7 +91,13 @@ int Jack::process (jack_nframes_t nframes)
|
|||
// get buffers
|
||||
buffers.audio[Buffers::MASTER_INPUT] = (float*)jack_port_get_buffer( masterInput , nframes);
|
||||
buffers.audio[Buffers::MASTER_OUTPUT] = (float*)jack_port_get_buffer( masterOutput, nframes);
|
||||
buffers.midi[Buffers::MASTER_MIDI_INPUT]= (char*) jack_port_get_buffer( masterMidiInput, nframes );
|
||||
buffers.midi[Buffers::MASTER_MIDI_INPUT]= (unsigned char*) jack_port_get_buffer( masterMidiInput, nframes );
|
||||
buffers.midi[Buffers::APC_INPUT] = (unsigned char*) jack_port_get_buffer( apcMidiInput , nframes );
|
||||
buffers.midi[Buffers::APC_OUTPUT] = (unsigned char*) jack_port_get_buffer( apcMidiOutput , nframes );
|
||||
|
||||
// pre-zero output buffers
|
||||
memset( buffers.audio[Buffers::MASTER_OUTPUT], 0, sizeof(float) * nframes );
|
||||
jack_midi_clear_buffer( buffers.midi[Buffers::APC_OUTPUT] );
|
||||
|
||||
// process incoming MIDI
|
||||
jack_midi_event_t in_event;
|
||||
|
@ -95,14 +113,11 @@ int Jack::process (jack_nframes_t nframes)
|
|||
|
||||
// check each looper for MIDI match
|
||||
for(int i = 0; i < loopers.size(); i++)
|
||||
loopers.at(i)->midi( (char*)in_event.buffer );
|
||||
loopers.at(i)->midi( (unsigned char*)&in_event.buffer[0] );
|
||||
|
||||
masterMidiInputIndex++;
|
||||
}
|
||||
|
||||
// pre-zero output buffers
|
||||
memset( buffers.audio[Buffers::MASTER_OUTPUT], 0, sizeof(float) * nframes );
|
||||
|
||||
for(uint i = 0; i < loopers.size(); i++)
|
||||
loopers.at(i)->process( nframes, &buffers );
|
||||
|
||||
|
@ -132,6 +147,22 @@ int Jack::getSamplerate()
|
|||
return jack_get_sample_rate( client );
|
||||
}
|
||||
|
||||
void Jack::writeApcOutput( unsigned char* data )
|
||||
{
|
||||
void* apcOutput = buffers.midi[Buffers::APC_OUTPUT];
|
||||
|
||||
unsigned char* buf = jack_midi_event_reserve( apcOutput, 0, 3);
|
||||
if( buf )
|
||||
{
|
||||
memcpy( buf, data, sizeof( unsigned char ) * 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
EventGuiPrint e( "__FILE__ __LINE__ Buffer not valid" );
|
||||
writeToGuiRingbuffer( &e );
|
||||
}
|
||||
}
|
||||
|
||||
int Jack::timebase(jack_transport_state_t state,
|
||||
jack_nframes_t nframes,
|
||||
jack_position_t* pos,
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include "metronome.hxx"
|
||||
#include "timemanager.hxx"
|
||||
|
||||
#include "controller/apc.hxx"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class Jack
|
||||
|
@ -44,12 +46,16 @@ class Jack
|
|||
|
||||
Metronome* getMetronome(){return &metronome;}
|
||||
TimeManager* getTimeManager(){return &timeManager;}
|
||||
|
||||
void writeApcOutput( unsigned char* data );
|
||||
|
||||
private:
|
||||
Buffers buffers;
|
||||
Metronome metronome;
|
||||
TimeManager timeManager;
|
||||
|
||||
vector<Controller*> controllers;
|
||||
|
||||
vector<Looper*> loopers;
|
||||
|
||||
int nframes;
|
||||
|
@ -61,6 +67,8 @@ class Jack
|
|||
jack_port_t* masterInput;
|
||||
jack_port_t* masterOutput;
|
||||
|
||||
jack_port_t* apcMidiInput;
|
||||
jack_port_t* apcMidiOutput;
|
||||
jack_port_t* masterMidiInput;
|
||||
|
||||
// JACK callbacks
|
||||
|
|
|
@ -37,8 +37,25 @@ Looper::Looper(int t) :
|
|||
fRec0[i] = 0;
|
||||
}
|
||||
|
||||
void Looper::midi(char* data)
|
||||
void Looper::midi(unsigned char* data)
|
||||
{
|
||||
if ( data[0] - 144 == track )
|
||||
{
|
||||
switch ( data[1] )
|
||||
{
|
||||
case 48: setState( STATE_RECORD_QUEUED ); break;
|
||||
case 53: setState( STATE_PLAY_QUEUED ); break;
|
||||
case 52: setState( STATE_STOPPED ); break;
|
||||
}
|
||||
}
|
||||
else if ( data[0] - 128 == track )
|
||||
{
|
||||
switch ( data[1] )
|
||||
{
|
||||
case 48: setState( STATE_STOP_QUEUED );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -49,15 +66,17 @@ void Looper::setState(State s)
|
|||
stopRecordOnBar = true;
|
||||
}
|
||||
|
||||
// ensure we're not setting eg PLAY_QUEUED, if we're already PLAYING
|
||||
if ( static_cast<int>(s) != static_cast<int>(state) + 1)
|
||||
state = s;
|
||||
|
||||
if (state == STATE_RECORD_QUEUED )
|
||||
{
|
||||
state = s;
|
||||
|
||||
if (state == STATE_RECORDING)
|
||||
{
|
||||
numBeats = 0;
|
||||
}
|
||||
numBeats = 0;
|
||||
unsigned char data[3];
|
||||
data[0] == 144 + track;
|
||||
data[1] == 48; // record LED
|
||||
data[2] == 127;
|
||||
jack->writeApcOutput( &data[0] );
|
||||
cout << "wrote to APC" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,7 +165,7 @@ void Looper::bar()
|
|||
playPoint = 0;
|
||||
endPoint = lastWrittenSampleIndex;
|
||||
}
|
||||
if ( state == STATE_RECORD_QUEUED && state != STATE_RECORDING )
|
||||
if ( state == STATE_RECORD_QUEUED )
|
||||
{
|
||||
EventGuiPrint e( "Looper Q->Recording" );
|
||||
writeToGuiRingbuffer( &e );
|
||||
|
@ -156,7 +175,7 @@ void Looper::bar()
|
|||
endPoint = 0;
|
||||
lastWrittenSampleIndex = 0;
|
||||
}
|
||||
if ( state == STATE_PLAY_QUEUED && state != STATE_STOPPED )
|
||||
if ( state == STATE_PLAY_QUEUED )
|
||||
{
|
||||
EventGuiPrint e( "Looper Q->Stopped" );
|
||||
writeToGuiRingbuffer( &e );
|
||||
|
|
|
@ -24,7 +24,7 @@ class Looper : public Observer // for notifications
|
|||
|
||||
Looper(int t);
|
||||
|
||||
void midi(char* data);
|
||||
void midi(unsigned char* data);
|
||||
|
||||
void bar();
|
||||
void beat();
|
||||
|
@ -37,7 +37,7 @@ class Looper : public Observer // for notifications
|
|||
void process(int nframes, Buffers* buffers);
|
||||
|
||||
private:
|
||||
int track;
|
||||
const int track;
|
||||
State state;
|
||||
|
||||
int fpb;
|
||||
|
|
Loading…
Add table
Reference in a new issue