private static Func <float, float> AddFilterToChain(Func <float, float> func, IOnlineFilter filter) { if (func == null) { return(x => filter.Process(x)); } else { return(x => filter.Process(func(x))); } }
/// <summary> /// Filter signal with additional gain /// </summary> /// <param name="filter">Online filter</param> /// <param name="input">Input signal</param> /// <param name="gain">Gain</param> /// <returns>Filtered signal</returns> public static DiscreteSignal ApplyTo(this IOnlineFilter filter, DiscreteSignal input, float gain) { var output = input.Samples.Select(s => gain * filter.Process(s)); return(new DiscreteSignal(input.SamplingRate, output)); }
/// <summary> /// Method implements online filtering for discrete signals /// </summary> /// <param name="filter">Some filter</param> /// <param name="input">Input signal</param> /// <param name="method">General filtering strategy</param> /// <returns>Filtered signal</returns> public static DiscreteSignal Process(this IOnlineFilter filter, DiscreteSignal input) { var output = new float [input.Length]; filter.Process(input.Samples, output, output.Length); return(new DiscreteSignal(input.SamplingRate, output)); }
/// <summary> /// NOTE. For educational purposes and for testing online filtering. /// /// Implementation of offline filtering in time domain frame-by-frame. /// /// </summary> /// <param name="signal"></param> /// <param name="frameSize"></param> /// <param name="method"></param> /// <returns></returns> public static DiscreteSignal ProcessChunks(this IOnlineFilter filter, DiscreteSignal signal, int frameSize = 4096) { var input = signal.Samples; var output = new float[input.Length]; var i = 0; for (; i + frameSize < input.Length; i += frameSize) { filter.Process(input, output, frameSize, i, i); } // process last chunk filter.Process(input, output, input.Length - i, i, i); return(new DiscreteSignal(signal.SamplingRate, output)); }
/// <summary> /// Filters entire <paramref name="signal"/> by processing each signal sample in a loop. /// </summary> /// <param name="filter">Online filter</param> /// <param name="signal">Input signal</param> public static DiscreteSignal FilterOnline(this IOnlineFilter filter, DiscreteSignal signal) { var output = new float[signal.Length]; var samples = signal.Samples; for (var i = 0; i < samples.Length; i++) { output[i] = filter.Process(samples[i]); } return(new DiscreteSignal(signal.SamplingRate, output)); }
/// <summary> /// Online filtering /// </summary> /// <param name="input"></param> /// <returns></returns> public float Process(float input) { if (_isRight) { _isRight = false; return(_filterRight.Process(input)); } else { _isRight = true; return(_filterLeft.Process(input)); } }
/// <summary> /// Processes one sample. /// </summary> /// <param name="sample">Input sample</param> public float Process(float sample) { if (_isRight) { _isRight = false; return(_filterRight.Process(sample)); } else { _isRight = true; return(_filterLeft.Process(sample)); } }
private async Task ProcessAudioData() { var data = _data[0]; var filename = TempFileName; using (var tempStream = new FileStream(filename, FileMode.Create)) { // ==================================== main recording loop ======================================== while (_isRecording) { // ====================================== read data ============================================ //uncomment for PcmFloat mode: ============================ //await _recorder.ReadAsync(data, 0, _sizeInFloats, 0); //instead of Pcm16bit: await _recorder.ReadAsync(_bytes, 0, _bufferSize); ByteConverter.ToFloats16Bit(_bytes, _data); // ======================================================== // ===================================== process data ========================================== _pitchExtractor.ProcessFrame(data, _pitch); _pitchArgs.PitchZcr = Pitch.FromZeroCrossingsSchmitt(data, _samplingRate); _pitchArgs.PitchAutoCorr = _pitch[0]; PitchEstimated(this, _pitchArgs); // event _robotizer.Process(data, data); // ==================== write data to output stream (if necessary) ============================= //uncomment for PcmFloat mode: ========================= //Buffer.BlockCopy(data, 0, _bytes, 0, _bufferSize); // faster than writing float-after-float //await tempStream.WriteAsync(_bytes, 0, _bufferSize); //instead of Pcm16bit: Buffer.BlockCopy(data, 0, _temp, 0, _temp.Length); await tempStream.WriteAsync(_temp, 0, _temp.Length); // ===================================================== } } SaveToFile(); }
/// <summary> /// Calculate filtering gain so that frequency response is normalized onto [0, 1] range. /// </summary> /// <param name="filter"></param> /// <param name="fftSize"></param> /// <returns>Gain for filtering operations</returns> public static float EstimateGain(this IOnlineFilter filter, int fftSize = 512) { var unit = DiscreteSignal.Unit(fftSize); // get impulse response var response = unit.Samples.Select(s => filter.Process(s)).ToArray(); // get frequency response var spectrum = new float[fftSize / 2 + 1]; var fft = new RealFft(fftSize); fft.MagnitudeSpectrum(response, spectrum); return(1 / spectrum.Max(s => Math.Abs(s))); }
/// <summary> /// Method implements online filtering (frame-by-frame) /// </summary> /// <param name="input">Input block of samples</param> /// <param name="output">Block of filtered samples</param> /// <param name="count">Number of samples to filter</param> /// <param name="inputPos">Input starting position</param> /// <param name="outputPos">Output starting position</param> public static void Process(this IOnlineFilter filter, float[] input, float[] output, int count = 0, int inputPos = 0, int outputPos = 0) { if (count <= 0) { count = input.Length; } var endPos = inputPos + count; for (int n = inputPos, m = outputPos; n < endPos; n++, m++) { output[m] = filter.Process(input[n]); } }
/// <summary> /// Process one sample of a signal with additional gain /// </summary> /// <param name="filter">Online filter</param> /// <param name="sample">Input sample</param> /// <param name="gain">Gain</param> /// <returns></returns> public static float Process(this IOnlineFilter filter, float sample, float gain) { return(gain * filter.Process(sample)); }
public void ThrowsForNullInput1() { IOnlineFilter filter = null; filter.Process(new double[] { 1, 2, 3 }); }
private static double[] Accumulate(IOnlineFilter filter, params double[] samples) { return(samples.Select(x => filter.Process(x)).ToArray()); }