{"id":17658635,"url":"https://github.com/ruuda/bs1770","last_synced_at":"2025-05-07T02:01:55.855Z","repository":{"id":62438545,"uuid":"289528842","full_name":"ruuda/bs1770","owner":"ruuda","description":"A Rust library that implements ITU-R BS.1770-4 loudness measurement","archived":false,"fork":false,"pushed_at":"2022-09-19T20:04:50.000Z","size":60,"stargazers_count":20,"open_issues_count":3,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-31T05:11:16.331Z","etag":null,"topics":["bs1770","ebur128","itu-r","loudness","r128","tech3341"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ruuda.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-08-22T16:50:58.000Z","updated_at":"2024-10-19T16:48:02.000Z","dependencies_parsed_at":"2022-11-01T21:47:49.172Z","dependency_job_id":null,"html_url":"https://github.com/ruuda/bs1770","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruuda%2Fbs1770","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruuda%2Fbs1770/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruuda%2Fbs1770/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruuda%2Fbs1770/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ruuda","download_url":"https://codeload.github.com/ruuda/bs1770/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252798832,"owners_count":21805882,"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","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":["bs1770","ebur128","itu-r","loudness","r128","tech3341"],"created_at":"2024-10-23T15:27:43.660Z","updated_at":"2025-05-07T02:01:55.755Z","avatar_url":"https://github.com/ruuda.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# BS1770\n\nA Rust library that implements [ITU-R BS.1770-4][bs1770] loudness measurement.\n\nAlso includes a binary that writes loudness to flac tags.\n\n## Example\n\n```rust\nlet sample_rate_hz = 44_100;\nlet bits_per_sample = 16;\nlet channel_samples: [Vec\u003ci16\u003e; 2] = load_stereo_audio();\n\n// When converting integer samples to float, note that the maximum amplitude\n// is `1 \u003c\u003c (bits_per_sample - 1)`, one bit is the sign bit.\nlet normalizer = 1.0 / (1_u64 \u003c\u003c (bits_per_sample - 1)) as f32;\n\nlet channel_power: Vec\u003c_\u003e = channel_samples.iter().map(|samples| {\n    let mut meter = bs1770::ChannelLoudnessMeter::new(sample_rate_hz);\n    meter.push(samples.iter().map(|\u0026s| s as f32 * normalizer));\n    meter.into_100ms_windows()\n}).collect();\n\nlet stereo_power = bs1770::reduce_stereo(\n    channel_power[0].as_ref(),\n    channel_power[1].as_ref(),\n);\n\nlet gated_power = bs1770::gated_mean(stereo_power.as_ref());\nprintln!(\"Integrated loudness: {:.1} LUFS\", gated_power.loudness_lkfs());\n```\n\n## Tagging flac files\n\nThere is a binary `flacgain` included in the `examples` directory, build it with\n\n    RUSTFLAGS=\"-C target-cpu=native\" cargo build --release --example flacgain\n\nThen run\n\n    target/release/examples/flacgain FILE...\n\nThe program accepts file names or more flac files as arguments, and computes\nloudness for them, as well as for the collection of files (which is assumed to\nbe an album).\n\nBy default the program only prints loudness to stdout, add the `--write-tags`\nflag to also store loudness in the metadata tags. This adds the following tags:\n\n * `BS17704_TRACK_LOUDNESS`\n * `BS17704_ALBUM_LOUDNESS`\n\nIf any `REPLAYGAIN_*` tags exist, the program will remove these. The rationale\nfor these tags, instead of using ReplayGain, is that ReplayGain has become\nambigous: it stores a gain (the difference between target loudness and measured\nloudness), but different taggers use different reference levels, which means\nthat ReplayGain only normalizes loudness when you carefully ensure that all files\nin your collection use the same target setting. By storing the loudness instead\nof the gain, we sidestep the problem. By naming the tag after the particular\nloudness definition (BS.1770-4), future revisions of BS.1770 will not make these\ntags ambiguous.\n\nThe program writes a new file and moves it over the old file, so permission bits\nare currently lost. The program only replaces the `VORBIS_COMMENT` block and\nleaves any other parts of the file untouched. It uses `copy_file_range` to\nenable reflinking on file systems that support this.\n\nIf you have a collection of flac files, where every leaf directory contains a\nsingle album, you can use the included script `tag_collection.sh` to run\n`flacgain --write-tags` on every album in your collection.\n\n## Performance\n\nThe initial focus is on correctness, the library has not been optimized yet.\nThere is a lot of potential for optimization, for example by combining filters,\nunrolling loops, applying vectorization, etc.\n\n## References\n\n * [ITU-R BS.1770-4][bs1770], a standard that specifies how to measure loudness,\n   and which defines the LKFS unit (loudness units full scale, K-weighted).\n * [ITU-R BS.1771-1][bs1771] builds upon BS.1770 with a few requirements for\n   building loudness meters.\n * [EBU R 128][r128], which specifies a target loudness level, based on the\n   BS.1770 loudness measurement.\n * [EBU Tech 3341][tech3341], which specifies “EBU Mode” loudness meters, but\n   which in particular provides test vectors to confirm that a meter implements\n   BS.1770 correctly. It also proposes to move away from the term “LKFS”\n   introduced in BS.1770, in favor of the term “LUFS”. K-weighting would be\n   indicated elsewhere.\n * [EBU Tech 3342][tech3342], which specifies how to measure loudness range.\n\n[bs1770]:   https://www.itu.int/rec/R-REC-BS.1770-4-201510-I/en\n[bs1771]:   https://www.itu.int/rec/R-REC-BS.1771-1-201201-I/en\n[r128]:     https://tech.ebu.ch/publications/r128\n[tech3341]: https://tech.ebu.ch/publications/tech3341\n[tech3342]: https://tech.ebu.ch/publications/tech3342\n\n## Acknowledgements\n\n * The filter coefficient formulas are adapted from [pyloudnorm][pyloudnorm] by\n   Christian Steinmetz.\n * The filter coefficient formulas are [originally due to Brecht De Man][deman],\n   but the associated paper is not openly accessible.\n\n[pyloudnorm]: https://github.com/csteinmetz1/pyloudnorm\n[deman]:      https://github.com/BrechtDeMan/loudness.py\n\n## License\n\nBS1770 is licensed under the [Apache 2.0][apache2] license. It may be used in\nfree software as well as closed-source applications, both for commercial and\nnon-commercial use under the conditions given in the license. If you want to\nuse BS1770 in your GPLv2-licensed software, you can add an [exception][except]\nto your copyright notice. Please do not open an issue if you disagree with the\nchoice of license.\n\n[apache2]: https://www.apache.org/licenses/LICENSE-2.0\n[except]:  https://www.gnu.org/licenses/gpl-faq.html#GPLIncompatibleLibs\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fruuda%2Fbs1770","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fruuda%2Fbs1770","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fruuda%2Fbs1770/lists"}