From 76080a559586a0c9e0a3b1a6ef88e45f2f041c1e Mon Sep 17 00:00:00 2001 From: Daniel Gallups Date: Tue, 30 Sep 2025 14:56:11 -0400 Subject: [PATCH 1/4] update readme --- README.md | 35 +---------------------------------- src/channel.rs | 2 +- src/file/timed_event_iter.rs | 2 +- src/file_repr/chunk/mod.rs | 2 +- src/note.rs | 2 +- 5 files changed, 5 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 258be02..0a4bda3 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,6 @@ A suite of tools used to read, modify, and manage MIDI-related systems -### NOTE: The main branch is in development. Stable versions are on their own branches. - - ## Overview `midix` provides users with human readable MIDI structures without invariant states. That is, the midi 1.0 specification has been strongly typed such that programatic commands built with this crate are not invariant. @@ -91,14 +88,6 @@ The current MSRV is rust `1.87` This crate was originally forked from [`bevy_midi`](https://github.com/BlackPhlox/bevy_midi). Please check them out if this crate doesn't suit your needs! -## MIDIx feature roadmap -- `no_std` -- Streamer (midir ext) -- Interfaces between `MidiSource` and `Midi` (some representable MIDI type, like a file, events, etc.) -- MIDI writers - - Streamer (async timed stream event via midir) - - MidiFile - ## General feature schedule The SUPPORT.md file denotes the length of time major revisions are supported. @@ -106,14 +95,6 @@ When the major version of the crate is incremented, new features for the previou will likely be neglected. If you need a non-breaking feature for an older version before the end of its maintenence period, please let me know! -## Feature roadmap -- `no_std` -- Streamer (midir ext) -- Interfaces between `MidiSource` and `Midi` (some representable MIDI type, like a file, events, etc.) -- MIDI writers - - Streamer (async timed stream event via midir) - - MidiFile - ## Acknowledgments A lot of the documentation is copied directly from [this documentation](http://www.music.mcgill.ca/~ich/classes/mumt306/StandardMIDIfileformat.html). @@ -126,23 +107,9 @@ EMail: david@csw2.co.uk Web: http://www.csw2.co.uk ``` -Inspired by/copied from - -### `midix` +## Inspired by/copied from inspired by [`midly`](https://github.com/kovaxis/midly) and [`quick-xml`](https://github.com/tafia/quick-xml). -If you are in need of a MIDI writer, I highly -recommend using `midly`, as this `midix` does not yet -support file writing. - Thanks to these mainters and contributors for inspiration! - -### `bevy` feature - -Forked originally from [`bevy_midi`](https://github.com/BlackPhlox/bevy_midi). Huge thank you for the examples and docs! - -### hidden `synth` feature - -Forked originally from [rustysynth](https://github.com/sinshu/rustysynth). diff --git a/src/channel.rs b/src/channel.rs index 8192a6a..79379dd 100644 --- a/src/channel.rs +++ b/src/channel.rs @@ -11,7 +11,7 @@ use crate::message::{ChannelVoiceMessage, VoiceEvent}; /// Identifies a channel for MIDI. /// -/// To get this channel from a `u8`, use [`Channel::try_from_primitive`]. +/// To get this channel from a `u8`, use [`Channel::try_from_byte`]. #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, PartialOrd, Ord)] #[cfg_attr( feature = "bevy", diff --git a/src/file/timed_event_iter.rs b/src/file/timed_event_iter.rs index ed56c3a..d3a2c25 100644 --- a/src/file/timed_event_iter.rs +++ b/src/file/timed_event_iter.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -/// An iterator returned from [`ParsedMidiFile::into_events`]. +/// An iterator returned from [`MidiFile::into_events`]. pub enum OptTimedEventIterator<'a> { /// No tracks in the file None, diff --git a/src/file_repr/chunk/mod.rs b/src/file_repr/chunk/mod.rs index c3defe0..8872810 100644 --- a/src/file_repr/chunk/mod.rs +++ b/src/file_repr/chunk/mod.rs @@ -10,7 +10,7 @@ not fall into th ## [`RawHeaderChunk`] This chunk type contains meta information about the MIDI file, such as - [`RawFormat`](crate::prelude::RawFormat), which identifies how tracks should be played, and the claimed track count -- [`Timing`](crate::prelude::Timing), which defines how delta-seconds are to be interpreted +- [`Timing`], which defines how delta-seconds are to be interpreted ## [`] diff --git a/src/note.rs b/src/note.rs index 0380629..1ff9169 100644 --- a/src/note.rs +++ b/src/note.rs @@ -259,7 +259,7 @@ pub enum Key { B, } impl Key { - /// Returns an array beginning with [`Note::C`] to [`Note::B`] + /// Returns an array beginning with [`Key::C`] to [`Key::B`] pub fn all() -> [Key; 12] { use Key::*; [C, CSharp, D, DSharp, E, F, FSharp, G, GSharp, A, ASharp, B] From d7d15904976b16e31a17a2d519acb906e5a28c78 Mon Sep 17 00:00:00 2001 From: Daniel Gallups Date: Tue, 30 Sep 2025 15:00:54 -0400 Subject: [PATCH 2/4] add todo for benching --- README.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 0a4bda3..4830e96 100644 --- a/README.md +++ b/README.md @@ -14,12 +14,13 @@ calling [`Reader::read_event`](crate::prelude::Reader::read_event) will yield a Additionally, `midix` provides the user with [`LiveEvent::from_bytes`](crate::events::LiveEvent), which will parse events from a live MIDI source. -You may also make your own MIDI representation using the provided structs. A significant portion of -this library lives within the `bevy` feature. See details below on usage with the bevy engine. +You may also make your own MIDI representation using the provided structs. ## Goal `midix` is NOT designed to be as fast as possible. It is designed for a user to navigate the MIDI format to read and write to. Instead of working directly with bytes, use language to define what your MIDI is supposed to do. +TODO: Benches + ## Getting Started MIDI can be interpreted in two main ways: through `LiveEvent`s and regular file `Events`. @@ -80,14 +81,10 @@ assert_eq!(velocity.byte(), 96); ## Semantic Versioning and Support -`midix` will adhere to semantic versioning. This means that I've opted to use major versions, even if this crate does not consider itself feature complete (you might get a midix `v29.3.1` someday) +`midix` will adhere to semantic versioning. I've opted to use major versions. The current MSRV is rust `1.87` -## Acknowledgments - -This crate was originally forked from [`bevy_midi`](https://github.com/BlackPhlox/bevy_midi). Please check them out if this crate doesn't suit your needs! - ## General feature schedule The SUPPORT.md file denotes the length of time major revisions are supported. From 5df99ff89b5c784a2e1a3bd53bfdb2f88f950e6e Mon Sep 17 00:00:00 2001 From: dsgallups Date: Fri, 3 Oct 2025 03:55:04 -0400 Subject: [PATCH 3/4] fix: remove single-type read error kind --- src/file/builder.rs | 7 ++---- src/message/channel/voice.rs | 7 ++---- src/reader/error.rs | 46 ++++++++++++------------------------ 3 files changed, 19 insertions(+), 41 deletions(-) diff --git a/src/file/builder.rs b/src/file/builder.rs index edfbbf9..002f064 100644 --- a/src/file/builder.rs +++ b/src/file/builder.rs @@ -1,9 +1,6 @@ use alloc::vec::Vec; -use crate::{ - prelude::*, - reader::{ReadError, ReaderErrorKind}, -}; +use crate::{prelude::*, reader::ReaderErrorKind}; use super::MidiFile; @@ -109,7 +106,7 @@ impl<'a> MidiFileBuilder<'a> { self.unknown_chunks.push(data); Ok(()) } - EOF => Err(ReaderErrorKind::ReadError(ReadError::OutOfBounds)), + EOF => Err(ReaderErrorKind::OutOfBounds), } } pub fn build(self) -> Result, FileError> { diff --git a/src/message/channel/voice.rs b/src/message/channel/voice.rs index 7c342cd..e2c6f8e 100644 --- a/src/message/channel/voice.rs +++ b/src/message/channel/voice.rs @@ -3,7 +3,7 @@ use crate::{ channel::Channel, events::FromLiveEventBytes, message::VoiceEvent, - reader::{MidiSource, ReadError, ReadResult, Reader, ReaderError, ReaderErrorKind, inv_data}, + reader::{MidiSource, ReadResult, Reader, ReaderError, ReaderErrorKind, inv_data}, }; /// Represents a MIDI voice message. @@ -192,13 +192,10 @@ impl FromLiveEventBytes for ChannelVoiceMessage { velocity: Velocity::new(data.get_byte(1).ok_or(ParseError::MissingData)?)?, }, 0xB => { - // TODO: really need to unify this let mut temp = Reader::from_byte_slice(data); let c = Controller::read(&mut temp).map_err(|e| match e.kind { ReaderErrorKind::ParseError(p) => p, - ReaderErrorKind::ReadError(p) => match p { - ReadError::OutOfBounds => ParseError::MissingData, - }, + ReaderErrorKind::OutOfBounds => ParseError::MissingData, })?; VoiceEvent::ControlChange(c) } diff --git a/src/reader/error.rs b/src/reader/error.rs index ec39a67..6b90f55 100644 --- a/src/reader/error.rs +++ b/src/reader/error.rs @@ -3,7 +3,7 @@ use crate::{ChunkError, ParseError}; use thiserror::Error; #[doc = r#" -A set of errors that can occur while reading something into a midi representation +A set of errors that can occur while reading data into the midi representation "#] #[derive(Debug, Error)] #[error("Reading at Position {position}, {kind}")] @@ -18,9 +18,9 @@ pub enum ReaderErrorKind { /// Parsing errors #[error("Parsing {0}")] ParseError(#[from] ParseError), - /// Errors unrelated to parsing (out of bounds) - #[error("Reading {0}")] - ReadError(#[from] ReadError), + /// Reading out of bounds. + #[error("Read out of bounds!")] + OutOfBounds, } impl ReaderErrorKind { @@ -29,14 +29,6 @@ impl ReaderErrorKind { } } -/// Errors reading from some [`MidiSource`](crate::prelude::MidiSource) -#[derive(Debug, Error)] -pub enum ReadError { - /// Read out of bounds - #[error("Read out of bounds!")] - OutOfBounds, -} - impl ReaderError { /// Create a reader error from a position and kind pub const fn new(position: usize, kind: ReaderErrorKind) -> Self { @@ -44,10 +36,15 @@ impl ReaderError { } /// True if out of bounds or unexpected end of file pub const fn is_out_of_bounds(&self) -> bool { - matches!( - self.kind, - ReaderErrorKind::ReadError(ReadError::OutOfBounds) - ) + matches!(self.kind, ReaderErrorKind::OutOfBounds) + } + /// Returns the error kind of the reader. + pub fn error_kind(&self) -> &ReaderErrorKind { + &self.kind + } + /// Returns the position where the read error occurred. + pub fn position(&self) -> usize { + self.position } /// Create a new invalid data error @@ -62,31 +59,18 @@ impl ReaderError { pub const fn oob(position: usize) -> Self { Self { position, - kind: ReaderErrorKind::ReadError(ReadError::OutOfBounds), + kind: ReaderErrorKind::OutOfBounds, } } } -/// A result type that is either `T` or an [`io::Error`]. +/// The Read Result type (see [`ReaderError`]) /// /// This may change in a future release if `midix` /// should support `no-std` environments. pub type ReadResult = Result; -// pub(crate) fn unexp_eof() -> ReaderError { -// io::Error::new(ErrorKind::UnexpectedEof, "Read past the end of the file").into() -// } - pub(crate) fn inv_data(reader: &mut Reader, v: impl Into) -> ReaderError { reader.set_last_error_offset(reader.buffer_position()); ReaderError::parse_error(reader.buffer_position(), v.into()) } -// #[allow(dead_code)] -// pub(crate) fn inv_input(reader: &mut Reader, v: impl fmt::Display) -> ReaderError { -// reader.set_last_error_offset(reader.buffer_position()); -// io::Error::new( -// ErrorKind::InvalidInput, -// format!("Cursor at {}: {}", reader.buffer_position(), v), -// ) -// .into() -// } From 6d47979c2aa71b22b419aa469a32cca319a2f02a Mon Sep 17 00:00:00 2001 From: dsgallups Date: Fri, 3 Oct 2025 04:07:29 -0400 Subject: [PATCH 4/4] update note macro --- src/note.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/note.rs b/src/note.rs index 1ff9169..ba700fa 100644 --- a/src/note.rs +++ b/src/note.rs @@ -106,7 +106,7 @@ impl Note { self.0.0 } } -/// Efficiently make a note. +/// Create a note the easy way. /// /// /// ## Example