commit a29b8c720c156c309b59b51738c9fcdc4b3310a1 Author: Harry van Haaren Date: Sat Apr 20 11:37:36 2013 +0100 -Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6a4a812 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.waf* +.lock* +.build* + +planning/* diff --git a/README b/README new file mode 100644 index 0000000..995ac27 --- /dev/null +++ b/README @@ -0,0 +1 @@ + Repo for Luppp5 diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..01bb359 --- /dev/null +++ b/run.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +cd .build/ + +./luppp5 diff --git a/src/event.hxx b/src/event.hxx new file mode 100644 index 0000000..49ce3d3 --- /dev/null +++ b/src/event.hxx @@ -0,0 +1,97 @@ + +#ifndef LUPPP_EVENT_H +#define LUPPP_EVENT_H + +#include + +/* + event.hxx + + This file provides declarations for each type of event that the engine uses. + +*/ + +namespace Event +{ + enum { + LOAD_SAMPLE = 0, + PLAY_SAMPLE, + MASTER_VOL, + RECORD, + }; +}; + +using namespace Event; + +class AudioBuffer; + +class EventBase +{ + public: + virtual ~EventBase() {} + + virtual int type() = 0; + virtual uint32_t size() = 0; +}; + +class EventMasterVol : public EventBase +{ + public: + int type() { return int(MASTER_VOL); } + uint32_t size() { return sizeof(EventMasterVol); } + float vol; + + EventMasterVol(float v) + { + vol = v; + } +}; + +class EventLoadSample : public EventBase +{ + public: + int type() { return int(LOAD_SAMPLE); } + uint32_t size() { return sizeof(EventLoadSample); } + + AudioBuffer* audioBufferPtr; + + EventLoadSample(AudioBuffer* a) + { + audioBufferPtr = a; + } +}; + +class EventPlaySample : public EventBase +{ + public: + int type() { return int(PLAY_SAMPLE); } + uint32_t size() { return sizeof(EventPlaySample); } + + int track, bufferID; + + EventPlaySample(int t, int id) + { + track = t; + bufferID = id; + } +}; + +class EventRecord : public EventBase +{ + public: + int type() { return int(RECORD); } + uint32_t size() { return sizeof(EventRecord); } + + int track; + bool record; + + EventRecord(int t, bool b) + { + track = t; + record = b; + } +}; + + +#endif // LUPPP_EVENT_H + diff --git a/src/eventhandler.hxx b/src/eventhandler.hxx new file mode 100644 index 0000000..94c1a83 --- /dev/null +++ b/src/eventhandler.hxx @@ -0,0 +1,22 @@ + +#ifndef LUPPP_EVENT_HANDLER_H +#define LUPPP_EVENT_HANDLER_H + +#include + +extern char* processDspMem; +extern char* processOscMem; + +extern jack_ringbuffer_t* rbToDsp; +//extern jack_ringbuffer_t* ringbufferDspToGui; + +// to process events in the ringbuffer +extern void handleDspEvents(); +//extern void handleGuiEvents(); + +// to write events to the ringbuffer +extern void writeToDspRingbuffer(EventBase* e); +//extern void writeToGuiRingbuffer(EventBase* e); + +#endif // LUPPP_EVENT_HANDLER_H + diff --git a/src/eventhandlerdsp.cxx b/src/eventhandlerdsp.cxx new file mode 100644 index 0000000..f936428 --- /dev/null +++ b/src/eventhandlerdsp.cxx @@ -0,0 +1,90 @@ + +#ifndef LUPPP_EVENT_HANDLER_DSP_H +#define LUPPP_EVENT_HANDLER_DSP_H + + +// Library +#include +#include +#include + +// Internal +#include "jack.hxx" +#include "event.hxx" +#include "eventhandler.hxx" + +using namespace std; + +extern Jack* jack; + +extern void handleDspEvents() +{ + uint availableRead = jack_ringbuffer_read_space( rbToDsp ); + + while ( availableRead >= sizeof(EventBase) ) + { + jack_ringbuffer_peek( rbToDsp, (char*)processDspMem, sizeof(EventBase) ); + + EventBase* e = (EventBase*)processDspMem; + + // recheck the size against the actual event size + if ( availableRead >= e->size() ) + { + switch ( e->type() ) + { + case Event::MASTER_VOL: { + if ( availableRead >= sizeof(EventMasterVol) ) { + EventMasterVol ev(0); + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMasterVol) ); + //jack->masterVolume = ev.vol; + } break; } + case Event::LOAD_SAMPLE: { + if ( availableRead >= sizeof(EventLoadSample) ) { + EventLoadSample ev(0); + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventLoadSample) ); + //jack->addAudioBuffer( ev.audioBufferPtr ); + } break; } + case Event::PLAY_SAMPLE: { + if ( availableRead >= sizeof(EventPlaySample) ) { + EventPlaySample ev(0,0); + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventPlaySample) ); + //jack->setPlayBuffer( ev.track, ev.bufferID ); + } break; } + case Event::RECORD: { + if ( availableRead >= sizeof(EventRecord) ) { + EventRecord ev(0,0); + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventRecord) ); + //jack->setRecord( ev.track, ev.record ); + } break; } + default: + { + // just do nothing + break; + } + } + } + else + { + // next call will get the half-written event + return; + } + + // update available read, and loop over events + availableRead = jack_ringbuffer_read_space( rbToDsp ); + } +} + +void writeToDspRingbuffer(EventBase* e) +{ + if ( jack_ringbuffer_write_space(rbToDsp) >= e->size() ) + { + jack_ringbuffer_write( rbToDsp, (const char*)e, e->size() ); + } + else + { + cout << "->DSP ringbuffer full!" << endl; + } +} + +#endif // LUPPP_EVENT_HANDLER_DSP_H + diff --git a/src/jack.cxx b/src/jack.cxx new file mode 100644 index 0000000..9e6b89e --- /dev/null +++ b/src/jack.cxx @@ -0,0 +1,102 @@ + +#include "jack.hxx" + +#include +#include +#include + + +using namespace std; + +extern int jackSamplerate; + +Jack::Jack() +{ + // open the client + client = jack_client_open ( "Luppp", JackNullOption , 0 , 0 ); + + nframes = jack_get_buffer_size( client ); + samplerate = jack_get_sample_rate( client ); + + masterOutput = jack_port_register( client, + "master_out", + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsOutput, + 0 ); + + masterInput = jack_port_register( client, + "master_in", + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsInput, + 0 ); + + if ( jack_set_process_callback( client, + static_process, + static_cast(this)) ) + { + cerr << "Jack() error setting process callback" << endl; + } +} + + +void Jack::activate() +{ + jack_activate( client ); +} + + +int Jack::process (jack_nframes_t nframes) +{ + // update values from the ringbuffer + //processDsp(); + + // 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); + + // pre-zero output buffers + memset( buffers.audio[Buffers::MASTER_OUTPUT], 0, sizeof(float) * nframes ); + + float* input = buffers.audio[Buffers::MASTER_INPUT]; + float* output = buffers.audio[Buffers::MASTER_OUTPUT]; + + for(uint i = 0; i < nframes; i++) + { + *output = *input; + } + + return false; +} + +int Jack::getBuffersize() +{ + return jack_get_buffer_size( client ); +} + +int Jack::getSamplerate() +{ + return jack_get_sample_rate( client ); +} + +int Jack::timebase(jack_transport_state_t, + jack_nframes_t, + jack_position_t*, + int) +{ + return 0; +} + +int Jack::static_process(jack_nframes_t nframes, void *instance) +{ + return static_cast(instance)->process(nframes); +} + +int Jack::static_timebase(jack_transport_state_t state, + jack_nframes_t nframes, + jack_position_t* pos, + int newPos, + void* instance) +{ + return static_cast(instance)->timebase(state,nframes, pos, newPos ); +} + diff --git a/src/jack.hxx b/src/jack.hxx new file mode 100644 index 0000000..6627702 --- /dev/null +++ b/src/jack.hxx @@ -0,0 +1,74 @@ + +#ifndef LUPPP_JACK_H +#define LUPPP_JACK_H + +/* + jack.hxx + + This code contains the JACK client. + It allows reading / writing of audio / midi. + +*/ + +// Library +#include +#include +#include + +class Buffers +{ + public: + Buffers() + { + memset( audio, 0, sizeof(float*)*2); + } + float* audio[2]; + + enum BUFFER { + MASTER_OUTPUT = 0, + MASTER_INPUT, + }; +}; + +class Jack +{ + public: + Jack(); + + void activate(); + int getBuffersize(); + int getSamplerate(); + + private: + Buffers buffers; + + int nframes; + int samplerate; + + // JACK member variables + jack_client_t* client; + + jack_port_t* masterInput; + jack_port_t* masterOutput; + + // JACK callbacks + int process (jack_nframes_t); + + int timebase(jack_transport_state_t, + jack_nframes_t, + jack_position_t*, + int ); + + // static JACK callbacks + static int static_process (jack_nframes_t, void *); + + static int static_timebase (jack_transport_state_t, + jack_nframes_t, + jack_position_t*, + int, + void* ); + +}; + +#endif // LUPPP_JACK_H + diff --git a/src/main.cxx b/src/main.cxx new file mode 100644 index 0000000..ec96445 --- /dev/null +++ b/src/main.cxx @@ -0,0 +1,31 @@ + + +// Library +#include +#include + +#include + +// Internal +#include "jack.hxx" + + +char* processDspMem = 0; +char* processOscMem = 0; + +jack_ringbuffer_t* rbToDsp = 0; +jack_ringbuffer_t* rbToGui = 0; + +Jack* jack = 0; + +int main() +{ + + jack = new Jack(); + + jack->activate(); + + sleep(10); + + +} diff --git a/waf b/waf new file mode 100755 index 0000000..30d8a7f Binary files /dev/null and b/waf differ diff --git a/wscript b/wscript new file mode 100644 index 0000000..9121fa6 --- /dev/null +++ b/wscript @@ -0,0 +1,26 @@ +#! /usr/bin/env python + +VERSION='5.0.0' +APPNAME='Luppp' + +top = '.' +out = '.build' + +def options(opt): + opt.load('compiler_cxx') + +def configure(conf): + conf.load('compiler_cxx') + conf.env.append_value('CXXFLAGS', ['-g', '-Wall']) #'-O2' + conf.check_cfg(package='jack',at_least_version='0.118',args='--cflags --libs',uselib_store='JACK') + #conf.check_cfg(package='lilv-0',at_least_version='1.0',args='--cflags --libs',uselib_store='LILV') + #conf.check_cfg(package='sndfile',at_least_version='1.0',args='--cflags --libs',uselib_store='SNDFILE') + +def build(bld): + + sources = ['src/main.cxx', + 'src/jack.cxx', + 'src/eventhandlerdsp.cxx'] + + bld.program(source = sources, target='luppp5', use='JACK') +