{"id":17609983,"url":"https://github.com/diffapf/torchcomp","last_synced_at":"2025-09-03T02:06:55.012Z","repository":{"id":230304994,"uuid":"767634952","full_name":"DiffAPF/torchcomp","owner":"DiffAPF","description":"Differentiable dynamic range controller in PyTorch.","archived":false,"fork":false,"pushed_at":"2024-11-27T10:45:46.000Z","size":53,"stargazers_count":50,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-08-29T16:08:16.752Z","etag":null,"topics":["audio-effects","compressor","ddsp","limiter"],"latest_commit_sha":null,"homepage":"","language":"Python","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/DiffAPF.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-03-05T16:40:38.000Z","updated_at":"2025-07-23T14:07:33.000Z","dependencies_parsed_at":"2024-06-28T16:03:29.875Z","dependency_job_id":"8733a452-cc07-4815-a9a4-c39251690b44","html_url":"https://github.com/DiffAPF/torchcomp","commit_stats":null,"previous_names":["yoyololicon/torchcomp","diffapf/torchcomp"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/DiffAPF/torchcomp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DiffAPF%2Ftorchcomp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DiffAPF%2Ftorchcomp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DiffAPF%2Ftorchcomp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DiffAPF%2Ftorchcomp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DiffAPF","download_url":"https://codeload.github.com/DiffAPF/torchcomp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DiffAPF%2Ftorchcomp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273377153,"owners_count":25094528,"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-09-03T02:00:09.631Z","response_time":76,"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":["audio-effects","compressor","ddsp","limiter"],"created_at":"2024-10-22T17:42:33.800Z","updated_at":"2025-09-03T02:06:54.987Z","avatar_url":"https://github.com/DiffAPF.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# TorchComp\n\nDifferentiable dynamic range controller in PyTorch.\n\n## Installation\n\n```bash\npip install torchcomp\n```\n\n\n## Compressor/Expander gain function\n\nThis function calculates the gain reduction $g[n]$ for a compressor/expander. \nIt takes the RMS of the input signal $x[n]$ and the compressor/expander parameters as input. \nThe function returns the gain $g[n]$ in linear scale.\nTo use it as a regular compressor/expander, multiply the result $g[n]$ with the signal $x[n]$.\n\n### Function signature\n\n```python   \ndef compexp_gain(\n    x_rms: torch.Tensor,\n    comp_thresh: Union[torch.Tensor, float],\n    comp_ratio: Union[torch.Tensor, float],\n    exp_thresh: Union[torch.Tensor, float],\n    exp_ratio: Union[torch.Tensor, float],\n    at: Union[torch.Tensor, float],\n    rt: Union[torch.Tensor, float],\n) -\u003e torch.Tensor:\n    \"\"\"Compressor-Expander gain function.\n\n    Args:\n        x_rms (torch.Tensor): Input signal RMS.\n        comp_thresh (torch.Tensor): Compressor threshold in dB.\n        comp_ratio (torch.Tensor): Compressor ratio.\n        exp_thresh (torch.Tensor): Expander threshold in dB.\n        exp_ratio (torch.Tensor): Expander ratio.\n        at (torch.Tensor): Attack time.\n        rt (torch.Tensor): Release time.\n\n    Shape:\n        - x_rms: :math:`(B, T)` where :math:`B` is the batch size and :math:`T` is the number of samples.\n        - comp_thresh: :math:`(B,)` or a scalar.\n        - comp_ratio: :math:`(B,)` or a scalar.\n        - exp_thresh: :math:`(B,)` or a scalar.\n        - exp_ratio: :math:`(B,)` or a scalar.\n        - at: :math:`(B,)` or a scalar.\n        - rt: :math:`(B,)` or a scalar.\n\n    \"\"\"\n```\n\n__Note__: \n`x_rms` should be non-negative.\nYou can calculate it using $\\sqrt{x^2[n]}$ and smooth it with `avg`.\n\n\n### Equations\n\n$$\nx_{\\rm log}[n] = 20 \\log_{10} x_{\\rm rms}[n]\n$$\n\n$$\ng_{\\rm log}[n] = \\min\\left(0, \\left(1 - \\frac{1}{CR}\\right)\\left(CT - x_{\\rm log}[n]\\right), \\left(1 - \\frac{1}{ER}\\right)\\left(ET - x_{\\rm log}[n]\\right)\\right)\n$$\n\n$$\ng[n] = 10^{g_{\\rm log}[n] / 20}\n$$\n\n$$\n\\hat{g}[n] = \\begin{rcases} \\begin{dcases}\n    \\alpha_{\\rm at} g[n] + (1 - \\alpha_{\\rm at}) \\hat{g}[n-1] \u0026 \\text{if } g[n] \u003c \\hat{g}[n-1] \\\\\n    \\alpha_{\\rm rt} g[n] + (1 - \\alpha_{\\rm rt}) \\hat{g}[n-1] \u0026 \\text{otherwise}\n\\end{dcases}\\end{rcases}\n$$\n\n### Block diagram\n\n```mermaid\ngraph TB\n    input((x))\n    output((g))\n    amp2db[amp2db]\n    db2amp[db2amp]\n    min[Min]\n    delay[z^-1]\n    zero( 0 )\n\n    input --\u003e amp2db --\u003e neg[\"*(-1)\"] --\u003e plusCT[\"+CT\"] \u0026 plusET[\"+ET\"]\n    plusCT --\u003e multCS[\"*(1 - 1/CR)\"]\n    plusET --\u003e multES[\"*(1 - 1/ER)\"]\n    zero \u0026 multCS \u0026 multES --\u003e min --\u003e db2amp\n\n    db2amp \u0026 delay --\u003e ifelse{\u003c}\n    output --\u003e delay --\u003e multATT[\"*(1 - AT)\"] \u0026 multRTT[\"*(1 - RT)\"]\n\n    subgraph Compressor\n        ifelse --\u003e|yes| multAT[\"*AT\"]\n        subgraph Attack\n            multAT \u0026 multATT --\u003e plus1((\"+\"))\n        end\n\n        ifelse --\u003e|no| multRT[\"*RT\"]\n        subgraph Release\n            multRT \u0026 multRTT --\u003e plus2((\"+\"))\n        end\n    end\n\n    plus1 \u0026 plus2 --\u003e output\n```\n\n## Limiter gain function\n\nThis function calculates the gain reduction $g[n]$ for a limiter.\nTo use it as a regular limiter, multiply the result $g[n]$ with the input signal $x[n]$.\n\n### Function signature\n\n```python\ndef limiter_gain(\n    x: torch.Tensor,\n    threshold: torch.Tensor,\n    at: torch.Tensor,\n    rt: torch.Tensor,\n) -\u003e torch.Tensor:\n    \"\"\"Limiter gain function.\n    This implementation use the same attack and release time for level detection and gain smoothing.\n\n    Args:\n        x (torch.Tensor): Input signal.\n        threshold (torch.Tensor): Limiter threshold in dB.\n        at (torch.Tensor): Attack time.\n        rt (torch.Tensor): Release time.\n\n    Shape:\n        - x: :math:`(B, T)` where :math:`B` is the batch size and :math:`T` is the number of samples.\n        - threshold: :math:`(B,)` or a scalar.\n        - at: :math:`(B,)` or a scalar.\n        - rt: :math:`(B,)` or a scalar.\n\n    \"\"\"\n```\n\n### Equations\n\n$$\nx_{\\rm peak}[n] = \\begin{rcases} \\begin{dcases}\n    \\alpha_{\\rm at} |x[n]| + (1 - \\alpha_{\\rm at}) x_{\\rm peak}[n-1] \u0026 \\text{if } |x[n]| \u003e x_{\\rm peak}[n-1] \\\\\n    \\alpha_{\\rm rt} |x[n]| + (1 - \\alpha_{\\rm rt}) x_{\\rm peak}[n-1] \u0026 \\text{otherwise}\n\\end{dcases}\\end{rcases}\n$$\n\n$$\ng[n] = \\min(1, \\frac{10^\\frac{T}{20}}{x_{\\rm peak}[n]})\n$$\n\n$$\n\\hat{g}[n] = \\begin{rcases} \\begin{dcases}\n    \\alpha_{\\rm at} g[n] + (1 - \\alpha_{\\rm at}) \\hat{g}[n-1] \u0026 \\text{if } g[n] \u003c \\hat{g}[n-1] \\\\\n    \\alpha_{\\rm rt} g[n] + (1 - \\alpha_{\\rm rt}) \\hat{g}[n-1] \u0026 \\text{otherwise}\n\\end{dcases}\\end{rcases}\n$$\n\n\n### Block diagram\n\n```mermaid\ngraph TB\n    input((x))\n    output((g))\n    peak((x_peak))\n    abs[abs]\n    delay[z^-1]\n    zero( 0 )\n\n    ifelse1{\u003e}\n    ifelse2{\u003c}\n\n    input --\u003e abs --\u003e ifelse1\n\n    subgraph Peak detector\n        ifelse1 --\u003e|yes| multAT[\"*AT\"]\n        subgraph at1 [Attack]\n            multAT \u0026 multATT --\u003e plus1((\"+\"))\n        end\n\n        ifelse1 --\u003e|no| multRT[\"*RT\"]\n        subgraph rt1 [Release]\n            multRT \u0026 multRTT --\u003e plus2((\"+\"))\n        end\n    end\n    \n    plus1 \u0026 plus2 --\u003e peak\n    peak --\u003e delay --\u003e multATT[\"*(1 - AT)\"] \u0026 multRTT[\"*(1 - RT)\"] \u0026 ifelse1\n\n    peak --\u003e amp2db[amp2db] --\u003e neg[\"*(-1)\"] --\u003e plusT[\"+T\"]\n    zero \u0026 plusT --\u003e min[Min] --\u003e db2amp[db2amp] --\u003e ifelse2{\u003c}\n\n    subgraph gain smoothing\n        ifelse2 --\u003e|yes| multAT2[\"*AT\"]\n        subgraph at2 [Attack]\n            multAT2 \u0026 multATT2 --\u003e plus3((\"+\"))\n        end\n\n        ifelse2 --\u003e|no| multRT2[\"*RT\"]\n        subgraph rt2 [Release]\n            multRT2 \u0026 multRTT2 --\u003e plus4((\"+\"))\n        end\n    end\n\n    output --\u003e delay2[z^-1] --\u003e multATT2[\"*(1 - AT)\"] \u0026 multRTT2[\"*(1 - RT)\"] \u0026 ifelse2\n\n    plus3 \u0026 plus4 --\u003e output\n```\n\n## Average filter\n\n### Function signature\n\n```python\ndef avg(rms: torch.Tensor, avg_coef: Union[torch.Tensor, float]):\n    \"\"\"Compute the running average of a signal.\n\n    Args:\n        rms (torch.Tensor): Input signal.\n        avg_coef (torch.Tensor): Coefficient for the average RMS.\n\n    Shape:\n        - rms: :math:`(B, T)` where :math:`B` is the batch size and :math:`T` is the number of samples.\n        - avg_coef: :math:`(B,)` or a scalar.\n\n    \"\"\"\n```\n\n### Equations\n\n```math\n\\hat{x}_{\\rm rms}[n] = \\alpha_{\\rm avg} x_{\\rm rms}[n] + (1 - \\alpha_{\\rm avg}) \\hat{x}_{\\rm rms}[n-1]\n```\n\n## TODO\n\n- [x] CUDA acceleration in Numba\n- [ ] PyTorch CPP extension\n- [ ] Native CUDA extension\n- [x] Forward mode autograd\n- [ ] Examples\n\n## Citation\n\nIf you find this repository useful in your research, please cite our work with the following BibTex entry:\n\n```bibtex\n@inproceedings{ycy2024diffapf,\n    title={Differentiable All-pole Filters for Time-varying Audio Systems},\n    author={Chin-Yun Yu and Christopher Mitcheltree and Alistair Carson and Stefan Bilbao and Joshua D. Reiss and György Fazekas},\n    booktitle={International Conference on Digital Audio Effects (DAFx)},\n    year={2024},\n    pages={345--352},\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdiffapf%2Ftorchcomp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdiffapf%2Ftorchcomp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdiffapf%2Ftorchcomp/lists"}