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