@@ -221,7 +221,7 @@ protected: | |||
float* efxoutr; | |||
// FIXME - is this thread-safe? | |||
SharedResourcePointer<Allocator> fAllocator; | |||
SharedResourcePointer<AllocatorClass> fAllocator; | |||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FxAbstractPlugin) | |||
}; | |||
@@ -69,8 +69,11 @@ public: | |||
fPrograms.append(new ProgramInfo(0, 0, "default", "")); | |||
Config config; | |||
config.init(); | |||
SYNTH_T synth; | |||
Master master(synth); | |||
Master master(synth, &config); | |||
// refresh banks | |||
master.bank.rescanforbanks(); | |||
@@ -210,6 +213,7 @@ public: | |||
fMutex() | |||
{ | |||
sPrograms.initIfNeeded(); | |||
fConfig.init(); | |||
// init parameters to default | |||
fParameters[kParamPart01Enabled] = 1.0f; | |||
@@ -716,6 +720,7 @@ private: | |||
MiddleWare* fMiddleWare; | |||
Master* fMaster; | |||
SYNTH_T fSynth; | |||
Config fConfig; | |||
bool fIsActive; | |||
float fParameters[kParamCount]; | |||
@@ -768,7 +773,7 @@ private: | |||
void _initMaster() | |||
{ | |||
fMiddleWare = new MiddleWare(fSynth); | |||
fMiddleWare = new MiddleWare(std::move(fSynth), &fConfig); | |||
fMiddleWare->setUiCallback(__uiCallback, this); | |||
fMiddleWare->setIdleCallback(_idleCallback, this); | |||
_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) | |||
}; | |||
@@ -24,6 +24,7 @@ | |||
#include "../Misc/Allocator.h" | |||
#include "Unison.h" | |||
#include "globals.h" | |||
#ifndef errx | |||
#include <err.h> | |||
@@ -205,41 +205,26 @@ float EQ::getfreqresponse(float freq) | |||
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 | |||
//be fast enough in practice | |||
void EQ::getFilter(float *a, float *b) const | |||
{ | |||
a[0] = 1; | |||
b[0] = 1; | |||
off_t off=0; | |||
for(int i = 0; i < MAX_EQ_BANDS; ++i) { | |||
auto &F = filter[i]; | |||
if(F.Ptype == 0) | |||
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) { | |||
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); | |||
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: | |||
//Parameters | |||
unsigned char Pvolume; | |||
@@ -24,6 +24,7 @@ | |||
#include "../Misc/Util.h" | |||
#include <cmath> | |||
#include "globals.h" | |||
EffectLFO::EffectLFO(float srate_f, float bufsize_f) | |||
:Pfreq(40), | |||
@@ -79,7 +80,7 @@ float EffectLFO::getlfoshape(float x) | |||
break; | |||
//when adding more, ensure ::updateparams() gets updated | |||
default: | |||
out = cosf(x * 2.0f * PI); //EffectLFO_SINE | |||
out = cosf(x * 2.0f * PI); //EffectLFO_SINE // TODO: use M_PI ? | |||
} | |||
return out; | |||
} | |||
@@ -26,12 +26,14 @@ | |||
#include "EffectMgr.h" | |||
#include "Effect.h" | |||
#include "Alienwah.h" | |||
#include "Reverb.h" | |||
#include "Echo.h" | |||
#include "Chorus.h" | |||
#include "Distorsion.h" | |||
#include "EQ.h" | |||
#include "DynamicFilter.h" | |||
#include "Phaser.h" | |||
#include "../Misc/XMLwrapper.h" | |||
#include "../Misc/Util.h" | |||
#include "../Params/FilterParams.h" | |||
@@ -75,8 +77,8 @@ static const rtosc::Ports local_ports = { | |||
if(eff->nefx != 7) | |||
return; | |||
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(b, 0, sizeof(b)); | |||
eq->getFilter(a,b); | |||
@@ -307,8 +309,8 @@ void EffectMgr::out(float *smpsl, float *smpsr) | |||
return; | |||
} | |||
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; | |||
efxoutr[i] = 0.0f; | |||
} | |||
@@ -24,22 +24,15 @@ | |||
#include <pthread.h> | |||
#include "Alienwah.h" | |||
#include "Phaser.h" | |||
#include "../Params/Presets.h" | |||
class Effect; | |||
class FilterParams; | |||
class XMLwrapper; | |||
class Allocator; | |||
#include "Distorsion.h" | |||
#include "EQ.h" | |||
#include "DynamicFilter.h" | |||
#include "../Params/FilterParams.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 | |||
{ | |||
public: | |||
@@ -7,7 +7,7 @@ | |||
#include "Allocator.h" | |||
//Used for dummy allocations | |||
Allocator DummyAlloc; | |||
DummyAllocator DummyAlloc; | |||
//recursive type class to avoid void *v = *(void**)v style casting | |||
struct next_t | |||
@@ -57,7 +57,7 @@ Allocator::~Allocator(void) | |||
delete impl; | |||
} | |||
void *Allocator::alloc_mem(size_t mem_size) | |||
void *AllocatorClass::alloc_mem(size_t mem_size) | |||
{ | |||
impl->totalAlloced += 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); | |||
return mem; | |||
} | |||
void Allocator::dealloc_mem(void *memory) | |||
void AllocatorClass::dealloc_mem(void *memory) | |||
{ | |||
//printf("dealloc_mem(%d)\n", tlsf_block_size(memory)); | |||
tlsf_free(impl->tlsf, 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 | |||
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; | |||
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; | |||
#endif | |||
bool Allocator::memFree(void *pool) | |||
bool Allocator::memFree(void *pool) const | |||
{ | |||
size_t bh_shift = sizeof(next_t)+sizeof(size_t); | |||
//Assume that memory is free to start with | |||
@@ -145,7 +145,7 @@ bool Allocator::memFree(void *pool) | |||
return isFree; | |||
} | |||
int Allocator::memPools() | |||
int Allocator::memPools() const | |||
{ | |||
int i = 1; | |||
next_t *n = impl->pools; | |||
@@ -156,7 +156,7 @@ int Allocator::memPools() | |||
return i; | |||
} | |||
int Allocator::freePools() | |||
int Allocator::freePools() const | |||
{ | |||
int i = 0; | |||
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; | |||
} | |||
@@ -2,14 +2,17 @@ | |||
#include <cstdlib> | |||
#include <utility> | |||
//! Allocator Base class | |||
//! subclasses must specify allocation and deallocation | |||
class Allocator | |||
{ | |||
public: | |||
Allocator(void); | |||
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> | |||
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 | |||
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 | |||
int memPools(); | |||
int memPools() const; | |||
int freePools(); | |||
int freePools() const; | |||
unsigned long long totalAlloced(); | |||
unsigned long long totalAlloced() const; | |||
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 | |||
@@ -46,16 +46,16 @@ | |||
using namespace std; | |||
Bank::Bank() | |||
:bankpos(0), defaultinsname(" ") | |||
Bank::Bank(Config *config) | |||
:bankpos(0), defaultinsname(" "), config(config) | |||
{ | |||
clearbank(); | |||
bankfiletitle = dirname; | |||
rescanforbanks(); | |||
loadbank(config.cfg.currentBankDir); | |||
loadbank(config->cfg.currentBankDir); | |||
for(unsigned i=0; i<banks.size(); ++i) { | |||
if(banks[i].dir == config.cfg.currentBankDir) { | |||
if(banks[i].dir == config->cfg.currentBankDir) { | |||
bankpos = i; | |||
break; | |||
} | |||
@@ -270,7 +270,7 @@ int Bank::loadbank(string bankdirname) | |||
closedir(dir); | |||
if(!dirname.empty()) | |||
config.cfg.currentBankDir = dirname; | |||
config->cfg.currentBankDir = dirname; | |||
return 0; | |||
} | |||
@@ -281,7 +281,7 @@ int Bank::loadbank(string bankdirname) | |||
int Bank::newbank(string newbankdirname) | |||
{ | |||
string bankdir; | |||
bankdir = config.cfg.bankRootDirList[0]; | |||
bankdir = config->cfg.bankRootDirList[0]; | |||
if(((bankdir[bankdir.size() - 1]) != '/') | |||
&& ((bankdir[bankdir.size() - 1]) != '\\')) | |||
@@ -361,8 +361,8 @@ void Bank::rescanforbanks() | |||
banks.clear(); | |||
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(banks.begin(), banks.end()); | |||
@@ -26,6 +26,7 @@ | |||
#include <string> | |||
#include <vector> | |||
#include "../globals.h" | |||
#include "Config.h" | |||
//entries in a bank | |||
#define BANK_SIZE 160 | |||
@@ -35,7 +36,7 @@ class Bank | |||
{ | |||
public: | |||
/**Constructor*/ | |||
Bank(); | |||
Bank(Config* config); | |||
~Bank(); | |||
std::string getname(unsigned int ninstrument); | |||
std::string getnamenumbered(unsigned int ninstrument); | |||
@@ -96,6 +97,8 @@ class Bank | |||
std::string dirname; | |||
void scanrootdir(std::string rootdir); //scans a root dir for banks | |||
Config* const config; | |||
}; | |||
#endif |
@@ -28,6 +28,7 @@ | |||
#include <rtosc/port-sugar.h> | |||
#include "Config.h" | |||
#include "globals.h" | |||
#include "XMLwrapper.h" | |||
#define rStdString(name, len, ...) \ | |||
@@ -46,7 +47,7 @@ | |||
#if 1 | |||
#define rObject Config | |||
static rtosc::Ports ports = { | |||
static const rtosc::Ports ports = { | |||
//rString(cfg.LinuxOSSWaveOutDev), | |||
//rString(cfg.LinuxOSSSeqInDev), | |||
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))); | |||
}}, | |||
}; | |||
rtosc::Ports &Config::ports = ::ports; | |||
const rtosc::Ports &Config::ports = ::ports; | |||
#endif | |||
Config::Config() | |||
@@ -160,10 +161,10 @@ void Config::init() | |||
cfg.OscilSize = 1024; | |||
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.WindowsMidiInId = 0; | |||
@@ -228,8 +229,8 @@ void Config::init() | |||
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) | |||
delete [] winmididevices[i].name; | |||
@@ -237,7 +238,7 @@ Config::~Config() | |||
} | |||
void Config::save() | |||
void Config::save() const | |||
{ | |||
char filename[MAX_STRING_SIZE]; | |||
getConfigFileName(filename, MAX_STRING_SIZE); | |||
@@ -330,10 +331,10 @@ void Config::readConfig(const char *filename) | |||
//linux stuff | |||
xmlcfg.getparstr("linux_oss_wave_out_dev", | |||
cfg.LinuxOSSWaveOutDev, | |||
cfg.oss_devs.linux_wave_out, | |||
MAX_STRING_SIZE); | |||
xmlcfg.getparstr("linux_oss_seq_in_dev", | |||
cfg.LinuxOSSSeqInDev, | |||
cfg.oss_devs.linux_seq_in, | |||
MAX_STRING_SIZE); | |||
//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))); | |||
} | |||
void Config::saveConfig(const char *filename) | |||
void Config::saveConfig(const char *filename) const | |||
{ | |||
XMLwrapper *xmlcfg = new XMLwrapper(); | |||
@@ -392,8 +393,8 @@ void Config::saveConfig(const char *filename) | |||
xmlcfg->addpar("interpolation", cfg.Interpolation); | |||
//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 | |||
xmlcfg->addpar("windows_wave_out_id", cfg.WindowsWaveOutId); | |||
@@ -401,15 +402,13 @@ void Config::saveConfig(const char *filename) | |||
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); | |||
} | |||
void Config::getConfigFileName(char *name, int namesize) | |||
void Config::getConfigFileName(char *name, int namesize) const | |||
{ | |||
name[0] = 0; | |||
snprintf(name, namesize, "%s%s", getenv("HOME"), "/.zynaddsubfxXML.cfg"); | |||
@@ -22,21 +22,32 @@ | |||
#ifndef CONFIG_H | |||
#define CONFIG_H | |||
#include "../globals.h" | |||
#include <string> | |||
#define MAX_STRING_SIZE 4000 | |||
#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*/ | |||
class Config | |||
{ | |||
public: | |||
/** Constructor*/ | |||
Config(); | |||
/** Destructor*/ | |||
Config(const Config& ) = delete; | |||
~Config(); | |||
struct { | |||
char *LinuxOSSWaveOutDev, *LinuxOSSSeqInDev; | |||
oss_devs_t oss_devs; | |||
int SampleRate, SoundBufferSize, OscilSize, SwapStereo; | |||
int WindowsWaveOutId, WindowsMidiInId; | |||
int BankUIAutoClose; | |||
@@ -62,12 +73,12 @@ class Config | |||
void clearbankrootdirlist(); | |||
void clearpresetsdirlist(); | |||
void init(); | |||
void save(); | |||
void save() const; | |||
static rtosc::Ports &ports; | |||
static const rtosc::Ports &ports; | |||
private: | |||
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 |
@@ -25,6 +25,8 @@ | |||
#include "Part.h" | |||
#include "../Misc/Stereo.h" | |||
#include "../Misc/Util.h" | |||
#include "../Params/LFOParams.h" | |||
#include "../Effects/EffectMgr.h" | |||
#include "../DSP/FFTwrapper.h" | |||
@@ -286,12 +288,15 @@ vuData::vuData(void) | |||
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; | |||
uToB = NULL; | |||
memory = new Allocator(); | |||
memory = new AllocatorClass(); | |||
swaplr = 0; | |||
off = 0; | |||
smps = 0; | |||
@@ -310,7 +315,8 @@ Master::Master(const SYNTH_T &synth_) | |||
} | |||
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 | |||
for(int nefx = 0; nefx < NUM_INS_EFX; ++nefx) | |||
@@ -1044,7 +1050,7 @@ int Master::saveXML(const char *filename) | |||
add2XML(xml); | |||
xml->endbranch(); | |||
int result = xml->saveXMLfile(filename); | |||
int result = xml->saveXMLfile(filename, gzip_compression); | |||
delete (xml); | |||
return result; | |||
} | |||
@@ -49,7 +49,7 @@ class Master | |||
{ | |||
public: | |||
/** Constructor TODO make private*/ | |||
Master(const SYNTH_T &synth); | |||
Master(const SYNTH_T &synth, class Config *config); | |||
/** Destructor*/ | |||
~Master(); | |||
@@ -171,6 +171,7 @@ class Master | |||
rtosc::ThreadLink *uToB; | |||
bool pendingMemory; | |||
const SYNTH_T &synth; | |||
const int& gzip_compression; //!< value from config | |||
private: | |||
float sysefxvol[NUM_SYS_EFX][NUM_MIDI_PARTS]; | |||
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(); | |||
} | |||
@@ -688,7 +689,7 @@ int Microtonal::saveXML(const char *filename) const | |||
add2XML(xml); | |||
xml->endbranch(); | |||
int result = xml->saveXMLfile(filename); | |||
int result = xml->saveXMLfile(filename, gzip_compression); | |||
delete (xml); | |||
return result; | |||
} | |||
@@ -36,7 +36,7 @@ class Microtonal | |||
{ | |||
public: | |||
/**Constructor*/ | |||
Microtonal(); | |||
Microtonal(const int& gzip_compression); | |||
/**Destructor*/ | |||
~Microtonal(); | |||
void defaults(); | |||
@@ -131,6 +131,8 @@ class Microtonal | |||
//the real tunning is x1/x2 | |||
unsigned int x1, x2; | |||
} octave[MAX_OCTAVE_SIZE], tmpoctave[MAX_OCTAVE_SIZE]; | |||
const int& gzip_compression; | |||
}; | |||
#endif |
@@ -12,7 +12,6 @@ | |||
#include <lo/lo.h> | |||
#include <unistd.h> | |||
#include <dirent.h> | |||
#include "../UI/Connection.h" | |||
#include "../UI/Fl_Osc_Interface.h" | |||
@@ -20,6 +19,7 @@ | |||
#include <map> | |||
#include "Util.h" | |||
#include "TmpFileMgr.h" | |||
#include "Master.h" | |||
#include "Part.h" | |||
#include "PresetExtractor.h" | |||
@@ -459,13 +459,12 @@ namespace Nio | |||
} | |||
/* Implementation */ | |||
class MiddleWareImpl | |||
class MiddleWareImpl : TmpFileMgr | |||
{ | |||
static constexpr const char* tmp_nam_prefix = "/tmp/zynaddsubfx_"; | |||
MiddleWare *parent; | |||
//Detect if the name of the process is 'zynaddsubfx' | |||
bool isPlugin() | |||
bool isPlugin() const | |||
{ | |||
std::string proc_file = "/proc/" + to_s(getpid()) + "/comm"; | |||
std::ifstream ifs(proc_file); | |||
@@ -477,113 +476,11 @@ class MiddleWareImpl | |||
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: | |||
MiddleWareImpl(MiddleWare *mw, SYNTH_T synth, int prefered_port); | |||
MiddleWareImpl(MiddleWare *mw, SYNTH_T synth, Config* config, | |||
int preferred_port); | |||
~MiddleWareImpl(void); | |||
void warnMemoryLeaks(void); | |||
@@ -670,7 +567,10 @@ public: | |||
auto alloc = std::async(std::launch::async, | |||
[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)) | |||
fprintf(stderr, "Warning: failed to load part<%s>!\n", filename); | |||
@@ -704,7 +604,10 @@ public: | |||
{ | |||
if(npart == -1) | |||
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(); | |||
obj_store.extractPart(p, npart); | |||
kits.extractPart(p, npart); | |||
@@ -721,7 +624,7 @@ public: | |||
//structures at once... TODO error handling | |||
void loadMaster(const char *filename) | |||
{ | |||
Master *m = new Master(synth); | |||
Master *m = new Master(synth, config); | |||
m->uToB = uToB; | |||
m->bToU = bToU; | |||
if(filename) { | |||
@@ -829,7 +732,7 @@ public: | |||
{ | |||
char buffer[1024]; | |||
memset(buffer, 0, sizeof(buffer)); | |||
DummyDataObj d(buffer, 1024, (void*)&config, this, uToB); | |||
DummyDataObj d(buffer, 1024, (void*)config, this, uToB); | |||
strcpy(buffer, "/config/"); | |||
Config::ports.dispatch(msg+8, d); | |||
@@ -896,15 +799,20 @@ public: | |||
//Synthesis Rate Parameters | |||
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); | |||
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 | |||
server = lo_server_new_with_proto(NULL, LO_UDP, liblo_error_cb); | |||
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 | |||
the_bToU = bToU; | |||
#endif | |||
master = new Master(synth); | |||
master = new Master(synth, config); | |||
master->bToU = bToU; | |||
master->uToB = uToB; | |||
osc = GUI::genOscInterface(mw); | |||
@@ -1340,8 +1248,9 @@ void MiddleWareImpl::warnMemoryLeaks(void) | |||
/****************************************************************************** | |||
* 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) | |||
{ | |||
@@ -1432,3 +1341,13 @@ const char* MiddleWare::getServerAddress(void) const | |||
{ | |||
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> | |||
struct SYNTH_T; | |||
class Master; | |||
class Config; | |||
class Master; | |||
class PresetsStore; | |||
//Link between realtime and non-realtime layers | |||
class MiddleWare | |||
{ | |||
public: | |||
MiddleWare(SYNTH_T synth, int prefered_port = -1); | |||
MiddleWare(SYNTH_T synth, Config *config, | |||
int preferred_port = -1); | |||
~MiddleWare(void); | |||
void updateResources(Master *m); | |||
//returns internal master pointer | |||
@@ -39,6 +43,9 @@ class MiddleWare | |||
const SYNTH_T &getSynth(void) const; | |||
//liblo stuff | |||
const char* getServerAddress(void) const; | |||
const PresetsStore& getPresetsStore() const; | |||
PresetsStore& getPresetsStore(); | |||
private: | |||
class MiddleWareImpl *impl; | |||
}; |
@@ -159,6 +159,10 @@ static const Ports kitPorts = { | |||
rToggle(Ppadenabled, "PADsynth enable"), | |||
rParamZyn(Psendtoparteffect, "Effect Levels"), | |||
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, | |||
[](const char *msg, RtData &d) { | |||
rObject &o = *(rObject*)d.obj; | |||
@@ -184,8 +188,12 @@ static const Ports kitPorts = { | |||
const Ports &Part::Kit::ports = kitPorts; | |||
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_; | |||
fft = fft_; | |||
@@ -195,6 +203,7 @@ Part::Part(Allocator &alloc, const SYNTH_T &synth_, Microtonal *microtonal_, FFT | |||
monomemClear(); | |||
for(int n = 0; n < NUM_KIT_ITEMS; ++n) { | |||
kit[n].parent = this; | |||
kit[n].Pname = new char [PART_MAX_NAME_LEN]; | |||
kit[n].adpars = nullptr; | |||
kit[n].subpars = nullptr; | |||
@@ -328,16 +337,16 @@ void Part::cleanup(bool final_) | |||
for(int k = 0; k < POLYPHONY; ++k) | |||
KillNotePos(k); | |||
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(); | |||
for(int nefx = 0; nefx < NUM_PART_EFX; ++nefx) | |||
partefx[nefx]->cleanup(); | |||
for(int n = 0; n < NUM_PART_EFX + 1; ++n) | |||
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); | |||
if(kit[0].Ppadenabled) | |||
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) | |||
@@ -598,7 +608,8 @@ void Part::NoteOn(unsigned char note, | |||
memory.alloc<SUBnote>(kit[0].subpars, pars); | |||
if(kit[0].Ppadenabled) | |||
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) | |||
partnote[posb].itemsplaying++; | |||
@@ -627,7 +638,8 @@ void Part::NoteOn(unsigned char note, | |||
if(kit[item].padpars && kit[item].Ppadenabled) | |||
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 | |||
if(legatomodevalid) { | |||
@@ -643,7 +655,8 @@ void Part::NoteOn(unsigned char note, | |||
memory.alloc<SUBnote>(kit[item].subpars, pars); | |||
if(kit[item].padpars && kit[item].Ppadenabled) | |||
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) | |||
partnote[posb].itemsplaying++; | |||
@@ -1193,7 +1206,7 @@ int Part::saveXML(const char *filename) | |||
add2XMLinstrument(&xml); | |||
xml.endbranch(); | |||
int result = xml.saveXMLfile(filename); | |||
int result = xml.saveXMLfile(filename, gzip_compression); | |||
return result; | |||
} | |||
@@ -37,7 +37,9 @@ class Part | |||
/**Constructor | |||
* @param microtonal_ Pointer to the microtonal object | |||
* @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*/ | |||
~Part(); | |||
@@ -85,6 +87,7 @@ class Part | |||
//the part's kit | |||
struct Kit { | |||
Part *parent; | |||
bool Penabled, Pmuted; | |||
unsigned char Pminkey, Pmaxkey; | |||
char *Pname; | |||
@@ -198,6 +201,7 @@ class Part | |||
FFTwrapper *fft; | |||
Allocator &memory; | |||
const SYNTH_T &synth; | |||
const int &gzip_compression, &interpolation; | |||
}; | |||
#endif |
@@ -17,7 +17,6 @@ | |||
#include "../Params/PADnoteParameters.h" | |||
#include "../Params/Presets.h" | |||
#include "../Params/PresetsArray.h" | |||
#include "../Params/PresetsStore.h" | |||
#include "../Params/SUBnoteParameters.h" | |||
#include "../Misc/MiddleWare.h" | |||
#include "PresetExtractor.h" | |||
@@ -32,8 +31,9 @@ const rtosc::Ports real_preset_ports = | |||
{ | |||
{"scan-for-presets:", 0, 0, | |||
[](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()); | |||
for(unsigned i=0; i<pre.size();++i) | |||
d.reply(d.loc, "isss", i, | |||
@@ -84,11 +84,13 @@ const rtosc::Ports real_preset_ports = | |||
}}, | |||
{"clipboard-type:", 0, 0, | |||
[](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, | |||
[](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"); | |||
//Extract Via mxml | |||
//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(); | |||
@@ -241,7 +243,7 @@ std::string doArrayCopy(MiddleWare &mw, int field, string url, string name) | |||
//Get the pointer | |||
T *t = (T*)capture<void*>(m, url+"self"); | |||
//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(); | |||
@@ -415,7 +417,7 @@ void presetPaste(MiddleWare &mw, std::string url, std::string name) | |||
string data = ""; | |||
XMLwrapper xml; | |||
if(name.empty()) { | |||
data = presetsstore.clipboard.data; | |||
data = mw.getPresetsStore().clipboard.data; | |||
if(data.length() < 20) | |||
return; | |||
if(!xml.putXMLdata(data.c_str())) | |||
@@ -440,7 +442,7 @@ void presetPasteArray(MiddleWare &mw, std::string url, int field, std::string na | |||
string data = ""; | |||
XMLwrapper xml; | |||
if(name.empty()) { | |||
data = presetsstore.clipboard.data; | |||
data = mw.getPresetsStore().clipboard.data; | |||
if(data.length() < 20) | |||
return; | |||
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 <vector> | |||
#include <cassert> | |||
@@ -45,10 +46,6 @@ | |||
prng_t prng_state = 0x1234; | |||
Config config; | |||
float *denormalkillbuf; | |||
/* | |||
* Transform the velocity according the scaling parameter (velocity sensing) | |||
*/ | |||
@@ -28,8 +28,6 @@ | |||
#include <stdint.h> | |||
#include <algorithm> | |||
#include <set> | |||
#include "Config.h" | |||
#include "../globals.h" | |||
using std::min; | |||
using std::max; | |||
@@ -58,10 +56,6 @@ std::string os_pid_as_padded_string(); | |||
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); | |||
template<class T> | |||
@@ -31,7 +31,7 @@ | |||
#include <iostream> | |||
#include <sstream> | |||
#include "../globals.h" | |||
#include "globals.h" | |||
#include "Util.h" | |||
using namespace std; | |||
@@ -187,13 +187,12 @@ bool XMLwrapper::hasPadSynth() const | |||
/* SAVE XML members */ | |||
int XMLwrapper::saveXMLfile(const string &filename) const | |||
int XMLwrapper::saveXMLfile(const string &filename, int compression) const | |||
{ | |||
char *xmldata = getXMLdata(); | |||
if(xmldata == NULL) | |||
return -2; | |||
int compression = config.cfg.GzipCompression; | |||
int result = dosavefile(filename.c_str(), compression, xmldata); | |||
free(xmldata); | |||
@@ -49,7 +49,7 @@ class XMLwrapper | |||
* @param filename the name of the destination file. | |||
* @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. | |||
@@ -25,13 +25,14 @@ | |||
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; | |||
} | |||
EngineMgr::EngineMgr(const SYNTH_T *synth) | |||
EngineMgr::EngineMgr(const SYNTH_T *synth, const oss_devs_t& oss_devs) | |||
{ | |||
assert(synth); | |||
Engine *defaultEng = new NulEngine(*synth); | |||
@@ -39,8 +40,8 @@ EngineMgr::EngineMgr(const SYNTH_T *synth) | |||
//conditional compiling mess (but contained) | |||
engines.push_back(defaultEng); | |||
#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 | |||
#if ALSA | |||
engines.push_back(new AlsaEngine(*synth)); | |||
@@ -14,7 +14,9 @@ struct SYNTH_T; | |||
class EngineMgr | |||
{ | |||
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(); | |||
/**Gets requested engine | |||
@@ -39,6 +41,6 @@ class EngineMgr | |||
AudioOut *defaultOut; | |||
MidiIn *defaultIn; | |||
private: | |||
EngineMgr(const SYNTH_T *synth); | |||
EngineMgr(const SYNTH_T *synth, const oss_devs_t &oss_devs); | |||
}; | |||
#endif |
@@ -5,6 +5,7 @@ | |||
#include "MidiIn.h" | |||
#include "AudioOut.h" | |||
#include "WavEngine.h" | |||
#include "../Misc/Config.h" | |||
#include <cstring> | |||
#include <iostream> | |||
#include <algorithm> | |||
@@ -30,11 +31,12 @@ bool Nio::pidInClientName = false; | |||
string Nio::defaultSource = IN_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 | |||
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); | |||
out->setMaster(master); | |||
@@ -6,13 +6,14 @@ | |||
class WavFile; | |||
class Master; | |||
struct SYNTH_T; | |||
class oss_devs_t; | |||
/**Interface to Nio Subsystem | |||
* | |||
* Should be only externally included header */ | |||
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); | |||
void stop(void); | |||
@@ -22,6 +22,7 @@ | |||
#include "OssEngine.h" | |||
#include "../Misc/Util.h" | |||
#include "../Misc/Config.h" | |||
#include "../globals.h" | |||
#include <cstring> | |||
@@ -179,8 +180,11 @@ OssMidiParse(struct OssMidiParse &midi_parse, | |||
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"; | |||
@@ -212,7 +216,7 @@ bool OssEngine::openAudio() | |||
const char *device = getenv("DSP_DEVICE"); | |||
if(device == NULL) | |||
device = config.cfg.LinuxOSSWaveOutDev; | |||
device = linux_oss_wave_out_dev; | |||
/* NOTE: PIPEs and FIFOs can block when opening them */ | |||
audio.handle = open(device, O_WRONLY, O_NONBLOCK); | |||
@@ -350,7 +354,7 @@ bool OssEngine::openMidi() | |||
const char *device = getenv("MIDI_DEVICE"); | |||
if(device == NULL) | |||
device = config.cfg.LinuxOSSSeqInDev; | |||
device = linux_oss_seq_in_dev; | |||
/* NOTE: PIPEs and FIFOs can block when opening them */ | |||
handle = open(device, O_RDONLY, O_NONBLOCK); | |||
@@ -45,7 +45,7 @@ struct OssMidiParse { | |||
class OssEngine:public AudioOut, MidiIn | |||
{ | |||
public: | |||
OssEngine(const SYNTH_T &synth); | |||
OssEngine(const SYNTH_T &synth, const class oss_devs_t& oss_devs); | |||
~OssEngine(); | |||
bool Start(); | |||
@@ -83,6 +83,8 @@ class OssEngine:public AudioOut, MidiIn | |||
bool en; | |||
bool is32bit; | |||
} audio; | |||
const char* linux_oss_wave_out_dev; | |||
//Midi | |||
bool openMidi(); | |||
@@ -94,6 +96,8 @@ class OssEngine:public AudioOut, MidiIn | |||
bool en; | |||
bool run; | |||
} midi; | |||
const char* linux_oss_seq_in_dev; | |||
}; | |||
#endif |
@@ -43,8 +43,10 @@ extern MiddleWare *middleware; | |||
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 */ | |||
name = "OSS-MULTI"; | |||
@@ -81,7 +83,7 @@ OssMultiEngine :: openAudio() | |||
const char *device = getenv("DSP_DEVICE"); | |||
if(device == 0) | |||
device = config.cfg.LinuxOSSWaveOutDev; | |||
device = linux_oss_wave_out_dev; | |||
/* NOTE: PIPEs and FIFOs can block when opening them */ | |||
handle = open(device, O_WRONLY, O_NONBLOCK); | |||
@@ -29,7 +29,8 @@ | |||
class OssMultiEngine : public AudioOut | |||
{ | |||
public: | |||
OssMultiEngine(const SYNTH_T &synth); | |||
OssMultiEngine(const SYNTH_T &synth, | |||
const class oss_devs_t& oss_devs); | |||
~OssMultiEngine(); | |||
bool Start(); | |||
@@ -62,6 +63,8 @@ class OssMultiEngine : public AudioOut | |||
bool en; | |||
bool is32bit; | |||
const char* linux_oss_wave_out_dev; | |||
}; | |||
#endif |
@@ -2,6 +2,7 @@ | |||
#define OUTMGR_H | |||
#include "../Misc/Stereo.h" | |||
#include "../globals.h" | |||
#include <list> | |||
#include <string> | |||
#include <semaphore.h> | |||
@@ -16,7 +17,7 @@ class OutMgr | |||
~OutMgr(); | |||
/**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 | |||
* @param n number of requested samples (defaults to 1) | |||
@@ -30,13 +30,14 @@ | |||
#include "PresetsStore.h" | |||
#include "../Misc/XMLwrapper.h" | |||
#include "../Misc/Util.h" | |||
#include "../Misc/Config.h" | |||
using namespace std; | |||
//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"); | |||
xml.saveXMLfile(filename); | |||
xml.saveXMLfile(filename, config.cfg.GzipCompression); | |||
} | |||
bool PresetsStore::pastepreset(XMLwrapper &xml, unsigned int npreset) | |||
@@ -29,8 +29,9 @@ | |||
class XMLwrapper; | |||
class PresetsStore | |||
{ | |||
const class Config& config; | |||
public: | |||
PresetsStore(); | |||
PresetsStore(const class Config &config); | |||
~PresetsStore(); | |||
//Clipboard stuff | |||
@@ -62,5 +63,5 @@ class PresetsStore | |||
void clearpresets(); | |||
}; | |||
extern PresetsStore presetsstore; | |||
//extern PresetsStore presetsstore; | |||
#endif |
@@ -1434,8 +1434,8 @@ inline void ADnote::ComputeVoiceNoise(int nvoice) | |||
*/ | |||
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) | |||
return 0; | |||
@@ -482,7 +482,8 @@ void OscilGen::changebasefunction(void) | |||
{ | |||
if(Pcurrentbasefunc != 0) { | |||
getbasefunction(tmpsmps); | |||
fft->smps2freqs(tmpsmps, basefuncFFTfreqs); | |||
if(fft) | |||
fft->smps2freqs(tmpsmps, basefuncFFTfreqs); | |||
clearDC(basefuncFFTfreqs); | |||
} | |||
else //in this case basefuncFFTfreqs are not used | |||
@@ -1139,6 +1140,8 @@ void OscilGen::paste(OscilGen &o) | |||
RESTORE(fft); | |||
RESTORE(basefuncFFTfreqs); | |||
RESTORE(res); | |||
if(this->Pcurrentbasefunc) | |||
changebasefunction(); | |||
this->prepare(); | |||
} | |||
@@ -29,8 +29,8 @@ | |||
#include "../Misc/Util.h" | |||
PADnote::PADnote(PADnoteParameters *parameters, | |||
SynthParams pars) | |||
:SynthNote(pars), pars(*parameters) | |||
SynthParams pars, const int& interpolation) | |||
:SynthNote(pars), pars(*parameters), interpolation(interpolation) | |||
{ | |||
firsttime = true; | |||
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); | |||
if(config.cfg.Interpolation) | |||
if(interpolation) | |||
Compute_Cubic(outl, outr, freqhi, freqlo); | |||
else | |||
Compute_Linear(outl, outr, freqhi, freqlo); | |||
@@ -30,7 +30,8 @@ | |||
class PADnote:public SynthNote | |||
{ | |||
public: | |||
PADnote(PADnoteParameters *parameters, SynthParams pars); | |||
PADnote(PADnoteParameters *parameters, SynthParams pars, | |||
const int &interpolation); | |||
~PADnote(); | |||
void legatonote(LegatoParams pars); | |||
@@ -104,6 +105,7 @@ class PADnote:public SynthNote | |||
float globaloldamplitude, globalnewamplitude, velocity, realfreq; | |||
const int& interpolation; | |||
}; | |||
@@ -491,8 +491,8 @@ void SUBnote::computecurrentparameters() | |||
*/ | |||
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) | |||
return 0; | |||
@@ -39,7 +39,13 @@ decl {\#include "../Misc/Util.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 | |||
} | |||
@@ -943,7 +949,7 @@ stagescounter->oscMove("parameter"+to_s(npb+4));} | |||
Fl_Counter stagescounter { | |||
label {St.} | |||
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");} | |||
class Fl_Osc_Counter | |||
} | |||
@@ -223,3 +223,13 @@ void EnvelopeFreeEdit::update(void) | |||
oscWrite("Penvval"); | |||
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_BW 5 | |||
class EnvelopeFreeEdit : public Fl_Box, Fl_Osc_Widget | |||
class EnvelopeFreeEdit : public Fl_Box, public Fl_Osc_Widget | |||
{ | |||
public: | |||
EnvelopeFreeEdit(int x,int y, int w, int h, const char *label=0); | |||
void init(void); | |||
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 update(void); | |||
void update(void) override; | |||
void rebase(std::string new_base) override; | |||
int lastpoint; | |||
@@ -24,6 +24,6 @@ class Fl_EQGraph:public Fl_Box, public Fl_Osc_Widget | |||
float getfreqpos(float freq) const; | |||
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; | |||
} else { | |||
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(); | |||
} | |||
} | |||
@@ -141,16 +141,24 @@ void Fl_EQGraph::draw(void) | |||
double Fl_EQGraph::getresponse(int maxy,float freq) const | |||
{ | |||
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 | |||
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) | |||
{ | |||
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) | |||
@@ -95,11 +98,10 @@ void Fl_Osc_Dial::cb(void) | |||
{ | |||
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())); | |||
else | |||
oscWrite(ext, "i", (int)(value())); | |||
if(cb_data.first) | |||
cb_data.first(this, cb_data.second); | |||
@@ -4,7 +4,7 @@ | |||
#include "Fl_Osc_Widget.H" | |||
#include <string> | |||
class Fl_Osc_DialF:public WidgetPDial, Fl_Osc_Widget | |||
class Fl_Osc_DialF:public WidgetPDial, public Fl_Osc_Widget | |||
{ | |||
public: | |||
@@ -4,7 +4,7 @@ | |||
#include "Fl_Osc_Widget.H" | |||
//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: | |||
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_Interface.h" | |||
class PADnoteOvertonePosition: public Fl_Box, Fl_Osc_Widget | |||
class PADnoteOvertonePosition: public Fl_Box, public Fl_Osc_Widget | |||
{ | |||
public: | |||
PADnoteOvertonePosition(int x,int y, int w, int h, const char *label=0) | |||
@@ -13,7 +13,7 @@ | |||
class FilterParams; | |||
class FormantFilterGraph : public Fl_Box, Fl_Osc_Widget { | |||
class FormantFilterGraph : public Fl_Box, public Fl_Osc_Widget { | |||
public: | |||
FormantFilterGraph(int x,int y, int w, int h, const char *label=0); | |||
void init(int *nvowel_, int *nformant_); | |||
@@ -17,7 +17,7 @@ decl {\#include <stdio.h>} {public local | |||
decl {\#include <string.h>} {public local | |||
} | |||
decl {\#if defined(__linux__) && ! defined(PLUGINVERSION) | |||
decl {\#if ! defined(PLUGINVERSION) && HAS_X11 | |||
\#include "zynaddsubfx.xpm" | |||
\#endif} {public local | |||
} | |||
@@ -76,7 +76,7 @@ extern NSM_Client *nsm; | |||
\#endif} {public local | |||
} | |||
decl {\#if defined(__linux__) && ! defined(PLUGINVERSION) | |||
decl {\#if !defined(PLUGINVERSION) && HAS_X11 | |||
\#include <X11/xpm.h> | |||
\#endif} {public local | |||
} | |||
@@ -1502,7 +1502,7 @@ configui=new ConfigUI(osc); | |||
make_window(); | |||
fl_open_display(); | |||
\#if defined(__linux__) && ! defined(PLUGINVERSION) | |||
\#if !defined(PLUGINVERSION) && HAS_X11 | |||
Pixmap p, mask; | |||
XCreatePixmapFromData(fl_display, DefaultRootWindow(fl_display), | |||
(char**)zynaddsubfx_xpm, &p, &mask, NULL); | |||
@@ -112,13 +112,17 @@ class PartKitItem {open : {public Fl_Osc_Group} | |||
} | |||
Fl_Button {} { | |||
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 | |||
class Fl_Osc_Button | |||
} | |||
Fl_Button {} { | |||
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 | |||
class Fl_Osc_Button | |||
} | |||
@@ -124,7 +124,7 @@ if (x==0) o->selection_color(0); | |||
callback {int x=64; | |||
if (Fl::event_button1() || Fl::event() == FL_MOUSEWHEEL) x=127-(int)o->value(); | |||
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 | |||
class PPSlider | |||
} | |||
@@ -153,7 +153,8 @@ make_window(); | |||
harmonic->show(); | |||
mag->ext = "Phmag" + to_s(n); | |||
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)); | |||
end();} {} | |||
@@ -161,7 +162,7 @@ end();} {} | |||
Function {refresh()} {} { | |||
code {// request values for the widgets | |||
mag->oscWrite(mag->ext); | |||
osc->requestValue(base+"Phrelbw"+to_s(n));} {} | |||
bw->oscWrite(bw->ext);} {} | |||
} | |||
Function {~SUBnoteharmonic()} {} { | |||
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 | |||
#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 | |||
struct SYNTH_T { | |||
SYNTH_T(void) | |||
:samplerate(44100), buffersize(256), oscilsize(1024) | |||
{ | |||
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*/ | |||
unsigned int samplerate; | |||
/** | |||
* 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 | |||
* decrease this the CPU requirements gets high. | |||
*/ | |||
@@ -291,13 +320,7 @@ struct SYNTH_T { | |||
{ | |||
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 | |||
}; | |||
#endif |
@@ -76,7 +76,7 @@ NSM_Client *nsm = 0; | |||
char *instance_name = 0; | |||
void exitprogram(); | |||
void exitprogram(const Config &config); | |||
extern pthread_t main_thread; | |||
@@ -91,21 +91,21 @@ void sigterm_exit(int /*sig*/) | |||
/* | |||
* 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->swaplr = swaplr; | |||
signal(SIGINT, sigterm_exit); | |||
signal(SIGTERM, sigterm_exit); | |||
Nio::init(master->synth, master); | |||
Nio::init(master->synth, config->cfg.oss_devs, master); | |||
} | |||
/* | |||
* Program exit | |||
*/ | |||
void exitprogram() | |||
void exitprogram(const Config& config) | |||
{ | |||
Nio::stop(); | |||
config.save(); | |||
@@ -121,7 +121,6 @@ void exitprogram() | |||
delete nsm; | |||
#endif | |||
delete [] denormalkillbuf; | |||
FFT_cleanup(); | |||
} | |||
@@ -129,6 +128,7 @@ int main(int argc, char *argv[]) | |||
{ | |||
main_thread = pthread_self(); | |||
SYNTH_T synth; | |||
Config config; | |||
config.init(); | |||
int noui = 0; | |||
cerr | |||
@@ -375,12 +375,14 @@ int main(int argc, char *argv[]) | |||
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()) { | |||
int tmp = master->loadXML(loadfile.c_str()); | |||
@@ -413,13 +415,6 @@ int main(int argc, char *argv[]) | |||
//Run the Nio system | |||
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()) { | |||
cout << "Executing user supplied command: " << execAfterInit << endl; | |||
@@ -519,6 +514,6 @@ done: | |||
middleware->tick(); | |||
} | |||
exitprogram(); | |||
exitprogram(config); | |||
return 0; | |||
} |