protected override void FillBuffer(float[] buffer, int offset, int count) { if (InputSignal.Value != null) { InputSignal.Read(buffer, offset, count); //write to buffer FRingBuffer.Write(buffer, offset, count); //calc fft var fftSize = FRingBuffer.Size; if (FFFTBuffer.Length != fftSize) { FFFTBuffer = new double[fftSize]; FFTOut = new double[fftSize]; FWindow = AudioUtils.CreateWindowDouble(fftSize, WindowFunc); } FRingBuffer.ReadDoubleWindowed(FFFTBuffer, FWindow, 0, fftSize); FFFT.RealFFT(FFFTBuffer, true); Array.Copy(FFFTBuffer, FFTOut, fftSize); } }
private void OscBasic(float[] buffer, int count) { var t2 = 2 * T; var slope = MathUtils.Clamp(Slope.Value, 0.01, 0.99); switch (WaveForm.Value) { case WaveFormSelection.Sine: for (int i = 0; i < count; i++) { CalcFrequencyConsts(FreqBuffer[i] + FrequencyOffset.Value); buffer[i] = (float)(Gain.Value * Math.Sin(FBasicPhase * Math.PI)); FBasicPhase += t2 + FMBuffer[i] * FMLevel.Value; if (FBasicPhase > 1) { FBasicPhase -= 2; } } break; case WaveFormSelection.Triangle: for (int i = 0; i < count; i++) { CalcFrequencyConsts(FreqBuffer[i] + FrequencyOffset.Value); var phase = FBasicPhase * 0.5f + 0.5f; buffer[i] = (float)(Gain.Value * AudioUtils.Triangle(phase, slope)); FBasicPhase += t2 + FMBuffer[i] * FMLevel.Value; if (FBasicPhase >= 1) { FBasicPhase -= 2f; } } break; case WaveFormSelection.Square: for (int i = 0; i < count; i++) { CalcFrequencyConsts(FreqBuffer[i] + FrequencyOffset.Value); buffer[i] = FBasicPhase < 2 * slope ? Gain.Value : -Gain.Value; FBasicPhase += t2 + FMBuffer[i] * FMLevel.Value; if (FBasicPhase >= 2.0f) { FBasicPhase -= 2.0f; } } break; case WaveFormSelection.Sawtooth: for (int i = 0; i < count; i++) { CalcFrequencyConsts(FreqBuffer[i] + FrequencyOffset.Value); buffer[i] = (float)(Gain.Value * FBasicPhase); FBasicPhase += t2 + FMBuffer[i] * FMLevel.Value; if (FBasicPhase > 1.0f) { FBasicPhase -= 2.0f; } } break; } }
private void OscEPTR(float[] buffer, int count) { bool sync = false; var slope = Slope.Value; var t2 = 2 * T; switch (WaveForm.Value) { case WaveFormSelection.Sine: for (int i = 0; i < count; i++) { CalcFrequencyConsts(FreqBuffer[i] + FrequencyOffset.Value); buffer[i] = (float)(Gain.Value * Math.Sin(FEPTRPhase * Math.PI)); FEPTRPhase += t2 + FMBuffer[i] * FMLevel.Value; if (FEPTRPhase > 1) { FEPTRPhase -= 2; } } break; case WaveFormSelection.Sawtooth: slope = AudioUtils.Wrap(slope + 0.5f, 0, 1); goto case WaveFormSelection.Triangle; case WaveFormSelection.Triangle: //per sample loop for (int i = 0; i < count; i++) { CalcFrequencyConsts(FreqBuffer[i] + FrequencyOffset.Value); CalcTriangleCoefficients(Slope.Value); double sample; if (slope >= 0.99f) // rising saw { FEPTRPhase = sync ? -1 : FEPTRPhase + t2 + FMBuffer[i] * FMLevel.Value; if (FEPTRPhase > 1.0f - T) //transition { sample = FEPTRPhase - (FEPTRPhase / T) + (1.0f / T) - 1.0f; FEPTRPhase -= 2.0f; } else { sample = FEPTRPhase; } } else if (slope <= 0.01f) // falling saw { FEPTRPhase = sync ? -1 : FEPTRPhase + t2 + FMBuffer[i] * FMLevel.Value; if (FEPTRPhase > 1.0f - T) //transition { sample = -FEPTRPhase + (FEPTRPhase / T) - (1.0f / T) + 1.0f; FEPTRPhase -= 2.0f; } else { sample = -FEPTRPhase; } } else //triangle { if (FTriangleUp) //counting up { FEPTRPhase = sync ? -1 : FEPTRPhase + t2 * A + FMBuffer[i] * FMLevel.Value; if (FEPTRPhase > 1 - A * T) { //transitionregion sample = a2 * (FEPTRPhase * FEPTRPhase) + a1 * FEPTRPhase + a0; FEPTRPhase = 1 + (FEPTRPhase - 1) * BoverA; FTriangleUp = false; } else //linearregion { sample = FEPTRPhase; } } else //counting down { FEPTRPhase = sync ? -1 : FEPTRPhase + t2 * B + FMBuffer[i] * FMLevel.Value; if (FEPTRPhase < -1 - B * T) { //transitionregion sample = b2 * (FEPTRPhase * FEPTRPhase) + b1 * FEPTRPhase + b0; FEPTRPhase = -1 + (FEPTRPhase + 1) * AoverB; FTriangleUp = true; } else //linearregion { sample = FEPTRPhase; } } } buffer[i] = (float)(sample * Gain.Value); } break; case WaveFormSelection.Square: //per sample loop for (int i = 0; i < count; i++) { CalcFrequencyConsts(FreqBuffer[i] + FrequencyOffset.Value); //from http://www.yofiel.com/software/cycling-74-patches/antialiased-oscillators // The ramp works in the range -1~+1, to prevent phase inversion // by negative wraps from FM signals FEPTRPhase = sync ? -1 : FEPTRPhase + t2 + FMBuffer[i] * FMLevel.Value; if (FEPTRPhase > 1.0) { FEPTRPhase -= 2.0; } var r2 = FEPTRPhase * 0.5 + 0.5; // ramp rescaled to 0-1 for EPTR calcs // if (inc2<.125){ // if Fc<sr/16 (2756Hz @441000 sr) var d1 = t2 * 2; // width of phase transition region (4*fc/sr) buffer[i] = (float)(EPTR(r2, 2 * t2, slope) * Gain.Value); // } else { // adding 3x oversampling at higher freqs // t0 = delta(r2); // if (t0>0){ t2 = r2 -t0 *.6666667; //z-2 // t1 = r2 -t0 *.3333333; //z-1 // } else { t2 =wrap(zt *.3333333 +zr, 0, 1); //z-2 // t1 =wrap(zt *.6666667 +zr, 0, 1); //z-1 // } // zt = t0; // ramp and delta history for interp // zr = r2; // d1 = inc2; // shrink transition region // t2 =eptr(t2, d1, w1); // t1 =eptr(t1, d1, w1); // t0 =eptr(r2, d1, w1); // // if (t2==t1 && t1==t0) out1 = t0; // else if (t2!=-1 && t1==-1 && t0!=-1) out1 = -1; // else if (t2!=1 && t1==1 && t0!=1) out1 = 1; // else out1 = (t2 + t1 + t0) * .33333333; // } } break; } }