synthahol_phase_plant/io/
mod.rs

1//! Phase Plant preset reading and writing.
2//!
3//! Functionality for reading and writing presets should be confined to this module where possible.
4//!
5//! # File Format
6//!
7//! The file format changed in some ways between Phase Plant 2.0.11 and 2.0.12.
8//! In particular there is an additional 256 bytes in the init preset starting
9//! at position 19055.
10
11use std::mem::size_of;
12
13use serde::{Deserialize, Serialize};
14
15pub(crate) use generators::GeneratorBlock;
16pub(crate) use modulators::ModulatorBlock;
17
18pub use self::effects::*;
19pub use self::read::*;
20pub use self::write::*;
21
22pub(crate) mod effects;
23mod generators;
24mod modulators;
25mod read;
26mod write;
27
28#[derive(Debug, Serialize, Deserialize)]
29struct MetadataJson {
30    pub description: Option<String>,
31    pub author: Option<String>,
32}
33
34#[derive(Debug)]
35pub struct DataBlockHeader {
36    /// Size of the block, not including the header and mode ID.
37    data_length: usize,
38    is_used: bool,
39    mode_id: Option<u32>,
40}
41
42impl DataBlockHeader {
43    pub const UNUSED_BLOCK_HEADER_SIZE: usize = size_of::<u32>() + size_of::<u8>();
44    pub const USED_BLOCK_HEADER_SIZE: usize = Self::UNUSED_BLOCK_HEADER_SIZE + size_of::<u32>();
45
46    /// * `data_length` - size of the block, not including the header and optional mode
47    fn new(data_length: usize, is_used: bool, mode_id: Option<u32>) -> Self {
48        Self {
49            data_length,
50            is_used,
51            mode_id,
52        }
53    }
54
55    fn new_unused() -> Self {
56        Self {
57            data_length: 0,
58            is_used: false,
59            mode_id: None,
60        }
61    }
62
63    /// * `data_length` - size of the block, not including the header mode
64    fn new_used(data_length: usize, mode_id: u32) -> Self {
65        Self {
66            data_length,
67            is_used: true,
68            mode_id: Some(mode_id),
69        }
70    }
71
72    fn data_length_with_header(&self) -> usize {
73        self.data_length
74            + if self.is_used {
75                Self::USED_BLOCK_HEADER_SIZE
76            } else {
77                Self::UNUSED_BLOCK_HEADER_SIZE
78            }
79    }
80
81    pub(crate) fn is_used(&self) -> bool {
82        self.is_used
83    }
84
85    /// Will be `None` if the block is not used.
86    pub(crate) fn mode_id(&self) -> Option<u32> {
87        self.mode_id
88    }
89}