Skip to content

Commit 1c69f39

Browse files
committed
Add --resample parameter to seaconv CLI
1 parent 7c24f2f commit 1c69f39

13 files changed

Lines changed: 508 additions & 36 deletions

File tree

.github/workflows/build_cli.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ jobs:
4343
with:
4444
command: build
4545
target: ${{ matrix.platform.target }}
46-
args: "--example=seaconv --locked --release"
46+
args: "--example=seaconv --features resample --locked --release"
4747
strip: false
4848

4949
- name: Copy examples to parent dir

.github/workflows/build_wasm.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030

3131
- name: Build WASM file
3232
run: |
33-
cargo build --release --target wasm32-unknown-unknown
33+
cargo build --release --features wasm-api --target wasm32-unknown-unknown
3434
cp ./target/wasm32-unknown-unknown/release/sea_codec.wasm ./web/codec.wasm
3535
3636
- name: Set up Node.js

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
## 0.7.0 (2026-01-24)
2+
3+
- Add --resample option to seaconv CLI tool and web demo
4+

Cargo.lock

Lines changed: 192 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "sea-codec"
3-
version = "0.6.1"
3+
version = "0.7.0"
44
description = "Low-complexity, lossy audio codec designed for embedded devices"
55
homepage = "https://github.com/Daninet/sea-codec"
66
repository = "https://github.com/Daninet/sea-codec"
@@ -12,6 +12,8 @@ license = "MIT"
1212

1313
[dependencies]
1414
libm = "0.2.15"
15+
rubato = { version = "1.0.1", optional = true }
16+
audioadapter-buffers = { version = "2.0.0", optional = true }
1517

1618
[dev-dependencies]
1719
hound = "3.5.1"
@@ -21,7 +23,8 @@ clap = "4.5.30"
2123
crate-type = ["cdylib", "staticlib", "rlib"]
2224

2325
[features]
24-
default = ["wasm-api"]
26+
default = ["std"]
2527
std = []
26-
wasm-api = ["std"]
28+
resample = ["std", "rubato", "audioadapter-buffers"]
29+
wasm-api = ["resample"]
2730
c-api = []

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ Options:
4444
Sets the distance between scale factors in frames [default: 20]
4545
-v, --vbr
4646
Enables Variable Bit Rate (VBR)
47+
-r, --resample <resample>
48+
Sets the target sample rate for resampling
4749
-h, --help
4850
Print help
4951
```

examples/seaconv.rs

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,12 @@ fn main() {
143143
.action(ArgAction::SetTrue)
144144
.help("Enables Variable Bit Rate (VBR)"),
145145
)
146+
.arg(
147+
Arg::new("resample")
148+
.long("resample")
149+
.short('r')
150+
.help("Sets the target sample rate for resampling"),
151+
)
146152
.get_matches();
147153

148154
let settings = get_encoder_settings(&matches);
@@ -165,12 +171,38 @@ fn main() {
165171
std::process::exit(1);
166172
});
167173

174+
let mut samples = input_wave.samples;
175+
let mut sample_rate = input_wave.sample_rate;
176+
177+
if let Some(target_rate_str) = matches.get_one::<String>("resample") {
178+
let target_rate = target_rate_str.parse::<u32>().unwrap_or_else(|_| {
179+
eprintln!("Error: Failed to parse resample rate");
180+
std::process::exit(1);
181+
});
182+
183+
#[cfg(feature = "resample")]
184+
{
185+
samples = sea_codec::resample::resample(
186+
&samples,
187+
sample_rate,
188+
target_rate,
189+
input_wave.channels as u32,
190+
);
191+
sample_rate = target_rate;
192+
}
193+
#[cfg(not(feature = "resample"))]
194+
{
195+
eprintln!("Error: Resampling feature is not enabled. Recompile with --features resample");
196+
std::process::exit(1);
197+
}
198+
}
199+
168200
let mut sea_encoder = SeaEncoder::from_slice(
169201
input_wave.channels as u8,
170-
input_wave.sample_rate,
171-
Some(input_wave.samples.len() as u32 / input_wave.channels),
202+
sample_rate,
203+
Some(samples.len() as u32 / input_wave.channels as u32),
172204
settings,
173-
&input_wave.samples,
205+
&samples,
174206
)
175207
.unwrap_or_else(|_| {
176208
eprintln!("Error: Failed to create encoder");
@@ -215,11 +247,36 @@ fn main() {
215247
{}
216248

217249
let info = sea_decoder.get_header();
250+
let mut samples = sea_decoded;
251+
let mut sample_rate = info.sample_rate;
252+
253+
if let Some(target_rate_str) = matches.get_one::<String>("resample") {
254+
let target_rate = target_rate_str.parse::<u32>().unwrap_or_else(|_| {
255+
eprintln!("Error: Failed to parse resample rate");
256+
std::process::exit(1);
257+
});
258+
259+
#[cfg(feature = "resample")]
260+
{
261+
samples = sea_codec::resample::resample(
262+
&samples,
263+
sample_rate,
264+
target_rate,
265+
info.channels as u32,
266+
);
267+
sample_rate = target_rate;
268+
}
269+
#[cfg(not(feature = "resample"))]
270+
{
271+
eprintln!("Error: Resampling feature is not enabled. Recompile with --features resample");
272+
std::process::exit(1);
273+
}
274+
}
218275

219276
write_wav(
220-
sea_decoded.as_slice(),
277+
samples.as_slice(),
221278
info.channels as u16,
222-
info.sample_rate,
279+
sample_rate,
223280
output,
224281
)
225282
.unwrap_or_else(|_| {

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ mod codec;
1010
mod cursor;
1111
pub mod decoder;
1212
pub mod encoder;
13+
pub mod resample;
1314
#[cfg(all(target_arch = "wasm32", feature = "wasm-api"))]
1415
pub mod wasm_api;
1516

0 commit comments

Comments
 (0)