#include #include #include #include #include "AudioEffect.hpp" #include "AEffEditor.hpp" //----------------------------------------------------------------------------- long dispatchEffectClass (AEffect *e, long opCode, long index, long value, void *ptr, float opt) { AudioEffect *ae = (AudioEffect *)(e->object); if(opCode == effClose) { ae->dispatcher(opCode, index, value, ptr, opt); delete ae; return 1; } return ae->dispatcher(opCode, index, value, ptr, opt); } //----------------------------------------------------------------------------- float getParameterClass(AEffect *e, long index) { AudioEffect *ae = (AudioEffect *)(e->object); return ae->getParameter(index); } //----------------------------------------------------------------------------- void setParameterClass(AEffect *e, long index, float value) { AudioEffect *ae = (AudioEffect *)(e->object); ae->setParameter(index, value); } //----------------------------------------------------------------------------- void processClass(AEffect *e, float **inputs, float **outputs, long sampleFrames) { AudioEffect *ae = (AudioEffect *)(e->object); ae->process(inputs, outputs, sampleFrames); } //----------------------------------------------------------------------------- void processClassReplacing(AEffect *e, float **inputs, float **outputs, long sampleFrames) { AudioEffect *ae = (AudioEffect *)(e->object); ae->processReplacing(inputs, outputs, sampleFrames); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- AudioEffect::AudioEffect(audioMasterCallback audioMaster, long numPrograms, long numParams) { this->audioMaster = audioMaster; editor = 0; this->numPrograms = numPrograms; this->numParams = numParams; curProgram = 0; memset(&cEffect, 0, sizeof(cEffect)); cEffect.magic = kEffectMagic; cEffect.dispatcher = dispatchEffectClass; cEffect.process = processClass; cEffect.setParameter = setParameterClass; cEffect.getParameter = getParameterClass; cEffect.numPrograms = numPrograms; cEffect.numParams = numParams; cEffect.numInputs = 1; cEffect.numOutputs = 2; cEffect.flags = 0; cEffect.resvd1 = 0; cEffect.resvd2 = 0; cEffect.initialDelay = 0; cEffect.realQualities = 0; cEffect.offQualities = 0; cEffect.ioRatio = 1.f; cEffect.object = this; cEffect.user = 0; cEffect.uniqueID = 'NoEf'; // you must set this! cEffect.version = 1; cEffect.processReplacing = processClassReplacing; sampleRate = 44100.f; blockSize = 1024L; } //----------------------------------------------------------------------------- AudioEffect::~AudioEffect() { if(editor) delete editor; } //----------------------------------------------------------------------------- long AudioEffect::dispatcher(long opCode, long index, long value, void *ptr, float opt) { long v = 0; switch(opCode) { case effOpen: open(); break; case effClose: close(); break; case effSetProgram: if(value < numPrograms) setProgram(value); break; case effGetProgram: v = getProgram(); break; case effSetProgramName: setProgramName((char *)ptr); break; case effGetProgramName: getProgramName((char *)ptr); break; case effGetParamLabel: getParameterLabel(index, (char *)ptr); break; case effGetParamDisplay: getParameterDisplay(index, (char *)ptr); break; case effGetParamName: getParameterName(index, (char *)ptr); break; case effSetSampleRate: setSampleRate(opt); break; case effSetBlockSize: setBlockSize(value); break; case effMainsChanged: if(!value) suspend(); else resume(); break; case effGetVu: v = (long)(getVu() * 32767.); break; // editor case effEditGetRect: if(editor) v = editor->getRect((ERect **)ptr); break; case effEditOpen: if(editor) v = editor->open(ptr); break; case effEditClose: if(editor) editor->close(); break; case effEditIdle: if(editor) editor->idle(); break; #if MAC case effEditDraw: if(editor) editor->draw((ERect *)ptr); break; case effEditMouse: if(editor) v = editor->mouse(index, value); break; case effEditKey: if(editor) v = editor->key(value); break; case effEditTop: if(editor) editor->top(); break; case effEditSleep: if(editor) editor->sleep(); break; #endif // new case effIdentify: v = 'NvEf'; break; case effGetChunk: v = getChunk((void**)ptr, index ? true : false); break; case effSetChunk: v = setChunk(ptr, value, index ? true : false); break; } return v; } //----------------------------------------------------------------------------- long AudioEffect::getMasterVersion() { long version = 1; if(audioMaster) { version = audioMaster(&cEffect, audioMasterVersion, 0, 0, 0, 0); if(!version) // old version = 1; } return version; } //----------------------------------------------------------------------------- long AudioEffect::getCurrentUniqueId() { long id = 0; if(audioMaster) id = audioMaster(&cEffect, audioMasterCurrentId, 0, 0, 0, 0); return id; } //----------------------------------------------------------------------------- void AudioEffect::masterIdle() { if(audioMaster) audioMaster(&cEffect, audioMasterIdle, 0, 0, 0, 0); } //----------------------------------------------------------------------------- bool AudioEffect::isInputConnected(long input) { long ret = 0; if(audioMaster) ret = audioMaster(&cEffect, audioMasterPinConnected, input, 0, 0, 0); return ret ? false : true; // return value is 0 for true } //----------------------------------------------------------------------------- bool AudioEffect::isOutputConnected(long output) { long ret = 0; if(audioMaster) ret = audioMaster(&cEffect, audioMasterPinConnected, output, 1, 0, 0); return ret ? false : true; // return value is 0 for true } //----------------------------------------------------------------------------- // flags //----------------------------------------------------------------------------- void AudioEffect::hasVu(bool state) { if(state) cEffect.flags |= effFlagsHasVu; else cEffect.flags &= ~effFlagsHasVu; } //----------------------------------------------------------------------------- void AudioEffect::hasClip(bool state) { if(state) cEffect.flags |= effFlagsHasClip; else cEffect.flags &= ~effFlagsHasClip; } //----------------------------------------------------------------------------- void AudioEffect::canMono(bool state) { if(state) cEffect.flags |= effFlagsCanMono; else cEffect.flags &= ~effFlagsCanMono; } //----------------------------------------------------------------------------- void AudioEffect::canProcessReplacing(bool state) { if(state) cEffect.flags |= effFlagsCanReplacing; else cEffect.flags &= ~effFlagsCanReplacing; } //----------------------------------------------------------------------------- void AudioEffect::programsAreChunks(bool state) { if(state) cEffect.flags |= effFlagsProgramChunks; else cEffect.flags &= ~effFlagsProgramChunks; } //----------------------------------------------------------------------------- void AudioEffect::setRealtimeQualities(long qualities) { cEffect.realQualities = qualities; } //----------------------------------------------------------------------------- void AudioEffect::setOfflineQualities(long qualities) { cEffect.offQualities = qualities; } //----------------------------------------------------------------------------- void AudioEffect::setInitialDelay(long delay) { cEffect.initialDelay = delay; } //----------------------------------------------------------------------------- // string //----------------------------------------------------------------------------- void AudioEffect::dB2string(float value, char *text) { if(value <= 0) #if MAC strcpy(text, " -° "); #else strcpy(text, " -oo "); #endif else float2string((float)(20. * log10(value)), text); } //----------------------------------------------------------------------------- void AudioEffect::Hz2string(float samples, char *text) { float sampleRate = getSampleRate(); if(!samples) float2string(0, text); else float2string(sampleRate / samples, text); } //----------------------------------------------------------------------------- void AudioEffect::ms2string(float samples, char *text) { float2string((float)(samples * 1000. / getSampleRate()), text); } //----------------------------------------------------------------------------- void AudioEffect::float2string(float value, char *text) { long c = 0, neg = 0; char string[32]; char *s; double v, integ, i10, mantissa, m10, ten = 10.; v = (double)value; if(v < 0) { neg = 1; value = -value; v = -v; c++; if(v > 9999999.) { strcpy(string, " Huge! "); return; } } else if(v > 99999999.) { strcpy(string, " Huge! "); return; } s = string + 31; *s-- = 0; *s-- = '.'; c++; integ = floor(v); i10 = fmod(integ, ten); *s-- = (long)i10 + '0'; integ /= ten; c++; while(integ >= 1. && c < 8) { i10 = fmod(integ, ten); *s-- = (long)i10 + '0'; integ /= ten; c++; } if(neg) *s-- = '-'; strcpy(text, s + 1); if(c >= 8) return; s = string + 31; *s-- = 0; mantissa = fmod(v, 1.); mantissa *= pow(ten, (double)(8 - c)); while(c < 8) { if(mantissa <= 0) *s-- = '0'; else { m10 = fmod(mantissa, ten); *s-- = (long)m10 + '0'; mantissa /= 10.; } c++; } strcat(text, s + 1); } //----------------------------------------------------------------------------- void AudioEffect::long2string(long value, char *text) { char string[32]; if(value >= 100000000) { strcpy(text, " Huge! "); return; } sprintf(string, "%7d", value); string[8] = 0; strcpy(text, (char *)string); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void AudioEffect::setParameterAutomated(long index, float value) { setParameter(index, value); if(audioMaster) audioMaster(&cEffect, audioMasterAutomate, index, 0, 0, value); // value is in opt }