mirror of
https://github.com/vale981/openAV-Luppp
synced 2025-03-05 09:01:39 -05:00
-Working on sample loading, most of infrastructure in place, need to send event
This commit is contained in:
parent
1120f3782b
commit
8eec3e1426
11 changed files with 159 additions and 21 deletions
54
src/audiobuffer.hxx
Normal file
54
src/audiobuffer.hxx
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
|
||||||
|
#ifndef LUPPP_AUDIOBUFFER_H
|
||||||
|
#define LUPPP_AUDIOBUFFER_H
|
||||||
|
|
||||||
|
// System
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// AudioBuffer stores float samples in a big vector. The vector can be
|
||||||
|
// accessed only by const reference, so its state is immutable
|
||||||
|
class AudioBuffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AudioBuffer()
|
||||||
|
{
|
||||||
|
ID = privateID++;
|
||||||
|
}
|
||||||
|
~AudioBuffer();
|
||||||
|
|
||||||
|
int getID()
|
||||||
|
{
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getBeats()
|
||||||
|
{
|
||||||
|
return numBeats;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setBeats(int b)
|
||||||
|
{
|
||||||
|
numBeats = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<float>& get()
|
||||||
|
{
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nonRtSetSample(std::vector<float>& sample)
|
||||||
|
{
|
||||||
|
buffer.swap(sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static int privateID;
|
||||||
|
int ID;
|
||||||
|
|
||||||
|
int numBeats;
|
||||||
|
|
||||||
|
std::vector<float> buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -21,6 +21,7 @@ namespace Event
|
||||||
MASTER_VOL,
|
MASTER_VOL,
|
||||||
RECORD,
|
RECORD,
|
||||||
|
|
||||||
|
LOOPER_LOAD,
|
||||||
LOOPER_STATE,
|
LOOPER_STATE,
|
||||||
LOOPER_PROGRESS,
|
LOOPER_PROGRESS,
|
||||||
LOOPER_LOOP_LENGTH,
|
LOOPER_LOOP_LENGTH,
|
||||||
|
@ -96,18 +97,18 @@ class EventLooperLoopLength : public EventBase
|
||||||
EventLooperLoopLength(int t, float s) : track(t), scale(s){}
|
EventLooperLoopLength(int t, float s) : track(t), scale(s){}
|
||||||
};
|
};
|
||||||
|
|
||||||
class EventLoadSample : public EventBase
|
class EventLooperLoad : public EventBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int type() { return int(LOAD_SAMPLE); }
|
int type() { return int(LOAD_SAMPLE); }
|
||||||
uint32_t size() { return sizeof(EventLoadSample); }
|
uint32_t size() { return sizeof(EventLooperLoad); }
|
||||||
|
|
||||||
AudioBuffer* audioBufferPtr;
|
int track;
|
||||||
|
int clip;
|
||||||
|
AudioBuffer* audioBuffer;
|
||||||
|
|
||||||
EventLoadSample(AudioBuffer* a)
|
EventLooperLoad(){}
|
||||||
{
|
EventLooperLoad(int t, int c, AudioBuffer* ab) : track(t), clip(c), audioBuffer(ab) {}
|
||||||
audioBufferPtr = a;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class EventPlaySample : public EventBase
|
class EventPlaySample : public EventBase
|
||||||
|
|
|
@ -38,11 +38,12 @@ void handleDspEvents()
|
||||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMasterVol) );
|
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMasterVol) );
|
||||||
//jack->masterVolume = ev.vol;
|
//jack->masterVolume = ev.vol;
|
||||||
} break; }
|
} break; }
|
||||||
case Event::LOAD_SAMPLE: {
|
case Event::LOOPER_LOAD: {
|
||||||
if ( availableRead >= sizeof(EventLoadSample) ) {
|
if ( availableRead >= sizeof(EventLooperLoad) ) {
|
||||||
EventLoadSample ev(0);
|
EventLooperLoad ev;
|
||||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventLoadSample) );
|
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventLooperLoad) );
|
||||||
//jack->addAudioBuffer( ev.audioBufferPtr );
|
Looper* l = jack->getLooper( ev.track );
|
||||||
|
|
||||||
} break; }
|
} break; }
|
||||||
case Event::PLAY_SAMPLE: {
|
case Event::PLAY_SAMPLE: {
|
||||||
if ( availableRead >= sizeof(EventPlaySample) ) {
|
if ( availableRead >= sizeof(EventPlaySample) ) {
|
||||||
|
|
|
@ -40,12 +40,6 @@ void handleGuiEvents()
|
||||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMasterVol) );
|
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventMasterVol) );
|
||||||
//jack->masterVolume = ev.vol;
|
//jack->masterVolume = ev.vol;
|
||||||
} break; }
|
} break; }
|
||||||
case Event::LOAD_SAMPLE: {
|
|
||||||
if ( availableRead >= sizeof(EventLoadSample) ) {
|
|
||||||
EventLoadSample ev(0);
|
|
||||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventLoadSample) );
|
|
||||||
//jack->addAudioBuffer( ev.audioBufferPtr );
|
|
||||||
} break; }
|
|
||||||
case Event::PLAY_SAMPLE: {
|
case Event::PLAY_SAMPLE: {
|
||||||
if ( availableRead >= sizeof(EventPlaySample) ) {
|
if ( availableRead >= sizeof(EventPlaySample) ) {
|
||||||
EventPlaySample ev(0,0);
|
EventPlaySample ev(0,0);
|
||||||
|
|
|
@ -8,16 +8,41 @@
|
||||||
#include <FL/Fl_Group.H>
|
#include <FL/Fl_Group.H>
|
||||||
#include <FL/Fl_Slider.H>
|
#include <FL/Fl_Slider.H>
|
||||||
#include <FL/Fl_Progress.H>
|
#include <FL/Fl_Progress.H>
|
||||||
|
#include <FL/Fl_Native_File_Chooser.H>
|
||||||
|
|
||||||
#include "avtk/avtk_dial.h"
|
#include "avtk/avtk_dial.h"
|
||||||
#include "avtk/avtk_button.h"
|
#include "avtk/avtk_button.h"
|
||||||
#include "avtk/avtk_background.h"
|
#include "avtk/avtk_background.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "worker.hxx"
|
||||||
|
#include "audiobuffer.hxx"
|
||||||
#include "eventhandler.hxx"
|
#include "eventhandler.hxx"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
static string choose_file()
|
||||||
|
{
|
||||||
|
string path;
|
||||||
|
Fl_Native_File_Chooser fnfc;
|
||||||
|
fnfc.title("Pick a file");
|
||||||
|
fnfc.type(Fl_Native_File_Chooser::BROWSE_FILE);
|
||||||
|
//fnfc.filter("Wav\t*.wav");
|
||||||
|
fnfc.directory( getenv("HOME") ); // default directory to use
|
||||||
|
// Show native chooser
|
||||||
|
switch ( fnfc.show() ) {
|
||||||
|
case -1: printf("ERROR: %s\n", fnfc.errmsg()); break; // ERROR
|
||||||
|
case 1: printf("CANCEL\n"); break; // CANCEL
|
||||||
|
default: printf("Loading directory: %s\n", fnfc.filename());
|
||||||
|
|
||||||
|
// update path and load it
|
||||||
|
path = fnfc.filename();
|
||||||
|
|
||||||
|
break; // FILE CHOSEN
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
static void gtrack_button_callback(Fl_Widget *w, void *data) {
|
static void gtrack_button_callback(Fl_Widget *w, void *data) {
|
||||||
int track = 0;
|
int track = 0;
|
||||||
if ( data )
|
if ( data )
|
||||||
|
@ -49,6 +74,13 @@ static void gtrack_button_callback(Fl_Widget *w, void *data) {
|
||||||
EventLooperLoopLength e = EventLooperLoopLength(track, 0.5);
|
EventLooperLoopLength e = EventLooperLoopLength(track, 0.5);
|
||||||
writeToDspRingbuffer( &e );
|
writeToDspRingbuffer( &e );
|
||||||
}
|
}
|
||||||
|
else if ( strcmp( w->label() , "Load" ) == 0 )
|
||||||
|
{
|
||||||
|
AudioBuffer* ab = Worker::loadSample( choose_file() );
|
||||||
|
|
||||||
|
EventLooperLoad e = EventLooperLoad( track, 0 , ab );
|
||||||
|
writeToDspRingbuffer( &e );
|
||||||
|
}
|
||||||
else if ( strcmp( w->label() , "Vol" ) == 0 )
|
else if ( strcmp( w->label() , "Vol" ) == 0 )
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -73,7 +105,7 @@ class GTrack : public Fl_Group
|
||||||
button4(x + 5, y + 84, 48, 18,"-"),
|
button4(x + 5, y + 84, 48, 18,"-"),
|
||||||
button5(x +57, y + 84, 48, 18,"+"),
|
button5(x +57, y + 84, 48, 18,"+"),
|
||||||
|
|
||||||
button6(x + 5, y +104, 18, 18,"6"),
|
button6(x + 5, y +104, 100, 18,"Load"),
|
||||||
|
|
||||||
volume(x+55-22, y +175, 34, 34, "Vol"),
|
volume(x+55-22, y +175, 34, 34, "Vol"),
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,12 @@
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "audiobuffer.hxx"
|
||||||
|
|
||||||
// Hack, move to gtrack.cpp
|
// Hack, move to gtrack.cpp
|
||||||
int GTrack::privateID = 0;
|
int GTrack::privateID = 0;
|
||||||
int GMasterTrack::privateID = 0;
|
int GMasterTrack::privateID = 0;
|
||||||
|
int AudioBuffer::privateID = 0;
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,10 @@ class Jack
|
||||||
{
|
{
|
||||||
loopers.at(t)->setLoopLength(l);
|
loopers.at(t)->setLoopLength(l);
|
||||||
}
|
}
|
||||||
|
Looper* getLooper(int t)
|
||||||
|
{
|
||||||
|
return loopers.at(t);
|
||||||
|
}
|
||||||
|
|
||||||
Metronome* getMetronome(){return &metronome;}
|
Metronome* getMetronome(){return &metronome;}
|
||||||
TimeManager* getTimeManager(){return &timeManager;}
|
TimeManager* getTimeManager(){return &timeManager;}
|
||||||
|
|
|
@ -122,6 +122,17 @@ void Looper::updateControllers()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Looper::setSample(int c, int nB, int bS, float* bP)
|
||||||
|
{
|
||||||
|
if ( bS > SAMPLE_SIZE )
|
||||||
|
{
|
||||||
|
EventGuiPrint e( "Looper setSample() size > incoming sample" );
|
||||||
|
writeToGuiRingbuffer( &e );
|
||||||
|
}
|
||||||
|
numBeats = nB;
|
||||||
|
memcpy( &sample[0], bP, bS ); // copy sample data to pre-allocated buffer
|
||||||
|
}
|
||||||
|
|
||||||
void Looper::process(int nframes, Buffers* buffers)
|
void Looper::process(int nframes, Buffers* buffers)
|
||||||
{
|
{
|
||||||
float* in = buffers->audio[Buffers::MASTER_INPUT];
|
float* in = buffers->audio[Buffers::MASTER_INPUT];
|
||||||
|
|
|
@ -26,6 +26,8 @@ class Looper : public Observer // for notifications
|
||||||
|
|
||||||
Looper(int t);
|
Looper(int t);
|
||||||
|
|
||||||
|
void setSample(int c, int nB, int bS, float* bP);
|
||||||
|
|
||||||
void midi(unsigned char* data);
|
void midi(unsigned char* data);
|
||||||
|
|
||||||
void bar();
|
void bar();
|
||||||
|
|
36
src/worker.hxx
Normal file
36
src/worker.hxx
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
|
||||||
|
#ifndef LUPPP_WORKER_H
|
||||||
|
#define LUPPP_WORKER_H
|
||||||
|
|
||||||
|
// Library
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <sndfile.hh>
|
||||||
|
|
||||||
|
#include "audiobuffer.hxx"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace Worker
|
||||||
|
{
|
||||||
|
static AudioBuffer* loadSample( string path )
|
||||||
|
{
|
||||||
|
SndfileHandle infile( path, SFM_READ );
|
||||||
|
|
||||||
|
|
||||||
|
AudioBuffer* ab = new AudioBuffer();
|
||||||
|
|
||||||
|
std::vector<float> buf( infile.frames(), 0.f );
|
||||||
|
|
||||||
|
infile.read( &buf[0] , infile.frames() );
|
||||||
|
|
||||||
|
// read data from file
|
||||||
|
ab->setBeats(4);
|
||||||
|
ab->nonRtSetSample( buf );
|
||||||
|
|
||||||
|
cout << "Worker: loadSample() " << path << " size: " << infile.frames() << endl;
|
||||||
|
return ab;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // LUPPP_WORKER_H
|
4
wscript
4
wscript
|
@ -15,7 +15,7 @@ def configure(conf):
|
||||||
conf.check_cfg(package='ntk',at_least_version='1.3',args='--cflags --libs',uselib_store='NTK')
|
conf.check_cfg(package='ntk',at_least_version='1.3',args='--cflags --libs',uselib_store='NTK')
|
||||||
conf.check_cfg(package='jack',at_least_version='0.118',args='--cflags --libs',uselib_store='JACK')
|
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='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')
|
conf.check_cfg(package='sndfile',at_least_version='1.0',args='--cflags --libs',uselib_store='SNDFILE')
|
||||||
|
|
||||||
def build(bld):
|
def build(bld):
|
||||||
|
|
||||||
|
@ -27,5 +27,5 @@ def build(bld):
|
||||||
'src/eventhandlergui.cxx',
|
'src/eventhandlergui.cxx',
|
||||||
'src/eventhandlerdsp.cxx']
|
'src/eventhandlerdsp.cxx']
|
||||||
|
|
||||||
bld.program(source = sources, target='luppp5', use='JACK NTK')
|
bld.program(source = sources, target='luppp5', use='JACK NTK SNDFILE')
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue