public static void OnFilterThread(LogEntryEventArgs e) { FilterThread?.Invoke(null, e); }
/* * Filters the wave by convolution of the given filter * * params: * f - Filter to use on the wave * caller - the FrequencyDomain form that requested the filter */ public void filter(float[] f, Form caller) { // Create new arrays with padded 0s and pull in sample values filterResult = new float[samples.Length * 8 / sampleBit + f.Length - 1]; fSamples = new int[samples.Length * 8 / sampleBit + f.Length - 1]; if (sampleBit == 16) { for (int i = 0; i < fSamples.Length - f.Length + 1; i++) { fSamples[i] = BitConverter.ToInt16(samples, i * 2); } } else { for (int i = 0; i < samples.Length; i++) { fSamples[i] = samples[i]; } } Stopwatch time = new Stopwatch(); time.Start(); // Start filter based on selected options if (main.threaded) { Thread[] worker = new Thread[Environment.ProcessorCount]; FilterThread[] fData = new FilterThread[worker.Length]; for (int i = 0; i < worker.Length; i++) { fData[i] = new FilterThread(f, fSamples, i, numSamples / worker.Length, new FilterCallback(filterCallback)); worker[i] = new Thread(fData[i].filterProc); worker[i].Start(); } for (int i = 0; i < worker.Length; i++) { worker[i].Join(); } } else if (main.assembly) { convolution_filter(f, filterResult, fSamples, f.Length, numSamples); } else { for (int i = 0; i < fSamples.Length - f.Length + 1; i++) { for (int j = 0; j < f.Length; j++) { filterResult[i] += fSamples[i + j] * f[j]; } } } time.Stop(); // Converts sample values back into bytes and stores them in sample array if (sampleBit == 16) { for (int i = 0; i < fSamples.Length - f.Length + 1; i++) { byte[] sample = BitConverter.GetBytes((Int16)filterResult[i]); samples[i * 2] = sample[0]; samples[i * 2 + 1] = sample[1]; } } else { for (int i = 0; i < samples.Length; i++) { samples[i] = (byte)filterResult[i]; } } caller.Close(); pLog(main.threaded ? "Convolved Filter (Threaded): " : "Convolved Filter: ", String.Format("{0}", time.ElapsedMilliseconds)); Invalidate(); }
/* * Down-samples given samples to desired sample rate * * params: * samples - samples to down-sample * sSR - sample rate of the source samples * dSR - desired sample rate to down-sample to * * returns: array of sample bytes after being down-sampled */ private byte[] downSampled(byte[] samples, int sSR, int dSR) { Stopwatch time = new Stopwatch(); // Builds filter to remove frequencies more than half the destination sampling rate float[] filter = new float[samples.Length / 2]; filter[0] = 1; int fBin = filter.Length * dSR / 2 / sSR; for (int i = 1; i <= fBin; i++) { filter[i] = 1; filter[filter.Length - i] = 1; } // Converts filter to time-domain by Inverse DFT float[] f = new float[filter.Length]; time.Start(); for (int t = 0; t < f.Length; t++) { for (int freq = 0; freq < f.Length; freq++) { f[t] += (float)(filter[freq] * Math.Cos(2 * Math.PI * t * freq / samples.Length) - filter[freq] * Math.Sin(2 * Math.PI * t * freq / f.Length)); } f[t] /= f.Length; } time.Stop(); pLog("IDFT", String.Format("{0}", time.ElapsedMilliseconds)); time.Reset(); // Builds arrays to hold samples with padded 0s filterResult = new float[samples.Length * 8 / sampleBit + f.Length - 1]; fSamples = new int[samples.Length * 8 / sampleBit + f.Length - 1]; if (sampleBit == 16) { for (int i = 0; i < fSamples.Length - f.Length + 1; i++) { fSamples[i] = BitConverter.ToInt16(samples, i * 2); } } else { for (int i = 0; i < samples.Length; i++) { fSamples[i] = samples[i]; } } time.Start(); // Filters the samples by convolution based on options if (main.threaded) { Thread[] worker = new Thread[Environment.ProcessorCount]; FilterThread[] fData = new FilterThread[worker.Length]; for (int i = 0; i < worker.Length; i++) { fData[i] = new FilterThread(f, fSamples, i, (fSamples.Length - f.Length) / worker.Length, new FilterCallback(filterCallback)); worker[i] = new Thread(fData[i].filterProc); worker[i].Start(); } for (int i = 0; i < worker.Length; i++) { worker[i].Join(); } } else { for (int i = 0; i < fSamples.Length - f.Length + 1; i++) { for (int j = 0; j < f.Length; j++) { filterResult[i] += fSamples[i + j] * f[j]; } } } time.Stop(); pLog(main.threaded ? "Convolved Filter (Threaded): " : "Convolved Filter: ", String.Format("{0}", time.ElapsedMilliseconds)); // Creates a ratio in lowest terms of destination samples to source samples int gcd = GCD(dSR, sSR); sSR /= gcd; dSR /= gcd; float[] result = new float[(int)(((double)(fSamples.Length - f.Length) / sSR) * dSR)]; bool skip = false; int sCount = 0; // Builds sample array by skipping samples to match new sample rate for (int i = 1, rCount = 0; i < filterResult.Length - f.Length; i++) { if (!skip) { result[rCount++] = filterResult[i - 1]; if (i % dSR == 0) { skip = true; sCount = 0; } } else if (++sCount == sSR - dSR) { skip = false; } } // Converts samples to byte array and returns the result byte[] dsResult = new byte[result.Length * sampleBit / 8]; if (sampleBit == 16) { for (int i = 0; i < fSamples.Length - f.Length + 1; i++) { byte[] sample = BitConverter.GetBytes((Int16)result[i]); dsResult[i * 2] = sample[0]; dsResult[i * 2 + 1] = sample[1]; } } else { for (int i = 0; i < result.Length; i++) { dsResult[i] = (byte)result[i]; } } return(dsResult); }
/* * NOTE: DOESN'T WORK * * Up-samples given samples to desired sample rate * * params: * samples - samples to down-sample * sSR - sample rate of the source samples * dSR - desired sample rate to up-sample to * * returns: array of sample bytes after being up-sampled */ private byte[] upSampled(byte[] samples, int sSR, int dSR) { Stopwatch time = new Stopwatch(); float[] filter = new float[samples.Length / 2]; filter[0] = 1; int fBin = filter.Length * sSR / 2 / dSR; for (int i = 1; i <= fBin; i++) { filter[i] = 1; filter[filter.Length - i] = 1; } float[] f = new float[filter.Length]; time.Start(); for (int t = 0; t < f.Length; t++) { for (int freq = 0; freq < f.Length; freq++) { f[t] += (float)(filter[freq] * Math.Cos(2 * Math.PI * t * freq / samples.Length) - filter[freq] * Math.Sin(2 * Math.PI * t * freq / f.Length)); } f[t] /= f.Length; } time.Stop(); pLog("IDFT", String.Format("{0}", time.ElapsedMilliseconds)); time.Reset(); filterResult = new float[samples.Length * 8 / sampleBit + f.Length - 1]; fSamples = new int[samples.Length * 8 / sampleBit + f.Length - 1]; if (sampleBit == 16) { for (int i = 0; i < fSamples.Length - f.Length + 1; i++) { fSamples[i] = BitConverter.ToInt16(samples, i * 2); } } else { for (int i = 0; i < samples.Length; i++) { fSamples[i] = samples[i]; } } int gcd = GCD(dSR, sSR); sSR /= gcd; dSR /= gcd; float[] result = new float[(int)(((double)(fSamples.Length - f.Length) / sSR) * dSR) + f.Length]; bool skip = false; int sCount = 0; float last = 0; for (int i = 1, rCount = 0; i < result.Length - f.Length; i++) { if (!skip) { result[i - 1] = filterResult[rCount++]; if (i % sSR == 0) { last = result[i]; sCount = 0; skip = true; } } else { result[i - 1] = last; if (++sCount == dSR - sSR) { skip = false; } } } time.Start(); if (main.threaded) { Thread[] worker = new Thread[Environment.ProcessorCount]; FilterThread[] fData = new FilterThread[worker.Length]; for (int i = 0; i < worker.Length; i++) { fData[i] = new FilterThread(f, fSamples, i, (fSamples.Length - f.Length) / worker.Length, new FilterCallback(filterCallback)); worker[i] = new Thread(fData[i].filterProc); worker[i].Start(); } for (int i = 0; i < worker.Length; i++) { worker[i].Join(); } } else { for (int i = 0; i < fSamples.Length - f.Length + 1; i++) { for (int j = 0; j < f.Length; j++) { filterResult[i] += fSamples[i + j] * f[j]; } } } time.Stop(); pLog(main.threaded ? "Convolved Filter (Threaded): " : "Convolved Filter: ", String.Format("{0}", time.ElapsedMilliseconds)); byte[] usResult = new byte[(fSamples.Length - f.Length) * sampleBit / 8]; if (sampleBit == 16) { for (int i = 0; i < fSamples.Length - f.Length + 1; i++) { byte[] sample = BitConverter.GetBytes((Int16)fSamples[i]); usResult[i * 2] = sample[0]; usResult[i * 2 + 1] = sample[1]; } } else { for (int i = 0; i < usResult.Length; i++) { usResult[i] = (byte)fSamples[i]; } } return(usResult); }