| @@ -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; | ||||
| } | } | ||||