@@ -221,7 +221,7 @@ protected: | |||||
float* efxoutr; | float* efxoutr; | ||||
// FIXME - is this thread-safe? | // FIXME - is this thread-safe? | ||||
SharedResourcePointer<Allocator> fAllocator; | |||||
SharedResourcePointer<AllocatorClass> fAllocator; | |||||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FxAbstractPlugin) | CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FxAbstractPlugin) | ||||
}; | }; | ||||
@@ -69,8 +69,11 @@ public: | |||||
fPrograms.append(new ProgramInfo(0, 0, "default", "")); | fPrograms.append(new ProgramInfo(0, 0, "default", "")); | ||||
Config config; | |||||
config.init(); | |||||
SYNTH_T synth; | SYNTH_T synth; | ||||
Master master(synth); | |||||
Master master(synth, &config); | |||||
// refresh banks | // refresh banks | ||||
master.bank.rescanforbanks(); | master.bank.rescanforbanks(); | ||||
@@ -210,6 +213,7 @@ public: | |||||
fMutex() | fMutex() | ||||
{ | { | ||||
sPrograms.initIfNeeded(); | sPrograms.initIfNeeded(); | ||||
fConfig.init(); | |||||
// init parameters to default | // init parameters to default | ||||
fParameters[kParamPart01Enabled] = 1.0f; | fParameters[kParamPart01Enabled] = 1.0f; | ||||
@@ -716,6 +720,7 @@ private: | |||||
MiddleWare* fMiddleWare; | MiddleWare* fMiddleWare; | ||||
Master* fMaster; | Master* fMaster; | ||||
SYNTH_T fSynth; | SYNTH_T fSynth; | ||||
Config fConfig; | |||||
bool fIsActive; | bool fIsActive; | ||||
float fParameters[kParamCount]; | float fParameters[kParamCount]; | ||||
@@ -768,7 +773,7 @@ private: | |||||
void _initMaster() | void _initMaster() | ||||
{ | { | ||||
fMiddleWare = new MiddleWare(fSynth); | |||||
fMiddleWare = new MiddleWare(std::move(fSynth), &fConfig); | |||||
fMiddleWare->setUiCallback(__uiCallback, this); | fMiddleWare->setUiCallback(__uiCallback, this); | ||||
fMiddleWare->setIdleCallback(_idleCallback, this); | fMiddleWare->setIdleCallback(_idleCallback, this); | ||||
_masterChangedCallback(fMiddleWare->spawnMaster()); | _masterChangedCallback(fMiddleWare->spawnMaster()); | ||||
@@ -891,32 +896,7 @@ private: | |||||
// ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
public: | |||||
static NativePluginHandle _instantiate(const NativeHostDescriptor* host) | |||||
{ | |||||
static bool needsInit = true; | |||||
if (needsInit) | |||||
{ | |||||
needsInit = false; | |||||
config.init(); | |||||
sprng(static_cast<prng_t>(std::time(nullptr))); | |||||
// FIXME - kill this | |||||
denormalkillbuf = new float[8192]; | |||||
for (int i=0; i < 8192; ++i) | |||||
denormalkillbuf[i] = (RND - 0.5f) * 1e-16f; | |||||
} | |||||
return new ZynAddSubFxPlugin(host); | |||||
} | |||||
static void _cleanup(NativePluginHandle handle) | |||||
{ | |||||
delete (ZynAddSubFxPlugin*)handle; | |||||
} | |||||
PluginClassEND(ZynAddSubFxPlugin) | |||||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ZynAddSubFxPlugin) | CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ZynAddSubFxPlugin) | ||||
}; | }; | ||||
@@ -24,6 +24,7 @@ | |||||
#include "../Misc/Allocator.h" | #include "../Misc/Allocator.h" | ||||
#include "Unison.h" | #include "Unison.h" | ||||
#include "globals.h" | |||||
#ifndef errx | #ifndef errx | ||||
#include <err.h> | #include <err.h> | ||||
@@ -205,41 +205,26 @@ float EQ::getfreqresponse(float freq) | |||||
return rap2dB(resp * outvolume); | return rap2dB(resp * outvolume); | ||||
} | } | ||||
//full taps & three filter taps | |||||
static void convolve(float *a, const float *filter) | |||||
{ | |||||
float tmp[MAX_EQ_BANDS*2+1]; | |||||
for(int i=0; i<MAX_EQ_BANDS*2+1; ++i) | |||||
tmp[i] = a[i]; | |||||
//Base Case | |||||
a[0] = tmp[0]*filter[0]; | |||||
a[1] = tmp[0]*filter[1] + tmp[1]*filter[0]; | |||||
for(int i=2; i<MAX_EQ_BANDS+1; ++i) { | |||||
a[i] = filter[0]*tmp[i] + | |||||
filter[1]*tmp[i-1] + | |||||
filter[2]*tmp[i-2]; | |||||
} | |||||
} | |||||
//Not exactly the most efficient manner to derive the total taps, but it should | //Not exactly the most efficient manner to derive the total taps, but it should | ||||
//be fast enough in practice | //be fast enough in practice | ||||
void EQ::getFilter(float *a, float *b) const | void EQ::getFilter(float *a, float *b) const | ||||
{ | { | ||||
a[0] = 1; | a[0] = 1; | ||||
b[0] = 1; | b[0] = 1; | ||||
off_t off=0; | |||||
for(int i = 0; i < MAX_EQ_BANDS; ++i) { | for(int i = 0; i < MAX_EQ_BANDS; ++i) { | ||||
auto &F = filter[i]; | auto &F = filter[i]; | ||||
if(F.Ptype == 0) | if(F.Ptype == 0) | ||||
continue; | continue; | ||||
float Fb[3] = {F.l->coeff.c[0], F.l->coeff.c[1], F.l->coeff.c[2]}; | |||||
float Fa[3] = {1.0f, -F.l->coeff.d[1], -F.l->coeff.d[2]}; | |||||
const double Fb[3] = {F.l->coeff.c[0], F.l->coeff.c[1], F.l->coeff.c[2]}; | |||||
const double Fa[3] = {1.0f, -F.l->coeff.d[1], -F.l->coeff.d[2]}; | |||||
for(int j=0; j<F.Pstages+1; ++j) { | for(int j=0; j<F.Pstages+1; ++j) { | ||||
convolve(b, Fb); | |||||
convolve(a, Fa); | |||||
for(int k=0; k<3; ++k) { | |||||
a[off] = Fa[k]; | |||||
b[off] = Fb[k]; | |||||
off++; | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -38,8 +38,8 @@ class EQ:public Effect | |||||
void cleanup(void); | void cleanup(void); | ||||
float getfreqresponse(float freq); | float getfreqresponse(float freq); | ||||
void getFilter(float *a/*[MAX_EQ_BANDS*MAX_FILTER_STAGES*2+1]*/, | |||||
float *b/*[MAX_EQ_BANDS*MAX_FILTER_STAGES*2+1]*/) const; | |||||
void getFilter(float *a/*[MAX_EQ_BANDS*MAX_FILTER_STAGES*3]*/, | |||||
float *b/*[MAX_EQ_BANDS*MAX_FILTER_STAGES*3]*/) const; | |||||
private: | private: | ||||
//Parameters | //Parameters | ||||
unsigned char Pvolume; | unsigned char Pvolume; | ||||
@@ -24,6 +24,7 @@ | |||||
#include "../Misc/Util.h" | #include "../Misc/Util.h" | ||||
#include <cmath> | #include <cmath> | ||||
#include "globals.h" | |||||
EffectLFO::EffectLFO(float srate_f, float bufsize_f) | EffectLFO::EffectLFO(float srate_f, float bufsize_f) | ||||
:Pfreq(40), | :Pfreq(40), | ||||
@@ -79,7 +80,7 @@ float EffectLFO::getlfoshape(float x) | |||||
break; | break; | ||||
//when adding more, ensure ::updateparams() gets updated | //when adding more, ensure ::updateparams() gets updated | ||||
default: | default: | ||||
out = cosf(x * 2.0f * PI); //EffectLFO_SINE | |||||
out = cosf(x * 2.0f * PI); //EffectLFO_SINE // TODO: use M_PI ? | |||||
} | } | ||||
return out; | return out; | ||||
} | } | ||||
@@ -26,12 +26,14 @@ | |||||
#include "EffectMgr.h" | #include "EffectMgr.h" | ||||
#include "Effect.h" | #include "Effect.h" | ||||
#include "Alienwah.h" | |||||
#include "Reverb.h" | #include "Reverb.h" | ||||
#include "Echo.h" | #include "Echo.h" | ||||
#include "Chorus.h" | #include "Chorus.h" | ||||
#include "Distorsion.h" | #include "Distorsion.h" | ||||
#include "EQ.h" | #include "EQ.h" | ||||
#include "DynamicFilter.h" | #include "DynamicFilter.h" | ||||
#include "Phaser.h" | |||||
#include "../Misc/XMLwrapper.h" | #include "../Misc/XMLwrapper.h" | ||||
#include "../Misc/Util.h" | #include "../Misc/Util.h" | ||||
#include "../Params/FilterParams.h" | #include "../Params/FilterParams.h" | ||||
@@ -75,8 +77,8 @@ static const rtosc::Ports local_ports = { | |||||
if(eff->nefx != 7) | if(eff->nefx != 7) | ||||
return; | return; | ||||
EQ *eq = (EQ*)eff->efx; | EQ *eq = (EQ*)eff->efx; | ||||
float a[MAX_EQ_BANDS*MAX_FILTER_STAGES*2+1]; | |||||
float b[MAX_EQ_BANDS*MAX_FILTER_STAGES*2+1]; | |||||
float a[MAX_EQ_BANDS*MAX_FILTER_STAGES*3]; | |||||
float b[MAX_EQ_BANDS*MAX_FILTER_STAGES*3]; | |||||
memset(a, 0, sizeof(a)); | memset(a, 0, sizeof(a)); | ||||
memset(b, 0, sizeof(b)); | memset(b, 0, sizeof(b)); | ||||
eq->getFilter(a,b); | eq->getFilter(a,b); | ||||
@@ -307,8 +309,8 @@ void EffectMgr::out(float *smpsl, float *smpsr) | |||||
return; | return; | ||||
} | } | ||||
for(int i = 0; i < synth.buffersize; ++i) { | for(int i = 0; i < synth.buffersize; ++i) { | ||||
smpsl[i] += denormalkillbuf[i]; | |||||
smpsr[i] += denormalkillbuf[i]; | |||||
smpsl[i] += synth.denormalkillbuf[i]; | |||||
smpsr[i] += synth.denormalkillbuf[i]; | |||||
efxoutl[i] = 0.0f; | efxoutl[i] = 0.0f; | ||||
efxoutr[i] = 0.0f; | efxoutr[i] = 0.0f; | ||||
} | } | ||||
@@ -24,22 +24,15 @@ | |||||
#include <pthread.h> | #include <pthread.h> | ||||
#include "Alienwah.h" | |||||
#include "Phaser.h" | |||||
#include "../Params/Presets.h" | |||||
class Effect; | class Effect; | ||||
class FilterParams; | class FilterParams; | ||||
class XMLwrapper; | class XMLwrapper; | ||||
class Allocator; | class Allocator; | ||||
#include "Distorsion.h" | |||||
#include "EQ.h" | |||||
#include "DynamicFilter.h" | |||||
#include "../Params/FilterParams.h" | #include "../Params/FilterParams.h" | ||||
#include "../Params/Presets.h" | #include "../Params/Presets.h" | ||||
/**Effect manager, an interface betwen the program and effects*/ | |||||
/** Effect manager, an interface between the program and effects */ | |||||
class EffectMgr:public Presets | class EffectMgr:public Presets | ||||
{ | { | ||||
public: | public: | ||||
@@ -7,7 +7,7 @@ | |||||
#include "Allocator.h" | #include "Allocator.h" | ||||
//Used for dummy allocations | //Used for dummy allocations | ||||
Allocator DummyAlloc; | |||||
DummyAllocator DummyAlloc; | |||||
//recursive type class to avoid void *v = *(void**)v style casting | //recursive type class to avoid void *v = *(void**)v style casting | ||||
struct next_t | struct next_t | ||||
@@ -57,7 +57,7 @@ Allocator::~Allocator(void) | |||||
delete impl; | delete impl; | ||||
} | } | ||||
void *Allocator::alloc_mem(size_t mem_size) | |||||
void *AllocatorClass::alloc_mem(size_t mem_size) | |||||
{ | { | ||||
impl->totalAlloced += mem_size; | impl->totalAlloced += mem_size; | ||||
void *mem = tlsf_malloc(impl->tlsf, mem_size); | void *mem = tlsf_malloc(impl->tlsf, mem_size); | ||||
@@ -66,14 +66,14 @@ void *Allocator::alloc_mem(size_t mem_size) | |||||
//printf("Allocator result = %p\n", mem); | //printf("Allocator result = %p\n", mem); | ||||
return mem; | return mem; | ||||
} | } | ||||
void Allocator::dealloc_mem(void *memory) | |||||
void AllocatorClass::dealloc_mem(void *memory) | |||||
{ | { | ||||
//printf("dealloc_mem(%d)\n", tlsf_block_size(memory)); | //printf("dealloc_mem(%d)\n", tlsf_block_size(memory)); | ||||
tlsf_free(impl->tlsf, memory); | tlsf_free(impl->tlsf, memory); | ||||
//free(memory); | //free(memory); | ||||
} | } | ||||
bool Allocator::lowMemory(unsigned n, size_t chunk_size) | |||||
bool AllocatorClass::lowMemory(unsigned n, size_t chunk_size) const | |||||
{ | { | ||||
//This should stay on the stack | //This should stay on the stack | ||||
void *buf[n]; | void *buf[n]; | ||||
@@ -90,7 +90,7 @@ bool Allocator::lowMemory(unsigned n, size_t chunk_size) | |||||
} | } | ||||
void Allocator::addMemory(void *v, size_t mem_size) | |||||
void AllocatorClass::addMemory(void *v, size_t mem_size) | |||||
{ | { | ||||
next_t *n = impl->pools; | next_t *n = impl->pools; | ||||
while(n->next) n = n->next; | while(n->next) n = n->next; | ||||
@@ -124,7 +124,7 @@ typedef struct block_header_t | |||||
static const size_t block_header_free_bit = 1 << 0; | static const size_t block_header_free_bit = 1 << 0; | ||||
#endif | #endif | ||||
bool Allocator::memFree(void *pool) | |||||
bool Allocator::memFree(void *pool) const | |||||
{ | { | ||||
size_t bh_shift = sizeof(next_t)+sizeof(size_t); | size_t bh_shift = sizeof(next_t)+sizeof(size_t); | ||||
//Assume that memory is free to start with | //Assume that memory is free to start with | ||||
@@ -145,7 +145,7 @@ bool Allocator::memFree(void *pool) | |||||
return isFree; | return isFree; | ||||
} | } | ||||
int Allocator::memPools() | |||||
int Allocator::memPools() const | |||||
{ | { | ||||
int i = 1; | int i = 1; | ||||
next_t *n = impl->pools; | next_t *n = impl->pools; | ||||
@@ -156,7 +156,7 @@ int Allocator::memPools() | |||||
return i; | return i; | ||||
} | } | ||||
int Allocator::freePools() | |||||
int Allocator::freePools() const | |||||
{ | { | ||||
int i = 0; | int i = 0; | ||||
next_t *n = impl->pools->next; | next_t *n = impl->pools->next; | ||||
@@ -169,7 +169,7 @@ int Allocator::freePools() | |||||
} | } | ||||
unsigned long long Allocator::totalAlloced() | |||||
unsigned long long Allocator::totalAlloced() const | |||||
{ | { | ||||
return impl->totalAlloced; | return impl->totalAlloced; | ||||
} | } | ||||
@@ -2,14 +2,17 @@ | |||||
#include <cstdlib> | #include <cstdlib> | ||||
#include <utility> | #include <utility> | ||||
//! Allocator Base class | |||||
//! subclasses must specify allocation and deallocation | |||||
class Allocator | class Allocator | ||||
{ | { | ||||
public: | public: | ||||
Allocator(void); | Allocator(void); | ||||
Allocator(const Allocator&) = delete; | Allocator(const Allocator&) = delete; | ||||
~Allocator(void); | |||||
void *alloc_mem(size_t mem_size); | |||||
void dealloc_mem(void *memory); | |||||
virtual ~Allocator(void); | |||||
virtual void *alloc_mem(size_t mem_size) = 0; | |||||
virtual void dealloc_mem(void *memory) = 0; | |||||
template <typename T, typename... Ts> | template <typename T, typename... Ts> | ||||
T *alloc(Ts&&... ts) | T *alloc(Ts&&... ts) | ||||
@@ -64,23 +67,47 @@ class Allocator | |||||
} | } | ||||
} | } | ||||
void addMemory(void *, size_t mem_size); | |||||
virtual void addMemory(void *, size_t mem_size) = 0; | |||||
//Return true if the current pool cannot allocate n chunks of chunk_size | //Return true if the current pool cannot allocate n chunks of chunk_size | ||||
bool lowMemory(unsigned n, size_t chunk_size); | |||||
bool memFree(void *pool); | |||||
virtual bool lowMemory(unsigned n, size_t chunk_size) const = 0; | |||||
bool memFree(void *pool) const; | |||||
//returns number of pools | //returns number of pools | ||||
int memPools(); | |||||
int memPools() const; | |||||
int freePools(); | |||||
int freePools() const; | |||||
unsigned long long totalAlloced(); | |||||
unsigned long long totalAlloced() const; | |||||
struct AllocatorImpl *impl; | struct AllocatorImpl *impl; | ||||
}; | }; | ||||
extern Allocator DummyAlloc; | |||||
//! the allocator for normal use | |||||
class AllocatorClass : public Allocator | |||||
{ | |||||
void *alloc_mem(size_t mem_size); | |||||
void dealloc_mem(void *memory); | |||||
void addMemory(void *, size_t mem_size); | |||||
bool lowMemory(unsigned n, size_t chunk_size) const; | |||||
using Allocator::Allocator; | |||||
}; | |||||
//! the dummy allocator, which does not allow any allocation | |||||
class DummyAllocator : public Allocator | |||||
{ | |||||
void not_allowed() const { | |||||
throw "(de)allocation forbidden"; // TODO: std exception | |||||
} | |||||
public: | |||||
void *alloc_mem(size_t ) { return not_allowed(), nullptr; } | |||||
void dealloc_mem(void* ) { not_allowed(); } // TODO: more functions? | |||||
void addMemory(void *, size_t ) { not_allowed(); } | |||||
bool lowMemory(unsigned , size_t ) const { return not_allowed(), true; } | |||||
using Allocator::Allocator; | |||||
}; | |||||
extern DummyAllocator DummyAlloc; | |||||
/** | /** | ||||
* General notes on Memory Allocation Within ZynAddSubFX | * General notes on Memory Allocation Within ZynAddSubFX | ||||
@@ -46,16 +46,16 @@ | |||||
using namespace std; | using namespace std; | ||||
Bank::Bank() | |||||
:bankpos(0), defaultinsname(" ") | |||||
Bank::Bank(Config *config) | |||||
:bankpos(0), defaultinsname(" "), config(config) | |||||
{ | { | ||||
clearbank(); | clearbank(); | ||||
bankfiletitle = dirname; | bankfiletitle = dirname; | ||||
rescanforbanks(); | rescanforbanks(); | ||||
loadbank(config.cfg.currentBankDir); | |||||
loadbank(config->cfg.currentBankDir); | |||||
for(unsigned i=0; i<banks.size(); ++i) { | for(unsigned i=0; i<banks.size(); ++i) { | ||||
if(banks[i].dir == config.cfg.currentBankDir) { | |||||
if(banks[i].dir == config->cfg.currentBankDir) { | |||||
bankpos = i; | bankpos = i; | ||||
break; | break; | ||||
} | } | ||||
@@ -270,7 +270,7 @@ int Bank::loadbank(string bankdirname) | |||||
closedir(dir); | closedir(dir); | ||||
if(!dirname.empty()) | if(!dirname.empty()) | ||||
config.cfg.currentBankDir = dirname; | |||||
config->cfg.currentBankDir = dirname; | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -281,7 +281,7 @@ int Bank::loadbank(string bankdirname) | |||||
int Bank::newbank(string newbankdirname) | int Bank::newbank(string newbankdirname) | ||||
{ | { | ||||
string bankdir; | string bankdir; | ||||
bankdir = config.cfg.bankRootDirList[0]; | |||||
bankdir = config->cfg.bankRootDirList[0]; | |||||
if(((bankdir[bankdir.size() - 1]) != '/') | if(((bankdir[bankdir.size() - 1]) != '/') | ||||
&& ((bankdir[bankdir.size() - 1]) != '\\')) | && ((bankdir[bankdir.size() - 1]) != '\\')) | ||||
@@ -361,8 +361,8 @@ void Bank::rescanforbanks() | |||||
banks.clear(); | banks.clear(); | ||||
for(int i = 0; i < MAX_BANK_ROOT_DIRS; ++i) | for(int i = 0; i < MAX_BANK_ROOT_DIRS; ++i) | ||||
if(!config.cfg.bankRootDirList[i].empty()) | |||||
scanrootdir(config.cfg.bankRootDirList[i]); | |||||
if(!config->cfg.bankRootDirList[i].empty()) | |||||
scanrootdir(config->cfg.bankRootDirList[i]); | |||||
//sort the banks | //sort the banks | ||||
sort(banks.begin(), banks.end()); | sort(banks.begin(), banks.end()); | ||||
@@ -26,6 +26,7 @@ | |||||
#include <string> | #include <string> | ||||
#include <vector> | #include <vector> | ||||
#include "../globals.h" | #include "../globals.h" | ||||
#include "Config.h" | |||||
//entries in a bank | //entries in a bank | ||||
#define BANK_SIZE 160 | #define BANK_SIZE 160 | ||||
@@ -35,7 +36,7 @@ class Bank | |||||
{ | { | ||||
public: | public: | ||||
/**Constructor*/ | /**Constructor*/ | ||||
Bank(); | |||||
Bank(Config* config); | |||||
~Bank(); | ~Bank(); | ||||
std::string getname(unsigned int ninstrument); | std::string getname(unsigned int ninstrument); | ||||
std::string getnamenumbered(unsigned int ninstrument); | std::string getnamenumbered(unsigned int ninstrument); | ||||
@@ -96,6 +97,8 @@ class Bank | |||||
std::string dirname; | std::string dirname; | ||||
void scanrootdir(std::string rootdir); //scans a root dir for banks | void scanrootdir(std::string rootdir); //scans a root dir for banks | ||||
Config* const config; | |||||
}; | }; | ||||
#endif | #endif |
@@ -28,6 +28,7 @@ | |||||
#include <rtosc/port-sugar.h> | #include <rtosc/port-sugar.h> | ||||
#include "Config.h" | #include "Config.h" | ||||
#include "globals.h" | |||||
#include "XMLwrapper.h" | #include "XMLwrapper.h" | ||||
#define rStdString(name, len, ...) \ | #define rStdString(name, len, ...) \ | ||||
@@ -46,7 +47,7 @@ | |||||
#if 1 | #if 1 | ||||
#define rObject Config | #define rObject Config | ||||
static rtosc::Ports ports = { | |||||
static const rtosc::Ports ports = { | |||||
//rString(cfg.LinuxOSSWaveOutDev), | //rString(cfg.LinuxOSSWaveOutDev), | ||||
//rString(cfg.LinuxOSSSeqInDev), | //rString(cfg.LinuxOSSSeqInDev), | ||||
rParamI(cfg.SampleRate, "samples of audio per second"), | rParamI(cfg.SampleRate, "samples of audio per second"), | ||||
@@ -145,7 +146,7 @@ static rtosc::Ports ports = { | |||||
d.broadcast(d.loc, "i", (int)(log(c.cfg.OscilSize*1.0)/log(2.0))); | d.broadcast(d.loc, "i", (int)(log(c.cfg.OscilSize*1.0)/log(2.0))); | ||||
}}, | }}, | ||||
}; | }; | ||||
rtosc::Ports &Config::ports = ::ports; | |||||
const rtosc::Ports &Config::ports = ::ports; | |||||
#endif | #endif | ||||
Config::Config() | Config::Config() | ||||
@@ -160,10 +161,10 @@ void Config::init() | |||||
cfg.OscilSize = 1024; | cfg.OscilSize = 1024; | ||||
cfg.SwapStereo = 0; | cfg.SwapStereo = 0; | ||||
cfg.LinuxOSSWaveOutDev = new char[MAX_STRING_SIZE]; | |||||
snprintf(cfg.LinuxOSSWaveOutDev, MAX_STRING_SIZE, "/dev/dsp"); | |||||
cfg.LinuxOSSSeqInDev = new char[MAX_STRING_SIZE]; | |||||
snprintf(cfg.LinuxOSSSeqInDev, MAX_STRING_SIZE, "/dev/sequencer"); | |||||
cfg.oss_devs.linux_wave_out = new char[MAX_STRING_SIZE]; | |||||
snprintf(cfg.oss_devs.linux_wave_out, MAX_STRING_SIZE, "/dev/dsp"); | |||||
cfg.oss_devs.linux_seq_in = new char[MAX_STRING_SIZE]; | |||||
snprintf(cfg.oss_devs.linux_seq_in, MAX_STRING_SIZE, "/dev/sequencer"); | |||||
cfg.WindowsWaveOutId = 0; | cfg.WindowsWaveOutId = 0; | ||||
cfg.WindowsMidiInId = 0; | cfg.WindowsMidiInId = 0; | ||||
@@ -228,8 +229,8 @@ void Config::init() | |||||
Config::~Config() | Config::~Config() | ||||
{ | { | ||||
delete [] cfg.LinuxOSSWaveOutDev; | |||||
delete [] cfg.LinuxOSSSeqInDev; | |||||
delete [] cfg.oss_devs.linux_wave_out; | |||||
delete [] cfg.oss_devs.linux_seq_in; | |||||
for(int i = 0; i < winmidimax; ++i) | for(int i = 0; i < winmidimax; ++i) | ||||
delete [] winmididevices[i].name; | delete [] winmididevices[i].name; | ||||
@@ -237,7 +238,7 @@ Config::~Config() | |||||
} | } | ||||
void Config::save() | |||||
void Config::save() const | |||||
{ | { | ||||
char filename[MAX_STRING_SIZE]; | char filename[MAX_STRING_SIZE]; | ||||
getConfigFileName(filename, MAX_STRING_SIZE); | getConfigFileName(filename, MAX_STRING_SIZE); | ||||
@@ -330,10 +331,10 @@ void Config::readConfig(const char *filename) | |||||
//linux stuff | //linux stuff | ||||
xmlcfg.getparstr("linux_oss_wave_out_dev", | xmlcfg.getparstr("linux_oss_wave_out_dev", | ||||
cfg.LinuxOSSWaveOutDev, | |||||
cfg.oss_devs.linux_wave_out, | |||||
MAX_STRING_SIZE); | MAX_STRING_SIZE); | ||||
xmlcfg.getparstr("linux_oss_seq_in_dev", | xmlcfg.getparstr("linux_oss_seq_in_dev", | ||||
cfg.LinuxOSSSeqInDev, | |||||
cfg.oss_devs.linux_seq_in, | |||||
MAX_STRING_SIZE); | MAX_STRING_SIZE); | ||||
//windows stuff | //windows stuff | ||||
@@ -352,7 +353,7 @@ void Config::readConfig(const char *filename) | |||||
cfg.OscilSize = (int) powf(2, ceil(logf(cfg.OscilSize - 1.0f) / logf(2.0f))); | cfg.OscilSize = (int) powf(2, ceil(logf(cfg.OscilSize - 1.0f) / logf(2.0f))); | ||||
} | } | ||||
void Config::saveConfig(const char *filename) | |||||
void Config::saveConfig(const char *filename) const | |||||
{ | { | ||||
XMLwrapper *xmlcfg = new XMLwrapper(); | XMLwrapper *xmlcfg = new XMLwrapper(); | ||||
@@ -392,8 +393,8 @@ void Config::saveConfig(const char *filename) | |||||
xmlcfg->addpar("interpolation", cfg.Interpolation); | xmlcfg->addpar("interpolation", cfg.Interpolation); | ||||
//linux stuff | //linux stuff | ||||
xmlcfg->addparstr("linux_oss_wave_out_dev", cfg.LinuxOSSWaveOutDev); | |||||
xmlcfg->addparstr("linux_oss_seq_in_dev", cfg.LinuxOSSSeqInDev); | |||||
xmlcfg->addparstr("linux_oss_wave_out_dev", cfg.oss_devs.linux_wave_out); | |||||
xmlcfg->addparstr("linux_oss_seq_in_dev", cfg.oss_devs.linux_seq_in); | |||||
//windows stuff | //windows stuff | ||||
xmlcfg->addpar("windows_wave_out_id", cfg.WindowsWaveOutId); | xmlcfg->addpar("windows_wave_out_id", cfg.WindowsWaveOutId); | ||||
@@ -401,15 +402,13 @@ void Config::saveConfig(const char *filename) | |||||
xmlcfg->endbranch(); | xmlcfg->endbranch(); | ||||
int tmp = cfg.GzipCompression; | |||||
cfg.GzipCompression = 0; | |||||
xmlcfg->saveXMLfile(filename); | |||||
cfg.GzipCompression = tmp; | |||||
// for some reason (which one?), the gzip compression is bashed to 0 | |||||
xmlcfg->saveXMLfile(filename, 0); | |||||
delete (xmlcfg); | delete (xmlcfg); | ||||
} | } | ||||
void Config::getConfigFileName(char *name, int namesize) | |||||
void Config::getConfigFileName(char *name, int namesize) const | |||||
{ | { | ||||
name[0] = 0; | name[0] = 0; | ||||
snprintf(name, namesize, "%s%s", getenv("HOME"), "/.zynaddsubfxXML.cfg"); | snprintf(name, namesize, "%s%s", getenv("HOME"), "/.zynaddsubfxXML.cfg"); | ||||
@@ -22,21 +22,32 @@ | |||||
#ifndef CONFIG_H | #ifndef CONFIG_H | ||||
#define CONFIG_H | #define CONFIG_H | ||||
#include "../globals.h" | |||||
#include <string> | #include <string> | ||||
#define MAX_STRING_SIZE 4000 | #define MAX_STRING_SIZE 4000 | ||||
#define MAX_BANK_ROOT_DIRS 100 | #define MAX_BANK_ROOT_DIRS 100 | ||||
namespace rtosc | |||||
{ | |||||
struct Ports; | |||||
} | |||||
class oss_devs_t | |||||
{ | |||||
public: | |||||
char *linux_wave_out, *linux_seq_in; | |||||
}; | |||||
/**Configuration file functions*/ | /**Configuration file functions*/ | ||||
class Config | class Config | ||||
{ | { | ||||
public: | public: | ||||
/** Constructor*/ | |||||
Config(); | Config(); | ||||
/** Destructor*/ | |||||
Config(const Config& ) = delete; | |||||
~Config(); | ~Config(); | ||||
struct { | struct { | ||||
char *LinuxOSSWaveOutDev, *LinuxOSSSeqInDev; | |||||
oss_devs_t oss_devs; | |||||
int SampleRate, SoundBufferSize, OscilSize, SwapStereo; | int SampleRate, SoundBufferSize, OscilSize, SwapStereo; | ||||
int WindowsWaveOutId, WindowsMidiInId; | int WindowsWaveOutId, WindowsMidiInId; | ||||
int BankUIAutoClose; | int BankUIAutoClose; | ||||
@@ -62,12 +73,12 @@ class Config | |||||
void clearbankrootdirlist(); | void clearbankrootdirlist(); | ||||
void clearpresetsdirlist(); | void clearpresetsdirlist(); | ||||
void init(); | void init(); | ||||
void save(); | |||||
void save() const; | |||||
static rtosc::Ports &ports; | |||||
static const rtosc::Ports &ports; | |||||
private: | private: | ||||
void readConfig(const char *filename); | void readConfig(const char *filename); | ||||
void saveConfig(const char *filename); | |||||
void getConfigFileName(char *name, int namesize); | |||||
void saveConfig(const char *filename) const; | |||||
void getConfigFileName(char *name, int namesize) const; | |||||
}; | }; | ||||
#endif | #endif |
@@ -25,6 +25,8 @@ | |||||
#include "Part.h" | #include "Part.h" | ||||
#include "../Misc/Stereo.h" | |||||
#include "../Misc/Util.h" | |||||
#include "../Params/LFOParams.h" | #include "../Params/LFOParams.h" | ||||
#include "../Effects/EffectMgr.h" | #include "../Effects/EffectMgr.h" | ||||
#include "../DSP/FFTwrapper.h" | #include "../DSP/FFTwrapper.h" | ||||
@@ -286,12 +288,15 @@ vuData::vuData(void) | |||||
rmspeakl(0.0f), rmspeakr(0.0f), clipped(0) | rmspeakl(0.0f), rmspeakr(0.0f), clipped(0) | ||||
{} | {} | ||||
Master::Master(const SYNTH_T &synth_) | |||||
:HDDRecorder(synth_), ctl(synth_), midi(Master::ports), frozenState(false), pendingMemory(false), synth(synth_) | |||||
Master::Master(const SYNTH_T &synth_, Config* config) | |||||
:HDDRecorder(synth_), ctl(synth_), | |||||
microtonal(config->cfg.GzipCompression), bank(config), | |||||
midi(Master::ports), frozenState(false), pendingMemory(false), | |||||
synth(synth_), gzip_compression(config->cfg.GzipCompression) | |||||
{ | { | ||||
bToU = NULL; | bToU = NULL; | ||||
uToB = NULL; | uToB = NULL; | ||||
memory = new Allocator(); | |||||
memory = new AllocatorClass(); | |||||
swaplr = 0; | swaplr = 0; | ||||
off = 0; | off = 0; | ||||
smps = 0; | smps = 0; | ||||
@@ -310,7 +315,8 @@ Master::Master(const SYNTH_T &synth_) | |||||
} | } | ||||
for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart) | for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart) | ||||
part[npart] = new Part(*memory, synth, µtonal, fft); | |||||
part[npart] = new Part(*memory, synth, config->cfg.GzipCompression, | |||||
config->cfg.Interpolation, µtonal, fft); | |||||
//Insertion Effects init | //Insertion Effects init | ||||
for(int nefx = 0; nefx < NUM_INS_EFX; ++nefx) | for(int nefx = 0; nefx < NUM_INS_EFX; ++nefx) | ||||
@@ -1044,7 +1050,7 @@ int Master::saveXML(const char *filename) | |||||
add2XML(xml); | add2XML(xml); | ||||
xml->endbranch(); | xml->endbranch(); | ||||
int result = xml->saveXMLfile(filename); | |||||
int result = xml->saveXMLfile(filename, gzip_compression); | |||||
delete (xml); | delete (xml); | ||||
return result; | return result; | ||||
} | } | ||||
@@ -49,7 +49,7 @@ class Master | |||||
{ | { | ||||
public: | public: | ||||
/** Constructor TODO make private*/ | /** Constructor TODO make private*/ | ||||
Master(const SYNTH_T &synth); | |||||
Master(const SYNTH_T &synth, class Config *config); | |||||
/** Destructor*/ | /** Destructor*/ | ||||
~Master(); | ~Master(); | ||||
@@ -171,6 +171,7 @@ class Master | |||||
rtosc::ThreadLink *uToB; | rtosc::ThreadLink *uToB; | ||||
bool pendingMemory; | bool pendingMemory; | ||||
const SYNTH_T &synth; | const SYNTH_T &synth; | ||||
const int& gzip_compression; //!< value from config | |||||
private: | private: | ||||
float sysefxvol[NUM_SYS_EFX][NUM_MIDI_PARTS]; | float sysefxvol[NUM_SYS_EFX][NUM_MIDI_PARTS]; | ||||
float sysefxsend[NUM_SYS_EFX][NUM_SYS_EFX]; | float sysefxsend[NUM_SYS_EFX][NUM_SYS_EFX]; | ||||
@@ -75,7 +75,8 @@ const rtosc::Ports Microtonal::ports = { | |||||
}; | }; | ||||
Microtonal::Microtonal() | |||||
Microtonal::Microtonal(const int &gzip_compression) | |||||
: gzip_compression(gzip_compression) | |||||
{ | { | ||||
defaults(); | defaults(); | ||||
} | } | ||||
@@ -688,7 +689,7 @@ int Microtonal::saveXML(const char *filename) const | |||||
add2XML(xml); | add2XML(xml); | ||||
xml->endbranch(); | xml->endbranch(); | ||||
int result = xml->saveXMLfile(filename); | |||||
int result = xml->saveXMLfile(filename, gzip_compression); | |||||
delete (xml); | delete (xml); | ||||
return result; | return result; | ||||
} | } | ||||
@@ -36,7 +36,7 @@ class Microtonal | |||||
{ | { | ||||
public: | public: | ||||
/**Constructor*/ | /**Constructor*/ | ||||
Microtonal(); | |||||
Microtonal(const int& gzip_compression); | |||||
/**Destructor*/ | /**Destructor*/ | ||||
~Microtonal(); | ~Microtonal(); | ||||
void defaults(); | void defaults(); | ||||
@@ -131,6 +131,8 @@ class Microtonal | |||||
//the real tunning is x1/x2 | //the real tunning is x1/x2 | ||||
unsigned int x1, x2; | unsigned int x1, x2; | ||||
} octave[MAX_OCTAVE_SIZE], tmpoctave[MAX_OCTAVE_SIZE]; | } octave[MAX_OCTAVE_SIZE], tmpoctave[MAX_OCTAVE_SIZE]; | ||||
const int& gzip_compression; | |||||
}; | }; | ||||
#endif | #endif |
@@ -12,7 +12,6 @@ | |||||
#include <lo/lo.h> | #include <lo/lo.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#include <dirent.h> | |||||
#include "../UI/Connection.h" | #include "../UI/Connection.h" | ||||
#include "../UI/Fl_Osc_Interface.h" | #include "../UI/Fl_Osc_Interface.h" | ||||
@@ -20,6 +19,7 @@ | |||||
#include <map> | #include <map> | ||||
#include "Util.h" | #include "Util.h" | ||||
#include "TmpFileMgr.h" | |||||
#include "Master.h" | #include "Master.h" | ||||
#include "Part.h" | #include "Part.h" | ||||
#include "PresetExtractor.h" | #include "PresetExtractor.h" | ||||
@@ -459,13 +459,12 @@ namespace Nio | |||||
} | } | ||||
/* Implementation */ | /* Implementation */ | ||||
class MiddleWareImpl | |||||
class MiddleWareImpl : TmpFileMgr | |||||
{ | { | ||||
static constexpr const char* tmp_nam_prefix = "/tmp/zynaddsubfx_"; | |||||
MiddleWare *parent; | MiddleWare *parent; | ||||
//Detect if the name of the process is 'zynaddsubfx' | //Detect if the name of the process is 'zynaddsubfx' | ||||
bool isPlugin() | |||||
bool isPlugin() const | |||||
{ | { | ||||
std::string proc_file = "/proc/" + to_s(getpid()) + "/comm"; | std::string proc_file = "/proc/" + to_s(getpid()) + "/comm"; | ||||
std::ifstream ifs(proc_file); | std::ifstream ifs(proc_file); | ||||
@@ -477,113 +476,11 @@ class MiddleWareImpl | |||||
return true; | return true; | ||||
} | } | ||||
//! returns file name to where UDP port is saved | |||||
std::string get_tmp_nam() const | |||||
{ | |||||
return tmp_nam_prefix + to_s(getpid()); | |||||
} | |||||
void create_tmp_file(unsigned server_port) | |||||
{ | |||||
std::string tmp_nam = get_tmp_nam(); | |||||
if(0 == access(tmp_nam.c_str(), F_OK)) { | |||||
fprintf(stderr, "Error: Cannot overwrite file %s. " | |||||
"You should probably remove it.", tmp_nam.c_str()); | |||||
exit(EXIT_FAILURE); | |||||
} | |||||
FILE* tmp_fp = fopen(tmp_nam.c_str(), "w"); | |||||
if(!tmp_fp) | |||||
fprintf(stderr, "Warning: could not create new file %s.\n", | |||||
tmp_nam.c_str()); | |||||
else | |||||
fprintf(tmp_fp, "%u", server_port); | |||||
fclose(tmp_fp); | |||||
} | |||||
void clean_up_tmp_nams() const | |||||
{ | |||||
DIR *dir; | |||||
struct dirent *entry; | |||||
if ((dir = opendir ("/tmp/")) != nullptr) | |||||
{ | |||||
while ((entry = readdir (dir)) != nullptr) | |||||
{ | |||||
std::string name = std::string("/tmp/") + entry->d_name; | |||||
if(!name.compare(0, strlen(tmp_nam_prefix),tmp_nam_prefix)) | |||||
{ | |||||
std::string pid = name.substr(strlen(tmp_nam_prefix)); | |||||
std::string proc_file = "/proc/" + std::move(pid) + | |||||
"/comm"; | |||||
std::ifstream ifs(proc_file); | |||||
bool remove = false; | |||||
if(!ifs.good()) | |||||
{ | |||||
fprintf(stderr, "Note: trying to remove %s - the " | |||||
"process does not exist anymore.\n", | |||||
name.c_str()); | |||||
remove = true; | |||||
} | |||||
else | |||||
{ | |||||
std::string comm_name; | |||||
ifs >> comm_name; | |||||
if(comm_name == "zynaddsubfx") | |||||
fprintf(stderr, "Note: detected running " | |||||
"zynaddsubfx with PID %s.\n", | |||||
name.c_str() + strlen(tmp_nam_prefix)); | |||||
else { | |||||
fprintf(stderr, "Note: trying to remove %s - the " | |||||
"PID is owned by\n another " | |||||
"process: %s\n", | |||||
name.c_str(), comm_name.c_str()); | |||||
remove = true; | |||||
} | |||||
} | |||||
if(remove) | |||||
{ | |||||
// make sure this file contains only one unsigned | |||||
unsigned udp_port; | |||||
std::ifstream ifs2(name); | |||||
if(!ifs2.good()) | |||||
fprintf(stderr, "Warning: could not open %s.\n", | |||||
name.c_str()); | |||||
else | |||||
{ | |||||
ifs2 >> udp_port; | |||||
if(ifs.good()) | |||||
fprintf(stderr, "Warning: could not remove " | |||||
"%s, \n it has not been " | |||||
"written by zynaddsubfx\n", | |||||
name.c_str()); | |||||
else | |||||
{ | |||||
if(std::remove(name.c_str()) != 0) | |||||
fprintf(stderr, "Warning: can not remove " | |||||
"%s.\n", name.c_str()); | |||||
} | |||||
} | |||||
} | |||||
/* one might want to connect to zyn here, | |||||
but it is not necessary: | |||||
lo_address la = lo_address_new(nullptr, udp_port.c_str()); | |||||
if(lo_send(la, "/echo", nullptr) <= 0) | |||||
fputs("Note: found crashed file %s\n", stderr); | |||||
lo_address_free(la);*/ | |||||
} | |||||
} | |||||
closedir (dir); | |||||
} else { | |||||
fputs("Warning: can not read /tmp.\n", stderr); | |||||
} | |||||
} | |||||
Config* const config; | |||||
public: | public: | ||||
MiddleWareImpl(MiddleWare *mw, SYNTH_T synth, int prefered_port); | |||||
MiddleWareImpl(MiddleWare *mw, SYNTH_T synth, Config* config, | |||||
int preferred_port); | |||||
~MiddleWareImpl(void); | ~MiddleWareImpl(void); | ||||
void warnMemoryLeaks(void); | void warnMemoryLeaks(void); | ||||
@@ -670,7 +567,10 @@ public: | |||||
auto alloc = std::async(std::launch::async, | auto alloc = std::async(std::launch::async, | ||||
[master,filename,this,npart](){ | [master,filename,this,npart](){ | ||||
Part *p = new Part(*master->memory, synth, &master->microtonal, master->fft); | |||||
Part *p = new Part(*master->memory, synth, | |||||
config->cfg.GzipCompression, | |||||
config->cfg.Interpolation, | |||||
&master->microtonal, master->fft); | |||||
if(p->loadXMLinstrument(filename)) | if(p->loadXMLinstrument(filename)) | ||||
fprintf(stderr, "Warning: failed to load part<%s>!\n", filename); | fprintf(stderr, "Warning: failed to load part<%s>!\n", filename); | ||||
@@ -704,7 +604,10 @@ public: | |||||
{ | { | ||||
if(npart == -1) | if(npart == -1) | ||||
return; | return; | ||||
Part *p = new Part(*master->memory, synth, &master->microtonal, master->fft); | |||||
Part *p = new Part(*master->memory, synth, | |||||
config->cfg.GzipCompression, | |||||
config->cfg.Interpolation, | |||||
&master->microtonal, master->fft); | |||||
p->applyparameters(); | p->applyparameters(); | ||||
obj_store.extractPart(p, npart); | obj_store.extractPart(p, npart); | ||||
kits.extractPart(p, npart); | kits.extractPart(p, npart); | ||||
@@ -721,7 +624,7 @@ public: | |||||
//structures at once... TODO error handling | //structures at once... TODO error handling | ||||
void loadMaster(const char *filename) | void loadMaster(const char *filename) | ||||
{ | { | ||||
Master *m = new Master(synth); | |||||
Master *m = new Master(synth, config); | |||||
m->uToB = uToB; | m->uToB = uToB; | ||||
m->bToU = bToU; | m->bToU = bToU; | ||||
if(filename) { | if(filename) { | ||||
@@ -829,7 +732,7 @@ public: | |||||
{ | { | ||||
char buffer[1024]; | char buffer[1024]; | ||||
memset(buffer, 0, sizeof(buffer)); | memset(buffer, 0, sizeof(buffer)); | ||||
DummyDataObj d(buffer, 1024, (void*)&config, this, uToB); | |||||
DummyDataObj d(buffer, 1024, (void*)config, this, uToB); | |||||
strcpy(buffer, "/config/"); | strcpy(buffer, "/config/"); | ||||
Config::ports.dispatch(msg+8, d); | Config::ports.dispatch(msg+8, d); | ||||
@@ -896,15 +799,20 @@ public: | |||||
//Synthesis Rate Parameters | //Synthesis Rate Parameters | ||||
const SYNTH_T synth; | const SYNTH_T synth; | ||||
PresetsStore presetsstore; | |||||
}; | }; | ||||
MiddleWareImpl::MiddleWareImpl(MiddleWare *mw, SYNTH_T synth_, int prefered_port) | |||||
:parent(mw), ui(nullptr), synth(synth_) | |||||
MiddleWareImpl::MiddleWareImpl(MiddleWare *mw, SYNTH_T synth_, | |||||
Config* config, int preferrred_port) | |||||
:parent(mw), config(config), ui(nullptr), synth(std::move(synth_)), | |||||
presetsstore(*config) | |||||
{ | { | ||||
bToU = new rtosc::ThreadLink(4096*2,1024); | bToU = new rtosc::ThreadLink(4096*2,1024); | ||||
uToB = new rtosc::ThreadLink(4096*2,1024); | uToB = new rtosc::ThreadLink(4096*2,1024); | ||||
if(prefered_port != -1) | |||||
server = lo_server_new_with_proto(to_s(prefered_port).c_str(), LO_UDP, liblo_error_cb); | |||||
if(preferrred_port != -1) | |||||
server = lo_server_new_with_proto(to_s(preferrred_port).c_str(), | |||||
LO_UDP, liblo_error_cb); | |||||
else | else | ||||
server = lo_server_new_with_proto(NULL, LO_UDP, liblo_error_cb); | server = lo_server_new_with_proto(NULL, LO_UDP, liblo_error_cb); | ||||
lo_server_add_method(server, NULL, NULL, handler_function, mw); | lo_server_add_method(server, NULL, NULL, handler_function, mw); | ||||
@@ -925,7 +833,7 @@ MiddleWareImpl::MiddleWareImpl(MiddleWare *mw, SYNTH_T synth_, int prefered_port | |||||
#ifndef PLUGINVERSION | #ifndef PLUGINVERSION | ||||
the_bToU = bToU; | the_bToU = bToU; | ||||
#endif | #endif | ||||
master = new Master(synth); | |||||
master = new Master(synth, config); | |||||
master->bToU = bToU; | master->bToU = bToU; | ||||
master->uToB = uToB; | master->uToB = uToB; | ||||
osc = GUI::genOscInterface(mw); | osc = GUI::genOscInterface(mw); | ||||
@@ -1340,8 +1248,9 @@ void MiddleWareImpl::warnMemoryLeaks(void) | |||||
/****************************************************************************** | /****************************************************************************** | ||||
* MidleWare Forwarding Stubs * | * MidleWare Forwarding Stubs * | ||||
******************************************************************************/ | ******************************************************************************/ | ||||
MiddleWare::MiddleWare(SYNTH_T synth, int prefered_port) | |||||
:impl(new MiddleWareImpl(this, synth, prefered_port)) | |||||
MiddleWare::MiddleWare(SYNTH_T synth, Config* config, | |||||
int preferred_port) | |||||
:impl(new MiddleWareImpl(this, std::move(synth), config, preferred_port)) | |||||
{} | {} | ||||
MiddleWare::~MiddleWare(void) | MiddleWare::~MiddleWare(void) | ||||
{ | { | ||||
@@ -1432,3 +1341,13 @@ const char* MiddleWare::getServerAddress(void) const | |||||
{ | { | ||||
return lo_server_get_url(impl->server); | return lo_server_get_url(impl->server); | ||||
} | } | ||||
const PresetsStore& MiddleWare::getPresetsStore() const | |||||
{ | |||||
return impl->presetsstore; | |||||
} | |||||
PresetsStore& MiddleWare::getPresetsStore() | |||||
{ | |||||
return impl->presetsstore; | |||||
} |
@@ -4,12 +4,16 @@ | |||||
#include <string> | #include <string> | ||||
struct SYNTH_T; | struct SYNTH_T; | ||||
class Master; | |||||
class Config; | |||||
class Master; | |||||
class PresetsStore; | |||||
//Link between realtime and non-realtime layers | //Link between realtime and non-realtime layers | ||||
class MiddleWare | class MiddleWare | ||||
{ | { | ||||
public: | public: | ||||
MiddleWare(SYNTH_T synth, int prefered_port = -1); | |||||
MiddleWare(SYNTH_T synth, Config *config, | |||||
int preferred_port = -1); | |||||
~MiddleWare(void); | ~MiddleWare(void); | ||||
void updateResources(Master *m); | void updateResources(Master *m); | ||||
//returns internal master pointer | //returns internal master pointer | ||||
@@ -39,6 +43,9 @@ class MiddleWare | |||||
const SYNTH_T &getSynth(void) const; | const SYNTH_T &getSynth(void) const; | ||||
//liblo stuff | //liblo stuff | ||||
const char* getServerAddress(void) const; | const char* getServerAddress(void) const; | ||||
const PresetsStore& getPresetsStore() const; | |||||
PresetsStore& getPresetsStore(); | |||||
private: | private: | ||||
class MiddleWareImpl *impl; | class MiddleWareImpl *impl; | ||||
}; | }; |
@@ -159,6 +159,10 @@ static const Ports kitPorts = { | |||||
rToggle(Ppadenabled, "PADsynth enable"), | rToggle(Ppadenabled, "PADsynth enable"), | ||||
rParamZyn(Psendtoparteffect, "Effect Levels"), | rParamZyn(Psendtoparteffect, "Effect Levels"), | ||||
rString(Pname, PART_MAX_NAME_LEN, "Kit User Specified Label"), | rString(Pname, PART_MAX_NAME_LEN, "Kit User Specified Label"), | ||||
{"captureMin:", NULL, NULL, [](const char *, RtData &r) | |||||
{Part::Kit *p = (Part::Kit*)r.obj; p->Pminkey = p->parent->lastnote;}}, | |||||
{"captureMax:", NULL, NULL, [](const char *, RtData &r) | |||||
{Part::Kit *p = (Part::Kit*)r.obj; p->Pmaxkey = p->parent->lastnote;}}, | |||||
{"padpars-data:b", rProp(internal), 0, | {"padpars-data:b", rProp(internal), 0, | ||||
[](const char *msg, RtData &d) { | [](const char *msg, RtData &d) { | ||||
rObject &o = *(rObject*)d.obj; | rObject &o = *(rObject*)d.obj; | ||||
@@ -184,8 +188,12 @@ static const Ports kitPorts = { | |||||
const Ports &Part::Kit::ports = kitPorts; | const Ports &Part::Kit::ports = kitPorts; | ||||
const Ports &Part::ports = partPorts; | const Ports &Part::ports = partPorts; | ||||
Part::Part(Allocator &alloc, const SYNTH_T &synth_, Microtonal *microtonal_, FFTwrapper *fft_) | |||||
:ctl(synth_), memory(alloc), synth(synth_) | |||||
Part::Part(Allocator &alloc, const SYNTH_T &synth_, | |||||
const int &gzip_compression, const int &interpolation, | |||||
Microtonal *microtonal_, FFTwrapper *fft_) | |||||
:ctl(synth_), memory(alloc), synth(synth_), | |||||
gzip_compression(gzip_compression), | |||||
interpolation(interpolation) | |||||
{ | { | ||||
microtonal = microtonal_; | microtonal = microtonal_; | ||||
fft = fft_; | fft = fft_; | ||||
@@ -195,6 +203,7 @@ Part::Part(Allocator &alloc, const SYNTH_T &synth_, Microtonal *microtonal_, FFT | |||||
monomemClear(); | monomemClear(); | ||||
for(int n = 0; n < NUM_KIT_ITEMS; ++n) { | for(int n = 0; n < NUM_KIT_ITEMS; ++n) { | ||||
kit[n].parent = this; | |||||
kit[n].Pname = new char [PART_MAX_NAME_LEN]; | kit[n].Pname = new char [PART_MAX_NAME_LEN]; | ||||
kit[n].adpars = nullptr; | kit[n].adpars = nullptr; | ||||
kit[n].subpars = nullptr; | kit[n].subpars = nullptr; | ||||
@@ -328,16 +337,16 @@ void Part::cleanup(bool final_) | |||||
for(int k = 0; k < POLYPHONY; ++k) | for(int k = 0; k < POLYPHONY; ++k) | ||||
KillNotePos(k); | KillNotePos(k); | ||||
for(int i = 0; i < synth.buffersize; ++i) { | for(int i = 0; i < synth.buffersize; ++i) { | ||||
partoutl[i] = final_ ? 0.0f : denormalkillbuf[i]; | |||||
partoutr[i] = final_ ? 0.0f : denormalkillbuf[i]; | |||||
partoutl[i] = final_ ? 0.0f : synth.denormalkillbuf[i]; | |||||
partoutr[i] = final_ ? 0.0f : synth.denormalkillbuf[i]; | |||||
} | } | ||||
ctl.resetall(); | ctl.resetall(); | ||||
for(int nefx = 0; nefx < NUM_PART_EFX; ++nefx) | for(int nefx = 0; nefx < NUM_PART_EFX; ++nefx) | ||||
partefx[nefx]->cleanup(); | partefx[nefx]->cleanup(); | ||||
for(int n = 0; n < NUM_PART_EFX + 1; ++n) | for(int n = 0; n < NUM_PART_EFX + 1; ++n) | ||||
for(int i = 0; i < synth.buffersize; ++i) { | for(int i = 0; i < synth.buffersize; ++i) { | ||||
partfxinputl[n][i] = final_ ? 0.0f : denormalkillbuf[i]; | |||||
partfxinputr[n][i] = final_ ? 0.0f : denormalkillbuf[i]; | |||||
partfxinputl[n][i] = final_ ? 0.0f : synth.denormalkillbuf[i]; | |||||
partfxinputr[n][i] = final_ ? 0.0f : synth.denormalkillbuf[i]; | |||||
} | } | ||||
} | } | ||||
@@ -579,7 +588,8 @@ void Part::NoteOn(unsigned char note, | |||||
memory.alloc<SUBnote>(kit[0].subpars, pars); | memory.alloc<SUBnote>(kit[0].subpars, pars); | ||||
if(kit[0].Ppadenabled) | if(kit[0].Ppadenabled) | ||||
partnote[pos].kititem[0].padnote = | partnote[pos].kititem[0].padnote = | ||||
memory.alloc<PADnote>(kit[0].padpars, pars); | |||||
memory.alloc<PADnote>(kit[0].padpars, pars, | |||||
interpolation); | |||||
if(kit[0].Padenabled || kit[0].Psubenabled || kit[0].Ppadenabled) | if(kit[0].Padenabled || kit[0].Psubenabled || kit[0].Ppadenabled) | ||||
@@ -598,7 +608,8 @@ void Part::NoteOn(unsigned char note, | |||||
memory.alloc<SUBnote>(kit[0].subpars, pars); | memory.alloc<SUBnote>(kit[0].subpars, pars); | ||||
if(kit[0].Ppadenabled) | if(kit[0].Ppadenabled) | ||||
partnote[posb].kititem[0].padnote = | partnote[posb].kititem[0].padnote = | ||||
memory.alloc<PADnote>(kit[0].padpars, pars); | |||||
memory.alloc<PADnote>(kit[0].padpars, pars, | |||||
interpolation); | |||||
if(kit[0].Padenabled || kit[0].Psubenabled || kit[0].Ppadenabled) | if(kit[0].Padenabled || kit[0].Psubenabled || kit[0].Ppadenabled) | ||||
partnote[posb].itemsplaying++; | partnote[posb].itemsplaying++; | ||||
@@ -627,7 +638,8 @@ void Part::NoteOn(unsigned char note, | |||||
if(kit[item].padpars && kit[item].Ppadenabled) | if(kit[item].padpars && kit[item].Ppadenabled) | ||||
note1.padnote = | note1.padnote = | ||||
memory.alloc<PADnote>(kit[item].padpars, pars); | |||||
memory.alloc<PADnote>(kit[item].padpars, pars, | |||||
interpolation); | |||||
// Spawn another note (but silent) if legatomodevalid==true | // Spawn another note (but silent) if legatomodevalid==true | ||||
if(legatomodevalid) { | if(legatomodevalid) { | ||||
@@ -643,7 +655,8 @@ void Part::NoteOn(unsigned char note, | |||||
memory.alloc<SUBnote>(kit[item].subpars, pars); | memory.alloc<SUBnote>(kit[item].subpars, pars); | ||||
if(kit[item].padpars && kit[item].Ppadenabled) | if(kit[item].padpars && kit[item].Ppadenabled) | ||||
note2.padnote = | note2.padnote = | ||||
memory.alloc<PADnote>(kit[item].padpars, pars); | |||||
memory.alloc<PADnote>(kit[item].padpars, pars, | |||||
interpolation); | |||||
if(kit[item].adpars || kit[item].subpars || kit[item].padpars) | if(kit[item].adpars || kit[item].subpars || kit[item].padpars) | ||||
partnote[posb].itemsplaying++; | partnote[posb].itemsplaying++; | ||||
@@ -1193,7 +1206,7 @@ int Part::saveXML(const char *filename) | |||||
add2XMLinstrument(&xml); | add2XMLinstrument(&xml); | ||||
xml.endbranch(); | xml.endbranch(); | ||||
int result = xml.saveXMLfile(filename); | |||||
int result = xml.saveXMLfile(filename, gzip_compression); | |||||
return result; | return result; | ||||
} | } | ||||
@@ -37,7 +37,9 @@ class Part | |||||
/**Constructor | /**Constructor | ||||
* @param microtonal_ Pointer to the microtonal object | * @param microtonal_ Pointer to the microtonal object | ||||
* @param fft_ Pointer to the FFTwrapper*/ | * @param fft_ Pointer to the FFTwrapper*/ | ||||
Part(Allocator &alloc, const SYNTH_T &synth, Microtonal *microtonal_, FFTwrapper *fft_); | |||||
Part(Allocator &alloc, const SYNTH_T &synth, | |||||
const int& gzip_compression, const int& interpolation, | |||||
Microtonal *microtonal_, FFTwrapper *fft_); | |||||
/**Destructor*/ | /**Destructor*/ | ||||
~Part(); | ~Part(); | ||||
@@ -85,6 +87,7 @@ class Part | |||||
//the part's kit | //the part's kit | ||||
struct Kit { | struct Kit { | ||||
Part *parent; | |||||
bool Penabled, Pmuted; | bool Penabled, Pmuted; | ||||
unsigned char Pminkey, Pmaxkey; | unsigned char Pminkey, Pmaxkey; | ||||
char *Pname; | char *Pname; | ||||
@@ -198,6 +201,7 @@ class Part | |||||
FFTwrapper *fft; | FFTwrapper *fft; | ||||
Allocator &memory; | Allocator &memory; | ||||
const SYNTH_T &synth; | const SYNTH_T &synth; | ||||
const int &gzip_compression, &interpolation; | |||||
}; | }; | ||||
#endif | #endif |
@@ -17,7 +17,6 @@ | |||||
#include "../Params/PADnoteParameters.h" | #include "../Params/PADnoteParameters.h" | ||||
#include "../Params/Presets.h" | #include "../Params/Presets.h" | ||||
#include "../Params/PresetsArray.h" | #include "../Params/PresetsArray.h" | ||||
#include "../Params/PresetsStore.h" | |||||
#include "../Params/SUBnoteParameters.h" | #include "../Params/SUBnoteParameters.h" | ||||
#include "../Misc/MiddleWare.h" | #include "../Misc/MiddleWare.h" | ||||
#include "PresetExtractor.h" | #include "PresetExtractor.h" | ||||
@@ -32,8 +31,9 @@ const rtosc::Ports real_preset_ports = | |||||
{ | { | ||||
{"scan-for-presets:", 0, 0, | {"scan-for-presets:", 0, 0, | ||||
[](const char *msg, rtosc::RtData &d) { | [](const char *msg, rtosc::RtData &d) { | ||||
presetsstore.scanforpresets(); | |||||
auto &pre = presetsstore.presets; | |||||
MiddleWare &mw = *(MiddleWare*)d.obj; | |||||
mw.getPresetsStore().scanforpresets(); | |||||
auto &pre = mw.getPresetsStore().presets; | |||||
d.reply(d.loc, "i", pre.size()); | d.reply(d.loc, "i", pre.size()); | ||||
for(unsigned i=0; i<pre.size();++i) | for(unsigned i=0; i<pre.size();++i) | ||||
d.reply(d.loc, "isss", i, | d.reply(d.loc, "isss", i, | ||||
@@ -84,11 +84,13 @@ const rtosc::Ports real_preset_ports = | |||||
}}, | }}, | ||||
{"clipboard-type:", 0, 0, | {"clipboard-type:", 0, 0, | ||||
[](const char *msg, rtosc::RtData &d) { | [](const char *msg, rtosc::RtData &d) { | ||||
d.reply(d.loc, "s", presetsstore.clipboard.type.c_str()); | |||||
const MiddleWare &mw = *(MiddleWare*)d.obj; | |||||
d.reply(d.loc, "s", mw.getPresetsStore().clipboard.type.c_str()); | |||||
}}, | }}, | ||||
{"delete:s", 0, 0, | {"delete:s", 0, 0, | ||||
[](const char *msg, rtosc::RtData &d) { | [](const char *msg, rtosc::RtData &d) { | ||||
presetsstore.deletepreset(rtosc_argument(msg,0).s); | |||||
MiddleWare &mw = *(MiddleWare*)d.obj; | |||||
mw.getPresetsStore().deletepreset(rtosc_argument(msg,0).s); | |||||
}}, | }}, | ||||
}; | }; | ||||
@@ -202,7 +204,7 @@ std::string doCopy(MiddleWare &mw, string url, string name) | |||||
T *t = (T*)capture<void*>(m, url+"self"); | T *t = (T*)capture<void*>(m, url+"self"); | ||||
//Extract Via mxml | //Extract Via mxml | ||||
//t->add2XML(&xml); | //t->add2XML(&xml); | ||||
t->copy(presetsstore, name.empty()? NULL:name.c_str()); | |||||
t->copy(mw.getPresetsStore(), name.empty()? NULL:name.c_str()); | |||||
}); | }); | ||||
return "";//xml.getXMLdata(); | return "";//xml.getXMLdata(); | ||||
@@ -241,7 +243,7 @@ std::string doArrayCopy(MiddleWare &mw, int field, string url, string name) | |||||
//Get the pointer | //Get the pointer | ||||
T *t = (T*)capture<void*>(m, url+"self"); | T *t = (T*)capture<void*>(m, url+"self"); | ||||
//Extract Via mxml | //Extract Via mxml | ||||
t->copy(presetsstore, field, name.empty()?NULL:name.c_str()); | |||||
t->copy(mw.getPresetsStore(), field, name.empty()?NULL:name.c_str()); | |||||
}); | }); | ||||
return "";//xml.getXMLdata(); | return "";//xml.getXMLdata(); | ||||
@@ -415,7 +417,7 @@ void presetPaste(MiddleWare &mw, std::string url, std::string name) | |||||
string data = ""; | string data = ""; | ||||
XMLwrapper xml; | XMLwrapper xml; | ||||
if(name.empty()) { | if(name.empty()) { | ||||
data = presetsstore.clipboard.data; | |||||
data = mw.getPresetsStore().clipboard.data; | |||||
if(data.length() < 20) | if(data.length() < 20) | ||||
return; | return; | ||||
if(!xml.putXMLdata(data.c_str())) | if(!xml.putXMLdata(data.c_str())) | ||||
@@ -440,7 +442,7 @@ void presetPasteArray(MiddleWare &mw, std::string url, int field, std::string na | |||||
string data = ""; | string data = ""; | ||||
XMLwrapper xml; | XMLwrapper xml; | ||||
if(name.empty()) { | if(name.empty()) { | ||||
data = presetsstore.clipboard.data; | |||||
data = mw.getPresetsStore().clipboard.data; | |||||
if(data.length() < 20) | if(data.length() < 20) | ||||
return; | return; | ||||
if(!xml.putXMLdata(data.c_str())) | if(!xml.putXMLdata(data.c_str())) | ||||
@@ -0,0 +1,114 @@ | |||||
#include <cstdlib> | |||||
#include <cstring> | |||||
#include <string> | |||||
#include <cstdio> | |||||
#include <fstream> | |||||
#include <unistd.h> | |||||
#include <dirent.h> | |||||
#include "Util.h" | |||||
#include "TmpFileMgr.h" | |||||
std::string TmpFileMgr::get_tmp_nam() const | |||||
{ | |||||
return tmp_nam_prefix + to_s(getpid()); | |||||
} | |||||
void TmpFileMgr::create_tmp_file(unsigned server_port) const | |||||
{ | |||||
std::string tmp_nam = get_tmp_nam(); | |||||
if(0 == access(tmp_nam.c_str(), F_OK)) { | |||||
fprintf(stderr, "Error: Cannot overwrite file %s. " | |||||
"You should probably remove it.", tmp_nam.c_str()); | |||||
exit(EXIT_FAILURE); | |||||
} | |||||
FILE* tmp_fp = fopen(tmp_nam.c_str(), "w"); | |||||
if(!tmp_fp) | |||||
fprintf(stderr, "Warning: could not create new file %s.\n", | |||||
tmp_nam.c_str()); | |||||
else | |||||
fprintf(tmp_fp, "%u", server_port); | |||||
fclose(tmp_fp); | |||||
} | |||||
void TmpFileMgr::clean_up_tmp_nams() const | |||||
{ | |||||
DIR *dir; | |||||
struct dirent *entry; | |||||
if ((dir = opendir ("/tmp/")) != nullptr) | |||||
{ | |||||
while ((entry = readdir (dir)) != nullptr) | |||||
{ | |||||
std::string name = std::string("/tmp/") + entry->d_name; | |||||
if(!name.compare(0, strlen(tmp_nam_prefix),tmp_nam_prefix)) | |||||
{ | |||||
std::string pid = name.substr(strlen(tmp_nam_prefix)); | |||||
std::string proc_file = "/proc/" + std::move(pid) + | |||||
"/comm"; | |||||
std::ifstream ifs(proc_file); | |||||
bool remove = false; | |||||
if(!ifs.good()) | |||||
{ | |||||
fprintf(stderr, "Note: trying to remove %s - the " | |||||
"process does not exist anymore.\n", | |||||
name.c_str()); | |||||
remove = true; | |||||
} | |||||
else | |||||
{ | |||||
std::string comm_name; | |||||
ifs >> comm_name; | |||||
if(comm_name == "zynaddsubfx") | |||||
fprintf(stderr, "Note: detected running " | |||||
"zynaddsubfx with PID %s.\n", | |||||
name.c_str() + strlen(tmp_nam_prefix)); | |||||
else { | |||||
fprintf(stderr, "Note: trying to remove %s - the " | |||||
"PID is owned by\n another " | |||||
"process: %s\n", | |||||
name.c_str(), comm_name.c_str()); | |||||
remove = true; | |||||
} | |||||
} | |||||
if(remove) | |||||
{ | |||||
// make sure this file contains only one unsigned | |||||
unsigned udp_port; | |||||
std::ifstream ifs2(name); | |||||
if(!ifs2.good()) | |||||
fprintf(stderr, "Warning: could not open %s.\n", | |||||
name.c_str()); | |||||
else | |||||
{ | |||||
ifs2 >> udp_port; | |||||
if(ifs.good()) | |||||
fprintf(stderr, "Warning: could not remove " | |||||
"%s, \n it has not been " | |||||
"written by zynaddsubfx\n", | |||||
name.c_str()); | |||||
else | |||||
{ | |||||
if(std::remove(name.c_str()) != 0) | |||||
fprintf(stderr, "Warning: can not remove " | |||||
"%s.\n", name.c_str()); | |||||
} | |||||
} | |||||
} | |||||
/* one might want to connect to zyn here, | |||||
but it is not necessary: | |||||
lo_address la = lo_address_new(nullptr, udp_port.c_str()); | |||||
if(lo_send(la, "/echo", nullptr) <= 0) | |||||
fputs("Note: found crashed file %s\n", stderr); | |||||
lo_address_free(la);*/ | |||||
} | |||||
} | |||||
closedir (dir); | |||||
} else { | |||||
fputs("Warning: can not read /tmp.\n", stderr); | |||||
} | |||||
} |
@@ -0,0 +1,18 @@ | |||||
/** | |||||
This file provides routines for using zyn's tmp files. | |||||
*/ | |||||
class TmpFileMgr | |||||
{ | |||||
static constexpr const char* tmp_nam_prefix = "/tmp/zynaddsubfx_"; | |||||
public: | |||||
//! returns file name to where UDP port is saved | |||||
std::string get_tmp_nam() const; | |||||
//! creates a tmp file with given UDP port information | |||||
void create_tmp_file(unsigned server_port) const; | |||||
//! cleans up as many tmp files as possible | |||||
void clean_up_tmp_nams() const; | |||||
}; |
@@ -20,6 +20,7 @@ | |||||
*/ | */ | ||||
#include "globals.h" | |||||
#include "Util.h" | #include "Util.h" | ||||
#include <vector> | #include <vector> | ||||
#include <cassert> | #include <cassert> | ||||
@@ -45,10 +46,6 @@ | |||||
prng_t prng_state = 0x1234; | prng_t prng_state = 0x1234; | ||||
Config config; | |||||
float *denormalkillbuf; | |||||
/* | /* | ||||
* Transform the velocity according the scaling parameter (velocity sensing) | * Transform the velocity according the scaling parameter (velocity sensing) | ||||
*/ | */ | ||||
@@ -28,8 +28,6 @@ | |||||
#include <stdint.h> | #include <stdint.h> | ||||
#include <algorithm> | #include <algorithm> | ||||
#include <set> | #include <set> | ||||
#include "Config.h" | |||||
#include "../globals.h" | |||||
using std::min; | using std::min; | ||||
using std::max; | using std::max; | ||||
@@ -58,10 +56,6 @@ std::string os_pid_as_padded_string(); | |||||
std::string legalizeFilename(std::string filename); | std::string legalizeFilename(std::string filename); | ||||
extern float *denormalkillbuf; /**<the buffer to add noise in order to avoid denormalisation*/ | |||||
extern class Config config; | |||||
void invSignal(float *sig, size_t len); | void invSignal(float *sig, size_t len); | ||||
template<class T> | template<class T> | ||||
@@ -31,7 +31,7 @@ | |||||
#include <iostream> | #include <iostream> | ||||
#include <sstream> | #include <sstream> | ||||
#include "../globals.h" | |||||
#include "globals.h" | |||||
#include "Util.h" | #include "Util.h" | ||||
using namespace std; | using namespace std; | ||||
@@ -187,13 +187,12 @@ bool XMLwrapper::hasPadSynth() const | |||||
/* SAVE XML members */ | /* SAVE XML members */ | ||||
int XMLwrapper::saveXMLfile(const string &filename) const | |||||
int XMLwrapper::saveXMLfile(const string &filename, int compression) const | |||||
{ | { | ||||
char *xmldata = getXMLdata(); | char *xmldata = getXMLdata(); | ||||
if(xmldata == NULL) | if(xmldata == NULL) | ||||
return -2; | return -2; | ||||
int compression = config.cfg.GzipCompression; | |||||
int result = dosavefile(filename.c_str(), compression, xmldata); | int result = dosavefile(filename.c_str(), compression, xmldata); | ||||
free(xmldata); | free(xmldata); | ||||
@@ -49,7 +49,7 @@ class XMLwrapper | |||||
* @param filename the name of the destination file. | * @param filename the name of the destination file. | ||||
* @returns 0 if ok or -1 if the file cannot be saved. | * @returns 0 if ok or -1 if the file cannot be saved. | ||||
*/ | */ | ||||
int saveXMLfile(const std::string &filename) const; | |||||
int saveXMLfile(const std::string &filename, int compression) const; | |||||
/** | /** | ||||
* Return XML tree as a string. | * Return XML tree as a string. | ||||
@@ -25,13 +25,14 @@ | |||||
using namespace std; | using namespace std; | ||||
EngineMgr &EngineMgr::getInstance(const SYNTH_T *synth) | |||||
EngineMgr &EngineMgr::getInstance(const SYNTH_T *synth, | |||||
const oss_devs_t *oss_devs) | |||||
{ | { | ||||
static EngineMgr instance(synth); | |||||
static EngineMgr instance(synth, *oss_devs); | |||||
return instance; | return instance; | ||||
} | } | ||||
EngineMgr::EngineMgr(const SYNTH_T *synth) | |||||
EngineMgr::EngineMgr(const SYNTH_T *synth, const oss_devs_t& oss_devs) | |||||
{ | { | ||||
assert(synth); | assert(synth); | ||||
Engine *defaultEng = new NulEngine(*synth); | Engine *defaultEng = new NulEngine(*synth); | ||||
@@ -39,8 +40,8 @@ EngineMgr::EngineMgr(const SYNTH_T *synth) | |||||
//conditional compiling mess (but contained) | //conditional compiling mess (but contained) | ||||
engines.push_back(defaultEng); | engines.push_back(defaultEng); | ||||
#if OSS | #if OSS | ||||
engines.push_back(new OssEngine(*synth)); | |||||
engines.push_back(new OssMultiEngine(*synth)); | |||||
engines.push_back(new OssEngine(*synth, oss_devs)); | |||||
engines.push_back(new OssMultiEngine(*synth, oss_devs)); | |||||
#endif | #endif | ||||
#if ALSA | #if ALSA | ||||
engines.push_back(new AlsaEngine(*synth)); | engines.push_back(new AlsaEngine(*synth)); | ||||
@@ -14,7 +14,9 @@ struct SYNTH_T; | |||||
class EngineMgr | class EngineMgr | ||||
{ | { | ||||
public: | public: | ||||
static EngineMgr &getInstance(const SYNTH_T *synth=NULL); | |||||
static EngineMgr &getInstance( | |||||
const SYNTH_T *synth = nullptr, | |||||
const class oss_devs_t* oss_devs = nullptr); | |||||
~EngineMgr(); | ~EngineMgr(); | ||||
/**Gets requested engine | /**Gets requested engine | ||||
@@ -39,6 +41,6 @@ class EngineMgr | |||||
AudioOut *defaultOut; | AudioOut *defaultOut; | ||||
MidiIn *defaultIn; | MidiIn *defaultIn; | ||||
private: | private: | ||||
EngineMgr(const SYNTH_T *synth); | |||||
EngineMgr(const SYNTH_T *synth, const oss_devs_t &oss_devs); | |||||
}; | }; | ||||
#endif | #endif |
@@ -5,6 +5,7 @@ | |||||
#include "MidiIn.h" | #include "MidiIn.h" | ||||
#include "AudioOut.h" | #include "AudioOut.h" | ||||
#include "WavEngine.h" | #include "WavEngine.h" | ||||
#include "../Misc/Config.h" | |||||
#include <cstring> | #include <cstring> | ||||
#include <iostream> | #include <iostream> | ||||
#include <algorithm> | #include <algorithm> | ||||
@@ -30,11 +31,12 @@ bool Nio::pidInClientName = false; | |||||
string Nio::defaultSource = IN_DEFAULT; | string Nio::defaultSource = IN_DEFAULT; | ||||
string Nio::defaultSink = OUT_DEFAULT; | string Nio::defaultSink = OUT_DEFAULT; | ||||
void Nio::init(const SYNTH_T &synth, class Master *master) | |||||
void Nio::init(const SYNTH_T &synth, const oss_devs_t& oss_devs, | |||||
class Master *master) | |||||
{ | { | ||||
in = &InMgr::getInstance(); //Enable input wrapper | in = &InMgr::getInstance(); //Enable input wrapper | ||||
out = &OutMgr::getInstance(&synth); //Initialize the Output Systems | out = &OutMgr::getInstance(&synth); //Initialize the Output Systems | ||||
eng = &EngineMgr::getInstance(&synth); //Initialize The Engines | |||||
eng = &EngineMgr::getInstance(&synth, &oss_devs); //Initialize the Engines | |||||
in->setMaster(master); | in->setMaster(master); | ||||
out->setMaster(master); | out->setMaster(master); | ||||
@@ -6,13 +6,14 @@ | |||||
class WavFile; | class WavFile; | ||||
class Master; | class Master; | ||||
struct SYNTH_T; | struct SYNTH_T; | ||||
class oss_devs_t; | |||||
/**Interface to Nio Subsystem | /**Interface to Nio Subsystem | ||||
* | * | ||||
* Should be only externally included header */ | * Should be only externally included header */ | ||||
namespace Nio | namespace Nio | ||||
{ | { | ||||
void init(const SYNTH_T &synth, Master *master); | |||||
void init(const SYNTH_T &synth, const oss_devs_t &oss_devs, Master *master); | |||||
bool start(void); | bool start(void); | ||||
void stop(void); | void stop(void); | ||||
@@ -22,6 +22,7 @@ | |||||
#include "OssEngine.h" | #include "OssEngine.h" | ||||
#include "../Misc/Util.h" | #include "../Misc/Util.h" | ||||
#include "../Misc/Config.h" | |||||
#include "../globals.h" | #include "../globals.h" | ||||
#include <cstring> | #include <cstring> | ||||
@@ -179,8 +180,11 @@ OssMidiParse(struct OssMidiParse &midi_parse, | |||||
return (0); | return (0); | ||||
} | } | ||||
OssEngine::OssEngine(const SYNTH_T &synth) | |||||
:AudioOut(synth), audioThread(NULL), midiThread(NULL) | |||||
OssEngine::OssEngine(const SYNTH_T &synth, | |||||
const oss_devs_t& oss_devs) | |||||
:AudioOut(synth), audioThread(NULL), midiThread(NULL), | |||||
linux_oss_wave_out_dev(oss_devs.linux_wave_out), | |||||
linux_oss_seq_in_dev(oss_devs.linux_seq_in) | |||||
{ | { | ||||
name = "OSS"; | name = "OSS"; | ||||
@@ -212,7 +216,7 @@ bool OssEngine::openAudio() | |||||
const char *device = getenv("DSP_DEVICE"); | const char *device = getenv("DSP_DEVICE"); | ||||
if(device == NULL) | if(device == NULL) | ||||
device = config.cfg.LinuxOSSWaveOutDev; | |||||
device = linux_oss_wave_out_dev; | |||||
/* NOTE: PIPEs and FIFOs can block when opening them */ | /* NOTE: PIPEs and FIFOs can block when opening them */ | ||||
audio.handle = open(device, O_WRONLY, O_NONBLOCK); | audio.handle = open(device, O_WRONLY, O_NONBLOCK); | ||||
@@ -350,7 +354,7 @@ bool OssEngine::openMidi() | |||||
const char *device = getenv("MIDI_DEVICE"); | const char *device = getenv("MIDI_DEVICE"); | ||||
if(device == NULL) | if(device == NULL) | ||||
device = config.cfg.LinuxOSSSeqInDev; | |||||
device = linux_oss_seq_in_dev; | |||||
/* NOTE: PIPEs and FIFOs can block when opening them */ | /* NOTE: PIPEs and FIFOs can block when opening them */ | ||||
handle = open(device, O_RDONLY, O_NONBLOCK); | handle = open(device, O_RDONLY, O_NONBLOCK); | ||||
@@ -45,7 +45,7 @@ struct OssMidiParse { | |||||
class OssEngine:public AudioOut, MidiIn | class OssEngine:public AudioOut, MidiIn | ||||
{ | { | ||||
public: | public: | ||||
OssEngine(const SYNTH_T &synth); | |||||
OssEngine(const SYNTH_T &synth, const class oss_devs_t& oss_devs); | |||||
~OssEngine(); | ~OssEngine(); | ||||
bool Start(); | bool Start(); | ||||
@@ -83,6 +83,8 @@ class OssEngine:public AudioOut, MidiIn | |||||
bool en; | bool en; | ||||
bool is32bit; | bool is32bit; | ||||
} audio; | } audio; | ||||
const char* linux_oss_wave_out_dev; | |||||
//Midi | //Midi | ||||
bool openMidi(); | bool openMidi(); | ||||
@@ -94,6 +96,8 @@ class OssEngine:public AudioOut, MidiIn | |||||
bool en; | bool en; | ||||
bool run; | bool run; | ||||
} midi; | } midi; | ||||
const char* linux_oss_seq_in_dev; | |||||
}; | }; | ||||
#endif | #endif |
@@ -43,8 +43,10 @@ extern MiddleWare *middleware; | |||||
using namespace std; | using namespace std; | ||||
OssMultiEngine :: OssMultiEngine(const SYNTH_T &synth) | |||||
:AudioOut(synth) | |||||
OssMultiEngine :: OssMultiEngine(const SYNTH_T &synth, | |||||
const oss_devs_t &oss_devs) | |||||
:AudioOut(synth), | |||||
linux_oss_wave_out_dev(oss_devs.linux_wave_out) | |||||
{ | { | ||||
/* setup variables */ | /* setup variables */ | ||||
name = "OSS-MULTI"; | name = "OSS-MULTI"; | ||||
@@ -81,7 +83,7 @@ OssMultiEngine :: openAudio() | |||||
const char *device = getenv("DSP_DEVICE"); | const char *device = getenv("DSP_DEVICE"); | ||||
if(device == 0) | if(device == 0) | ||||
device = config.cfg.LinuxOSSWaveOutDev; | |||||
device = linux_oss_wave_out_dev; | |||||
/* NOTE: PIPEs and FIFOs can block when opening them */ | /* NOTE: PIPEs and FIFOs can block when opening them */ | ||||
handle = open(device, O_WRONLY, O_NONBLOCK); | handle = open(device, O_WRONLY, O_NONBLOCK); | ||||
@@ -29,7 +29,8 @@ | |||||
class OssMultiEngine : public AudioOut | class OssMultiEngine : public AudioOut | ||||
{ | { | ||||
public: | public: | ||||
OssMultiEngine(const SYNTH_T &synth); | |||||
OssMultiEngine(const SYNTH_T &synth, | |||||
const class oss_devs_t& oss_devs); | |||||
~OssMultiEngine(); | ~OssMultiEngine(); | ||||
bool Start(); | bool Start(); | ||||
@@ -62,6 +63,8 @@ class OssMultiEngine : public AudioOut | |||||
bool en; | bool en; | ||||
bool is32bit; | bool is32bit; | ||||
const char* linux_oss_wave_out_dev; | |||||
}; | }; | ||||
#endif | #endif |
@@ -2,6 +2,7 @@ | |||||
#define OUTMGR_H | #define OUTMGR_H | ||||
#include "../Misc/Stereo.h" | #include "../Misc/Stereo.h" | ||||
#include "../globals.h" | |||||
#include <list> | #include <list> | ||||
#include <string> | #include <string> | ||||
#include <semaphore.h> | #include <semaphore.h> | ||||
@@ -16,7 +17,7 @@ class OutMgr | |||||
~OutMgr(); | ~OutMgr(); | ||||
/**Execute a tick*/ | /**Execute a tick*/ | ||||
const Stereo<float *> tick(unsigned int frameSize) __attribute__((annotate("realtime"))); | |||||
const Stereo<float *> tick(unsigned int frameSize) REALTIME; | |||||
/**Request a new set of samples | /**Request a new set of samples | ||||
* @param n number of requested samples (defaults to 1) | * @param n number of requested samples (defaults to 1) | ||||
@@ -30,13 +30,14 @@ | |||||
#include "PresetsStore.h" | #include "PresetsStore.h" | ||||
#include "../Misc/XMLwrapper.h" | #include "../Misc/XMLwrapper.h" | ||||
#include "../Misc/Util.h" | #include "../Misc/Util.h" | ||||
#include "../Misc/Config.h" | |||||
using namespace std; | using namespace std; | ||||
//XXX to remove | //XXX to remove | ||||
PresetsStore presetsstore; | |||||
//PresetsStore presetsstore; | |||||
PresetsStore::PresetsStore() | |||||
PresetsStore::PresetsStore(const Config& config) : config(config) | |||||
{ | { | ||||
} | } | ||||
@@ -154,7 +155,7 @@ void PresetsStore::copypreset(XMLwrapper &xml, char *type, string name) | |||||
string filename("" + dirname + tmps + name + "." + &type[1] + ".xpz"); | string filename("" + dirname + tmps + name + "." + &type[1] + ".xpz"); | ||||
xml.saveXMLfile(filename); | |||||
xml.saveXMLfile(filename, config.cfg.GzipCompression); | |||||
} | } | ||||
bool PresetsStore::pastepreset(XMLwrapper &xml, unsigned int npreset) | bool PresetsStore::pastepreset(XMLwrapper &xml, unsigned int npreset) | ||||
@@ -29,8 +29,9 @@ | |||||
class XMLwrapper; | class XMLwrapper; | ||||
class PresetsStore | class PresetsStore | ||||
{ | { | ||||
const class Config& config; | |||||
public: | public: | ||||
PresetsStore(); | |||||
PresetsStore(const class Config &config); | |||||
~PresetsStore(); | ~PresetsStore(); | ||||
//Clipboard stuff | //Clipboard stuff | ||||
@@ -62,5 +63,5 @@ class PresetsStore | |||||
void clearpresets(); | void clearpresets(); | ||||
}; | }; | ||||
extern PresetsStore presetsstore; | |||||
//extern PresetsStore presetsstore; | |||||
#endif | #endif |
@@ -1434,8 +1434,8 @@ inline void ADnote::ComputeVoiceNoise(int nvoice) | |||||
*/ | */ | ||||
int ADnote::noteout(float *outl, float *outr) | int ADnote::noteout(float *outl, float *outr) | ||||
{ | { | ||||
memcpy(outl, denormalkillbuf, synth.bufferbytes); | |||||
memcpy(outr, denormalkillbuf, synth.bufferbytes); | |||||
memcpy(outl, synth.denormalkillbuf, synth.bufferbytes); | |||||
memcpy(outr, synth.denormalkillbuf, synth.bufferbytes); | |||||
if(NoteEnabled == OFF) | if(NoteEnabled == OFF) | ||||
return 0; | return 0; | ||||
@@ -482,7 +482,8 @@ void OscilGen::changebasefunction(void) | |||||
{ | { | ||||
if(Pcurrentbasefunc != 0) { | if(Pcurrentbasefunc != 0) { | ||||
getbasefunction(tmpsmps); | getbasefunction(tmpsmps); | ||||
fft->smps2freqs(tmpsmps, basefuncFFTfreqs); | |||||
if(fft) | |||||
fft->smps2freqs(tmpsmps, basefuncFFTfreqs); | |||||
clearDC(basefuncFFTfreqs); | clearDC(basefuncFFTfreqs); | ||||
} | } | ||||
else //in this case basefuncFFTfreqs are not used | else //in this case basefuncFFTfreqs are not used | ||||
@@ -1139,6 +1140,8 @@ void OscilGen::paste(OscilGen &o) | |||||
RESTORE(fft); | RESTORE(fft); | ||||
RESTORE(basefuncFFTfreqs); | RESTORE(basefuncFFTfreqs); | ||||
RESTORE(res); | RESTORE(res); | ||||
if(this->Pcurrentbasefunc) | |||||
changebasefunction(); | |||||
this->prepare(); | this->prepare(); | ||||
} | } | ||||
@@ -29,8 +29,8 @@ | |||||
#include "../Misc/Util.h" | #include "../Misc/Util.h" | ||||
PADnote::PADnote(PADnoteParameters *parameters, | PADnote::PADnote(PADnoteParameters *parameters, | ||||
SynthParams pars) | |||||
:SynthNote(pars), pars(*parameters) | |||||
SynthParams pars, const int& interpolation) | |||||
:SynthNote(pars), pars(*parameters), interpolation(interpolation) | |||||
{ | { | ||||
firsttime = true; | firsttime = true; | ||||
setup(pars.frequency, pars.velocity, pars.portamento, pars.note); | setup(pars.frequency, pars.velocity, pars.portamento, pars.note); | ||||
@@ -347,7 +347,7 @@ int PADnote::noteout(float *outl, float *outr) | |||||
float freqlo = freqrap - floor(freqrap); | float freqlo = freqrap - floor(freqrap); | ||||
if(config.cfg.Interpolation) | |||||
if(interpolation) | |||||
Compute_Cubic(outl, outr, freqhi, freqlo); | Compute_Cubic(outl, outr, freqhi, freqlo); | ||||
else | else | ||||
Compute_Linear(outl, outr, freqhi, freqlo); | Compute_Linear(outl, outr, freqhi, freqlo); | ||||
@@ -30,7 +30,8 @@ | |||||
class PADnote:public SynthNote | class PADnote:public SynthNote | ||||
{ | { | ||||
public: | public: | ||||
PADnote(PADnoteParameters *parameters, SynthParams pars); | |||||
PADnote(PADnoteParameters *parameters, SynthParams pars, | |||||
const int &interpolation); | |||||
~PADnote(); | ~PADnote(); | ||||
void legatonote(LegatoParams pars); | void legatonote(LegatoParams pars); | ||||
@@ -104,6 +105,7 @@ class PADnote:public SynthNote | |||||
float globaloldamplitude, globalnewamplitude, velocity, realfreq; | float globaloldamplitude, globalnewamplitude, velocity, realfreq; | ||||
const int& interpolation; | |||||
}; | }; | ||||
@@ -491,8 +491,8 @@ void SUBnote::computecurrentparameters() | |||||
*/ | */ | ||||
int SUBnote::noteout(float *outl, float *outr) | int SUBnote::noteout(float *outl, float *outr) | ||||
{ | { | ||||
memcpy(outl, denormalkillbuf, synth.bufferbytes); | |||||
memcpy(outr, denormalkillbuf, synth.bufferbytes); | |||||
memcpy(outl, synth.denormalkillbuf, synth.bufferbytes); | |||||
memcpy(outr, synth.denormalkillbuf, synth.bufferbytes); | |||||
if(NoteEnabled == OFF) | if(NoteEnabled == OFF) | ||||
return 0; | return 0; | ||||
@@ -39,7 +39,13 @@ decl {\#include "../Misc/Util.h"} {public local | |||||
} | } | ||||
decl {\#include "../Effects/EffectMgr.h"} {public local | decl {\#include "../Effects/EffectMgr.h"} {public local | ||||
} | |||||
} | |||||
decl {\#include "../Effects/Phaser.h" /* for macros only, TODO */} {public local | |||||
} | |||||
decl {\#include "../Effects/Alienwah.h" /* for macros only, TODO */ } {public local | |||||
} | |||||
decl {\#include "PresetsUI.h"} {public local | decl {\#include "PresetsUI.h"} {public local | ||||
} | } | ||||
@@ -943,7 +949,7 @@ stagescounter->oscMove("parameter"+to_s(npb+4));} | |||||
Fl_Counter stagescounter { | Fl_Counter stagescounter { | ||||
label {St.} | label {St.} | ||||
callback {eqgraph->update();} | callback {eqgraph->update();} | ||||
tooltip {Additional filter stages} xywh {340 60 30 15} type Simple labelfont 1 labelsize 10 minimum 1 maximum 127 step 1 textfont 1 textsize 11 | |||||
tooltip {Additional filter stages} xywh {340 60 30 15} type Simple labelfont 1 labelsize 10 minimum 0 maximum 127 step 1 textfont 1 textsize 11 | |||||
code0 {o->init("parameter14");} | code0 {o->init("parameter14");} | ||||
class Fl_Osc_Counter | class Fl_Osc_Counter | ||||
} | } | ||||
@@ -223,3 +223,13 @@ void EnvelopeFreeEdit::update(void) | |||||
oscWrite("Penvval"); | oscWrite("Penvval"); | ||||
oscWrite("Penvsustain"); | oscWrite("Penvsustain"); | ||||
} | } | ||||
void EnvelopeFreeEdit::rebase(std::string new_base) | |||||
{ | |||||
osc->renameLink(loc+"Penvpoints", new_base+"Penvpoints", this); | |||||
osc->renameLink(loc+"Penvdt", new_base+"Penvdt", this); | |||||
osc->renameLink(loc+"Penvval", new_base+"Penvval", this); | |||||
osc->renameLink(loc+"Penvsustain", new_base+"Penvsustain", this); | |||||
loc = new_base; | |||||
update(); | |||||
} |
@@ -13,17 +13,18 @@ | |||||
#define ENV_ADSR_FILTER 4 | #define ENV_ADSR_FILTER 4 | ||||
#define ENV_ADSR_BW 5 | #define ENV_ADSR_BW 5 | ||||
class EnvelopeFreeEdit : public Fl_Box, Fl_Osc_Widget | |||||
class EnvelopeFreeEdit : public Fl_Box, public Fl_Osc_Widget | |||||
{ | { | ||||
public: | public: | ||||
EnvelopeFreeEdit(int x,int y, int w, int h, const char *label=0); | EnvelopeFreeEdit(int x,int y, int w, int h, const char *label=0); | ||||
void init(void); | void init(void); | ||||
void setpair(Fl_Box *pair_); | void setpair(Fl_Box *pair_); | ||||
int handle(int event); | |||||
int handle(int event) override; | |||||
void draw(void); | |||||
void draw(void) override; | |||||
void OSC_raw(const char *msg) override; | void OSC_raw(const char *msg) override; | ||||
void update(void); | |||||
void update(void) override; | |||||
void rebase(std::string new_base) override; | |||||
int lastpoint; | int lastpoint; | ||||
@@ -24,6 +24,6 @@ class Fl_EQGraph:public Fl_Box, public Fl_Osc_Widget | |||||
float getfreqpos(float freq) const; | float getfreqpos(float freq) const; | ||||
float samplerate; | float samplerate; | ||||
float num[MAX_EQ_BANDS*MAX_FILTER_STAGES*2+1]; | |||||
float dem[MAX_EQ_BANDS*MAX_FILTER_STAGES*2+1]; | |||||
float num[MAX_EQ_BANDS*MAX_FILTER_STAGES*3]; | |||||
float dem[MAX_EQ_BANDS*MAX_FILTER_STAGES*3]; | |||||
}; | }; |
@@ -32,7 +32,7 @@ void Fl_EQGraph::OSC_raw(const char *msg) | |||||
samplerate = rtosc_argument(msg, 0).f; | samplerate = rtosc_argument(msg, 0).f; | ||||
} else { | } else { | ||||
memcpy(dem, rtosc_argument(msg, 0).b.data, sizeof(dem)); | memcpy(dem, rtosc_argument(msg, 0).b.data, sizeof(dem)); | ||||
memcpy(num, rtosc_argument(msg, 1).b.data, sizeof(dem)); | |||||
memcpy(num, rtosc_argument(msg, 1).b.data, sizeof(num)); | |||||
redraw(); | redraw(); | ||||
} | } | ||||
} | } | ||||
@@ -141,16 +141,24 @@ void Fl_EQGraph::draw(void) | |||||
double Fl_EQGraph::getresponse(int maxy,float freq) const | double Fl_EQGraph::getresponse(int maxy,float freq) const | ||||
{ | { | ||||
const float angle = 2*PI*freq/samplerate; | const float angle = 2*PI*freq/samplerate; | ||||
std::complex<float> num_res = 0; | |||||
std::complex<float> dem_res = 0; | |||||
float mag = 1; | |||||
//std::complex<float> num_res = 0; | |||||
//std::complex<float> dem_res = 0; | |||||
for(int i = 0; i < MAX_EQ_BANDS*MAX_FILTER_STAGES*2+1; ++i) { | |||||
num_res += FFTpolar<float>(num[i], i*angle); | |||||
dem_res += FFTpolar<float>(dem[i], i*angle); | |||||
for(int i = 0; i < MAX_EQ_BANDS*MAX_FILTER_STAGES; ++i) { | |||||
if(num[3*i] == 0) | |||||
break; | |||||
std::complex<float> num_res= 0; | |||||
std::complex<float> dem_res= 0; | |||||
for(int j=0; j<3; ++j) { | |||||
num_res += FFTpolar<float>(num[3*i+j], j*angle); | |||||
dem_res += FFTpolar<float>(dem[3*i+j], j*angle); | |||||
} | |||||
mag *= abs(num_res/dem_res); | |||||
} | } | ||||
float dbresp=20*log(abs(num_res/dem_res))/log(10); | |||||
float dbresp=20*log(mag)/log(10); | |||||
//rescale | //rescale | ||||
return (int) ((dbresp/MAX_DB+1.0)*maxy/2.0); | return (int) ((dbresp/MAX_DB+1.0)*maxy/2.0); | ||||
@@ -78,7 +78,10 @@ int Fl_Osc_Dial::handle(int ev) | |||||
void Fl_Osc_Dial::OSC_value(int v) | void Fl_Osc_Dial::OSC_value(int v) | ||||
{ | { | ||||
value(v+minimum()+fmodf(value(), 1)); | |||||
if(64 != (int)minimum()) | |||||
value(v+minimum()+fmodf(value(), 1)); | |||||
else | |||||
value(v+fmodf(value(), 1)); | |||||
} | } | ||||
void Fl_Osc_Dial::OSC_value(char v) | void Fl_Osc_Dial::OSC_value(char v) | ||||
@@ -95,11 +98,10 @@ void Fl_Osc_Dial::cb(void) | |||||
{ | { | ||||
assert(osc); | assert(osc); | ||||
/* if((maximum()-minimum()) == 127 || (maximum()-minimum()) == 255) { | |||||
oscWrite(ext, "i", (int)(value()-minimum())); | |||||
} | |||||
else*/ | |||||
if(64 != (int)minimum()) | |||||
oscWrite(ext, "i", (int)(value()-minimum())); | oscWrite(ext, "i", (int)(value()-minimum())); | ||||
else | |||||
oscWrite(ext, "i", (int)(value())); | |||||
if(cb_data.first) | if(cb_data.first) | ||||
cb_data.first(this, cb_data.second); | cb_data.first(this, cb_data.second); | ||||
@@ -4,7 +4,7 @@ | |||||
#include "Fl_Osc_Widget.H" | #include "Fl_Osc_Widget.H" | ||||
#include <string> | #include <string> | ||||
class Fl_Osc_DialF:public WidgetPDial, Fl_Osc_Widget | |||||
class Fl_Osc_DialF:public WidgetPDial, public Fl_Osc_Widget | |||||
{ | { | ||||
public: | public: | ||||
@@ -4,7 +4,7 @@ | |||||
#include "Fl_Osc_Widget.H" | #include "Fl_Osc_Widget.H" | ||||
//consider merging with Fl_Oscilloscope | //consider merging with Fl_Oscilloscope | ||||
class Fl_OscilSpectrum : public Fl_Box, Fl_Osc_Widget | |||||
class Fl_OscilSpectrum : public Fl_Box, public Fl_Osc_Widget | |||||
{ | { | ||||
public: | public: | ||||
Fl_OscilSpectrum(int x,int y, int w, int h, const char *label=0) | Fl_OscilSpectrum(int x,int y, int w, int h, const char *label=0) | ||||
@@ -6,7 +6,7 @@ | |||||
#include "Fl_Osc_Widget.H" | #include "Fl_Osc_Widget.H" | ||||
#include "Fl_Osc_Interface.h" | #include "Fl_Osc_Interface.h" | ||||
class PADnoteOvertonePosition: public Fl_Box, Fl_Osc_Widget | |||||
class PADnoteOvertonePosition: public Fl_Box, public Fl_Osc_Widget | |||||
{ | { | ||||
public: | public: | ||||
PADnoteOvertonePosition(int x,int y, int w, int h, const char *label=0) | PADnoteOvertonePosition(int x,int y, int w, int h, const char *label=0) | ||||
@@ -13,7 +13,7 @@ | |||||
class FilterParams; | class FilterParams; | ||||
class FormantFilterGraph : public Fl_Box, Fl_Osc_Widget { | |||||
class FormantFilterGraph : public Fl_Box, public Fl_Osc_Widget { | |||||
public: | public: | ||||
FormantFilterGraph(int x,int y, int w, int h, const char *label=0); | FormantFilterGraph(int x,int y, int w, int h, const char *label=0); | ||||
void init(int *nvowel_, int *nformant_); | void init(int *nvowel_, int *nformant_); | ||||
@@ -17,7 +17,7 @@ decl {\#include <stdio.h>} {public local | |||||
decl {\#include <string.h>} {public local | decl {\#include <string.h>} {public local | ||||
} | } | ||||
decl {\#if defined(__linux__) && ! defined(PLUGINVERSION) | |||||
decl {\#if ! defined(PLUGINVERSION) && HAS_X11 | |||||
\#include "zynaddsubfx.xpm" | \#include "zynaddsubfx.xpm" | ||||
\#endif} {public local | \#endif} {public local | ||||
} | } | ||||
@@ -76,7 +76,7 @@ extern NSM_Client *nsm; | |||||
\#endif} {public local | \#endif} {public local | ||||
} | } | ||||
decl {\#if defined(__linux__) && ! defined(PLUGINVERSION) | |||||
decl {\#if !defined(PLUGINVERSION) && HAS_X11 | |||||
\#include <X11/xpm.h> | \#include <X11/xpm.h> | ||||
\#endif} {public local | \#endif} {public local | ||||
} | } | ||||
@@ -1502,7 +1502,7 @@ configui=new ConfigUI(osc); | |||||
make_window(); | make_window(); | ||||
fl_open_display(); | fl_open_display(); | ||||
\#if defined(__linux__) && ! defined(PLUGINVERSION) | |||||
\#if !defined(PLUGINVERSION) && HAS_X11 | |||||
Pixmap p, mask; | Pixmap p, mask; | ||||
XCreatePixmapFromData(fl_display, DefaultRootWindow(fl_display), | XCreatePixmapFromData(fl_display, DefaultRootWindow(fl_display), | ||||
(char**)zynaddsubfx_xpm, &p, &mask, NULL); | (char**)zynaddsubfx_xpm, &p, &mask, NULL); | ||||
@@ -112,13 +112,17 @@ class PartKitItem {open : {public Fl_Osc_Group} | |||||
} | } | ||||
Fl_Button {} { | Fl_Button {} { | ||||
label m | label m | ||||
callback {o->oscWrite("grabMinKey");} | |||||
callback {o->oscWrite("captureMin"); | |||||
minkcounter->update(); | |||||
maxkcounter->update();} | |||||
tooltip {set the minimum key to the last pressed key} xywh {285 3 15 12} box THIN_UP_BOX labelsize 10 | tooltip {set the minimum key to the last pressed key} xywh {285 3 15 12} box THIN_UP_BOX labelsize 10 | ||||
class Fl_Osc_Button | class Fl_Osc_Button | ||||
} | } | ||||
Fl_Button {} { | Fl_Button {} { | ||||
label M | label M | ||||
callback {o->oscWrite("grabMaxKey");} | |||||
callback {o->oscWrite("captureMax"); | |||||
minkcounter->update(); | |||||
maxkcounter->update();} | |||||
tooltip {set the maximum key to the last pressed key} xywh {315 3 15 12} box THIN_UP_BOX labelsize 10 | tooltip {set the maximum key to the last pressed key} xywh {315 3 15 12} box THIN_UP_BOX labelsize 10 | ||||
class Fl_Osc_Button | class Fl_Osc_Button | ||||
} | } | ||||
@@ -124,7 +124,7 @@ if (x==0) o->selection_color(0); | |||||
callback {int x=64; | callback {int x=64; | ||||
if (Fl::event_button1() || Fl::event() == FL_MOUSEWHEEL) x=127-(int)o->value(); | if (Fl::event_button1() || Fl::event() == FL_MOUSEWHEEL) x=127-(int)o->value(); | ||||
else o->value(x); | else o->value(x); | ||||
o->osc->writeValue(o->loc+"Phrelbw"+to_s(n), (char) x);} | |||||
o->osc->writeValue(o->loc + o->ext, (char) x)}; | |||||
tooltip {harmonic's bandwidth} xywh {0 157 10 130} type {Vert Knob} box FLAT_BOX selection_color 222 maximum 127 step 1 value 64 | tooltip {harmonic's bandwidth} xywh {0 157 10 130} type {Vert Knob} box FLAT_BOX selection_color 222 maximum 127 step 1 value 64 | ||||
class PPSlider | class PPSlider | ||||
} | } | ||||
@@ -153,7 +153,8 @@ make_window(); | |||||
harmonic->show(); | harmonic->show(); | ||||
mag->ext = "Phmag" + to_s(n); | mag->ext = "Phmag" + to_s(n); | ||||
mag->oscRegister(mag->ext.c_str()); | mag->oscRegister(mag->ext.c_str()); | ||||
osc->createLink(base+"Phrelbw"+to_s(n), bw); | |||||
bw->ext = "Phrelbw" + to_s(n); | |||||
bw->oscRegister(bw->ext.c_str()); | |||||
osc->requestValue(base+"Phrelbw"+to_s(n)); | osc->requestValue(base+"Phrelbw"+to_s(n)); | ||||
end();} {} | end();} {} | ||||
@@ -161,7 +162,7 @@ end();} {} | |||||
Function {refresh()} {} { | Function {refresh()} {} { | ||||
code {// request values for the widgets | code {// request values for the widgets | ||||
mag->oscWrite(mag->ext); | mag->oscWrite(mag->ext); | ||||
osc->requestValue(base+"Phrelbw"+to_s(n));} {} | |||||
bw->oscWrite(bw->ext);} {} | |||||
} | } | ||||
Function {~SUBnoteharmonic()} {} { | Function {~SUBnoteharmonic()} {} { | ||||
code {harmonic->hide(); | code {harmonic->hide(); | ||||
@@ -0,0 +1,40 @@ | |||||
/* | |||||
ZynAddSubFX - a software synthesizer | |||||
globals.h - it contains program settings and the program capabilities | |||||
like number of parts, of effects | |||||
Copyright (C) 2002-2005 Nasca Octavian Paul | |||||
Author: Nasca Octavian Paul | |||||
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 | |||||
*/ | |||||
#include "Misc/Util.h" | |||||
#include "globals.h" | |||||
void SYNTH_T::alias() | |||||
{ | |||||
halfsamplerate_f = (samplerate_f = samplerate) / 2.0f; | |||||
buffersize_f = buffersize; | |||||
bufferbytes = buffersize * sizeof(float); | |||||
oscilsize_f = oscilsize; | |||||
//produce denormal buf | |||||
// note: once there will be more buffers, use a cleanup function | |||||
// for deleting the buffers and also call it in the dtor | |||||
denormalkillbuf.resize(buffersize); | |||||
for(int i = 0; i < buffersize; ++i) | |||||
denormalkillbuf[i] = (RND - 0.5f) * 1e-16; | |||||
} |
@@ -252,22 +252,51 @@ enum LegatoMsg { | |||||
#define O_BINARY 0 | #define O_BINARY 0 | ||||
#endif | #endif | ||||
template<class T> | |||||
class m_unique_ptr | |||||
{ | |||||
T* ptr = nullptr; | |||||
public: | |||||
m_unique_ptr() = default; | |||||
m_unique_ptr(m_unique_ptr&& other) { | |||||
ptr = other.ptr; | |||||
other.ptr = nullptr; | |||||
} | |||||
m_unique_ptr(const m_unique_ptr& other) = delete; | |||||
~m_unique_ptr() { ptr = nullptr; } | |||||
void resize(unsigned sz) { | |||||
delete[] ptr; | |||||
ptr = new T[sz]; } | |||||
operator T*() { return ptr; } | |||||
operator const T*() const { return ptr; } | |||||
T& operator[](unsigned idx) { return ptr[idx]; } | |||||
const T& operator[](unsigned idx) const { return ptr[idx]; } | |||||
}; | |||||
//temporary include for synth->{samplerate/buffersize} members | //temporary include for synth->{samplerate/buffersize} members | ||||
struct SYNTH_T { | struct SYNTH_T { | ||||
SYNTH_T(void) | SYNTH_T(void) | ||||
:samplerate(44100), buffersize(256), oscilsize(1024) | :samplerate(44100), buffersize(256), oscilsize(1024) | ||||
{ | { | ||||
alias(); | alias(); | ||||
} | } | ||||
SYNTH_T(const SYNTH_T& ) = delete; | |||||
SYNTH_T(SYNTH_T&& ) = default; | |||||
/** the buffer to add noise in order to avoid denormalisation */ | |||||
m_unique_ptr<float> denormalkillbuf; | |||||
/**Sampling rate*/ | /**Sampling rate*/ | ||||
unsigned int samplerate; | unsigned int samplerate; | ||||
/** | /** | ||||
* The size of a sound buffer (or the granularity) | * The size of a sound buffer (or the granularity) | ||||
* All internal transfer of sound data use buffer of this size | |||||
* All parameters are constant during this period of time, exception | |||||
* some parameters(like amplitudes) which are linear interpolated. | |||||
* All internal transfer of sound data use buffer of this size. | |||||
* All parameters are constant during this period of time, except | |||||
* some parameters(like amplitudes) which are linearly interpolated. | |||||
* If you increase this you'll ecounter big latencies, but if you | * If you increase this you'll ecounter big latencies, but if you | ||||
* decrease this the CPU requirements gets high. | * decrease this the CPU requirements gets high. | ||||
*/ | */ | ||||
@@ -291,13 +320,7 @@ struct SYNTH_T { | |||||
{ | { | ||||
return buffersize_f / samplerate_f; | return buffersize_f / samplerate_f; | ||||
} | } | ||||
inline void alias(void) | |||||
{ | |||||
halfsamplerate_f = (samplerate_f = samplerate) / 2.0f; | |||||
buffersize_f = buffersize; | |||||
bufferbytes = buffersize * sizeof(float); | |||||
oscilsize_f = oscilsize; | |||||
} | |||||
void alias(void); | |||||
static float numRandom(void); //defined in Util.cpp for now | static float numRandom(void); //defined in Util.cpp for now | ||||
}; | }; | ||||
#endif | #endif |
@@ -76,7 +76,7 @@ NSM_Client *nsm = 0; | |||||
char *instance_name = 0; | char *instance_name = 0; | ||||
void exitprogram(); | |||||
void exitprogram(const Config &config); | |||||
extern pthread_t main_thread; | extern pthread_t main_thread; | ||||
@@ -91,21 +91,21 @@ void sigterm_exit(int /*sig*/) | |||||
/* | /* | ||||
* Program initialisation | * Program initialisation | ||||
*/ | */ | ||||
void initprogram(SYNTH_T synth, int prefered_port) | |||||
void initprogram(SYNTH_T synth, Config* config, int prefered_port) | |||||
{ | { | ||||
middleware = new MiddleWare(synth, prefered_port); | |||||
middleware = new MiddleWare(std::move(synth), config, prefered_port); | |||||
master = middleware->spawnMaster(); | master = middleware->spawnMaster(); | ||||
master->swaplr = swaplr; | master->swaplr = swaplr; | ||||
signal(SIGINT, sigterm_exit); | signal(SIGINT, sigterm_exit); | ||||
signal(SIGTERM, sigterm_exit); | signal(SIGTERM, sigterm_exit); | ||||
Nio::init(master->synth, master); | |||||
Nio::init(master->synth, config->cfg.oss_devs, master); | |||||
} | } | ||||
/* | /* | ||||
* Program exit | * Program exit | ||||
*/ | */ | ||||
void exitprogram() | |||||
void exitprogram(const Config& config) | |||||
{ | { | ||||
Nio::stop(); | Nio::stop(); | ||||
config.save(); | config.save(); | ||||
@@ -121,7 +121,6 @@ void exitprogram() | |||||
delete nsm; | delete nsm; | ||||
#endif | #endif | ||||
delete [] denormalkillbuf; | |||||
FFT_cleanup(); | FFT_cleanup(); | ||||
} | } | ||||
@@ -129,6 +128,7 @@ int main(int argc, char *argv[]) | |||||
{ | { | ||||
main_thread = pthread_self(); | main_thread = pthread_self(); | ||||
SYNTH_T synth; | SYNTH_T synth; | ||||
Config config; | |||||
config.init(); | config.init(); | ||||
int noui = 0; | int noui = 0; | ||||
cerr | cerr | ||||
@@ -375,12 +375,14 @@ int main(int argc, char *argv[]) | |||||
return 0; | return 0; | ||||
} | } | ||||
//produce denormal buf | |||||
denormalkillbuf = new float [synth.buffersize]; | |||||
for(int i = 0; i < synth.buffersize; ++i) | |||||
denormalkillbuf[i] = (RND - 0.5f) * 1e-16; | |||||
cerr.precision(1); | |||||
cerr << std::fixed; | |||||
cerr << "\nSample Rate = \t\t" << synth.samplerate << endl; | |||||
cerr << "Sound Buffer Size = \t" << synth.buffersize << " samples" << endl; | |||||
cerr << "Internal latency = \t" << synth.dt() * 1000.0f << " ms" << endl; | |||||
cerr << "ADsynth Oscil.Size = \t" << synth.oscilsize << " samples" << endl; | |||||
initprogram(synth, prefered_port); | |||||
initprogram(std::move(synth), &config, prefered_port); | |||||
if(!loadfile.empty()) { | if(!loadfile.empty()) { | ||||
int tmp = master->loadXML(loadfile.c_str()); | int tmp = master->loadXML(loadfile.c_str()); | ||||
@@ -413,13 +415,6 @@ int main(int argc, char *argv[]) | |||||
//Run the Nio system | //Run the Nio system | ||||
bool ioGood = Nio::start(); | bool ioGood = Nio::start(); | ||||
cerr.precision(1); | |||||
cerr << std::fixed; | |||||
cerr << "\nSample Rate = \t\t" << synth.samplerate << endl; | |||||
cerr << "Sound Buffer Size = \t" << synth.buffersize << " samples" << endl; | |||||
cerr << "Internal latency = \t" << synth.dt() * 1000.0f << " ms" << endl; | |||||
cerr << "ADsynth Oscil.Size = \t" << synth.oscilsize << " samples" << endl; | |||||
if(!execAfterInit.empty()) { | if(!execAfterInit.empty()) { | ||||
cout << "Executing user supplied command: " << execAfterInit << endl; | cout << "Executing user supplied command: " << execAfterInit << endl; | ||||
@@ -519,6 +514,6 @@ done: | |||||
middleware->tick(); | middleware->tick(); | ||||
} | } | ||||
exitprogram(); | |||||
exitprogram(config); | |||||
return 0; | return 0; | ||||
} | } |