public void changeSampleRate(int newRate) { if (newRate == wave.sampleRate) { return; } for (int channel = 0; channel < wave.channels; channel++) { wave.samples[channel] = DSP.resample(ref wave.samples[channel], wave.sampleRate, newRate); } wave.sampleRate = newRate; updateStatusBar(); calculateDFT(); panelWave.setSamples(wave.samples); panelWave.Invalidate(); }
public void applyFX(DSP_FX effect, object[] args) { int startIndex = Math.Max(tSelStart, 0); int endIndex; if (tSelEnd != tSelStart) { endIndex = tSelEnd; } else { endIndex = wave.getNumSamples(); } WaveFile data = wave.cutSelection(startIndex, endIndex); DSP.ApplyFX(effect, args, ref data); wave.pasteSelection(startIndex, data.samples); panelWave.setSamples(wave.samples); panelWave.Invalidate(); invalidPlayer = true; }
/* * ================ UI Update Helpers ================ */ private void calculateDFT() { Complex[][] DFT = new Complex[wave.channels][]; double[] samples = new double[fourierN]; //This is for display, so it (intentionally) grabs the first channel only for (int i = 0; i < samples.Length; i++) { samples[i] = 0; } int startIndex = Math.Max(tSelStart, 0); int N = Math.Min(wave.getNumSamples() - startIndex, fourierN); Array.Copy(wave.samples[0], startIndex, samples, 0, N); if (sampleWindowing == DSP_Window.triangle) { DSP.WindowTriangle(ref samples); } else if (sampleWindowing == DSP_Window.cosine) { DSP.WindowCosine(ref samples); } else if (sampleWindowing == DSP_Window.blackman) { DSP.WindowBlackman(ref samples); } //if DSP.WindowPassthrough or unknown, // pass through unchanged DFT[0] = DSP.DFT(ref samples); panelFourier.SampleRate = wave.sampleRate; panelFourier.Fourier = DFT; panelFourier.Invalidate(); }
/* * ================ Miscellaneous ================ */ public void filterSelectedFrequencies(DSP_FILTER method = DSP_FILTER.convolution) { if (fSelStart == fSelEnd) { return; } double[] filter = new double[fourierN]; for (int fbin = 0; fbin < filter.Length; fbin++) { if ((fbin >= fSelStart && fbin <= fSelEnd) || (fbin >= fourierN - fSelEnd && fbin <= fourierN - fSelStart)) { filter[fbin] = 0; } else { filter[fbin] = 1; } } double criticalPoint = 0; if (method == DSP_FILTER.IIRLowpass) { criticalPoint = fSelStart * SampleRate / fourierN; } else { criticalPoint = fSelEnd * SampleRate / fourierN; } for (int channel = 0; channel < wave.channels; channel++) { switch (method) { case DSP_FILTER.convolution: wave.samples[channel] = DSP.convolveFilter(ref wave.samples[channel], filter); break; case DSP_FILTER.DFT: wave.samples[channel] = DSP.dftFilter(wave.samples[channel], filter); break; case DSP_FILTER.IIRLowpass: //low pass // LowPass IIRFilter ( samples, 1x freq, 0x freq, 0, SampleRate ); wave.samples[channel] = DSP.IIRFilter(wave.samples[channel], Math.Min(criticalPoint + 5000, SampleRate / 2), Math.Max(0, criticalPoint - 5000), 0, SampleRate); break; case DSP_FILTER.IIRHighpass: //high pass // HighPass IIRFilter ( samples, 0x freq, 1x freq, 1, SampleRate ); wave.samples[channel] = DSP.IIRFilter(wave.samples[channel], Math.Max(0, criticalPoint - 7000), Math.Min(criticalPoint + 3000, SampleRate / 2), 1, SampleRate); break; default: MessageBox.Show("something went wrong."); break; } } panelWave.setSamples(wave.samples); panelWave.Invalidate(); calculateDFT(); invalidPlayer = true; }
/// <summary> /// Resample audio from one sample rate to another. /// Works by inserting 0s between existing samples at a particular ratio, /// running a lowpass filter, /// and selecting samples at a different ratio. /// </summary> /// <param name="samples"></param> /// <param name="oldRate"></param> /// <param name="newRate"></param> /// <returns></returns> public static double[] resample(ref double[] samples, int oldRate, int newRate) { double[] extendedSamples, result; int L, M; if (newRate == oldRate) { return(samples); } else if (newRate == 2 * oldRate) { L = 2; M = 1; } else if (newRate == 4 * oldRate) { L = 4; M = 1; } else if (newRate == 8 * oldRate) { L = 8; M = 1; } else if (newRate * 2 == oldRate) { L = 1; M = 2; } else if (newRate * 4 == oldRate) { L = 1; M = 4; } else if (newRate * 8 == oldRate) { L = 1; M = 8; } else { return(null); } //insert L-1 0s between each sample extendedSamples = new double[samples.Length * L]; int i = 0; for (int s = 0; s < samples.Length; s++) { extendedSamples[i] = samples[s]; i++; for (int extra = 0; extra < L - 1; extra++) { extendedSamples[i] = 0; i++; } } //lowpass filter int S = Math.Min(oldRate, newRate); extendedSamples = DSP.IIRFilter(extendedSamples, S / 2 + 5000, S / 2 - 5000, 0, S * 2); //select every Mth sample. result = new double[extendedSamples.Length / M]; i = 0; for (int s = 0; s < extendedSamples.Length; s += M) { result[i++] = extendedSamples[s]; } return(result); }