/// <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> /// 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> /// 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)); }
private static IProducer <double> MathNetFilter( IProducer <double> input, double sampleRate, Interpolator <double, double> sampleInterpolator, DateTime?alignmentDateTime, IOnlineFilter filter, DeliveryPolicy <double> deliveryPolicy) { // Sample the input stream at the desired rate and process through the given filter. var clock = Generators.Repeat(input.Out.Pipeline, 0, TimeSpan.FromSeconds(1.0 / sampleRate), alignmentDateTime); return(input.Interpolate(clock, sampleInterpolator, sourceDeliveryPolicy: deliveryPolicy, clockDeliveryPolicy: DeliveryPolicy.Unlimited) .Select(s => filter.ProcessSample(s), DeliveryPolicy.SynchronousOrThrottle)); }
/// <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))); }
public async void StartRecording() { if (_recorder != null) { StopRecording(); } var context = Android.App.Application.Context; var audioManager = (AudioManager)context.GetSystemService(Context.AudioService); _samplingRate = int.Parse(audioManager.GetProperty(AudioManager.PropertyOutputSampleRate)); //_bufferSize = 4 * AudioRecord.GetMinBufferSize(_samplingRate, ChannelIn.Mono, Encoding.PcmFloat); _bufferSize = 4 * AudioRecord.GetMinBufferSize(_samplingRate, ChannelIn.Mono, Encoding.Pcm16bit); _recorder = new AudioRecord(AudioSource.Mic, _samplingRate, _channelCount, _audioEncodingType, _bufferSize); //uncomment for PcmFloat mode: ===================== //_sizeInFloats = _bufferSize / sizeof(float); //instead of Pcm16bit: ============================= _sizeInFloats = _bufferSize / sizeof(short); _data = new float[1][]; _data[0] = new float[_sizeInFloats]; // only one channel (mono) _bytes = new byte[_bufferSize]; _temp = new byte[_sizeInFloats * sizeof(float)]; var options = new PitchOptions { SamplingRate = _samplingRate, FrameDuration = (double)_sizeInFloats / _samplingRate }; _pitchExtractor = new PitchExtractor(options); _pitch = new float[1]; _robotizer = new RobotEffect(216, 1024); _recorder.StartRecording(); _isRecording = true; await ProcessAudioData(); }
/// <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> /// 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 async Task TestBrainDeviceManager() { var cfg = ClientConfig.GetConfig(); var lowFilter = new LowPassFilter() { LowPassRate = 10 }; var highFilter = new HighPassFilter() { HighPassRate = 10000 }; var bPassFilter = new BandPassFilter() { LowCutoffRate = 20, HighCutoffRate = 30 }; var bStopFilter = new BandStopFilter() { LowPassRate = 35, HighPassRate = 38 }; var mFilter = new MedianFilter() { HalfMedianWindowSize = 7 }; var bandFilter = new BandPassStopFilter { BandFilterList = new List <BandFilter> { lowFilter, highFilter, bPassFilter, bStopFilter } }; bandFilter.Disable = true; var allFilter = new FilterTypeList() { Filters = new List <FilterType> { bandFilter, mFilter } }; var filterParameters = new Dictionary <string, string> { { FilterTypeList.FIRhalfOrderOptionName, 10.ToString() } }; cfg.FilterLst = allFilter; IOnlineFilter filter = null; WaveletReconstruction waveletRec = null; cfg.WaveletRecCfg = new WaveletReconstructionConfig { AvgLevel = 8, ConvolutionMode = ConvolutionModeEnum.Normal, ExtensionMode = SignalExtension.ExtensionMode.SymmetricHalfPoint, Level = 8, MotherWaveletName = "db5", WindowSize = 15 }; cfg.WriteToFile(ClientConfig.DefaultConfigFileName); BrainDeviceManager.Init(); var sender = await BrainDeviceManager.Connnect("127.0.0.1", 9211); BrainDevState currentState = default(BrainDevState); //保证设备参数正常才继续跑逻辑 BrainDeviceManager.BrainDeviceState.Subscribe(ss => { currentState = ss; filterParameters.Update( FilterTypeList.SampleRateOptionName, BrainDevState.SampleCountPer1Sec(ss.SampleRate).ToString() ); //AppLogger.Debug($"Brain Device State Changed Detected: {ss}"); }, () => { AppLogger.Debug("device stop detected"); }); int totalReceived = 0; var medianFilter = OnlineFirFilter.CreateDenoise(7); var fastMedianFilter = new OnlineFastMedianFilter(3); BrainDeviceManager.SampleDataStream.Subscribe(tuple => { var(order, datas, arr) = tuple; //Console.Write($" {order} "); var passTimes = BrainDevState.PassTimeMs(currentState.SampleRate, totalReceived) / 1000; var intArr = datas.CopyToArray(); var val = intArr[0]; var voltage = BitDataConverter.Calculatevoltage(val, 4.5f, currentState.Gain); totalReceived++; var m1 = medianFilter.ProcessSample(voltage); var m2 = fastMedianFilter.ProcessSample(voltage); AppLogger.Debug($"passTimes:{passTimes},val:{val},voltage:{voltage},median filter:{m1},fast:{m2},{m1==m2}"); if (filter == null) { filter = allFilter.CreateFilter(filterParameters); waveletRec = cfg.WaveletRecCfg.Create( BrainDevState.SampleCountPer1Sec(currentState.SampleRate)); waveletRec.ReconstructionStream.Subscribe(reconstruct => { var(vol, tim) = reconstruct; AppLogger.Debug($"wavelet reconstruction:{vol} at {tim}"); }); } waveletRec?.BufferData((voltage, passTimes)); AppLogger.Debug($"filter processed:{filter.ProcessSample(voltage)}"); //AppLogger.Debug($"order:{order}"); //AppLogger.Debug($"converted values:{datas.Show()}"); //AppLogger.Debug($"original datas:{arr.Show()}"); }, () => { AppLogger.Debug("device sampling stream closed detected"); }); var cmdResult = await sender.QueryParam(); AppLogger.Debug("QueryParam result:" + cmdResult); if (cmdResult != CommandError.Success) { AppLogger.Error("Failed to QueryParam, stop"); BrainDeviceManager.DisConnect(); return; } cmdResult = await sender.SetFilter(true); AppLogger.Debug("SetFilter result:" + cmdResult); cmdResult = await sender.SetTrap(TrapSettingEnum.Trap_50); AppLogger.Debug("SetTrap result:" + cmdResult); cmdResult = await sender.SetSampleRate(SampleRateEnum.SPS_2k); AppLogger.Debug("SetSampleRate result:" + cmdResult); cmdResult = await sender.QueryParam(); AppLogger.Debug("QueryParam result:" + cmdResult); cmdResult = await sender.QueryFaultState(); AppLogger.Debug("QueryFaultState result:" + cmdResult); cmdResult = await sender.TestSingleImpedance(1); AppLogger.Debug("TestSingleImpedance result:" + cmdResult); cmdResult = await sender.TestMultiImpedance(30); AppLogger.Debug("TestMultiImpedance result:" + cmdResult); Console.ReadLine(); var fs = new FileResource(currentState, 19801983, 1, BrainDeviceManager.BufMgr); fs.StartRecord(BrainDeviceManager.SampleDataStream); cmdResult = await sender.Start(); if (cmdResult != CommandError.Success) { AppLogger.Error("Failed to start sampler"); } else { AppLogger.Debug($"start receive sample data"); await Task.Delay(1000 *10); AppLogger.Debug($"stoping"); await sender.Stop(); AppLogger.Debug($"stop receive sample data"); await Task.Delay(1000); } BrainDeviceManager.DisConnect(); fs.Dispose(); var readf = new FileSampleData(fs.ResourceId, BrainDeviceManager.BufMgr); Console.WriteLine($"expecte to read {totalReceived} blocks"); Console.WriteLine($"start reading saved sampling data"); int readCount = 0; readf.DataStream.Subscribe(tuple => { var(order, datas, arr) = tuple; Console.Write($" {order} "); readCount++; //AppLogger.Debug($"order:{order}"); //AppLogger.Debug($"converted values:{datas.Show()}"); //AppLogger.Debug($"original datas:{arr.Show()}"); }, () => { AppLogger.Debug($"read sampling data file end,count :{readCount},expected count:{totalReceived}"); }); readf.Start(); await Task.Delay(1000 *10); Console.Write($"wait complete"); }
/// <summary> /// Constructor /// </summary> /// <param name="filterLeft"></param> /// <param name="filterRight"></param> public StereoFilter(IOnlineFilter filterLeft, IOnlineFilter filterRight) { _filterLeft = filterLeft; _filterRight = filterRight; }
/// <summary> /// Add filter to the chain /// </summary> /// <param name="filter"></param> public void Add(IOnlineFilter filter) => _filters.Add(filter);
/// <summary> /// Inserts <paramref name="filter"/> at specified <paramref name="index"/> in the chain. /// </summary> /// <param name="index">Index of the filter in chain</param> /// <param name="filter">Online filter</param> public void Insert(int index, IOnlineFilter filter) => _filters.Insert(index, filter);
private static double[] Accumulate(IOnlineFilter filter, params double[] samples) { return(samples.Select(x => filter.Process(x)).ToArray()); }
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))); } }