diff --git a/src/buffers.hxx b/src/buffers.hxx index 056513b..c59c603 100644 --- a/src/buffers.hxx +++ b/src/buffers.hxx @@ -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 diff --git a/src/controller/apc.cxx b/src/controller/apc.cxx new file mode 100644 index 0000000..e69de29 diff --git a/src/controller/apc.hxx b/src/controller/apc.hxx new file mode 100644 index 0000000..779c85c --- /dev/null +++ b/src/controller/apc.hxx @@ -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 + diff --git a/src/controller/controller.hxx b/src/controller/controller.hxx new file mode 100644 index 0000000..f4253a8 --- /dev/null +++ b/src/controller/controller.hxx @@ -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 + diff --git a/src/jack.cxx b/src/jack.cxx index f11e117..5d69d4f 100644 --- a/src/jack.cxx +++ b/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(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, diff --git a/src/jack.hxx b/src/jack.hxx index c40ba31..de823df 100644 --- a/src/jack.hxx +++ b/src/jack.hxx @@ -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 controllers; + vector 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 diff --git a/src/looper.cxx b/src/looper.cxx index b8d5b0a..99029eb 100644 --- a/src/looper.cxx +++ b/src/looper.cxx @@ -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(s) != static_cast(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 ); diff --git a/src/looper.hxx b/src/looper.hxx index ace3334..34f9b98 100644 --- a/src/looper.hxx +++ b/src/looper.hxx @@ -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;