boost::optional<Actions::Action> Actions::getOpt(std::int32_t ID) { if (auto res = Impl::get(session, ID)) { return fromDB(res.value()); } else { return {}; } }
/// ValueOfPixel() converts a y position on screen to an envelope value. /// @param y - y position, usually of the mouse.relative to the clip. /// @param height - height of the rectangle we are in. /// @upper - true if we are on the upper line, false if on lower. /// @dB - display mode either linear or log. /// @zoomMin - vertical scale, typically -1.0 /// @zoomMax - vertical scale, typically +1.0 /// @eMin - clips result to this range. /// @eMax - clips result to this range. float Envelope::ValueOfPixel( int y, int height, bool upper, bool dB, float zoomMin, float zoomMax, float eMin, float eMax ) { float v; wxASSERT( height > 0 ); v = zoomMax - (y/(float)height) * (zoomMax - zoomMin); if (mContourOffset) { if( v > 0.0 ) v += .5; else v -= .5; } if (dB) v = fromDB(v); // JC: The eMin/eMax code originally assumed a symmetrical range. // so only eMin was needed. I'm very dubious about the lower curve // behaviour and expect some funny behaviour when dragging // the lower curve when we have asymmetric ranges. // Upper curve: gets clamped between eMin and eMax. Looks OK. // Lower curve: reset to eMin if > 0 otherwise made positive and <=eMax. if ((upper && v < eMin) || (!upper && v > 0)) v = eMin; else if (!upper) v = -v; if(v > eMax) v = eMax; return v; }
void PowerJuiceX2Plugin::d_setParameterValue(uint32_t index, float value) { switch (index) { case paramAttack: attack = value; attackSamples = d_getSampleRate()*(attack/1000.0f); break; case paramRelease: release = value; releaseSamples = d_getSampleRate()*(release/1000.0f); break; case paramThreshold: threshold = value; break; case paramRatio: ratio = value; break; case paramMakeup: makeup = value; makeupFloat = fromDB(makeup); break; case paramMix: mix = value; break; } }
boost::optional<Reports::Report> Reports::get(std::int32_t ID) { auto sql = Table::Sql::select().where(Table::ID == ID); if (auto dbTuple = session.getResult(sql)) { return fromDB(dbTuple.value()); } else { return {}; } }
float Envelope::ValueOfPixel( int y, int height, bool upper, bool dB, float zoomMin, float zoomMax, float eMin ) { float v; v = zoomMax - (y/(float)height) * (zoomMax - zoomMin); if (mContourOffset) { if( v > 0.0 ) v += .5; else v -= .5; } if (dB) v = fromDB(v); if ((upper && v < eMin) || (!upper && v > 0)) v = eMin; else if (!upper) v = -v; return v; }
/// ValueOfPixel() converts a y position on screen to an envelope value. /// @param y - y position, usually of the mouse.relative to the clip. /// @param height - height of the rectangle we are in. /// @upper - true if we are on the upper line, false if on lower. /// @dB - display mode either linear or log. /// @zoomMin - vertical scale, typically -1.0 /// @zoomMax - vertical scale, typically +1.0 float Envelope::ValueOfPixel( int y, int height, bool upper, bool dB, float zoomMin, float zoomMax) { float v; wxASSERT( height > 0 ); v = zoomMax - (y/(float)height) * (zoomMax - zoomMin); if (mContourOffset) { if( v > 0.0 ) v += .5; else v -= .5; } if (dB) v = fromDB(v); // MB: this is mostly equivalent to what the old code did, I'm not sure // if anything special is needed for asymmetric ranges if(upper) return ClampValue(v); else return ClampValue(-v); }
// Returns true if parent needs to be redrawn bool Envelope::MouseEvent(wxMouseEvent & event, wxRect & r, double h, double pps, bool dB) { //h -= mOffset; int ctr, height; bool upper; if (mMirror) { height = r.height / 2; ctr = r.y + height; upper = (event.m_y < ctr); } else { height = r.height; ctr = r.y + height; upper = true; } if (event.ButtonDown()) { mIsDeleting = false; double tleft = h - mOffset; double tright = tleft + (r.width / pps); int bestNum = -1; int bestDist = 10; int len = mEnv.Count(); for (int i = 0; i < len; i++) { if (mEnv[i]->t >= tleft && mEnv[i]->t <= tright) { double v = mEnv[i]->val; int x = int ((mEnv[i]->t + mOffset - h) * pps) + r.x; int dy; if (dB) dy = int (toDB(v) * height); else dy = int (v * height); int y; if (upper) y = int (ctr - dy); else y = int (ctr + dy); #ifndef SQR #define SQR(X) ((X)*(X)) #endif int d = int (sqrt(SQR(x - event.m_x) + SQR(y - event.m_y)) + 0.5); if (d < bestDist) { bestNum = i; bestDist = d; } } } if (bestNum >= 0) { mDragPoint = bestNum; } else { // Create new point double when = h + (event.m_x - r.x) / pps - mOffset; int dy; if (upper) dy = ctr - event.m_y; else dy = event.m_y - ctr; double newVal; if (dB) newVal = fromDB(dy / double (height)); else newVal = dy / double (height); if (newVal < 0.0) newVal = 0.0; if (newVal > 1.0) newVal = 1.0; mDragPoint = Insert(when, newVal); mDirty = true; } mUpper = upper; mInitialWhen = mEnv[mDragPoint]->t; mInitialVal = mEnv[mDragPoint]->val; mInitialX = event.m_x; mInitialY = event.m_y; return true; } if (event.Dragging() && mDragPoint >= 0) { mDirty = true; wxRect larger = r; larger.Inflate(5, 5); if (!mIsDeleting && mDragPoint > 0 && mDragPoint < mEnv.Count() - 1 && !larger.Inside(event.m_x, event.m_y)) { mEnv[mDragPoint]->t = mEnv[mDragPoint - 1]->t; mEnv[mDragPoint]->val = mEnv[mDragPoint - 1]->val; mIsDeleting = true; return true; } if (larger.Inside(event.m_x, event.m_y)) mIsDeleting = false; if (mIsDeleting) return false; int y; if (mUpper) y = ctr - event.m_y; else y = event.m_y - ctr; double newVal; if (dB) newVal = fromDB(y / double (height)); else newVal = y / double (height); if (newVal < 0.0) newVal = 0.0; if (newVal > 1.0) newVal = 1.0; double newWhen = mInitialWhen + (event.m_x - mInitialX) / pps; if (mDragPoint > 0 && newWhen < mEnv[mDragPoint - 1]->t) newWhen = mEnv[mDragPoint - 1]->t; if (mDragPoint < mEnv.Count() - 1 && newWhen > mEnv[mDragPoint + 1]->t) newWhen = mEnv[mDragPoint + 1]->t; if (mDragPoint == 0) newWhen = 0; if (mDragPoint == mEnv.Count() - 1) newWhen = mTrackLen; mEnv[mDragPoint]->t = newWhen; mEnv[mDragPoint]->val = newVal; return true; } if (event.ButtonUp()) { if (mIsDeleting) { delete mEnv[mDragPoint]; mEnv.RemoveAt(mDragPoint); } mDragPoint = -1; return true; } return false; }
void PowerJuiceX2Plugin::d_run(const float** inputs, float** outputs, uint32_t frames) { const float* in1 = inputs[0]; const float* in2 = inputs[1]; float* out1 = outputs[0]; float* out2 = outputs[1]; float sum; float data; float difference; for (uint32_t i=0; i < frames; i++) { sum = 0.0f; data = 0.0f; difference = 0; //sanitizeDenormal(in1[i]); // FIXME - you cannot modify inputs //sanitizeDenormal(in2[i]); // FIXME - you cannot modify inputs /* compute last RMS */ //store audio samples in an RMS buffer line RMSStack.data[RMSStack.start++] = std::max(in1[i], in2[i]); if (RMSStack.start == kFloatRMSStackCount) RMSStack.start = 0; //compute RMS over last kFloatRMSStackCount samples for (int j=0; j < kFloatRMSStackCount; ++j) { data = RMSStack.data[(RMSStack.start+j) % kFloatRMSStackCount]; sum += data * data; } //root mean SQUARE float RMS = sqrt(sum / kFloatRMSStackCount); sanitizeDenormal(RMS); /* compute gain reduction if needed */ float RMSDB = toDB(RMS); if (RMSDB>threshold) { //attack stage float difference = (RMSDB-threshold); //sanitizeDenormal(difference); targetGR = difference - difference/ratio; if (targetGR>difference/(ratio/4.0f)) { targetGR = difference - difference/(ratio*1.5f); //more power! } // if (GR<targetGR) { //approach targetGR at attackSamples rate GR -= (GR-targetGR)/(attackSamples); } else { //approach targetGR at releaseSamples rate GR -= (GR-targetGR)/releaseSamples; } sanitizeDenormal(GR); } else { //release stage //approach targetGR at releaseSamples rate, targetGR = 0.0f GR -= GR/releaseSamples; } //store audio in lookahead buffer lookaheadStack.data[lookaheadStack.start++] = std::max(in1[i], in2[i]); //printf("rms\n"); if (lookaheadStack.start == kFloatLookaheadStackCount) lookaheadStack.start = 0; if (++averageCounter >= refreshSkip) { //add relevant values to the shared memory rms.data[rms.start++] = RMSDB; gainReduction.data[gainReduction.start++] = GR; //rewind stack reading heads if needed if (rms.start == kFloatStackCount) rms.start = 0; if (gainReduction.start == kFloatStackCount) gainReduction.start = 0; //saving in gfx format, for speed //share memory for (int j=0; j < kFloatStackCount; ++j) history.rms[j] = -toIEC(rms.data[(rms.start+j) % kFloatStackCount])/200*h +h +y; for (int j=0; j < kFloatStackCount; ++j) { history.gainReduction[j] = -toIEC(-gainReduction.data[(gainReduction.start+j) % kFloatStackCount])/200*h +h +y; } repaintSkip++; if (repaintSkip>5) { repaintSkip = 0; newRepaint = true; } averageCounter = 0; inputMax = 0.0f; } /* compress, mix, done. */ float realGR = fromDB(-GR); float compressedSignal1 = in1[i]*realGR; float compressedSignal2 = in2[i]*realGR; out1[i] = (compressedSignal1*makeupFloat*mix)+in1[i]*(1-mix); out2[i] = (compressedSignal2*makeupFloat*mix)+in2[i]*(1-mix); } }
void PowerJuiceX2Plugin::d_setProgram(uint32_t index) { if (index != 0) return; /* Default parameter values */ attack = 20.0f; release = 200.0f; threshold = 0.0f; ratio = 1.0f; makeup = 0.0f; mix = 1.0f; makeupFloat = fromDB(makeup); attackSamples = d_getSampleRate()*(attack/1000.0f); releaseSamples = d_getSampleRate()*(release/1000.0f); w = 563; //waveform plane size, size of the plane in pixels; w2 = 1126; //wavefowm array h = 121; //waveform plane height x = 27; //waveform plane positions y = 53; dc = 113; //0DC line y position /* Default variable values */ averageCounter = 0; inputMax = 0.0f; balancer = 1.0f; GR = 1.0f; newRepaint = false; input.start = 0; rms.start = 0; gainReduction.start = 0; RMSStack.start = 0; lookaheadStack.start = 0; repaintSkip = 0; kFloatRMSStackCount = 400.0f/44100.0f*d_getSampleRate(); RMSStack.data = (float*) calloc(kFloatRMSStackCount, sizeof(float)); kFloatLookaheadStackCount = 800.0f/44100.0f*d_getSampleRate(); lookaheadStack.data = (float*) calloc(kFloatLookaheadStackCount, sizeof(float)); refreshSkip= 300.0f/44100.0f*d_getSampleRate(); std::memset(rms.data, 0, sizeof(float)*kFloatStackCount); std::memset(gainReduction.data, 0, sizeof(float)*kFloatStackCount); std::memset(RMSStack.data, 0, sizeof(float)*kFloatRMSStackCount); std::memset(lookaheadStack.data, 0, sizeof(float)*kFloatLookaheadStackCount); for (int j=0; j < kFloatStackCount; ++j) history.rms[j] = h +y; for (int j=0; j < kFloatStackCount; ++j) history.gainReduction[j] = h +y; d_activate(); }