{"id":22120086,"url":"https://github.com/joshbrew/biquadfilters.js","last_synced_at":"2025-07-25T12:33:06.270Z","repository":{"id":57189709,"uuid":"345296537","full_name":"joshbrew/BiquadFilters.js","owner":"joshbrew","description":"Just a simple adaptation of a set of useful Biquad filters from an obscure arachnoid.com python tutorial to javascript. See the example html for usage","archived":false,"fork":false,"pushed_at":"2023-08-19T01:10:43.000Z","size":147,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-13T03:19:13.920Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/joshbrew.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-03-07T08:37:35.000Z","updated_at":"2024-05-05T14:11:30.000Z","dependencies_parsed_at":"2022-09-15T06:51:45.943Z","dependency_job_id":null,"html_url":"https://github.com/joshbrew/BiquadFilters.js","commit_stats":null,"previous_names":["moothyknight/biquadfilters.js"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/joshbrew/BiquadFilters.js","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshbrew%2FBiquadFilters.js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshbrew%2FBiquadFilters.js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshbrew%2FBiquadFilters.js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshbrew%2FBiquadFilters.js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/joshbrew","download_url":"https://codeload.github.com/joshbrew/BiquadFilters.js/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshbrew%2FBiquadFilters.js/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267007597,"owners_count":24020261,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-25T02:00:09.625Z","response_time":70,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-01T14:20:19.638Z","updated_at":"2025-07-25T12:33:05.961Z","avatar_url":"https://github.com/joshbrew.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# BiquadFilters.js\n\n`npm i biquadjs`\n\nA simple javascript adaptation of a set of useful Biquad filters from an obscure [arachnoid.com python tutorial](https://arachnoid.com/phase_locked_loop/index.html). See the example html for usage. I combed the internet for this and I use these for EEG signal filtering. These will work in nodejs with imports, or just paste it into your html page and delete the exports.\n\nFeatures:\n* Low pass\n* High pass\n* Band pass\n* Notch\n* Peak\n* High shelf\n* Low shelf\n\nSet Q-factor and other parameters as needed, you will want to experiment a bit for the notch, peak, and bandpass filters, the defaults otherwise are butterworth (1/root(2)) Q factors while I set relatively effective values for the aforementioned special cases. dbGain only applies to the shelf filters, which provide amplification above or below the set frequency.\n\nMain class: Biquad\n```js\n\nlet lowpass = new Biquad('lowpass',20,512); //20Hz lowpass at 512Hz. \n//let notch = makeNotchFilter(...) //macros\n//let bandpass = makeBandpassFilter(...) //macros\n```\n\nSecondary class: BiquadChannelFilterer - bundles biquad presets in a configurable way for easy device stream transforming.\n\nThere is a ready-made macro to use a list of filters, preset for getting biosignal data like EEG and ECG by applying notch and bandpass etc.\n```js\nlet filterer = new BiquadChannelFilterer({\n    sps:512,\n    useBandpass:true,\n    bandpassLower:3, //hz\n    bandpassUpper:45 //hz\n});\nlet result = filterer.apply(signal_step);\n``` \n\nAll settings:\n```ts\nexport type FilterSettings = {\n  sps:number, //required\n  useSMA4?:boolean,\n  useNotch50?:boolean,\n  useNotch60?:boolean,\n  useLowpass?: boolean,\n  lowpassHz?:number,\n  useHighpass?:boolean,\n  highpassHz?:number,\n  useBandpass?: boolean,\n  bandpassLower?:number,\n  bandpassUpper?:number,\n  useDCBlock?: boolean,\n  DCBresonance?: number,\n  useScaling?: boolean,\n  scalar?:number,\n  offset?:number, //+=\n  trimOutliers?:boolean,\n  outlierTolerance?:number\n}\n```\n\n* Scaling factor just applies a scalar e.g. ADC -\u003e Voltage conversion.\n* Filtering toggles whether the filter is applied when looping over it in a bigger program\n* Samplerate is fixed, calculate correctly or it won't work very well. You can start/stop streams just fine and the filters will correct otherwise.\n* Returns the result with filterer.apply(signal_step), where the signal step is the latest amplitude in a time domain sequence (which can be real time, see https://app.brainsatplay.com)\n\n\nFunctions:\n\n`let classinstance = new Biquad(type,freq,sps,Q,dbGain)` Create a new filter, these keep the latest sample and filter values so make a new one for each additional filter.\ntypes: 'lowpass','highpass','bandpass','notch','peak','lowshelf','highshelf'. Set the frequency and sample rate, with default butterworth Q values. dBGain only applies to the shelf filters. See below for notch and bandpass filter macros. I should add a peak filter macro..\n\n`let output =  classinstance.applyFilter(signal_step)` Apply the filter to the next sample in the sequence. Returns the filtered amplitude.\n\n`let z = classinstance.zResult(freq)` Returns the z-transfer function values (i.e. how much each frequency amplitude gets multiplied/reduced by the filter)\n\n`let dcblocker = new class DCBlocker(r)` Create a DC blocking filter which better highlights oscillations. Default r = 0.995. Use `output = dcblocker.applyFilter(y)` for each signal step.\n\n`makeNotchFilter(frequency,sps,bandwidth)` Macro to generate a notch filter with the correct Q factor for the specified bandwidth. Returns a Biquad class instance.\n\n`makeBandpassFilter(freqStart,freqEnd,sps,resonance)` Macro to generate a bandpass filter. Returns a Biquad class instance. The resonance value has a default setting that works pretty well, but I recommend experimenting. Having the resonance value being around 10^floor(log10(center frequency)) works well at least at low frequencies, I used 1 and 9.75 for a 3-45Hz bandpass filter in different cases while experimenting, for example. Applying 4 in a row seems to work well to get much sharper cancellation, though for some reason the output gets scaled by 1/n filters so you just need to multiply by how many filters you used to restore the amplitudes to the right values. \n\n![capture](Capture.PNG)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoshbrew%2Fbiquadfilters.js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoshbrew%2Fbiquadfilters.js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoshbrew%2Fbiquadfilters.js/lists"}