mirror of
https://github.com/ivabus/WAR.rs
synced 2024-11-23 17:05:11 +03:00
0.1.0: Initial commit
Signed-off-by: Ivan Bushchik <ivabus@ivabus.dev>
This commit is contained in:
commit
d68b861aea
7 changed files with 197 additions and 0 deletions
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
/target
|
||||||
|
.idea
|
||||||
|
*.DS_Store
|
||||||
|
*.wav
|
9
.rustfmt.toml
Normal file
9
.rustfmt.toml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
edition = "2021"
|
||||||
|
hard_tabs = true
|
||||||
|
merge_derives = true
|
||||||
|
reorder_imports = true
|
||||||
|
reorder_modules = true
|
||||||
|
use_field_init_shorthand = true
|
||||||
|
use_small_heuristics = "Off"
|
||||||
|
wrap_comments = true
|
||||||
|
comment_width = 80
|
65
Cargo.lock
generated
Normal file
65
Cargo.lock
generated
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dasp_frame"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b2a3937f5fe2135702897535c8d4a5553f8b116f76c1529088797f2eee7c5cd6"
|
||||||
|
dependencies = [
|
||||||
|
"dasp_sample",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dasp_sample"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ebur128"
|
||||||
|
version = "0.1.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "12aebdd6b6b47b5880c049efb0e77f8762178a0745ef778878908f5981c05f52"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"dasp_frame",
|
||||||
|
"dasp_sample",
|
||||||
|
"smallvec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "exp"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"ebur128",
|
||||||
|
"wav",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "riff"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b9b1a3d5f46d53f4a3478e2be4a5a5ce5108ea58b100dcd139830eae7f79a3a1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
version = "1.11.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wav"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a65e199c799848b4f997072aa4d673c034f80f40191f97fe2f0a23f410be1609"
|
||||||
|
dependencies = [
|
||||||
|
"riff",
|
||||||
|
]
|
14
Cargo.toml
Normal file
14
Cargo.toml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
[package]
|
||||||
|
name = "war-rs"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
repository = "https://github.com/ivabus/WAR.rs"
|
||||||
|
authors = [ "Ivan Bushchik <ivabus@ivabus.dev>" ]
|
||||||
|
license = "MIT"
|
||||||
|
description = "Automatic encoder of \"1-bit\" WAVE files with LUFS calculation"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
ebur128 = "0.1.8"
|
||||||
|
wav = "1.0.0"
|
20
LICENSE
Normal file
20
LICENSE
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2023 Ivan Bushchik
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is furnished
|
||||||
|
to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
||||||
|
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
||||||
|
OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
15
README.md
Normal file
15
README.md
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# WAR.rs
|
||||||
|
|
||||||
|
> Winner of THE LOUDNESS WAR
|
||||||
|
|
||||||
|
Automatic encoder of "1-bit" WAVE files with LUFS calculation.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```shell
|
||||||
|
cargo run <INPUT.wav> <OUTPUT.wav>
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
WAR.rs is licensed under the terms of the [MIT license](./LICENSE).
|
70
src/main.rs
Normal file
70
src/main.rs
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
use std::env::args;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::time::Instant;
|
||||||
|
use wav::BitDepth;
|
||||||
|
|
||||||
|
fn perform_voluming_i<T: Into<f64> + Copy>(data: Vec<T>) -> Vec<i16> {
|
||||||
|
data.iter()
|
||||||
|
.map(|i| {
|
||||||
|
if Into::<f64>::into(*i) > 0.0f64 {
|
||||||
|
0x7fff
|
||||||
|
} else {
|
||||||
|
-0x8000
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
// u8 PCM should be treated other way (if we are going without unsafing (we could transform it into i8)), than a i{16,32} and f32
|
||||||
|
fn perform_voluming_u8(data: Vec<u8>) -> Vec<i16> {
|
||||||
|
data.iter()
|
||||||
|
.map(|&i| {
|
||||||
|
if i > 128 {
|
||||||
|
0x7fff
|
||||||
|
} else {
|
||||||
|
-0x8000
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let args: Vec<String> = args().collect();
|
||||||
|
if args.len() != 3 {
|
||||||
|
eprintln!("WAR.rs: winner of THE LOUDNESS WAR");
|
||||||
|
eprintln!("Usage: {} <INPUT.wav> <OUTPUT.wav>", args[0]);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
let (input, output) = (args[1].clone(), args[2].clone());
|
||||||
|
let start = Instant::now();
|
||||||
|
let mut inp_file = File::open(Path::new(&input)).unwrap();
|
||||||
|
let (header, data) = wav::read(&mut inp_file).unwrap();
|
||||||
|
let new_header = wav::Header::new(
|
||||||
|
wav::header::WAV_FORMAT_PCM,
|
||||||
|
header.channel_count,
|
||||||
|
header.sampling_rate,
|
||||||
|
16,
|
||||||
|
);
|
||||||
|
|
||||||
|
let volumed = match data {
|
||||||
|
BitDepth::Eight(data) => perform_voluming_u8(data),
|
||||||
|
BitDepth::Sixteen(data) => perform_voluming_i(data),
|
||||||
|
BitDepth::TwentyFour(data) => perform_voluming_i(data),
|
||||||
|
BitDepth::ThirtyTwoFloat(data) => perform_voluming_i(data),
|
||||||
|
BitDepth::Empty => {
|
||||||
|
eprintln!("No audio data found in input file.");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut out_file = File::create(Path::new(&output)).unwrap();
|
||||||
|
wav::write(new_header, &BitDepth::Sixteen(volumed.clone()), &mut out_file).unwrap();
|
||||||
|
println!("Saved to {} in {} seconds", output, (Instant::now() - start).as_secs_f64());
|
||||||
|
|
||||||
|
let mut ebur =
|
||||||
|
ebur128::EbuR128::new(header.channel_count as u32, header.sampling_rate, ebur128::Mode::I)
|
||||||
|
.unwrap();
|
||||||
|
ebur.add_frames_i16(volumed.as_slice()).unwrap();
|
||||||
|
println!("New loudness:\t{} LUFS", ebur.loudness_global().unwrap());
|
||||||
|
}
|
Loading…
Reference in a new issue