Skip to content

Commit 3448d6e

Browse files
m_igashim_igashi
authored andcommitted
Initial commit: mp3rgain v0.1.0 - Lossless MP3 volume adjustment
0 parents  commit 3448d6e

File tree

7 files changed

+1061
-0
lines changed

7 files changed

+1061
-0
lines changed

.github/workflows/release.yml

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
build:
13+
name: Build for ${{ matrix.target }}
14+
runs-on: ${{ matrix.os }}
15+
strategy:
16+
matrix:
17+
include:
18+
- target: x86_64-apple-darwin
19+
os: macos-latest
20+
- target: aarch64-apple-darwin
21+
os: macos-latest
22+
- target: x86_64-unknown-linux-gnu
23+
os: ubuntu-latest
24+
25+
steps:
26+
- uses: actions/checkout@v4
27+
28+
- name: Install Rust
29+
uses: dtolnay/rust-action@stable
30+
with:
31+
targets: ${{ matrix.target }}
32+
33+
- name: Build
34+
run: cargo build --release --target ${{ matrix.target }}
35+
36+
- name: Upload artifact
37+
uses: actions/upload-artifact@v4
38+
with:
39+
name: mp3rgain-${{ matrix.target }}
40+
path: target/${{ matrix.target }}/release/mp3rgain
41+
42+
release:
43+
name: Create Release
44+
needs: build
45+
runs-on: macos-latest
46+
steps:
47+
- uses: actions/checkout@v4
48+
49+
- name: Download all artifacts
50+
uses: actions/download-artifact@v4
51+
with:
52+
path: artifacts
53+
54+
- name: Create universal macOS binary
55+
run: |
56+
mkdir -p dist
57+
lipo -create \
58+
artifacts/mp3rgain-x86_64-apple-darwin/mp3rgain \
59+
artifacts/mp3rgain-aarch64-apple-darwin/mp3rgain \
60+
-output dist/mp3rgain
61+
chmod +x dist/mp3rgain
62+
63+
- name: Create macOS tarball
64+
run: |
65+
cd dist
66+
tar -czvf mp3rgain-${{ github.ref_name }}-macos-universal.tar.gz mp3rgain
67+
shasum -a 256 mp3rgain-${{ github.ref_name }}-macos-universal.tar.gz > mp3rgain-${{ github.ref_name }}-macos-universal.tar.gz.sha256
68+
69+
- name: Create Linux tarball
70+
run: |
71+
cd artifacts/mp3rgain-x86_64-unknown-linux-gnu
72+
chmod +x mp3rgain
73+
tar -czvf ../../dist/mp3rgain-${{ github.ref_name }}-linux-x86_64.tar.gz mp3rgain
74+
cd ../../dist
75+
shasum -a 256 mp3rgain-${{ github.ref_name }}-linux-x86_64.tar.gz > mp3rgain-${{ github.ref_name }}-linux-x86_64.tar.gz.sha256
76+
77+
- name: Create Release
78+
uses: softprops/action-gh-release@v1
79+
with:
80+
files: |
81+
dist/mp3rgain-${{ github.ref_name }}-macos-universal.tar.gz
82+
dist/mp3rgain-${{ github.ref_name }}-macos-universal.tar.gz.sha256
83+
dist/mp3rgain-${{ github.ref_name }}-linux-x86_64.tar.gz
84+
dist/mp3rgain-${{ github.ref_name }}-linux-x86_64.tar.gz.sha256
85+
generate_release_notes: true

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/target
2+
Cargo.lock
3+
*.mp3
4+
.DS_Store

Cargo.toml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
[package]
2+
name = "mp3rgain"
3+
version = "0.1.0"
4+
edition = "2021"
5+
authors = ["Masanari Higashi <masanari@example.com>"]
6+
description = "Lossless MP3 volume adjustment - a modern mp3gain replacement written in Rust"
7+
license = "MIT"
8+
repository = "https://github.com/M-Igashi/mp3rgain"
9+
homepage = "https://github.com/M-Igashi/mp3rgain"
10+
readme = "README.md"
11+
keywords = ["mp3", "audio", "gain", "volume", "lossless"]
12+
categories = ["multimedia::audio", "command-line-utilities"]
13+
14+
[dependencies]
15+
anyhow = "1.0"
16+
clap = { version = "4.4", features = ["derive"] }
17+
colored = "2.0"
18+
19+
[lib]
20+
name = "mp3rgain"
21+
path = "src/lib.rs"
22+
23+
[[bin]]
24+
name = "mp3rgain"
25+
path = "src/main.rs"
26+
27+
[profile.release]
28+
lto = true
29+
codegen-units = 1
30+
strip = true

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 Masanari Higashi
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# mp3rgain
2+
3+
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4+
[![Rust](https://img.shields.io/badge/rust-1.70%2B-blue.svg)](https://www.rust-lang.org)
5+
6+
**Lossless MP3 volume adjustment - a modern mp3gain replacement written in Rust**
7+
8+
mp3rgain adjusts MP3 volume without re-encoding by modifying the `global_gain` field in each frame's side information. This preserves audio quality while achieving permanent volume changes.
9+
10+
## Features
11+
12+
- 🎵 **Lossless**: No re-encoding, preserves original audio quality
13+
-**Fast**: Direct binary manipulation, no audio decoding required
14+
- 🔄 **Reversible**: All changes can be undone
15+
- 📦 **Zero dependencies**: Single static binary (no ffmpeg, no mp3gain)
16+
- 🦀 **Pure Rust**: Memory-safe, cross-platform
17+
18+
## Installation
19+
20+
### Homebrew (macOS)
21+
22+
```bash
23+
brew install M-Igashi/tap/mp3rgain
24+
```
25+
26+
### From source
27+
28+
```bash
29+
cargo install mp3rgain
30+
```
31+
32+
### Download binary
33+
34+
Download the latest release from [GitHub Releases](https://github.com/M-Igashi/mp3rgain/releases).
35+
36+
## Usage
37+
38+
### Apply gain adjustment
39+
40+
```bash
41+
# Apply +2 steps (+3.0 dB)
42+
mp3rgain apply -g 2 song.mp3
43+
44+
# Apply +4.5 dB (rounds to nearest step)
45+
mp3rgain apply -d 4.5 song.mp3
46+
47+
# Reduce volume by 3 steps (-4.5 dB)
48+
mp3rgain apply -g -3 *.mp3
49+
```
50+
51+
### Show file information
52+
53+
```bash
54+
mp3rgain info song.mp3
55+
```
56+
57+
Output:
58+
```
59+
song.mp3
60+
Format: MPEG1 Layer III, Joint Stereo
61+
Frames: 5765
62+
Gain range: 89 - 217 (avg: 168.2)
63+
Headroom: 38 steps (+57.0 dB)
64+
```
65+
66+
### Undo previous adjustment
67+
68+
```bash
69+
# Undo a +2 step adjustment
70+
mp3rgain undo -g 2 song.mp3
71+
```
72+
73+
## Technical Details
74+
75+
### Gain Steps
76+
77+
Each gain step equals **1.5 dB** (fixed by MP3 specification). The `global_gain` field is 8 bits, allowing values 0-255.
78+
79+
| Steps | dB Change |
80+
|-------|-----------|
81+
| +1 | +1.5 dB |
82+
| +2 | +3.0 dB |
83+
| +4 | +6.0 dB |
84+
| -2 | -3.0 dB |
85+
86+
### How It Works
87+
88+
MP3 files contain a `global_gain` field in each frame's side information that controls playback volume. mp3rgain directly modifies these values without touching the audio data, making the adjustment completely lossless and reversible.
89+
90+
### Compatibility
91+
92+
- MPEG1 Layer III (MP3)
93+
- MPEG2 Layer III
94+
- MPEG2.5 Layer III
95+
- Mono, Stereo, Joint Stereo, Dual Channel
96+
- ID3v2 tags (preserved)
97+
- VBR and CBR files
98+
99+
## Why mp3rgain?
100+
101+
The original [mp3gain](http://mp3gain.sourceforge.net/) has been unmaintained since ~2015. mp3rgain is a modern replacement that:
102+
103+
- Is actively maintained
104+
- Has no external dependencies
105+
- Is written in memory-safe Rust
106+
- Provides a clean, modern CLI
107+
- Includes a library API for integration
108+
109+
## Library Usage
110+
111+
```rust
112+
use mp3rgain::{apply_gain, apply_gain_db, analyze};
113+
use std::path::Path;
114+
115+
// Apply +2 gain steps (+3.0 dB)
116+
let frames = apply_gain(Path::new("song.mp3"), 2)?;
117+
println!("Modified {} frames", frames);
118+
119+
// Analyze file
120+
let info = analyze(Path::new("song.mp3"))?;
121+
println!("Headroom: {} steps", info.headroom_steps);
122+
```
123+
124+
## License
125+
126+
MIT License - see [LICENSE](LICENSE) for details.
127+
128+
## Contributing
129+
130+
Contributions are welcome! Please open an issue or submit a pull request.
131+
132+
## See Also
133+
134+
- [headroom](https://github.com/M-Igashi/headroom) - DJ audio loudness optimizer (uses mp3rgain internally)

0 commit comments

Comments
 (0)