commit 229a227cbf2a8ac4c243c2c10a5dfdc00ce70bb9
parent 51591b3286dd2cb492979829c7f376e674763220
Author: fundamental <mark.d.mccurry@gmail.com>
Date: Fri, 20 May 2016 11:09:11 -0400
Get Watchpoints Practically Working
Diffstat:
9 files changed, 113 insertions(+), 46 deletions(-)
diff --git a/src/Misc/Master.cpp b/src/Misc/Master.cpp
@@ -75,7 +75,7 @@ static const Ports sysefxPort =
static const Ports sysefsendto =
{
- {"to#" STRINGIFY(NUM_SYS_EFX) "::i",
+ {"to#" STRINGIFY(NUM_SYS_EFX) "::i",
rProp(parameter) rDoc("sysefx to sysefx routing gain"), 0, [](const char *m, RtData&d)
{
//same ugly workaround as before
@@ -98,6 +98,16 @@ static const Ports sysefsendto =
}}
};
+#define rBegin [](const char *msg, RtData &d) { Master *m = (Master*)d.obj
+#define rEnd }
+
+static const Ports watchPorts = {
+ {"add:s", rDoc("Add synthesis state to watch"), 0,
+ rBegin;
+ m->watcher.add_watch(rtosc_argument(msg,0).s);
+ rEnd},
+};
+
static const Ports master_ports = {
rString(last_xmz, XMZ_PATH_MAX, "File name for last name loaded if any."),
rRecursp(part, 16, "Part"),//NUM_MIDI_PARTS
@@ -241,11 +251,16 @@ static const Ports master_ports = {
{"HDDRecorder/pause:", rDoc("Pause recording"), 0, [](const char *, RtData &d) {
Master *m = (Master*)d.obj;
m->HDDRecorder.pause();}},
- {"watch/add:s", rDoc("Add synthesis state to watch"), 0, [](const char *msg, RtData &d) {
- Master *m = (Master*)d.obj;
- m->watcher.add_watch(rtosc_argument(msg,0).s);}},
-
+ {"watch/", rDoc("Interface to grab out live synthesis state"), &watchPorts,
+ rBOIL_BEGIN;
+ SNIP;
+ watchPorts.dispatch(msg, data);
+ rBOIL_END},
};
+
+#undef rBegin
+#undef rEnd
+
const Ports &Master::ports = master_ports;
class DataObj:public rtosc::RtData
@@ -364,7 +379,7 @@ void Master::applyOscEvent(const char *msg)
DataObj d{loc_buf, 1024, this, bToU};
memset(loc_buf, 0, sizeof(loc_buf));
d.matches = 0;
-
+
if(strcmp(msg, "/get-vu") && false) {
fprintf(stdout, "%c[%d;%d;%dm", 0x1B, 0, 5 + 30, 0 + 40);
fprintf(stdout, "backend[*]: '%s'<%s>\n", msg,
@@ -690,7 +705,7 @@ bool Master::AudioOut(float *outr, float *outl)
}
if(events>1 && false)
fprintf(stderr, "backend: %d events per cycle\n",events);
-
+
//Swaps the Left channel with Right Channel
if(swaplr)
diff --git a/src/Misc/Part.cpp b/src/Misc/Part.cpp
@@ -502,14 +502,14 @@ bool Part::NoteOn(unsigned char note,
if(item.Padenabled)
notePool.insertNote(note, sendto,
{memory.alloc<ADnote>(kit[i].adpars, pars,
- wm, (pre+"kit"+i+"/add/").c_str), 0, i});
+ wm, (pre+"kit"+i+"/adpars/").c_str), 0, i});
if(item.Psubenabled)
notePool.insertNote(note, sendto,
{memory.alloc<SUBnote>(kit[i].subpars, pars), 1, i});
if(item.Ppadenabled)
notePool.insertNote(note, sendto,
{memory.alloc<PADnote>(kit[i].padpars, pars, interpolation, wm,
- (pre+"kit"+i+"/pad/").c_str), 2, i});
+ (pre+"kit"+i+"/padpars/").c_str), 2, i});
} catch (std::bad_alloc & ba) {
std::cerr << "dropped new note: " << ba.what() << std::endl;
}
diff --git a/src/Params/LFOParams.cpp b/src/Params/LFOParams.cpp
@@ -27,6 +27,8 @@ using namespace rtosc;
#define rObject LFOParams
#undef rChangeCb
#define rChangeCb if (obj->time) { obj->last_update_timestamp = obj->time->time(); }
+#define rBegin [](const char *msg, rtosc::RtData &d) {
+#define rEnd }
static const rtosc::Ports _ports = {
rSelf(LFOParams),
rPaste,
@@ -45,7 +47,20 @@ static const rtosc::Ports _ports = {
"0..4 second delay"),
rToggle(Pcontinous, rShort("c"), "Enable for global operation"),
rParamZyn(Pstretch, rShort("str"), rCentered, "Note frequency stretch"),
+
+ //Float valued aliases
+ {"delay::f", rProp(parameter) rMap(units, ms) rLog(0,4000), 0,
+ rBegin;
+
+ rEnd},
+#define rPseudoLog(a,b) rLog(a,b)
+ {"period::f", rProp(parameter) rMap(units, ms) rPseudoLog(0.10, 1500.0), 0,
+ rBegin;
+ rEnd},
};
+#undef rPseudoLog
+#undef rBegin
+#undef rEnd
#undef rChangeCb
const rtosc::Ports &LFOParams::ports = _ports;
diff --git a/src/Synth/ADnote.cpp b/src/Synth/ADnote.cpp
@@ -1886,11 +1886,11 @@ void ADnote::Global::initparameters(const ADnoteGlobalParam ¶m,
ScratchString pre = prefix;
FreqEnvelope = memory.alloc<Envelope>(*param.FreqEnvelope, basefreq, synth.dt());
FreqLfo = memory.alloc<LFO>(*param.FreqLfo, basefreq, time, wm,
- (pre+"FreqLfo/").c_str);
+ (pre+"GlobalPar/FreqLfo/").c_str);
AmpEnvelope = memory.alloc<Envelope>(*param.AmpEnvelope, basefreq, synth.dt());
AmpLfo = memory.alloc<LFO>(*param.AmpLfo, basefreq, time, wm,
- (pre+"AmpLfo/").c_str);
+ (pre+"GlobalPar/AmpLfo/").c_str);
Volume = 4.0f * powf(0.1f, 3.0f * (1.0f - param.PVolume / 96.0f)) //-60 dB .. 0 dB
* VelF(velocity, param.PAmpVelocityScaleFunction); //sensing
@@ -1900,7 +1900,7 @@ void ADnote::Global::initparameters(const ADnoteGlobalParam ¶m,
FilterEnvelope = memory.alloc<Envelope>(*param.FilterEnvelope, basefreq, synth.dt());
FilterLfo = memory.alloc<LFO>(*param.FilterLfo, basefreq, time, wm,
- (pre+"FilterLfo/").c_str);
+ (pre+"GlobalPar/FilterLfo/").c_str);
Filter->addMod(*FilterEnvelope);
Filter->addMod(*FilterLfo);
diff --git a/src/Synth/LFO.cpp b/src/Synth/LFO.cpp
@@ -27,8 +27,7 @@ LFO::LFO(const LFOParams &lfopars, float basefreq, const AbsTime &t, WatchManage
deterministic(!lfopars.Pfreqrand),
dt_(t.dt()),
lfopars_(lfopars), basefreq_(basefreq),
- watchPhase(m, watch_prefix, "phase"),
- watchMag(m, watch_prefix, "magnitude")
+ watchOut(m, watch_prefix, "out")
{
int stretch = lfopars.Pstretch;
if(stretch == 0)
@@ -170,8 +169,8 @@ float LFO::lfoout()
computeNextFreqRnd();
}
- watchPhase(phase);
- watchMag(out);
+ float watch_data[2] = {phase, out};
+ watchOut(watch_data, 2);
return out;
}
diff --git a/src/Synth/LFO.h b/src/Synth/LFO.h
@@ -65,8 +65,7 @@ class LFO
const LFOParams &lfopars_;
const float basefreq_;
- FloatWatchPoint watchPhase;
- FloatWatchPoint watchMag;
+ VecWatchPoint watchOut;
void computeNextFreqRnd(void);
};
diff --git a/src/Synth/WatchPoint.cpp b/src/Synth/WatchPoint.cpp
@@ -32,7 +32,6 @@ WatchPoint::WatchPoint(WatchManager *ref, const char *prefix, const char *id)
strncpy(identity, prefix, 128);
if(id)
strncat(identity, id, 128);
- //printf("new watchpoint ={%s:%s} <%s>\n", prefix, id, identity);
}
bool WatchPoint::is_active(void)
@@ -44,7 +43,7 @@ bool WatchPoint::is_active(void)
if(reference && reference->active(identity)) {
active = true;
- samples_left = reference->samples(identity);
+ samples_left = 1;
return true;
}
@@ -54,12 +53,17 @@ bool WatchPoint::is_active(void)
FloatWatchPoint::FloatWatchPoint(WatchManager *ref, const char *prefix, const char *id)
:WatchPoint(ref, prefix, id)
{}
+
+VecWatchPoint::VecWatchPoint(WatchManager *ref, const char *prefix, const char *id)
+ :WatchPoint(ref, prefix, id)
+{}
WatchManager::WatchManager(thrlnk *link)
:write_back(link), new_active(false)
{
memset(active_list, 0, sizeof(active_list));
memset(sample_list, 0, sizeof(sample_list));
+ memset(data_list, 0, sizeof(data_list));
memset(deactivate, 0, sizeof(deactivate));
}
@@ -70,6 +74,7 @@ void WatchManager::add_watch(const char *id)
if(!active_list[i][0]) {
strncpy(active_list[i], id, 128);
new_active = true;
+ sample_list[i] = 0;
break;
}
}
@@ -85,19 +90,39 @@ void WatchManager::del_watch(const char *id)
void WatchManager::tick(void)
{
+ //Try to send out any vector stuff
+ for(int i=0; i<MAX_WATCH; ++i) {
+ if(sample_list[i]) {
+ char arg_types[MAX_SAMPLE+1] = {0};
+ rtosc_arg_t arg_val[MAX_SAMPLE];
+ for(int j=0; j<sample_list[i]; ++j) {
+ arg_types[j] = 'f';
+ arg_val[j].f = data_list[i][j];
+ }
+
+ write_back->writeArray(active_list[i], arg_types, arg_val);
+ deactivate[i] = true;
+ }
+ }
+
+ //Cleanup internal data
new_active = false;
//Clear deleted slots
- for(int i=0; i<MAX_WATCH; ++i)
- if(deactivate[i])
+ for(int i=0; i<MAX_WATCH; ++i) {
+ if(deactivate[i]) {
memset(active_list[i], 0, 128);
+ sample_list[i] = 0;
+ }
+ }
+
}
bool WatchManager::active(const char *id) const
{
assert(this);
assert(id);
- if(new_active)
+ if(new_active || true)
for(int i=0; i<MAX_WATCH; ++i)
if(!strcmp(active_list[i], id))
return true;
@@ -121,3 +146,17 @@ void WatchManager::satisfy(const char *id, float f)
del_watch(id);
}
+void WatchManager::satisfy(const char *id, float *f, int n)
+{
+ int selected = -1;
+ for(int i=0; i<MAX_WATCH; ++i)
+ if(!strcmp(active_list[i], id))
+ selected = i;
+
+ if(selected == -1)
+ return;
+
+ //FIXME buffer overflow
+ for(int i=0; i<n; ++i)
+ data_list[selected][sample_list[selected]++] = f[i];
+}
diff --git a/src/Synth/WatchPoint.h b/src/Synth/WatchPoint.h
@@ -3,20 +3,12 @@
WatchPoint.h - Synthesis State Watcher
Copyright (C) 2015-2015 Mark McCurry
+ Author: Mark McCurry
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License
- as published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License (version 2 or later) for more details.
-
- You should have received a copy of the GNU General Public License (version 2)
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
*/
#pragma once
@@ -36,12 +28,15 @@ struct WatchPoint
};
#define MAX_WATCH 16
+#define MAX_WATCH_PATH 128
+#define MAX_SAMPLE 128
struct WatchManager
{
typedef rtosc::ThreadLink thrlnk;
thrlnk *write_back;
bool new_active;
- char active_list[128][MAX_WATCH];
+ char active_list[MAX_WATCH][MAX_WATCH_PATH];
+ float data_list[MAX_SAMPLE][MAX_WATCH];
int sample_list[MAX_WATCH];
bool deactivate[MAX_WATCH];
@@ -57,6 +52,7 @@ struct WatchManager
//Watch Point Response API
void satisfy(const char *, float);
+ void satisfy(const char *, float*, int);
};
struct FloatWatchPoint:public WatchPoint
@@ -71,11 +67,15 @@ struct FloatWatchPoint:public WatchPoint
}
};
-//struct VecWatchPoint:public WatchPoint
-//{
-// inline void operator()(float *f, int n)
-// {
-// if(!is_active()) {
-// }
-// }
-//};
+//basically the same as the float watch point, only it consumes tuples
+struct VecWatchPoint : public WatchPoint
+{
+ VecWatchPoint(WatchManager *ref, const char *prefix, const char *id);
+ inline void operator()(float *f, int n)
+ {
+ if(is_active() && reference) {
+ reference->satisfy(identity, f, n);
+ active = false;
+ }
+ }
+};
diff --git a/src/UI/Connection.cpp b/src/UI/Connection.cpp
@@ -407,7 +407,7 @@ class UI_Interface:public Fl_Osc_Interface
virtual void damage(const char *path) override
{
#ifndef NO_UI
- printf("\n\nDamage(\"%s\")\n", path);
+ //printf("\n\nDamage(\"%s\")\n", path);
std::set<Fl_Osc_Widget*> to_update;
for(auto pair:map) {
if(strstr(pair.first.c_str(), path)) {