@@ -492,7 +492,7 @@ std::vector<std::string> Bank::search(std::string s) const | |||||
std::vector<std::string> Bank::blist(std::string s) | std::vector<std::string> Bank::blist(std::string s) | ||||
{ | { | ||||
std::vector<std::string> out; | std::vector<std::string> out; | ||||
int result = loadbank(s); | |||||
loadbank(s); | |||||
for(int i=0; i<128; ++i) { | for(int i=0; i<128; ++i) { | ||||
if(ins[i].filename.empty()) | if(ins[i].filename.empty()) | ||||
out.push_back("Empty Preset"); | out.push_back("Empty Preset"); | ||||
@@ -80,17 +80,17 @@ static svec split(string s) | |||||
return vec; | return vec; | ||||
} | } | ||||
static string line(string s) | |||||
{ | |||||
string ss; | |||||
for(char c:s) { | |||||
if(c != '\n') | |||||
ss.push_back(c); | |||||
else | |||||
return ss; | |||||
} | |||||
return ss; | |||||
} | |||||
//static string line(string s) | |||||
//{ | |||||
// string ss; | |||||
// for(char c:s) { | |||||
// if(c != '\n') | |||||
// ss.push_back(c); | |||||
// else | |||||
// return ss; | |||||
// } | |||||
// return ss; | |||||
//} | |||||
bvec BankDb::search(std::string ss) const | bvec BankDb::search(std::string ss) const | ||||
{ | { | ||||
@@ -186,6 +186,7 @@ static const Ports auto_param_ports = { | |||||
rEnd}, | rEnd}, | ||||
{"mapping/", 0, &mapping_ports, | {"mapping/", 0, &mapping_ports, | ||||
rBegin; | rBegin; | ||||
(void) a; | |||||
SNIP; | SNIP; | ||||
mapping_ports.dispatch(msg, d); | mapping_ports.dispatch(msg, d); | ||||
rEnd}, | rEnd}, | ||||
@@ -664,7 +665,6 @@ void Master::loadAutomation(XMLwrapper &xml, rtosc::AutomationMgr &midi) | |||||
auto &slot = midi.slots[i]; | auto &slot = midi.slots[i]; | ||||
if(xml.enterbranch("slot", i)) { | if(xml.enterbranch("slot", i)) { | ||||
for(int j=0; j<midi.per_slot; ++j) { | for(int j=0; j<midi.per_slot; ++j) { | ||||
auto &au = slot.automations[j]; | |||||
if(xml.enterbranch("automation", j)) { | if(xml.enterbranch("automation", j)) { | ||||
float gain = 1.0; | float gain = 1.0; | ||||
float offset = 0.0; | float offset = 0.0; | ||||
@@ -870,6 +870,7 @@ void Microtonal::apply(void) | |||||
strncat(buf, tmpbuf, sizeof(buf)-1); | strncat(buf, tmpbuf, sizeof(buf)-1); | ||||
} | } | ||||
int err = texttotunings(buf); | int err = texttotunings(buf); | ||||
(void) err; | |||||
} | } | ||||
} | } | ||||
@@ -18,6 +18,7 @@ | |||||
#include <iostream> | #include <iostream> | ||||
#include <dirent.h> | #include <dirent.h> | ||||
#include <sys/stat.h> | #include <sys/stat.h> | ||||
#include <mutex> | |||||
#include <rtosc/undo-history.h> | #include <rtosc/undo-history.h> | ||||
#include <rtosc/thread-link.h> | #include <rtosc/thread-link.h> | ||||
@@ -59,6 +60,7 @@ | |||||
namespace zyncarla { | namespace zyncarla { | ||||
using std::string; | using std::string; | ||||
using std::mutex; | |||||
int Pexitprogram = 0; | int Pexitprogram = 0; | ||||
/****************************************************************************** | /****************************************************************************** | ||||
@@ -207,17 +209,19 @@ void preparePadSynth(string path, PADnoteParameters *p, rtosc::RtData &d) | |||||
assert(!path.empty()); | assert(!path.empty()); | ||||
path += "sample"; | path += "sample"; | ||||
unsigned max = 0; | |||||
p->sampleGenerator([&max,&path,&d] | |||||
(unsigned N, PADnoteParameters::Sample &s) | |||||
{ | |||||
max = max<N ? N : max; | |||||
//printf("sending info to '%s'\n", (path+to_s(N)).c_str()); | |||||
d.chain((path+to_s(N)).c_str(), "ifb", | |||||
s.size, s.basefreq, sizeof(float*), &s.smp); | |||||
}, []{return false;}); | |||||
std::mutex rtdata_mutex; | |||||
unsigned num = p->sampleGenerator([&rtdata_mutex,&path,&d] | |||||
(unsigned N, PADnoteParameters::Sample &s) | |||||
{ | |||||
//printf("sending info to '%s'\n", | |||||
// (path+to_s(N)).c_str()); | |||||
rtdata_mutex.lock(); | |||||
d.chain((path+to_s(N)).c_str(), "ifb", | |||||
s.size, s.basefreq, sizeof(float*), &s.smp); | |||||
rtdata_mutex.unlock(); | |||||
}, []{return false;}); | |||||
//clear out unused samples | //clear out unused samples | ||||
for(unsigned i = max+1; i < PAD_MAX_SAMPLES; ++i) { | |||||
for(unsigned i = num; i < PAD_MAX_SAMPLES; ++i) { | |||||
d.chain((path+to_s(i)).c_str(), "ifb", | d.chain((path+to_s(i)).c_str(), "ifb", | ||||
0, 440.0f, sizeof(float*), NULL); | 0, 440.0f, sizeof(float*), NULL); | ||||
} | } | ||||
@@ -1617,7 +1621,7 @@ void MiddleWareImpl::heartBeat(Master *master) | |||||
//Last provided beat | //Last provided beat | ||||
//Last acknowledged beat | //Last acknowledged beat | ||||
//Current offline status | //Current offline status | ||||
struct timespec time; | struct timespec time; | ||||
clock_gettime(CLOCK_MONOTONIC, &time); | clock_gettime(CLOCK_MONOTONIC, &time); | ||||
uint32_t now = (time.tv_sec-start_time_sec)*100 + | uint32_t now = (time.tv_sec-start_time_sec)*100 + | ||||
@@ -68,6 +68,7 @@ static const char *escape_string(const char *msg) | |||||
using std::ostream; | using std::ostream; | ||||
using std::string; | using std::string; | ||||
#if 0 | |||||
static int enum_min(Port::MetaContainer meta) | static int enum_min(Port::MetaContainer meta) | ||||
{ | { | ||||
int min = 0; | int min = 0; | ||||
@@ -125,6 +126,7 @@ static ostream &add_options(ostream &o, Port::MetaContainer meta) | |||||
return o; | return o; | ||||
} | } | ||||
#endif | |||||
/* | /* | ||||
* parameter : | * parameter : | ||||
@@ -253,7 +253,7 @@ void XMLwrapper::addparreal(const string &name, float val) | |||||
union { float in; uint32_t out; } convert; | union { float in; uint32_t out; } convert; | ||||
char buf[11]; | char buf[11]; | ||||
convert.in = val; | convert.in = val; | ||||
sprintf(buf, "0x%0.8X", convert.out); | |||||
sprintf(buf, "0x%.8X", convert.out); | |||||
addparams("par_real", 3, "name", name.c_str(), "value", | addparams("par_real", 3, "name", name.c_str(), "value", | ||||
stringFrom<float>(val).c_str(), "exact_value", buf); | stringFrom<float>(val).c_str(), "exact_value", buf); | ||||
} | } | ||||
@@ -55,8 +55,8 @@ class EnvelopeParams:public Presets | |||||
static float dt(char val); | static float dt(char val); | ||||
static char inv_dt(float val); | static char inv_dt(float val); | ||||
//! @brief defines where it is used and its default settings | |||||
//! corresponds to envelope_type_t | |||||
//! Defines where it is used and its default settings. | |||||
//! Corresponds to envelope_type_t | |||||
int envelope_type; | int envelope_type; | ||||
/* MIDI Parameters */ | /* MIDI Parameters */ | ||||
@@ -172,7 +172,6 @@ const rtosc::Ports FilterParams::ports = { | |||||
0.0, cf.d[1]); | 0.0, cf.d[1]); | ||||
} | } | ||||
} else if(obj->Pcategory == 2) { | } else if(obj->Pcategory == 2) { | ||||
int order = 0; | |||||
float gain = dB2rap(obj->getgain()); | float gain = dB2rap(obj->getgain()); | ||||
auto cf = SVFilter::computeResponse(obj->Ptype, | auto cf = SVFilter::computeResponse(obj->Ptype, | ||||
Filter::getrealfreq(obj->getfreq()), | Filter::getrealfreq(obj->getfreq()), | ||||
@@ -10,6 +10,7 @@ | |||||
as published by the Free Software Foundation; either version 2 | as published by the Free Software Foundation; either version 2 | ||||
of the License, or (at your option) any later version. | of the License, or (at your option) any later version. | ||||
*/ | */ | ||||
#include <limits> | |||||
#include <cmath> | #include <cmath> | ||||
#include "PADnoteParameters.h" | #include "PADnoteParameters.h" | ||||
#include "FilterParams.h" | #include "FilterParams.h" | ||||
@@ -20,6 +21,7 @@ | |||||
#include "../Misc/WavFile.h" | #include "../Misc/WavFile.h" | ||||
#include "../Misc/Time.h" | #include "../Misc/Time.h" | ||||
#include <cstdio> | #include <cstdio> | ||||
#include <thread> | |||||
#include <rtosc/ports.h> | #include <rtosc/ports.h> | ||||
#include <rtosc/port-sugar.h> | #include <rtosc/port-sugar.h> | ||||
@@ -304,8 +306,6 @@ PADnoteParameters::PADnoteParameters(const SYNTH_T &synth_, FFTwrapper *fft_, | |||||
{ | { | ||||
setpresettype("Ppadsynth"); | setpresettype("Ppadsynth"); | ||||
fft = fft_; | |||||
resonance = new Resonance(); | resonance = new Resonance(); | ||||
oscilgen = new OscilGen(synth, fft_, resonance); | oscilgen = new OscilGen(synth, fft_, resonance); | ||||
oscilgen->ADvsPAD = true; | oscilgen->ADvsPAD = true; | ||||
@@ -596,7 +596,7 @@ float PADnoteParameters::setPbandwidth(int Pbandwidth) | |||||
/* | /* | ||||
* Get the harmonic(overtone) position | * Get the harmonic(overtone) position | ||||
*/ | */ | ||||
float PADnoteParameters::getNhr(int n) | |||||
float PADnoteParameters::getNhr(int n) const | |||||
{ | { | ||||
float result = 1.0f; | float result = 1.0f; | ||||
const float par1 = powf(10.0f, -(1.0f - Phrpos.par1 / 255.0f) * 3.0f); | const float par1 = powf(10.0f, -(1.0f - Phrpos.par1 / 255.0f) * 3.0f); | ||||
@@ -696,9 +696,9 @@ static float Pbwscale_translate(char Pbwscale) | |||||
void PADnoteParameters::generatespectrum_bandwidthMode(float *spectrum, | void PADnoteParameters::generatespectrum_bandwidthMode(float *spectrum, | ||||
int size, | int size, | ||||
float basefreq, | float basefreq, | ||||
float *profile, | |||||
const float *profile, | |||||
int profilesize, | int profilesize, | ||||
float bwadjust) | |||||
float bwadjust) const | |||||
{ | { | ||||
float harmonics[synth.oscilsize]; | float harmonics[synth.oscilsize]; | ||||
memset(spectrum, 0, sizeof(float) * size); | memset(spectrum, 0, sizeof(float) * size); | ||||
@@ -712,7 +712,7 @@ void PADnoteParameters::generatespectrum_bandwidthMode(float *spectrum, | |||||
//Constants across harmonics | //Constants across harmonics | ||||
const float power = Pbwscale_translate(Pbwscale); | const float power = Pbwscale_translate(Pbwscale); | ||||
const float bandwidthcents = setPbandwidth(Pbandwidth); | |||||
const float bandwidthcents = const_cast<PADnoteParameters*>(this)->setPbandwidth(Pbandwidth); | |||||
for(int nh = 1; nh < synth.oscilsize / 2; ++nh) { //for each harmonic | for(int nh = 1; nh < synth.oscilsize / 2; ++nh) { //for each harmonic | ||||
const float realfreq = getNhr(nh) * basefreq; | const float realfreq = getNhr(nh) * basefreq; | ||||
@@ -773,7 +773,7 @@ void PADnoteParameters::generatespectrum_bandwidthMode(float *spectrum, | |||||
*/ | */ | ||||
void PADnoteParameters::generatespectrum_otherModes(float *spectrum, | void PADnoteParameters::generatespectrum_otherModes(float *spectrum, | ||||
int size, | int size, | ||||
float basefreq) | |||||
float basefreq) const | |||||
{ | { | ||||
float harmonics[synth.oscilsize]; | float harmonics[synth.oscilsize]; | ||||
memset(spectrum, 0, sizeof(float) * size); | memset(spectrum, 0, sizeof(float) * size); | ||||
@@ -830,21 +830,20 @@ void PADnoteParameters::applyparameters() | |||||
applyparameters([]{return false;}); | applyparameters([]{return false;}); | ||||
} | } | ||||
void PADnoteParameters::applyparameters(std::function<bool()> do_abort) | |||||
void PADnoteParameters::applyparameters(std::function<bool()> do_abort, | |||||
unsigned max_threads) | |||||
{ | { | ||||
if(do_abort()) | if(do_abort()) | ||||
return; | return; | ||||
unsigned max = 0; | |||||
sampleGenerator([&max,this] | |||||
(unsigned N, PADnoteParameters::Sample &smp) { | |||||
delete[] sample[N].smp; | |||||
sample[N] = smp; | |||||
max = max < N ? N : max; | |||||
}, | |||||
do_abort); | |||||
unsigned num = sampleGenerator([this] | |||||
(unsigned N, PADnoteParameters::Sample &smp) { | |||||
delete[] sample[N].smp; | |||||
sample[N] = smp; | |||||
}, | |||||
do_abort, max_threads); | |||||
//Delete remaining unused samples | //Delete remaining unused samples | ||||
for(unsigned i = max; i < PAD_MAX_SAMPLES; ++i) | |||||
for(unsigned i = num; i < PAD_MAX_SAMPLES; ++i) | |||||
deletesample(i); | deletesample(i); | ||||
} | } | ||||
@@ -854,13 +853,17 @@ void PADnoteParameters::applyparameters(std::function<bool()> do_abort) | |||||
// - Pquality.oct | // - Pquality.oct | ||||
// - Pquality.smpoct | // - Pquality.smpoct | ||||
// - spectrum at various frequencies (oodles of data) | // - spectrum at various frequencies (oodles of data) | ||||
void PADnoteParameters::sampleGenerator(PADnoteParameters::callback cb, | |||||
std::function<bool()> do_abort) | |||||
int PADnoteParameters::sampleGenerator(PADnoteParameters::callback cb, | |||||
std::function<bool()> do_abort, | |||||
unsigned max_threads) | |||||
{ | { | ||||
if(!max_threads) | |||||
max_threads = std::numeric_limits<unsigned>::max(); | |||||
const int samplesize = (((int) 1) << (Pquality.samplesize + 14)); | const int samplesize = (((int) 1) << (Pquality.samplesize + 14)); | ||||
const int spectrumsize = samplesize / 2; | const int spectrumsize = samplesize / 2; | ||||
float *spectrum = new float[spectrumsize]; | |||||
const int profilesize = 512; | const int profilesize = 512; | ||||
float profile[profilesize]; | float profile[profilesize]; | ||||
@@ -885,71 +888,92 @@ void PADnoteParameters::sampleGenerator(PADnoteParameters::callback cb, | |||||
if(samplemax > PAD_MAX_SAMPLES) | if(samplemax > PAD_MAX_SAMPLES) | ||||
samplemax = PAD_MAX_SAMPLES; | samplemax = PAD_MAX_SAMPLES; | ||||
//prepare a BIG FFT | |||||
FFTwrapper *fft = new FFTwrapper(samplesize); | |||||
fft_t *fftfreqs = new fft_t[samplesize / 2]; | |||||
//this is used to compute frequency relation to the base frequency | //this is used to compute frequency relation to the base frequency | ||||
float adj[samplemax]; | float adj[samplemax]; | ||||
for(int nsample = 0; nsample < samplemax; ++nsample) | for(int nsample = 0; nsample < samplemax; ++nsample) | ||||
adj[nsample] = (Pquality.oct + 1.0f) * (float)nsample / samplemax; | adj[nsample] = (Pquality.oct + 1.0f) * (float)nsample / samplemax; | ||||
for(int nsample = 0; nsample < samplemax; ++nsample) { | |||||
if(do_abort()) | |||||
goto exit; | |||||
const float basefreqadjust = | |||||
powf(2.0f, adj[nsample] - adj[samplemax - 1] * 0.5f); | |||||
if(Pmode == 0) | |||||
generatespectrum_bandwidthMode(spectrum, | |||||
spectrumsize, | |||||
basefreq * basefreqadjust, | |||||
profile, | |||||
profilesize, | |||||
bwadjust); | |||||
else | |||||
generatespectrum_otherModes(spectrum, spectrumsize, | |||||
basefreq * basefreqadjust); | |||||
//the last samples contains the first samples | |||||
//(used for linear/cubic interpolation) | |||||
const int extra_samples = 5; | |||||
PADnoteParameters::Sample newsample; | |||||
newsample.smp = new float[samplesize + extra_samples]; | |||||
newsample.smp[0] = 0.0f; | |||||
for(int i = 1; i < spectrumsize; ++i) //randomize the phases | |||||
fftfreqs[i] = FFTpolar(spectrum[i], (float)RND * 2 * PI); | |||||
//that's all; here is the only ifft for the whole sample; | |||||
//no windows are used ;-) | |||||
fft->freqs2smps(fftfreqs, newsample.smp); | |||||
//normalize(rms) | |||||
float rms = 0.0f; | |||||
for(int i = 0; i < samplesize; ++i) | |||||
rms += newsample.smp[i] * newsample.smp[i]; | |||||
rms = sqrt(rms); | |||||
if(rms < 0.000001f) | |||||
rms = 1.0f; | |||||
rms *= sqrt(262144.0f / samplesize);//262144=2^18 | |||||
for(int i = 0; i < samplesize; ++i) | |||||
newsample.smp[i] *= 1.0f / rms * 50.0f; | |||||
//prepare extra samples used by the linear or cubic interpolation | |||||
for(int i = 0; i < extra_samples; ++i) | |||||
newsample.smp[i + samplesize] = newsample.smp[i]; | |||||
//yield new sample | |||||
newsample.size = samplesize; | |||||
newsample.basefreq = basefreq * basefreqadjust; | |||||
cb(nsample, newsample); | |||||
} | |||||
exit: | |||||
//Cleanup | |||||
delete (fft); | |||||
delete[] fftfreqs; | |||||
delete[] spectrum; | |||||
const PADnoteParameters* this_c = this; | |||||
auto thread_cb = [basefreq, bwadjust, &cb, do_abort, | |||||
samplesize, samplemax, spectrumsize, | |||||
&adj, &profile, this_c]( | |||||
unsigned nthreads, unsigned threadno) | |||||
{ | |||||
//prepare a BIG IFFT | |||||
FFTwrapper *fft = new FFTwrapper(samplesize); | |||||
fft_t *fftfreqs = new fft_t[samplesize / 2]; | |||||
float *spectrum = new float[spectrumsize]; | |||||
for(int nsample = 0; nsample < samplemax; ++nsample) | |||||
if(nsample % nthreads == threadno) | |||||
{ | |||||
if(do_abort()) | |||||
break; | |||||
const float basefreqadjust = | |||||
powf(2.0f, adj[nsample] - adj[samplemax - 1] * 0.5f); | |||||
if(this_c->Pmode == 0) | |||||
this_c->generatespectrum_bandwidthMode(spectrum, | |||||
spectrumsize, | |||||
basefreq*basefreqadjust, | |||||
profile, | |||||
profilesize, | |||||
bwadjust); | |||||
else | |||||
this_c->generatespectrum_otherModes(spectrum, spectrumsize, | |||||
basefreq * basefreqadjust); | |||||
//the last samples contains the first samples | |||||
//(used for linear/cubic interpolation) | |||||
const int extra_samples = 5; | |||||
PADnoteParameters::Sample newsample; | |||||
newsample.smp = new float[samplesize + extra_samples]; | |||||
newsample.smp[0] = 0.0f; | |||||
for(int i = 1; i < spectrumsize; ++i) //randomize the phases | |||||
fftfreqs[i] = FFTpolar(spectrum[i], (float)RND * 2 * PI); | |||||
//that's all; here is the only ifft for the whole sample; | |||||
//no windows are used ;-) | |||||
fft->freqs2smps(fftfreqs, newsample.smp); | |||||
//normalize(rms) | |||||
float rms = 0.0f; | |||||
for(int i = 0; i < samplesize; ++i) | |||||
rms += newsample.smp[i] * newsample.smp[i]; | |||||
rms = sqrt(rms); | |||||
if(rms < 0.000001f) | |||||
rms = 1.0f; | |||||
rms *= sqrt(262144.0f / samplesize);//262144=2^18 | |||||
for(int i = 0; i < samplesize; ++i) | |||||
newsample.smp[i] *= 1.0f / rms * 50.0f; | |||||
//prepare extra samples used by the linear or cubic interpolation | |||||
for(int i = 0; i < extra_samples; ++i) | |||||
newsample.smp[i + samplesize] = newsample.smp[i]; | |||||
//yield new sample | |||||
newsample.size = samplesize; | |||||
newsample.basefreq = basefreq * basefreqadjust; | |||||
cb(nsample, newsample); | |||||
} | |||||
//Cleanup | |||||
delete (fft); | |||||
delete[] fftfreqs; | |||||
delete[] spectrum; | |||||
}; | |||||
unsigned nthreads = std::min(max_threads, | |||||
std::thread::hardware_concurrency()); | |||||
std::vector<std::thread> threads(nthreads); | |||||
for(unsigned i = 0; i < nthreads; ++i) | |||||
threads[i] = std::thread(thread_cb, nthreads, i); | |||||
for(unsigned i = 0; i < nthreads; ++i) | |||||
threads[i].join(); | |||||
return samplemax; | |||||
} | } | ||||
void PADnoteParameters::export2wav(std::string basefilename) | void PADnoteParameters::export2wav(std::string basefilename) | ||||
@@ -25,7 +25,7 @@ namespace zyncarla { | |||||
/** | /** | ||||
* Parameters for PAD synthesis | * Parameters for PAD synthesis | ||||
* | * | ||||
* Note - unlike most other parameter objects significant portions of this | |||||
* @note unlike most other parameter objects significant portions of this | |||||
* object are `owned' by the non-realtime context. The realtime context only | * object are `owned' by the non-realtime context. The realtime context only | ||||
* needs the samples generated by the PADsynth algorithm and modulators (ie | * needs the samples generated by the PADsynth algorithm and modulators (ie | ||||
* envelopes/filters/LFOs) for amplitude, frequency, and filters. | * envelopes/filters/LFOs) for amplitude, frequency, and filters. | ||||
@@ -146,26 +146,45 @@ class PADnoteParameters:public Presets | |||||
float setPbandwidth(int Pbandwidth); //returns the BandWidth in cents | |||||
float getNhr(int n); //gets the n-th overtone position relatively to N harmonic | |||||
float setPbandwidth(int Pbandwidth); //!< Return the BandWidth in cents | |||||
//! Get the n-th overtone position relatively to N harmonic | |||||
float getNhr(int n) const; | |||||
void applyparameters(void); | void applyparameters(void); | ||||
void applyparameters(std::function<bool()> do_abort); | |||||
//! Compute the #sample array from the other parameters. | |||||
//! For the function's parameters, see sampleGenerator() | |||||
void applyparameters(std::function<bool()> do_abort, | |||||
unsigned max_threads = 0); | |||||
void export2wav(std::string basefilename); | void export2wav(std::string basefilename); | ||||
OscilGen *oscilgen; | OscilGen *oscilgen; | ||||
Resonance *resonance; | Resonance *resonance; | ||||
//RT sample data | |||||
struct Sample { | struct Sample { | ||||
int size; | int size; | ||||
float basefreq; | float basefreq; | ||||
float *smp; | float *smp; | ||||
} sample[PAD_MAX_SAMPLES]; | |||||
}; | |||||
//! RT sample data | |||||
Sample sample[PAD_MAX_SAMPLES]; | |||||
typedef std::function<void(int,PADnoteParameters::Sample&)> callback; | typedef std::function<void(int,PADnoteParameters::Sample&)> callback; | ||||
void sampleGenerator(PADnoteParameters::callback cb, | |||||
std::function<bool()> do_abort); | |||||
//! PAD synth main function | |||||
//! Generate spectrum and run IFFTs on it | |||||
//! @param cb A callback that will be executed for each sample buffer | |||||
//! Note that this function can be executed by multiple | |||||
//! threads at the same time, so make sure you use mutexes | |||||
//! etc where required | |||||
//! @param do_abort Function that decides whether the calculation should | |||||
//! be aborted (probably because of interruptions by the | |||||
//! user) | |||||
//! @param max_threads Maximum number of threads for computation, or | |||||
//! zero if no maximum shall be set | |||||
int sampleGenerator(PADnoteParameters::callback cb, | |||||
std::function<bool()> do_abort, | |||||
unsigned max_threads = 0); | |||||
const AbsTime *time; | const AbsTime *time; | ||||
int64_t last_update_timestamp; | int64_t last_update_timestamp; | ||||
@@ -178,16 +197,15 @@ class PADnoteParameters:public Presets | |||||
void generatespectrum_bandwidthMode(float *spectrum, | void generatespectrum_bandwidthMode(float *spectrum, | ||||
int size, | int size, | ||||
float basefreq, | float basefreq, | ||||
float *profile, | |||||
const float *profile, | |||||
int profilesize, | int profilesize, | ||||
float bwadjust); | |||||
float bwadjust) const; | |||||
void generatespectrum_otherModes(float *spectrum, | void generatespectrum_otherModes(float *spectrum, | ||||
int size, | int size, | ||||
float basefreq); | |||||
float basefreq) const; | |||||
void deletesamples(); | void deletesamples(); | ||||
void deletesample(int n); | void deletesample(int n); | ||||
FFTwrapper *fft; | |||||
public: | public: | ||||
const SYNTH_T &synth; | const SYNTH_T &synth; | ||||
}; | }; | ||||
@@ -1,7 +1,7 @@ | |||||
#pragma once | |||||
#include <rtosc/ports.h> | #include <rtosc/ports.h> | ||||
#include <rtosc/rtosc.h> | #include <rtosc/rtosc.h> | ||||
#include <cassert> | #include <cassert> | ||||
#pragma once | |||||
namespace rtosc { | namespace rtosc { | ||||
struct AutomationMapping | struct AutomationMapping | ||||
{ | { | ||||
@@ -39,8 +39,10 @@ void AutomationMgr::createBinding(int slot, const char *path, bool start_midi_le | |||||
} | } | ||||
auto meta = port->meta(); | auto meta = port->meta(); | ||||
if(!(meta.find("min") && meta.find("max"))) { | if(!(meta.find("min") && meta.find("max"))) { | ||||
fprintf(stderr, "No bounds for '%s' known\n", path); | |||||
return; | |||||
if(!strstr(port->name, ":T")) { | |||||
fprintf(stderr, "No bounds for '%s' known\n", path); | |||||
return; | |||||
} | |||||
} | } | ||||
if(meta.find("internal") || meta.find("no learn")) { | if(meta.find("internal") || meta.find("no learn")) { | ||||
fprintf(stderr, "[Warning] port '%s' is unlearnable\n", path); | fprintf(stderr, "[Warning] port '%s' is unlearnable\n", path); | ||||
@@ -63,11 +65,18 @@ void AutomationMgr::createBinding(int slot, const char *path, bool start_midi_le | |||||
au.used = true; | au.used = true; | ||||
au.active = true; | au.active = true; | ||||
au.param_min = atof(meta["min"]); | |||||
au.param_max = atof(meta["max"]); | |||||
au.param_type = 'i'; | au.param_type = 'i'; | ||||
if(strstr(port->name, ":f")) | if(strstr(port->name, ":f")) | ||||
au.param_type = 'f'; | au.param_type = 'f'; | ||||
else if(strstr(port->name, ":T")) | |||||
au.param_type = 'T'; | |||||
if(au.param_type == 'T') { | |||||
au.param_min = 0.0; | |||||
au.param_max = 1.0; | |||||
} else { | |||||
au.param_min = atof(meta["min"]); | |||||
au.param_max = atof(meta["max"]); | |||||
} | |||||
strncpy(au.param_path, path, sizeof(au.param_path)); | strncpy(au.param_path, path, sizeof(au.param_path)); | ||||
au.map.gain = 100.0; | au.map.gain = 100.0; | ||||
@@ -688,6 +688,7 @@ class CapturePretty : public RtData | |||||
size_t wrt = rtosc_print_arg_vals(arg_vals, nargs, | size_t wrt = rtosc_print_arg_vals(arg_vals, nargs, | ||||
buffer, buffersize, NULL, | buffer, buffersize, NULL, | ||||
cols_used); | cols_used); | ||||
(void) wrt; | |||||
va_end(va); | va_end(va); | ||||
assert(wrt); | assert(wrt); | ||||
} | } | ||||
@@ -294,9 +294,9 @@ template<class T> constexpr T spice(T*t) {return *t;} | |||||
#define rBOIL_END } | #define rBOIL_END } | ||||
#define rLIMIT(var, convert) \ | #define rLIMIT(var, convert) \ | ||||
if(prop["min"] && var < convert(prop["min"])) \ | |||||
if(prop["min"] && var < (decltype(var)) convert(prop["min"])) \ | |||||
var = convert(prop["min"]);\ | var = convert(prop["min"]);\ | ||||
if(prop["max"] && var > convert(prop["max"])) \ | |||||
if(prop["max"] && var > (decltype(var)) convert(prop["max"])) \ | |||||
var = convert(prop["max"]); | var = convert(prop["max"]); | ||||
#define rTYPE(n) decltype(obj->n) | #define rTYPE(n) decltype(obj->n) | ||||
@@ -24,6 +24,8 @@ | |||||
/** | /** | ||||
* @file ports.h | * @file ports.h | ||||
* Collection of functions for ports. | |||||
* This includes dispatchin, reading metadata etc. | |||||
*/ | */ | ||||
#ifndef RTOSC_PORTS | #ifndef RTOSC_PORTS | ||||
@@ -54,8 +56,7 @@ struct RtData | |||||
RtData(void); | RtData(void); | ||||
/** | /** | ||||
* @brief location of where the dispatch routine is currently being called | |||||
* | |||||
* Location of where the dispatch routine is currently being called. | |||||
* If non-NULL, the dispatch routine will update the port name here while | * If non-NULL, the dispatch routine will update the port name here while | ||||
* walking through the Ports tree | * walking through the Ports tree | ||||
*/ | */ | ||||
@@ -253,7 +254,7 @@ struct MergePorts:public Ports | |||||
}; | }; | ||||
/** | /** | ||||
* @brief Returns a port's default value | |||||
* Return a port's default value | |||||
* | * | ||||
* Returns the default value of a given port, if any exists, as a string. | * Returns the default value of a given port, if any exists, as a string. | ||||
* For the parameters, see the overloaded function. | * For the parameters, see the overloaded function. | ||||
@@ -266,7 +267,7 @@ const char* get_default_value(const char* port_name, const Ports& ports, | |||||
int32_t idx = -1, int recursive = 1); | int32_t idx = -1, int recursive = 1); | ||||
/** | /** | ||||
* @brief Returns a port's default value | |||||
* Return a port's default value | |||||
* | * | ||||
* Returns the default value of a given port, if any exists, as an array of | * Returns the default value of a given port, if any exists, as an array of | ||||
* rtosc_arg_vals . The values in the resulting array are being canonicalized, | * rtosc_arg_vals . The values in the resulting array are being canonicalized, | ||||
@@ -299,7 +300,7 @@ int get_default_value(const char* port_name, const char *port_args, | |||||
/** | /** | ||||
* @brief Return a string list of all changed values | |||||
* Return a string list of all changed values | |||||
* | * | ||||
* Return a human readable list of the value that changed | * Return a human readable list of the value that changed | ||||
* corresponding to the rDefault macro | * corresponding to the rDefault macro | ||||
@@ -309,9 +310,8 @@ int get_default_value(const char* port_name, const char *port_args, | |||||
*/ | */ | ||||
std::string get_changed_values(const Ports& ports, void* runtime); | std::string get_changed_values(const Ports& ports, void* runtime); | ||||
//! @brief Class to modify messages loaded from savefiles | |||||
//! | |||||
//! Object of this class shall be passed to savefile loading routines. You can | |||||
//! Class to modify messages loaded from savefiles. | |||||
//! Objects of this class shall be passed to savefile loading routines. You can | |||||
//! inherit to change the behaviour, e.g. to modify or discard such messages. | //! inherit to change the behaviour, e.g. to modify or discard such messages. | ||||
class savefile_dispatcher_t | class savefile_dispatcher_t | ||||
{ | { | ||||
@@ -362,8 +362,7 @@ private: | |||||
}; | }; | ||||
/** | /** | ||||
* @brief Scan OSC messages from human readable format and dispatch them | |||||
* | |||||
* Scan OSC messages from human readable format and dispatch them. | |||||
* @param messages The OSC messages, whitespace-separated | * @param messages The OSC messages, whitespace-separated | ||||
* @param ports The static ports structure | * @param ports The static ports structure | ||||
* @param runtime The runtime object | * @param runtime The runtime object | ||||
@@ -378,9 +377,7 @@ int dispatch_printed_messages(const char* messages, | |||||
savefile_dispatcher_t *dispatcher = NULL); | savefile_dispatcher_t *dispatcher = NULL); | ||||
/** | /** | ||||
* @brief Return a savefile containing all values that differ from the default | |||||
* values. | |||||
* | |||||
* Return a savefile containing all values that differ from the default values. | |||||
* @param ports The static ports structure | * @param ports The static ports structure | ||||
* @param runtime The runtime object | * @param runtime The runtime object | ||||
* @param appname Name of the application calling this function | * @param appname Name of the application calling this function | ||||
@@ -391,8 +388,7 @@ std::string save_to_file(const Ports& ports, void* runtime, | |||||
const char* appname, rtosc_version appver); | const char* appname, rtosc_version appver); | ||||
/** | /** | ||||
* @brief Read save file and dispatch contained parameters | |||||
* | |||||
* Read save file and dispatch contained parameters. | |||||
* @param file_content The file as a C string | * @param file_content The file as a C string | ||||
* @param ports The static ports structure | * @param ports The static ports structure | ||||
* @param runtime The runtime object | * @param runtime The runtime object | ||||
@@ -410,9 +406,9 @@ int load_from_file(const char* file_content, | |||||
savefile_dispatcher_t* dispatcher = NULL); | savefile_dispatcher_t* dispatcher = NULL); | ||||
/** | /** | ||||
* @brief Convert given argument values to their canonical representation, e.g. | |||||
* to the ports first (or-wise) argument types. | |||||
* Convert given argument values to their canonical representation. | |||||
* | * | ||||
* The ports first (or-wise) argument types are defined as canonical. | |||||
* E.g. if passing two 'S' argument values, the | * E.g. if passing two 'S' argument values, the | ||||
* port could be `portname::ii:cc:SS` or `portname::ii:t`. | * port could be `portname::ii:cc:SS` or `portname::ii:t`. | ||||
* | * | ||||
@@ -428,8 +424,7 @@ int canonicalize_arg_vals(rtosc_arg_val_t* av, size_t n, | |||||
const char* port_args, Port::MetaContainer meta); | const char* port_args, Port::MetaContainer meta); | ||||
/** | /** | ||||
* @brief Converts each of the given arguments to their mapped symbol, if | |||||
* possible | |||||
* Convert each of the given arguments to their mapped symbol, if possible. | |||||
* @param av The input and output argument values | * @param av The input and output argument values | ||||
* @param n The size of @p av | * @param n The size of @p av | ||||
* @param meta The port's metadata container | * @param meta The port's metadata container | ||||
@@ -442,7 +437,7 @@ void map_arg_vals(rtosc_arg_val_t* av, size_t n, | |||||
*********************/ | *********************/ | ||||
//typedef std::function<void(const Port*,const char*)> port_walker_t; | //typedef std::function<void(const Port*,const char*)> port_walker_t; | ||||
/** | /** | ||||
* @brief function pointer type for port walking | |||||
* Function pointer type for port walking. | |||||
* | * | ||||
* accepts: | * accepts: | ||||
* - the currently walked port | * - the currently walked port | ||||
@@ -458,7 +453,7 @@ typedef void(*port_walker_t)(const Port*,const char*,const char*, | |||||
const Ports&,void*,void*); | const Ports&,void*,void*); | ||||
/** | /** | ||||
* @brief Call a function on all ports and subports | |||||
* Call a function on all ports and subports. | |||||
* @param base The base port of traversing | * @param base The base port of traversing | ||||
* @param name_buffer Buffer which will be filled with the port name; must be | * @param name_buffer Buffer which will be filled with the port name; must be | ||||
* reset to zero over the full length! | * reset to zero over the full length! | ||||
@@ -474,7 +469,7 @@ void walk_ports(const Ports *base, | |||||
void *runtime = NULL); | void *runtime = NULL); | ||||
/** | /** | ||||
* @brief Return the index with value @p value from the metadata's enumeration | |||||
* Return the index with value @p value from the metadata's enumeration. | |||||
* @param meta The metadata | * @param meta The metadata | ||||
* @param value The value to search the key for | * @param value The value to search the key for | ||||
* @return The first key holding value, or `std::numeric_limits<int>::min()` | * @return The first key holding value, or `std::numeric_limits<int>::min()` | ||||
@@ -44,7 +44,7 @@ typedef struct | |||||
} rtosc_print_options; | } rtosc_print_options; | ||||
/** | /** | ||||
* @brief Pretty-print rtosct_arg_val_t structure into buffer | |||||
* Pretty-print rtosct_arg_val_t structure into buffer | |||||
* | * | ||||
* @param arg Pointer to the structure that shall be printed | * @param arg Pointer to the structure that shall be printed | ||||
* @param buffer The buffer to write to | * @param buffer The buffer to write to | ||||
@@ -59,7 +59,7 @@ size_t rtosc_print_arg_val(const rtosc_arg_val_t* arg, char* buffer, | |||||
int* cols_used); | int* cols_used); | ||||
/** | /** | ||||
* @brief Pretty-print rtosct_arg_val_t array into buffer | |||||
* Pretty-print rtosct_arg_val_t array into buffer | |||||
* | * | ||||
* @see rtosc_print_message | * @see rtosc_print_message | ||||
* @warning in case of possible line breaks (almost always), buffer[-1] must | * @warning in case of possible line breaks (almost always), buffer[-1] must | ||||
@@ -71,7 +71,7 @@ size_t rtosc_print_arg_vals(const rtosc_arg_val_t *args, size_t n, | |||||
int cols_used); | int cols_used); | ||||
/** | /** | ||||
* @brief Pretty-print OSC message into string buffer | |||||
* Pretty-print OSC message into string buffer | |||||
* | * | ||||
* A newline will be appended. | * A newline will be appended. | ||||
* | * | ||||
@@ -91,7 +91,7 @@ size_t rtosc_print_message(const char* address, | |||||
int cols_used); | int cols_used); | ||||
/** | /** | ||||
* @brief Skip characters from a string until one argument value | |||||
* Skip characters from a string until one argument value | |||||
* would have been scanned | * would have been scanned | ||||
* @param src The string | * @param src The string | ||||
* @return The first character after that argument value | * @return The first character after that argument value | ||||
@@ -99,9 +99,9 @@ size_t rtosc_print_message(const char* address, | |||||
const char* rtosc_skip_next_printed_arg(const char* src); | const char* rtosc_skip_next_printed_arg(const char* src); | ||||
/** | /** | ||||
* @brief Count arguments that would be scanned and do a complete syntax check | |||||
* Count arguments that would be scanned and do a complete syntax check | |||||
* | * | ||||
* This functions should be run before rtosc_scan_arg_vals() in order | |||||
* This function should be run before rtosc_scan_arg_vals() in order | |||||
* to know the number of argument values. Also, rtosc_scan_arg_vals() does | * to know the number of argument values. Also, rtosc_scan_arg_vals() does | ||||
* no complete syntax check. | * no complete syntax check. | ||||
* | * | ||||
@@ -112,7 +112,7 @@ const char* rtosc_skip_next_printed_arg(const char* src); | |||||
int rtosc_count_printed_arg_vals(const char* src); | int rtosc_count_printed_arg_vals(const char* src); | ||||
/** | /** | ||||
* @brief Count arguments of a message that would be scanned and | |||||
* Count arguments of a message that would be scanned and | |||||
* do a complete syntax check | * do a complete syntax check | ||||
* | * | ||||
* @param msg The message to scan from | * @param msg The message to scan from | ||||
@@ -123,7 +123,7 @@ int rtosc_count_printed_arg_vals(const char* src); | |||||
int rtosc_count_printed_arg_vals_of_msg(const char* msg); | int rtosc_count_printed_arg_vals_of_msg(const char* msg); | ||||
/** | /** | ||||
* @brief Scans one argument value from a string | |||||
* Scan one argument value from a string | |||||
* | * | ||||
* This function does no complete syntaxcheck. Call | * This function does no complete syntaxcheck. Call | ||||
* rtosc_count_printed_arg_vals() before. | * rtosc_count_printed_arg_vals() before. | ||||
@@ -141,7 +141,7 @@ size_t rtosc_scan_arg_val(const char* src, | |||||
char* buffer_for_strings, size_t* bufsize); | char* buffer_for_strings, size_t* bufsize); | ||||
/** | /** | ||||
* @brief Scan a fixed number of argument values from a string. | |||||
* Scan a fixed number of argument values from a string | |||||
* | * | ||||
* This function does no complete syntaxcheck. Call | * This function does no complete syntaxcheck. Call | ||||
* rtosc_count_printed_arg_vals() before. This will also give you the @p n | * rtosc_count_printed_arg_vals() before. This will also give you the @p n | ||||
@@ -154,7 +154,7 @@ size_t rtosc_scan_arg_vals(const char* src, | |||||
char* buffer_for_strings, size_t bufsize); | char* buffer_for_strings, size_t bufsize); | ||||
/** | /** | ||||
* @brief Scan an OSC message from a string. | |||||
* Scan an OSC message from a string | |||||
* | * | ||||
* This function does no complete syntaxcheck. Call | * This function does no complete syntaxcheck. Call | ||||
* rtosc_count_printed_arg_vals() before. This will also give you the @p n | * rtosc_count_printed_arg_vals() before. This will also give you the @p n | ||||
@@ -24,6 +24,7 @@ | |||||
/** | /** | ||||
* @file rtosc-version.h | * @file rtosc-version.h | ||||
* Definition of rtosc's version struct | |||||
* @note the implementation is in version.c.in | * @note the implementation is in version.c.in | ||||
*/ | */ | ||||
@@ -24,6 +24,7 @@ | |||||
/** | /** | ||||
* @file rtosc.h | * @file rtosc.h | ||||
* Functions handling messages and arguments | |||||
*/ | */ | ||||
#ifndef RTOSC_H | #ifndef RTOSC_H | ||||
@@ -135,7 +136,7 @@ typedef struct | |||||
} rtosc_cmp_options; | } rtosc_cmp_options; | ||||
/** | /** | ||||
* @brief Check if two arrays of rtosc_arg_val_t are equal | |||||
* Check if two arrays of rtosc_arg_val_t are equal | |||||
* | * | ||||
* @param opt Comparison options or NULL for default options | * @param opt Comparison options or NULL for default options | ||||
* @return One if they are equal, zero if not | * @return One if they are equal, zero if not | ||||
@@ -145,8 +146,7 @@ int rtosc_arg_vals_eq(rtosc_arg_val_t* lhs, rtosc_arg_val_t* rhs, | |||||
const rtosc_cmp_options* opt); | const rtosc_cmp_options* opt); | ||||
/** | /** | ||||
* @brief Compare two arrays of rtosc_arg_val_t. | |||||
* | |||||
* Compare two arrays of rtosc_arg_val_t. | |||||
* Whether an argument value is less or greater than another is computed | * Whether an argument value is less or greater than another is computed | ||||
* - using memcmp for blobs | * - using memcmp for blobs | ||||
* - using strcmp for strings and identifiers | * - using strcmp for strings and identifiers | ||||
@@ -166,7 +166,7 @@ int rtosc_arg_vals_cmp(rtosc_arg_val_t* lhs, rtosc_arg_val_t* rhs, | |||||
typedef struct { va_list a; } rtosc_va_list_t; | typedef struct { va_list a; } rtosc_va_list_t; | ||||
/** | /** | ||||
* @brief Pack arguments into pre-allocated rtosc_arg_t array | |||||
* Pack arguments into pre-allocated rtosc_arg_t array | |||||
* | * | ||||
* @param args Pre-allocated array; size must be greater or equal @p nargs | * @param args Pre-allocated array; size must be greater or equal @p nargs | ||||
* @param nargs Size of elements to pack | * @param nargs Size of elements to pack | ||||
@@ -177,16 +177,14 @@ void rtosc_v2args(rtosc_arg_t* args, size_t nargs, | |||||
const char* arg_str, rtosc_va_list_t* ap); | const char* arg_str, rtosc_va_list_t* ap); | ||||
/** | /** | ||||
* @brief Pack parameters into pre-allocated rtosc_arg_val-t array | |||||
* | |||||
* Pack parameters into pre-allocated rtosc_arg_val-t array | |||||
* @see rtosc_v2args | * @see rtosc_v2args | ||||
*/ | */ | ||||
void rtosc_v2argvals(rtosc_arg_val_t* args, size_t nargs, | void rtosc_v2argvals(rtosc_arg_val_t* args, size_t nargs, | ||||
const char* arg_str, va_list ap); | const char* arg_str, va_list ap); | ||||
/** | /** | ||||
* @brief Pack parameters into pre-allocated rtosc_arg_val-t array | |||||
* | |||||
* Pack parameters into pre-allocated rtosc_arg_val-t array | |||||
* @see rtosc_v2args | * @see rtosc_v2args | ||||
*/ | */ | ||||
void rtosc_2argvals(rtosc_arg_val_t* args, size_t nargs, | void rtosc_2argvals(rtosc_arg_val_t* args, size_t nargs, | ||||