creek_core/write/
encoder.rs

1use std::error::Error;
2use std::fmt::Debug;
3use std::path::PathBuf;
4
5use super::WriteBlock;
6use crate::FileInfo;
7
8/// The return status of writing to a file.
9#[derive(Debug, Clone, Copy)]
10pub enum WriteStatus {
11    /// Written ok.
12    Ok,
13    /// Written ok, but the file has (or is about to) reach
14    /// the maximum file size for this codec. A new file
15    /// will be created to hold more data.
16    ///
17    /// This returns the total number of files.
18    /// (Including the one created with this stream and the new one that
19    /// is being created right now).
20    ReachedMaxSize { num_files: u32 },
21}
22
23/// A type that encodes a file in a write stream.
24pub trait Encoder: Sized + 'static {
25    /// The data type of a single sample. (i.e. `f32`)
26    type T: Copy + Clone + Default + Send;
27
28    /// Any additional options for creating a file with this encoder.
29    type AdditionalOpts: Send + Default + Debug;
30
31    /// Any additional information on the file.
32    type FileParams: Clone + Send;
33
34    /// The error type while opening the file.
35    type OpenError: Error + Send;
36
37    /// The error type when a fatal error occurs.
38    type FatalError: Error + Send;
39
40    /// The default number of frames in a write block.
41    const DEFAULT_BLOCK_SIZE: usize;
42
43    /// The default number of write blocks. This must be sufficiently large to
44    /// ensure there are enough write blocks for the client in the worst case
45    /// write latency scenario.
46    const DEFAULT_NUM_WRITE_BLOCKS: usize;
47
48    /// Open the file for writing.
49    ///
50    /// * `file` - The path of the file to open.
51    /// * `num_channels` - The number of audio channels in the file.
52    /// * `sample_rate` - The sample rate of the audio data.
53    /// * `block_size` - The block size to use.
54    /// * `max_num_write_blocks` - The number of write blocks this stream is using.
55    /// * `additional_opts` - Any additional encoder-specific options.
56    fn new(
57        file: PathBuf,
58        num_channels: u16,
59        sample_rate: u32,
60        block_size: usize,
61        num_write_blocks: usize,
62        additional_opts: Self::AdditionalOpts,
63    ) -> Result<(Self, FileInfo<Self::FileParams>), Self::OpenError>;
64
65    /// Write a block of data to the file.
66    ///
67    /// If the write was successful, return `WriteStatus::Ok`.
68    ///
69    /// If the codec has a maximum file size (i.e. 4GB for WAV), then keep track of
70    /// how many bytes were written. Once the file is full (or about full), finish the
71    /// file, close it, and create a new file with the characters "_XXX" appended to
72    /// the file name (i.e. "_001" for the first file, "_002" for the second, etc.)
73    /// This helper function `num_files_to_file_name_extension()` can be used to find
74    /// this extension.
75    fn encode(
76        &mut self,
77        write_block: &WriteBlock<Self::T>,
78    ) -> Result<WriteStatus, Self::FatalError>;
79
80    /// Finish up the file and then close it.
81    fn finish_file(&mut self) -> Result<(), Self::FatalError>;
82
83    /// Delete all created files. Do not start over.
84    fn discard_file(&mut self) -> Result<(), Self::FatalError>;
85
86    /// Delete all created files and start over from the beginning.
87    fn discard_and_restart(&mut self) -> Result<(), Self::FatalError>;
88}
89
90/// Converts the current total number of files created (including the one created
91/// with this stream and the new one that is being created right now) to the extension
92/// to append to the end of the file name.
93///
94/// This extension is in the format "_XXX". (i.e. "_001", "_002", etc.)
95pub fn num_files_to_file_name_extension(num_files: u32) -> String {
96    if num_files <= 1 {
97        return String::from("");
98    }
99
100    let extension_num = num_files - 1;
101    if extension_num < 10 {
102        format!("_00{}", extension_num)
103    } else if extension_num < 100 {
104        format!("_0{}", extension_num)
105    } else {
106        format!("_{}", extension_num)
107    }
108}