Skip to content

Commit 04b164f

Browse files
committed
[*] refactor
1 parent 95cd116 commit 04b164f

File tree

25 files changed

+682
-255
lines changed

25 files changed

+682
-255
lines changed

lib/video-editor/src/filters/audio.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
pub mod compressor;
2+
pub mod copy_channel;
23
pub mod denoise;
34
pub mod fade_in;
45
pub mod fade_out;
56
pub mod gain;
67
pub mod limiter;
7-
pub mod mute_left;
8-
pub mod mute_right;
8+
pub mod mute;
99
pub mod noise_gate;
1010
pub mod normalize;
1111

1212
pub use compressor::CompressorFilter;
13+
pub use copy_channel::{CopyChannelFilter, CopyDirection};
1314
pub use denoise::DenoiseFilter;
1415
pub use fade_in::FadeInFilter;
1516
pub use fade_out::FadeOutFilter;
1617
pub use gain::GainFilter;
1718
pub use limiter::LimiterFilter;
18-
pub use mute_left::MuteLeftFilter;
19-
pub use mute_right::MuteRightFilter;
19+
pub use mute::{MuteChannel, MuteFilter};
2020
pub use noise_gate::NoiseGateFilter;
2121
pub use normalize::NormalizeFilter;
2222

@@ -27,8 +27,8 @@ pub fn all_filter_names() -> &'static [&'static str] {
2727
FadeInFilter::NAME,
2828
FadeOutFilter::NAME,
2929
NormalizeFilter::NAME,
30-
MuteLeftFilter::NAME,
31-
MuteRightFilter::NAME,
30+
MuteFilter::NAME,
31+
CopyChannelFilter::NAME,
3232
LimiterFilter::NAME,
3333
NoiseGateFilter::NAME,
3434
CompressorFilter::NAME,
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
//! # 复制声道滤镜 (Copy Channel)
2+
//!
3+
//! ## 作用
4+
//! 将一个声道的内容复制到另一个声道,使两个声道输出相同的内容。
5+
//!
6+
//! ## 工作原理
7+
//! - 音频数据以交错格式存储:[L, R, L, R, L, R, ...]
8+
//! - `LeftToRight`: 将左声道样本(索引 0, 2, 4, ...)复制到右声道(索引 1, 3, 5, ...)
9+
//! - `RightToLeft`: 将右声道样本(索引 1, 3, 5, ...)复制到左声道(索引 0, 2, 4, ...)
10+
//!
11+
//! ## 使用场景
12+
//! 1. **音频修复**:当一个声道损坏或缺失时,用另一个声道替代
13+
//! 2. **单声道效果**:将立体声转为双声道单声道
14+
//! 3. **声道同步**:确保两个声道播放相同内容
15+
//!
16+
//! ## 注意事项
17+
//! - 仅适用于立体声音频(channels = 2)
18+
//! - 复制后输出的仍然是双声道音频
19+
20+
use crate::{
21+
Result,
22+
filters::traits::{AudioData, AudioFilter},
23+
};
24+
25+
/// 复制方向
26+
#[derive(
27+
Debug,
28+
Clone,
29+
Copy,
30+
PartialEq,
31+
Eq,
32+
Default,
33+
serde::Serialize,
34+
serde::Deserialize,
35+
num_enum::TryFromPrimitive,
36+
num_enum::IntoPrimitive,
37+
)]
38+
#[repr(u8)]
39+
pub enum CopyDirection {
40+
/// 左声道 → 右声道
41+
#[default]
42+
LeftToRight = 0,
43+
/// 右声道 → 左声道
44+
RightToLeft = 1,
45+
}
46+
47+
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
48+
pub struct CopyChannelFilter {
49+
/// 复制方向
50+
pub direction: CopyDirection,
51+
}
52+
53+
impl CopyChannelFilter {
54+
pub const NAME: &'static str = "copy channel";
55+
56+
pub fn new(direction: CopyDirection) -> Self {
57+
Self { direction }
58+
}
59+
60+
/// 创建左声道复制到右声道的滤镜
61+
pub fn left_to_right() -> Self {
62+
Self::new(CopyDirection::LeftToRight)
63+
}
64+
65+
/// 创建右声道复制到左声道的滤镜
66+
pub fn right_to_left() -> Self {
67+
Self::new(CopyDirection::RightToLeft)
68+
}
69+
}
70+
71+
impl Default for CopyChannelFilter {
72+
fn default() -> Self {
73+
Self::left_to_right()
74+
}
75+
}
76+
77+
impl AudioFilter for CopyChannelFilter {
78+
crate::impl_default_audio_filter!(CopyChannelFilter);
79+
80+
fn apply(&self, data: &mut AudioData) -> Result<()> {
81+
if data.samples.is_empty() {
82+
return Ok(());
83+
}
84+
85+
if data.config.channels != 2 {
86+
return Err(crate::Error::InvalidConfig(
87+
"CopyChannelFilter only supports stereo audio (2 channels)".to_string(),
88+
));
89+
}
90+
91+
match self.direction {
92+
CopyDirection::LeftToRight => {
93+
// 将左声道(索引 0, 2, 4, ...)复制到右声道(索引 1, 3, 5, ...)
94+
for i in (0..data.samples.len()).step_by(2) {
95+
if i + 1 < data.samples.len() {
96+
data.samples[i + 1] = data.samples[i];
97+
}
98+
}
99+
}
100+
CopyDirection::RightToLeft => {
101+
// 将右声道(索引 1, 3, 5, ...)复制到左声道(索引 0, 2, 4, ...)
102+
for i in (0..data.samples.len()).step_by(2) {
103+
if i + 1 < data.samples.len() {
104+
data.samples[i] = data.samples[i + 1];
105+
}
106+
}
107+
}
108+
}
109+
110+
Ok(())
111+
}
112+
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
//! # 静音滤镜 (Mute)
2+
//!
3+
//! ## 作用
4+
//! 将音频的一个或多个声道静音。
5+
//!
6+
//! ## 工作原理
7+
//! - 音频数据以交错格式存储:[L, R, L, R, L, R, ...]
8+
//! - `Left`: 将左声道样本(索引 0, 2, 4, ...)设置为 0
9+
//! - `Right`: 将右声道样本(索引 1, 3, 5, ...)设置为 0
10+
//! - `Both`: 将所有样本设置为 0(完全静音)
11+
//!
12+
//! ## 使用场景
13+
//! 1. **音频修复**:当某个声道有噪音或杂音时
14+
//! 2. **创意效果**:仅播放特定声道的内容
15+
//! 3. **声道隔离**:提取特定声道音频
16+
//! 4. **平衡调整**:临时禁用某声道进行对比试听
17+
//!
18+
//! ## 注意事项
19+
//! - `Left` 和 `Right` 模式仅适用于立体声音频(channels = 2)
20+
//! - `Both` 模式适用于任意声道数的音频
21+
//! - 静音后输出的音频声道数保持不变
22+
23+
use crate::{
24+
Result,
25+
filters::traits::{AudioData, AudioFilter},
26+
};
27+
28+
/// 静音声道选择
29+
#[derive(
30+
Debug,
31+
Clone,
32+
Copy,
33+
PartialEq,
34+
Eq,
35+
Default,
36+
serde::Serialize,
37+
serde::Deserialize,
38+
num_enum::TryFromPrimitive,
39+
num_enum::IntoPrimitive,
40+
)]
41+
#[repr(u8)]
42+
pub enum MuteChannel {
43+
/// 仅静音左声道
44+
#[default]
45+
Left = 0,
46+
/// 仅静音右声道
47+
Right = 1,
48+
/// 静音所有声道(完全静音)
49+
Both = 2,
50+
}
51+
52+
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
53+
pub struct MuteFilter {
54+
/// 静音的声道
55+
pub channel: MuteChannel,
56+
}
57+
58+
impl MuteFilter {
59+
pub const NAME: &'static str = "mute";
60+
61+
pub fn new(channel: MuteChannel) -> Self {
62+
Self { channel }
63+
}
64+
65+
/// 创建静音左声道的滤镜
66+
pub fn left() -> Self {
67+
Self::new(MuteChannel::Left)
68+
}
69+
70+
/// 创建静音右声道的滤镜
71+
pub fn right() -> Self {
72+
Self::new(MuteChannel::Right)
73+
}
74+
75+
/// 创建完全静音的滤镜
76+
pub fn both() -> Self {
77+
Self::new(MuteChannel::Both)
78+
}
79+
}
80+
81+
impl Default for MuteFilter {
82+
fn default() -> Self {
83+
Self {
84+
channel: MuteChannel::default(),
85+
}
86+
}
87+
}
88+
89+
impl AudioFilter for MuteFilter {
90+
crate::impl_default_audio_filter!(MuteFilter);
91+
92+
fn apply(&self, data: &mut AudioData) -> Result<()> {
93+
if data.samples.is_empty() {
94+
return Ok(());
95+
}
96+
97+
match self.channel {
98+
MuteChannel::Left => {
99+
if data.config.channels != 2 {
100+
return Err(crate::Error::InvalidConfig(
101+
"MuteFilter with Left channel only supports stereo audio (2 channels)"
102+
.to_string(),
103+
));
104+
}
105+
// 静音左声道(索引 0, 2, 4, ...)
106+
for i in (0..data.samples.len()).step_by(2) {
107+
data.samples[i] = 0.0;
108+
}
109+
}
110+
MuteChannel::Right => {
111+
if data.config.channels != 2 {
112+
return Err(crate::Error::InvalidConfig(
113+
"MuteFilter with Right channel only supports stereo audio (2 channels)"
114+
.to_string(),
115+
));
116+
}
117+
// 静音右声道(索引 1, 3, 5, ...)
118+
for i in (1..data.samples.len()).step_by(2) {
119+
data.samples[i] = 0.0;
120+
}
121+
}
122+
MuteChannel::Both => {
123+
// 完全静音(适用于任意声道数)
124+
data.samples.fill(0.0);
125+
}
126+
}
127+
128+
Ok(())
129+
}
130+
}

lib/video-editor/src/filters/audio/mute_left.rs

Lines changed: 0 additions & 65 deletions
This file was deleted.

0 commit comments

Comments
 (0)