libmosh/
fx.rs

1//! Effects
2
3/// Mutates provided bytes
4pub trait Mosh {
5    fn glitch(&self, value: &mut [u8]);
6}
7
8/// Chunk mutations
9pub enum MoshChunk {
10    ChannelSwap(usize, usize, usize),
11    Flip,
12}
13
14/// Line mutations within a chunk
15pub enum MoshLine {
16    ChannelShift(usize, usize, usize),
17    Shift(usize),
18    Reverse,
19}
20
21impl Mosh for MoshChunk {
22    fn glitch(&self, chunk: &mut [u8]) {
23        match self {
24            Self::ChannelSwap(channel_1, channel_2, channel_count) => {
25                let chunk_length = chunk.len();
26                let channel_value_count = chunk_length / channel_count;
27
28                for i in 0..channel_value_count {
29                    let channel_1_index = (i * channel_count) + channel_1;
30                    let channel_2_index = (i * channel_count) + channel_2;
31
32                    chunk.swap(channel_1_index, channel_2_index);
33                }
34            }
35
36            Self::Flip => chunk.reverse(),
37        }
38    }
39}
40
41impl Mosh for MoshLine {
42    fn glitch(&self, line: &mut [u8]) {
43        match self {
44            Self::ChannelShift(amount, channel, channel_count) => {
45                let line_length = line.len();
46                let channel_value_count = line_length / channel_count;
47
48                for i in 0..channel_value_count {
49                    let current_index = (i * channel_count + channel) % line_length;
50                    let target_index =
51                        (i * channel_count + channel + (channel + 1) * amount) % line_length;
52
53                    line.swap(current_index, target_index);
54                }
55            }
56
57            Self::Shift(amount) => line.rotate_left(*amount),
58            Self::Reverse => line.reverse(),
59        }
60    }
61}