sim_lib_stream_file/
midi.rs1use std::path::Path;
2
3use sim_kernel::{Error, Result};
4use sim_lib_midi_core::MemoryMidiSource;
5use sim_lib_midi_smf::{SmfFile, SmfFormat, SmfTrack, read_smf, write_smf};
6use sim_lib_stream_core::{StreamMetadata, StreamValue};
7use sim_lib_stream_midi::{midi_source_to_stream, midi_stream_to_sink};
8
9use crate::effect_io::{read_file_with_effect, write_file_with_effect};
10
11pub fn read_smf_stream(
17 cx: &mut sim_kernel::Cx,
18 path: impl AsRef<Path>,
19 max_events: usize,
20 metadata: StreamMetadata,
21) -> Result<StreamValue> {
22 let bytes = read_file_with_effect(cx, path)?;
23 smf_bytes_to_stream(&bytes, max_events, metadata)
24}
25
26pub fn smf_bytes_to_stream(
28 bytes: &[u8],
29 max_events: usize,
30 metadata: StreamMetadata,
31) -> Result<StreamValue> {
32 let file = read_smf(bytes).map_err(|err| Error::Eval(format!("malformed SMF file: {err}")))?;
33 smf_file_to_stream(&file, max_events, metadata)
34}
35
36pub fn smf_file_to_stream(
41 file: &SmfFile,
42 max_events: usize,
43 metadata: StreamMetadata,
44) -> Result<StreamValue> {
45 let events = file
46 .merged_events()
47 .into_iter()
48 .map(|tracked| tracked.event)
49 .collect();
50 let mut source = MemoryMidiSource::new(file.tpq, events);
51 midi_source_to_stream(&mut source, max_events, metadata)
52}
53
54pub fn write_smf_stream(
59 cx: &mut sim_kernel::Cx,
60 path: impl AsRef<Path>,
61 stream: &StreamValue,
62 tpq: u32,
63) -> Result<usize> {
64 let (file, count) = stream_to_smf_file(stream, tpq)?;
65 let bytes = write_smf(&file).map_err(|err| Error::Eval(format!("cannot write SMF: {err}")))?;
66 write_file_with_effect(cx, path, bytes)?;
67 Ok(count)
68}
69
70pub fn stream_to_smf_bytes(stream: &StreamValue, tpq: u32) -> Result<(Vec<u8>, usize)> {
74 let (file, count) = stream_to_smf_file(stream, tpq)?;
75 let bytes = write_smf(&file).map_err(|err| Error::Eval(format!("cannot write SMF: {err}")))?;
76 Ok((bytes, count))
77}
78
79pub fn stream_to_smf_file(stream: &StreamValue, tpq: u32) -> Result<(SmfFile, usize)> {
84 if u16::try_from(tpq).is_err() {
85 return Err(Error::Eval(format!(
86 "SMF TPQ {tpq} exceeds the Standard MIDI File range"
87 )));
88 }
89 let mut sink = sim_lib_midi_core::MemoryMidiSink::new(tpq);
90 let count = midi_stream_to_sink(stream, &mut sink)?;
91 let file = SmfFile {
92 format: SmfFormat::SingleTrack,
93 tpq,
94 tracks: vec![SmfTrack {
95 events: sink.events().to_vec(),
96 }],
97 };
98 Ok((file, count))
99}