1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use flate2::{
Compression,
write::GzEncoder,
};
use humansize::{FileSize, file_size_opts as options};
use crate::{
cli::CliDirective,
directives::{
estimate::{
gen_sim_file_size,
gen_sim_num_melodies,
pad_value_to_block,
},
gen::try_compression_from_str,
},
storage::{
IntoInner,
MIDIHashPathGenerator,
StorageBackend,
tar_archive::TarArchive,
},
utils::{
gen_num_melodies,
gen_sequences,
},
};
fn estimate_tar_gz_size(
notes: &libatm::MIDINoteVec,
melody_length: u32,
num_melodies: u64,
compression_level: Compression,
) -> u64 {
let mut archive = TarArchive::new(
GzEncoder::new(std::io::BufWriter::new(Vec::new()), compression_level),
MIDIHashPathGenerator
);
for (idx, melody_ref) in gen_sequences(notes, melody_length).enumerate() {
if idx as u64 == num_melodies { break; }
let melody = melody_ref.iter().map(|n| *n.clone()).collect::<libatm::MIDINoteVec>();
archive.append_melody(melody, None).unwrap();
}
archive
.into_inner()
.unwrap()
.finish()
.unwrap()
.into_inner()
.unwrap()
.len() as u64
}
#[derive(structopt::StructOpt)]
pub struct EstimateTarGzDirective {
#[structopt(flatten)]
pub note_set: crate::cli::NoteSetArg,
#[structopt(flatten)]
pub melody_length: crate::cli::MelodyLengthArg,
#[structopt(
short="C",
long="compress",
help="Compression level [0-9, default: 6]",
parse(try_from_str = try_compression_from_str))]
pub compression_level: Option<Compression>,
}
impl CliDirective for EstimateTarGzDirective {
fn run(self) {
let notes = libatm::MIDINoteVec::from(self.note_set.note_set);
let num_notes = notes.len() as u32;
let melody_length = self.melody_length.into();
let compression_level = self.compression_level.unwrap_or(Compression::new(6));
let num_melodies = gen_num_melodies(num_notes, melody_length);
let sim_num_melodies = gen_sim_num_melodies(num_melodies);
let sim_size_estimate = estimate_tar_gz_size(¬es, melody_length, sim_num_melodies, compression_level);
let sim_size_estimate = pad_value_to_block(sim_size_estimate, None);
let file_size = gen_sim_file_size(sim_num_melodies, num_melodies, sim_size_estimate);
println!(
concat!("Number of distinct notes: {num_notes}\n",
"Length of melodies (notes): {melody_length}\n",
"Compression level: {compression_level:?}\n",
"Total number of melodies: {num_melodies}\n",
"Number of melodies used in simulation: {sim_num_melodies}\n",
"Simulated output size: {sim_size_estimate}\n",
"Estimated approximate output file size: {file_size}\n",
"Caveats: Estimate calculated by creating a gzip-compressed tar file in memory \
containing {sim_num_melodies} melodies, and extrapolating from that size. Assumes underlying \
drive has block size of 512 bytes (see: 'estimate tar')."),
num_notes=num_notes,
melody_length=melody_length,
compression_level=compression_level,
num_melodies=num_melodies,
sim_num_melodies=sim_num_melodies,
sim_size_estimate=sim_size_estimate.file_size(options::CONVENTIONAL).unwrap(),
file_size=file_size.file_size(options::CONVENTIONAL).unwrap(),
);
}
}