mirror of
https://github.com/vale981/openAV-Luppp
synced 2025-03-05 09:01:39 -05:00
Add records n
beats feature.
This commit is contained in:
parent
e00c403b19
commit
afcda1c8a8
12 changed files with 282 additions and 66 deletions
|
@ -18,12 +18,13 @@
|
|||
|
||||
|
||||
#include "clipselector.hxx"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||
|
||||
#include "../gui.hxx"
|
||||
#define RECORD_BARS_MENU_ITEM(num) { #num, 0, setRecordBarsCb, (void*)num, FL_MENU_RADIO | ((clips[clipNum].getBeatsToRecord() == num*4) ? FL_MENU_VALUE : 0) | (empty ? 0 : FL_MENU_INACTIVE) }
|
||||
#define RECORD_LENGTH_MENU_ITEM(num) {#num, 0, setLengthCb, (void*)num, empty ? FL_MENU_INACTIVE : 0}
|
||||
|
||||
extern Gui* gui;
|
||||
|
||||
|
@ -90,6 +91,34 @@ void ClipSelector::clipName(int clip, std::string name)
|
|||
redraw();
|
||||
}
|
||||
|
||||
void ClipSelector::setClipBeats(int scene, int beats, bool isBeatsToRecord)
|
||||
{
|
||||
clips[scene].setBeats(beats, isBeatsToRecord);
|
||||
redraw();
|
||||
}
|
||||
|
||||
double getCairoTextWith(cairo_t * cr, const char * str)
|
||||
{
|
||||
cairo_text_extents_t ex;
|
||||
cairo_text_extents(cr, str, &ex);
|
||||
return ex.width;
|
||||
}
|
||||
|
||||
void trimStringToFit(cairo_t * cr, std::string * str, double maxWidth)
|
||||
{
|
||||
double ellWidth = getCairoTextWith(cr, "…");
|
||||
double textWidth = getCairoTextWith(cr, str->c_str());
|
||||
|
||||
if(textWidth > maxWidth) {
|
||||
while(textWidth + ellWidth > maxWidth){
|
||||
str->pop_back();
|
||||
textWidth = getCairoTextWith(cr, str->c_str());
|
||||
}
|
||||
|
||||
*str += "…";
|
||||
}
|
||||
}
|
||||
|
||||
void ClipSelector::setSpecial(int scene)
|
||||
{
|
||||
if ( special == -1 && scene == -1 ) {
|
||||
|
@ -196,16 +225,38 @@ void ClipSelector::draw()
|
|||
cairo_line_to( cr, x+clipHeight-1, drawY + clipHeight - 2);
|
||||
cairo_stroke(cr);
|
||||
|
||||
int beatLen = 0;
|
||||
|
||||
// clip bars
|
||||
if(!_master) {
|
||||
const char * bars = clips[i].getBarsText();
|
||||
const char * beats = clips[i].getBeatsText();
|
||||
bool toRecord = clips[i].getBeats() <= 0 && clips[i].getBeatsToRecord() > 0; // If there are BeatsToRecord, but no Beats
|
||||
|
||||
if(strlen(bars)) {
|
||||
if(toRecord) cairo_set_source_rgba(cr, 1.f, 0 / 255.f , 0 / 255.f, 1.f);
|
||||
else cairo_set_source_rgba( cr, 255 / 255.f, 255 / 255.f, 255 / 255.f , 0.9 );
|
||||
|
||||
cairo_move_to( cr, x + clipWidth - 5 - getCairoTextWith(cr, bars), drawY + textHeight - 8);
|
||||
cairo_set_font_size( cr, 11 );
|
||||
cairo_show_text( cr, bars);
|
||||
|
||||
beatLen = getCairoTextWith(cr, beats);
|
||||
cairo_move_to( cr, x + clipWidth - 5 - beatLen, drawY + textHeight + 7);
|
||||
cairo_show_text( cr, beats);
|
||||
}
|
||||
}
|
||||
|
||||
// clip name
|
||||
cairo_move_to( cr, x + clipHeight + 5, drawY + textHeight );
|
||||
cairo_set_source_rgba( cr, 255 / 255.f, 255 / 255.f , 255 / 255.f , 0.9 );
|
||||
cairo_set_font_size( cr, 11 );
|
||||
|
||||
std::string tmp = clips[i].getName().substr(0,8);
|
||||
|
||||
std::string tmp = clips[i].getName();
|
||||
trimStringToFit(cr, &tmp, clipWidth - (clipHeight + 15 + beatLen));
|
||||
cairo_show_text( cr, tmp.c_str() );
|
||||
|
||||
// special indicator?
|
||||
// special indicator
|
||||
if ( i == special ) {
|
||||
cairo_rectangle( cr, x+2, drawY, clipWidth -1, clipHeight - 3 );
|
||||
cairo_set_source_rgba(cr, 0.0, 153 / 255.f, 1.0, alpha);
|
||||
|
@ -232,7 +283,43 @@ void ClipSelector::resize(int X, int Y, int W, int H)
|
|||
redraw();
|
||||
}
|
||||
|
||||
void setRecordBarsCb(Fl_Widget *w, void* data)
|
||||
{
|
||||
if(!w || !data)
|
||||
return;
|
||||
|
||||
ClipSelector *track = (ClipSelector*)w;
|
||||
long bars = (long)data;
|
||||
if(bars == -2) {
|
||||
const char* answer = fl_input("Enter a custom number: ");
|
||||
if(!answer) {
|
||||
bars = -1;
|
||||
fl_message("Please enter value between 1 and %i.", MAX_BARS);
|
||||
} else
|
||||
bars = atoi(answer);
|
||||
}
|
||||
|
||||
if(bars > MAX_BARS) {
|
||||
bars = -1;
|
||||
fl_message("Please enter value between 1 and %i.", MAX_BARS);
|
||||
}
|
||||
|
||||
EventLooperBarsToRecord e(track->ID, track->getLastClipNum(), bars);
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
|
||||
void setLengthCb(Fl_Widget *w, void* data)
|
||||
{
|
||||
ClipSelector *track = (ClipSelector*)w;
|
||||
long beats = (long)data;
|
||||
EventLooperLoopLength e(track->ID, track->getLastClipNum(), beats);
|
||||
writeToDspRingbuffer( &e );
|
||||
}
|
||||
|
||||
int ClipSelector::getLastClipNum()
|
||||
{
|
||||
return clipNum;
|
||||
}
|
||||
|
||||
int ClipSelector::handle(int event)
|
||||
{
|
||||
|
@ -247,10 +334,12 @@ int ClipSelector::handle(int event)
|
|||
{
|
||||
// calculate the clicked clip number
|
||||
int clipHeight = (h / numClips);
|
||||
int clipNum = ( (Fl::event_y() ) - y ) / clipHeight;
|
||||
clipNum = ( (Fl::event_y() ) - y ) / clipHeight;
|
||||
if (clipNum >= numClips)
|
||||
clipNum = numClips -1; // fix for clicking the lowest pixel
|
||||
|
||||
return clipNum;
|
||||
|
||||
// handle right clicks: popup menu
|
||||
if ( Fl::event_state(FL_BUTTON3) ) {
|
||||
if ( _master ) {
|
||||
|
@ -264,18 +353,28 @@ int ClipSelector::handle(int event)
|
|||
}
|
||||
|
||||
|
||||
bool empty = clips[clipNum].getState() == GridLogic::STATE_EMPTY;
|
||||
Fl_Menu_Item rclick_menu[] = {
|
||||
{ "Load" },
|
||||
{ "Save" },
|
||||
{ "Special"},
|
||||
{ "Beats", 0, 0, 0, FL_SUBMENU | FL_MENU_DIVIDER },
|
||||
{"1 "},
|
||||
{"2"},
|
||||
{"4"},
|
||||
{"8"},
|
||||
{"16"},
|
||||
{"32"},
|
||||
{"64"},
|
||||
RECORD_LENGTH_MENU_ITEM(1),
|
||||
RECORD_LENGTH_MENU_ITEM(2),
|
||||
RECORD_LENGTH_MENU_ITEM(4),
|
||||
RECORD_LENGTH_MENU_ITEM(8),
|
||||
RECORD_LENGTH_MENU_ITEM(16),
|
||||
RECORD_LENGTH_MENU_ITEM(32),
|
||||
RECORD_LENGTH_MENU_ITEM(64),
|
||||
{0},
|
||||
{ "Bars to record", 0, 0, 0, FL_SUBMENU | FL_MENU_DIVIDER},
|
||||
RECORD_BARS_MENU_ITEM(1),
|
||||
RECORD_BARS_MENU_ITEM(2),
|
||||
RECORD_BARS_MENU_ITEM(4),
|
||||
RECORD_BARS_MENU_ITEM(6),
|
||||
RECORD_BARS_MENU_ITEM(8),
|
||||
{"Endless", 0, setRecordBarsCb, (void*)-1, FL_MENU_DIVIDER | FL_MENU_RADIO | ((clips[clipNum].getBeatsToRecord() <= 0) ? FL_MENU_VALUE : 0) | (empty ? 0 : FL_MENU_INACTIVE)},
|
||||
{"Custom", 0, setRecordBarsCb, (void*)-2, empty ? 0 : FL_MENU_INACTIVE},
|
||||
{0},
|
||||
//{ "Record" },
|
||||
{ "Use as tempo" },
|
||||
|
@ -302,27 +401,6 @@ int ClipSelector::handle(int event)
|
|||
free(tmp);
|
||||
gui->selectSaveSample( ID, clipNum );
|
||||
}
|
||||
} else if ( strcmp(m->label(), "1 ") == 0 ) {
|
||||
EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,1);
|
||||
writeToDspRingbuffer( &e );
|
||||
} else if ( strcmp(m->label(), "2") == 0 ) {
|
||||
EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,2);
|
||||
writeToDspRingbuffer( &e );
|
||||
} else if ( strcmp(m->label(), "4") == 0 ) {
|
||||
EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,4);
|
||||
writeToDspRingbuffer( &e );
|
||||
} else if ( strcmp(m->label(), "8") == 0 ) {
|
||||
EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,8);
|
||||
writeToDspRingbuffer( &e );
|
||||
} else if ( strcmp(m->label(), "16") == 0 ) {
|
||||
EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,16);
|
||||
writeToDspRingbuffer( &e );
|
||||
} else if ( strcmp(m->label(), "32") == 0 ) {
|
||||
EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,32);
|
||||
writeToDspRingbuffer( &e );
|
||||
} else if ( strcmp(m->label(), "64") == 0 ) {
|
||||
EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,64);
|
||||
writeToDspRingbuffer( &e );
|
||||
} else if ( strcmp(m->label(), "Use as tempo") == 0 ) {
|
||||
EventLooperUseAsTempo e (ID, clipNum);
|
||||
writeToDspRingbuffer( &e );
|
||||
|
@ -338,6 +416,8 @@ int ClipSelector::handle(int event)
|
|||
// for a clip to become 0
|
||||
EventGridState e( ID, clipNum, GridLogic::STATE_EMPTY );
|
||||
writeToDspRingbuffer( &e );
|
||||
} else {
|
||||
m->do_callback(this, m->user_data());
|
||||
}
|
||||
} else {
|
||||
if ( _master ) {
|
||||
|
@ -385,5 +465,21 @@ int ClipSelector::handle(int event)
|
|||
}
|
||||
}
|
||||
|
||||
void ClipState::setBeats(int numBeats, bool isBeatsToRecord)
|
||||
{
|
||||
if(numBeats > 0) {
|
||||
beatsText = std::to_string(numBeats);
|
||||
barsText = std::to_string(numBeats/4);
|
||||
if(isBeatsToRecord){
|
||||
beatsToRecord = numBeats;
|
||||
beats = 0;
|
||||
} else {
|
||||
beats = numBeats;
|
||||
if(numBeats <= 0)
|
||||
beatsToRecord = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
barsText = beatsText = std::string("");
|
||||
}
|
||||
} // Avtk
|
||||
|
||||
|
|
|
@ -41,7 +41,8 @@ class ClipState
|
|||
public:
|
||||
ClipState() :
|
||||
state(GridLogic::STATE_EMPTY),
|
||||
name("")
|
||||
name(""),
|
||||
barsText("")
|
||||
{}
|
||||
|
||||
void setName(std::string n)
|
||||
|
@ -64,16 +65,39 @@ public:
|
|||
return state;
|
||||
}
|
||||
|
||||
int getBeatsToRecord(){
|
||||
return beatsToRecord;
|
||||
}
|
||||
|
||||
int getBeats(){
|
||||
return beats;
|
||||
}
|
||||
|
||||
void setBeats(int numBeats, bool isBeatsToRecord);
|
||||
|
||||
const char *getBeatsText() {
|
||||
return beatsText.c_str();
|
||||
}
|
||||
|
||||
const char *getBarsText() {
|
||||
return barsText.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
GridLogic::State state;
|
||||
std::string name;
|
||||
std::string beatsText;
|
||||
std::string barsText;
|
||||
|
||||
int beatsToRecord = -1;
|
||||
int beats = 0;
|
||||
};
|
||||
|
||||
class ClipSelector : public Fl_Button
|
||||
{
|
||||
public:
|
||||
ClipSelector( int _x, int _y, int _w, int _h,
|
||||
const char *_label, bool master = false);
|
||||
char *_label, bool master = false);
|
||||
|
||||
int ID;
|
||||
|
||||
|
@ -97,15 +121,19 @@ public:
|
|||
void setState( int clipNum, GridLogic::State s );
|
||||
|
||||
void clipName(int clip, std::string name);
|
||||
void setClipBeats(int scene, int beats, bool isBeatsToRecord);
|
||||
|
||||
std::string clipName(int clip);
|
||||
|
||||
void draw();
|
||||
int handle(int event);
|
||||
|
||||
void resize(int X, int Y, int W, int H);
|
||||
};
|
||||
int getLastClipNum();
|
||||
|
||||
private:
|
||||
int clipNum;
|
||||
};
|
||||
} // Avtk
|
||||
|
||||
#endif // AVTK_CLIP_SELECTOR_H
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
#define LUPPP_RETURN_WARNING 1
|
||||
#define LUPPP_RETURN_ERROR 2
|
||||
|
||||
#define MAX_BARS 64
|
||||
|
||||
/// debug.hxx for printing convienience
|
||||
#include "debug.hxx"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/*
|
||||
* Author: Harry van Haaren 2013
|
||||
* harryhaaren@gmail.com
|
||||
*
|
||||
|
@ -23,7 +23,7 @@
|
|||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
event.hxx
|
||||
event.hxx
|
||||
|
||||
This file provides declarations for each type of event that the engine uses.
|
||||
*/
|
||||
|
@ -31,7 +31,6 @@
|
|||
#include "looper.hxx"
|
||||
#include "gridlogic.hxx"
|
||||
#include "transport.hxx"
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
|
||||
using namespace std;
|
||||
|
@ -97,6 +96,7 @@ enum EVENT_TYPE {
|
|||
LOOPER_PROGRESS,
|
||||
LOOPER_LOOP_LENGTH,
|
||||
LOOPER_LOOP_USE_AS_TEMPO,
|
||||
LOOPER_BARS_TO_RECORD, // choose how many bars to record
|
||||
|
||||
/// Transport etc
|
||||
METRONOME_ACTIVE,
|
||||
|
@ -127,6 +127,9 @@ enum EVENT_TYPE {
|
|||
|
||||
// for keeping loop index's inside the enum
|
||||
EVENT_TYPE_FINAL,
|
||||
|
||||
// Clip
|
||||
CLIP_BEATS_CHANGED,
|
||||
};
|
||||
|
||||
/// returns the pretty name of an event
|
||||
|
@ -267,6 +270,25 @@ public:
|
|||
EventGridSelectNewChosen(int t = -1, int s = -1):track(t),scene(s) {}
|
||||
};
|
||||
|
||||
class EventLooperBarsToRecord : public EventBase
|
||||
{
|
||||
public:
|
||||
int type()
|
||||
{
|
||||
return int(LOOPER_BARS_TO_RECORD);
|
||||
}
|
||||
uint32_t size()
|
||||
{
|
||||
return sizeof(EventLooperBarsToRecord);
|
||||
}
|
||||
|
||||
int track;
|
||||
int scene;
|
||||
int bars;
|
||||
EventLooperBarsToRecord(int t = -1, int s = -1, int b = -1) : track(t), scene(s), bars(b) {}
|
||||
};
|
||||
|
||||
|
||||
class EventQuit : public EventBase
|
||||
{
|
||||
public:
|
||||
|
@ -605,6 +627,7 @@ public:
|
|||
EventGridEvent(int t, int s, bool p): track(t), scene(s), pressed(p) {}
|
||||
};
|
||||
|
||||
|
||||
class EventGridState : public EventBase
|
||||
{
|
||||
public:
|
||||
|
@ -1151,6 +1174,26 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class EventClipBeatsChanged : public EventBase
|
||||
{
|
||||
public:
|
||||
int type()
|
||||
{
|
||||
return int(CLIP_BEATS_CHANGED);
|
||||
}
|
||||
uint32_t size()
|
||||
{
|
||||
return sizeof(EventClipBeatsChanged);
|
||||
}
|
||||
|
||||
int track;
|
||||
int scene;
|
||||
int beats;
|
||||
bool isBeatsToRecord;
|
||||
|
||||
EventClipBeatsChanged() {}
|
||||
EventClipBeatsChanged(int t, int s, int b, bool i) : track(t), scene(s), beats(b), isBeatsToRecord(i) {}
|
||||
};
|
||||
|
||||
|
||||
#endif // LUPPP_EVENT_H
|
||||
|
||||
|
|
|
@ -224,7 +224,6 @@ void handleDspEvents()
|
|||
break;
|
||||
}
|
||||
|
||||
|
||||
case Event::LOOPER_LOAD: {
|
||||
if ( availableRead >= sizeof(EventLooperLoad) ) {
|
||||
EventLooperLoad ev;
|
||||
|
@ -266,8 +265,14 @@ void handleDspEvents()
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case Event::LOOPER_BARS_TO_RECORD: {
|
||||
if ( availableRead >= sizeof(EventLooperBarsToRecord) ) {
|
||||
EventLooperBarsToRecord ev;
|
||||
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventLooperBarsToRecord) );
|
||||
jack->getLogic()->looperBarsToRecord( ev.track, ev.scene, ev.bars );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Event::LOOPER_LOOP_USE_AS_TEMPO: {
|
||||
if ( availableRead >= sizeof(EventLooperUseAsTempo) ) {
|
||||
EventLooperUseAsTempo ev;
|
||||
|
@ -486,4 +491,3 @@ void writeToDspRingbuffer(EventBase* e)
|
|||
}
|
||||
|
||||
#endif // LUPPP_EVENT_HANDLER_DSP_H
|
||||
|
||||
|
|
|
@ -221,7 +221,7 @@ void handleGuiEvents()
|
|||
delete ev.ab;
|
||||
} else {
|
||||
gui->getDiskWriter()->writeAudioBuffer(ev.track, ev.scene, ev.ab,
|
||||
gui->saveBufferPath.c_str());
|
||||
gui->saveBufferPath.c_str());
|
||||
gui->saveBufferPath = "";
|
||||
}
|
||||
|
||||
|
@ -279,6 +279,14 @@ void handleGuiEvents()
|
|||
break;
|
||||
}
|
||||
|
||||
case Event::CLIP_BEATS_CHANGED: {
|
||||
if ( availableRead >= sizeof(EventClipBeatsChanged) ) {
|
||||
EventClipBeatsChanged ev;
|
||||
jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventClipBeatsChanged) );
|
||||
gui->getTrack(ev.track)->getClipSelector()->setClipBeats(ev.scene, ev.beats, ev.isBeatsToRecord);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Event::TRACK_SEND: {
|
||||
if ( availableRead >= sizeof(EventTrackSend) ) {
|
||||
|
@ -491,4 +499,3 @@ void writeToGuiRingbuffer(EventBase* e)
|
|||
}
|
||||
|
||||
#endif // LUPPP_EVENT_HANDLER_DSP_H
|
||||
|
||||
|
|
|
@ -43,14 +43,14 @@ public:
|
|||
void sendVolume(float vol);
|
||||
|
||||
private:
|
||||
int m_trackid;
|
||||
AudioProcessor* m_previousProcessor;
|
||||
bool m_active;
|
||||
float m_sendvol;
|
||||
jack_port_t* m_sendport_l;
|
||||
jack_port_t* m_sendport_r;
|
||||
jack_port_t* m_returnport_l;
|
||||
jack_port_t* m_returnport_r;
|
||||
int m_trackid;
|
||||
AudioProcessor* m_previousProcessor;
|
||||
int m_counter;
|
||||
};
|
||||
|
||||
|
|
|
@ -157,6 +157,14 @@ void Logic::looperClipLenght(int t, int s, int l)
|
|||
}
|
||||
|
||||
|
||||
void Logic::looperBarsToRecord(int t, int s, int b)
|
||||
{
|
||||
if ( t >= 0 && t < NTRACKS ) {
|
||||
jack->getLooper( t )->getClip( s )->setBarsToRecord(b);
|
||||
} else { LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t );
|
||||
}
|
||||
}
|
||||
|
||||
void Logic::looperUseAsTempo(int t, int s)
|
||||
{
|
||||
size_t clipBeats = jack->getLooper( t )->getClip( s )->getBeats();
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#define LUPPP_LOGIC_H
|
||||
|
||||
#include "event.hxx"
|
||||
#include "avtk/clipselector.hxx"
|
||||
|
||||
/** Logic
|
||||
* This class contains an interface exposing most functionality in Luppp. The
|
||||
|
@ -63,6 +64,7 @@ public:
|
|||
void trackJackSend(int t, float vol);
|
||||
void looperUseAsTempo(int track, int scene);
|
||||
void looperClipLenght(int track, int scene, int lenght);
|
||||
void looperBarsToRecord(int track, int scene, int bars);
|
||||
};
|
||||
|
||||
#endif // LUPPP_LOGIC_H
|
||||
|
|
|
@ -89,7 +89,6 @@ void Looper::beat()
|
|||
// clips[i]->setPlayHead(iph-(iph%fpb)*playSpeed);
|
||||
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
void Looper::setRequestedBuffer(int s, AudioBuffer* ab)
|
||||
|
@ -110,6 +109,9 @@ void Looper::process(unsigned int nframes, Buffers* buffers)
|
|||
// handle state of clip, and do what needs doing:
|
||||
// record into buffer, play from buffer, etc
|
||||
if ( clips[clip]->recording() ) {
|
||||
if(clips[clip]->getBeatsToRecord() > 0 && clips[clip]->getBeats() >= clips[clip]->getBeatsToRecord() - 4)
|
||||
clips[clip]->queuePlay(true);
|
||||
|
||||
if ( clips[clip]->recordSpaceAvailable() < LOOPER_SAMPLES_BEFORE_REQUEST &&
|
||||
!clips[clip]->newBufferInTransit() ) {
|
||||
EventLooperClipRequestBuffer e( track, clip, clips[clip]->audioBufferSize() + LOOPER_SAMPLES_UPDATE_SIZE);
|
||||
|
@ -195,12 +197,11 @@ void Looper::pitchShift(int count, float* input, float* output)
|
|||
int iTemp5 = int(fTemp4);
|
||||
float out=output[0];
|
||||
out += (float)(((1 - fTemp3) * (((fTemp4 - iTemp5) *
|
||||
fVec0[(IOTA-int((int((1 + iTemp5)) & 65535)))&65535]) + ((0 - ((
|
||||
fRec0[0] + fSlow3) - iTemp5)) * fVec0[(IOTA-int((iTemp5 & 65535)))
|
||||
&65535]))) + (fTemp3 * (((fRec0[0] - iTemp1) * fVec0[(IOTA-int((int(
|
||||
iTemp2) & 65535)))&65535]) + ((iTemp2 - fRec0[0]) * fVec0[(IOTA-int((
|
||||
iTemp1 & 65535)))&65535]))));
|
||||
|
||||
fVec0[(IOTA-int((int((1 + iTemp5)) & 65535)))&65535]) + ((0 - ((
|
||||
fRec0[0] + fSlow3) - iTemp5)) * fVec0[(IOTA-int((iTemp5 & 65535)))
|
||||
&65535]))) + (fTemp3 * (((fRec0[0] - iTemp1) * fVec0[(IOTA-int((int(
|
||||
iTemp2) & 65535)))&65535]) + ((iTemp2 - fRec0[0]) * fVec0[(IOTA-int((
|
||||
iTemp1 & 65535)))&65535]))));
|
||||
output[0]=out;
|
||||
fRec0[1] = fRec0[0];
|
||||
IOTA = IOTA+1;
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "looperclip.hxx"
|
||||
|
||||
#include <stdio.h>
|
||||
#include "config.hxx"
|
||||
#include "jack.hxx"
|
||||
|
@ -51,6 +49,8 @@ void LooperClip::init()
|
|||
_queuePlay = false;
|
||||
_queueStop = false;
|
||||
_queueRecord= false;
|
||||
_beatsToRecord= -1;
|
||||
setBeats(0);
|
||||
|
||||
if ( _buffer ) {
|
||||
_buffer->init();
|
||||
|
@ -59,8 +59,6 @@ void LooperClip::init()
|
|||
|
||||
_playhead = 0;
|
||||
_recordhead = 0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void LooperClip::save()
|
||||
|
@ -116,6 +114,8 @@ void LooperClip::load( AudioBuffer* ab )
|
|||
}
|
||||
|
||||
_buffer = ab;
|
||||
EventClipBeatsChanged e( track, scene, _beatsToRecord, true );
|
||||
writeToGuiRingbuffer( &e );
|
||||
|
||||
_playhead = 0;
|
||||
jack->getControllerUpdater()->setTrackSceneProgress(track, scene, 0 );
|
||||
|
@ -183,11 +183,27 @@ void LooperClip::setPlayHead(float ph)
|
|||
{
|
||||
if(!_recording&&_playing) {
|
||||
_playhead = ph;
|
||||
jack->getControllerUpdater()->setTrackSceneProgress(track, scene, getProgress() );
|
||||
jack->getControllerUpdater()->setTrackSceneProgress( track, scene, getProgress() );
|
||||
}
|
||||
}
|
||||
|
||||
void LooperClip::setBarsToRecord(int bars)
|
||||
{
|
||||
if(!(_playing || _queuePlay || _queueStop || _loaded)) {
|
||||
_beatsToRecord = bars * 4; // we set beats
|
||||
EventClipBeatsChanged e( track, scene, _beatsToRecord, true);
|
||||
writeToGuiRingbuffer(&e);
|
||||
}
|
||||
}
|
||||
|
||||
int LooperClip::getBeatsToRecord()
|
||||
{
|
||||
return _beatsToRecord;
|
||||
}
|
||||
|
||||
int LooperClip::getBarsToRecord(){
|
||||
return _beatsToRecord / 4;
|
||||
}
|
||||
|
||||
void LooperClip::record(int count, float* L, float* R)
|
||||
{
|
||||
|
@ -239,8 +255,12 @@ size_t LooperClip::audioBufferSize()
|
|||
|
||||
void LooperClip::setBeats(int beats)
|
||||
{
|
||||
if ( _buffer ) {
|
||||
_buffer->setBeats( beats );
|
||||
if (_loaded || _playing || _queuePlay || _queueStop || beats == 0) {
|
||||
if(_buffer)
|
||||
_buffer->setBeats( beats );
|
||||
|
||||
EventClipBeatsChanged e(track, scene, beats, false);
|
||||
writeToGuiRingbuffer(&e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -275,7 +295,7 @@ void LooperClip::bar()
|
|||
// first update the buffer, as time has passed
|
||||
if ( _recording ) {
|
||||
// FIXME: assumes 4 beats in a bar
|
||||
_buffer->setBeats( _buffer->getBeats() + 4 );
|
||||
setBeats( _buffer->getBeats() + 4 );
|
||||
_buffer->setAudioFrames( jack->getTimeManager()->getFpb() * _buffer->getBeats() );
|
||||
}
|
||||
|
||||
|
|
|
@ -116,6 +116,11 @@ public:
|
|||
///reset the play head to zero. Does nothing when recording
|
||||
void setPlayHead(float ph);
|
||||
|
||||
// set how many beats to record (up to full bar)
|
||||
void setBarsToRecord(int bars);
|
||||
int getBeatsToRecord();
|
||||
int getBarsToRecord();
|
||||
|
||||
#ifdef BUILD_TESTS
|
||||
// used only in test cases
|
||||
void setState( bool load, bool play, bool rec, bool qPlay, bool qStop, bool qRec );
|
||||
|
@ -140,8 +145,9 @@ private:
|
|||
|
||||
float _playhead;
|
||||
float _recordhead;
|
||||
int _beatsToRecord;
|
||||
|
||||
AudioBuffer* _buffer;
|
||||
};
|
||||
|
||||
#endif // LUPPP_LOOPER_CLIP_H
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue