Skip to content

Commit 4c3b211

Browse files
committed
misc: refactors
1 parent 595eda0 commit 4c3b211

File tree

4 files changed

+76
-107
lines changed

4 files changed

+76
-107
lines changed

src/backend/midi/mod.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use midly::{
77

88
use super::{Backend, BackendResult};
99
use crate::parser::parser::{parse, ParseResult};
10-
use crate::parser::tab_element::TabElement3;
11-
use crate::parser::tab_element::TabElement3::Fret;
10+
use crate::parser::tab_element::TabElement;
11+
use crate::parser::tab_element::TabElement::Fret;
1212
use crate::{debugln, time};
1313

1414
const BPM: u32 = 80;
@@ -94,14 +94,14 @@ fn convert_to_midi(parsed: &ParseResult) -> Vec<Vec<TrackEvent<'static>>> {
9494
tracks[track].push(note_on);
9595
tracks[track].push(note_off);
9696
}
97-
TabElement3::Rest => delta_carry_on[track] += LENGTH_OF_EIGHTH.into(),
98-
TabElement3::Bend
99-
| TabElement3::HammerOn
100-
| TabElement3::Pull
101-
| TabElement3::Release
102-
| TabElement3::Slide
103-
| TabElement3::DeadNote
104-
| TabElement3::Vibrato => (),
97+
TabElement::Rest => delta_carry_on[track] += LENGTH_OF_EIGHTH.into(),
98+
TabElement::Bend
99+
| TabElement::HammerOn
100+
| TabElement::Pull
101+
| TabElement::Release
102+
| TabElement::Slide
103+
| TabElement::DeadNote
104+
| TabElement::Vibrato => (),
105105
}
106106
}
107107
tracks.iter_mut().for_each(|x| {

src/backend/muxml/mod.rs

Lines changed: 48 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ pub mod settings;
66
use crate::backend::errors::backend_error::BackendError;
77
use crate::parser::parser;
88
use crate::parser::parser::{source_location_from_stream, ParseResult};
9-
use crate::parser::tab_element::TabElement3;
9+
use crate::parser::tab_element::TabElement;
1010
use crate::{
1111
backend::{Backend, BackendResult},
1212
debugln, rlen, time, traceln,
@@ -53,37 +53,32 @@ pub enum Muxml2TabElement {
5353
Invalid,
5454
}
5555

56+
#[inline(always)]
57+
fn write_rest(buf: &mut impl std::fmt::Write, mut x: u32) -> std::fmt::Result {
58+
while x != 0 {
59+
for bound in [(8, "whole"), (4, "half"), (2, "quarter"), (1, "eighth")] {
60+
if x >= bound.0 {
61+
write_muxml2_rest(buf, bound.1, bound.0 as u8)?;
62+
x -= bound.0;
63+
}
64+
}
65+
}
66+
Ok(())
67+
}
68+
5669
impl Muxml2TabElement {
5770
fn write_muxml<A: std::fmt::Write>(
5871
&self, parsed: &ParseResult, buf: &mut A,
5972
note_properties: &HashMap<u32, NoteProperties, impl std::hash::BuildHasher>,
6073
) -> std::fmt::Result {
6174
match self {
62-
Muxml2TabElement::Rest(mut x) => {
63-
while x != 0 {
64-
if x >= 8 {
65-
write_muxml2_rest(buf, "whole", 8)?;
66-
x -= 8;
67-
} else if x >= 4 {
68-
write_muxml2_rest(buf, "half", 4)?;
69-
x -= 4;
70-
} else if x >= 2 {
71-
write_muxml2_rest(buf, "quarter", 2)?;
72-
x -= 2;
73-
} else {
74-
debug_assert_eq!(x, 1);
75-
write_muxml2_rest(buf, "eighth", 1)?;
76-
x -= 1;
77-
}
78-
}
79-
Ok(())
80-
}
75+
Muxml2TabElement::Rest(x) => write_rest(buf, *x),
8176
Muxml2TabElement::CopyTick(tick_idx) => {
8277
let note_range = *tick_idx as usize..=(*tick_idx as usize + 5);
8378
let notes_iter = parsed.tick_stream[note_range]
8479
.iter()
8580
.enumerate()
86-
.filter(|x| !matches!(x.1, TabElement3::Rest))
81+
.filter(|x| !matches!(x.1, TabElement::Rest))
8782
.map(|(x, y)| (x + *tick_idx as usize, y));
8883
// at least two notes here
8984
let tick_chord = notes_iter.clone().take(2).count() == 2;
@@ -95,37 +90,19 @@ impl Muxml2TabElement {
9590
let mut chord_first_written = false;
9691
for (elem_idx, elem) in notes_iter {
9792
let need_chord = tick_chord && chord_first_written;
98-
traceln!(depth = 1, "elem={elem:?}@{elem_idx} chord flag: {need_chord}");
93+
chord_first_written = true;
9994

100-
match elem {
101-
TabElement3::Fret(x) => {
102-
chord_first_written = true;
103-
let note =
104-
get_fretboard_note2(parsed.base_notes[elem_idx % 6], *x).unwrap();
105-
let (step, octave, sharp) = note.step_octave_sharp();
106-
let properties = note_properties.get(&(elem_idx as u32));
107-
write_muxml2_note(
108-
buf, step, octave, sharp, need_chord, false, properties,
109-
)?;
110-
}
111-
TabElement3::DeadNote => {
112-
chord_first_written = true;
113-
let note =
114-
get_fretboard_note2(parsed.base_notes[elem_idx % 6], 0).unwrap();
115-
let (step, octave, sharp) = note.step_octave_sharp();
116-
let properties = note_properties.get(&(elem_idx as u32));
117-
write_muxml2_note(
118-
buf, step, octave, sharp, need_chord, true, properties,
119-
)?;
120-
}
121-
TabElement3::Rest => unreachable!(),
122-
TabElement3::Bend
123-
| TabElement3::HammerOn
124-
| TabElement3::Pull
125-
| TabElement3::Release
126-
| TabElement3::Slide
127-
| TabElement3::Vibrato => {}
128-
}
95+
let Some((dead, fret)) = (match elem {
96+
TabElement::DeadNote => Some((true, 0)),
97+
TabElement::Fret(x) => Some((false, *x)),
98+
_ => None,
99+
}) else {
100+
continue;
101+
};
102+
let note = get_fretboard_note2(parsed.base_notes[elem_idx % 6], fret).unwrap();
103+
let (step, octave, sharp) = note.step_octave_sharp();
104+
let properties = note_properties.get(&(elem_idx as u32));
105+
write_muxml2_note(buf, step, octave, sharp, need_chord, dead, properties)?;
129106
}
130107

131108
Ok(())
@@ -174,16 +151,11 @@ pub enum Vibrato {
174151
Start,
175152
Stop,
176153
}
154+
177155
fn gen_muxml2(
178156
parse_time: Duration, mut parsed: ParseResult,
179157
settings: <MuxmlBackend as Backend>::BackendSettings,
180158
) -> (Option<String>, BackendResult) {
181-
// status of the project:
182-
// parser3 is mostly done and works well and fast,
183-
// but the codegen backends need to be adapted
184-
// muxml2 especially, as it can be made much faster
185-
// since, especially with std::simd, comparing the next 6 ticks against a TabElem3::Rest should be trivial
186-
// (with a splat-compare)
187159
let mut r = BackendResult::new(vec![], None, Some(parse_time), None);
188160
let number_of_measures = parsed.measures.len();
189161
let mut document = String::from(MUXML_INCOMPLETE_DOC_PRELUDE);
@@ -197,7 +169,7 @@ fn gen_muxml2(
197169
let mut note_properties: HashMap<u32, NoteProperties, FxBuildHasher> = HashMap::default();
198170
for measure_idx in 0..number_of_measures {
199171
traceln!("Muxml2: processing measure {}", measure_idx);
200-
let ticks_in_measure = rlen(&parsed.measures[measure_idx].data_range) / 6; // see assumption 2
172+
let ticks_in_measure = rlen(&parsed.measures[measure_idx].data_range) / 6;
201173
debug_assert!(rlen(&parsed.measures[measure_idx].data_range) % 6 == 0);
202174
// Length of actual content in measure. `remove_space_between_notes` will reduce this for
203175
// example
@@ -215,25 +187,22 @@ fn gen_muxml2(
215187
// "current elem: {elem:?}, note_count: {note_count}, proc_cnt = {stream_proc_cnt}"
216188
//);
217189
match elem {
218-
TabElement3::Fret(..) | TabElement3::DeadNote => {
219-
note_count += 1;
220-
}
221-
TabElement3::Rest => {}
222-
TabElement3::Vibrato => {
223-
let last_idx = stream_idx.saturating_sub(6);
224-
note_properties.entry(last_idx as u32).or_default().vibrato =
225-
Some(Vibrato::Start);
190+
TabElement::Fret(..) | TabElement::DeadNote => note_count += 1,
191+
TabElement::Rest => {}
192+
TabElement::Vibrato => {
193+
let last_idx = stream_idx.saturating_sub(6) as u32;
194+
note_properties.entry(last_idx).or_default().vibrato = Some(Vibrato::Start);
226195
let next_idx = stream_idx + 6;
227196
if next_idx >= parsed.tick_stream.len() {
228-
parsed.tick_stream.extend([const { TabElement3::Rest }; 6]);
197+
parsed.tick_stream.extend([const { TabElement::Rest }; 6]);
229198
}
230199
note_properties.entry(next_idx as u32).or_default().vibrato =
231200
Some(Vibrato::Stop);
232201
}
233-
TabElement3::Bend
234-
| TabElement3::HammerOn
235-
| TabElement3::Pull
236-
| TabElement3::Release => {
202+
TabElement::Bend
203+
| TabElement::HammerOn
204+
| TabElement::Pull
205+
| TabElement::Release => {
237206
// TODO: eventually mark hammerOns and pulls
238207
let last_idx = stream_idx.saturating_sub(6);
239208
traceln!(
@@ -248,27 +217,27 @@ fn gen_muxml2(
248217
match &parsed.tick_stream.get(next_idx) {
249218
None => {
250219
traceln!("hanging bend on {stream_idx} at stream end");
251-
let TabElement3::Fret(x) = parsed.tick_stream[last_idx] else {
220+
let TabElement::Fret(x) = parsed.tick_stream[last_idx] else {
252221
let (line, char) =
253222
source_location_from_stream(&parsed, stream_idx as u32);
254223
r.err = Some(BackendError::bend_on_invalid(line, char));
255224
return (None, r);
256225
};
257226

258-
parsed.tick_stream.extend([const { TabElement3::Rest }; 6]);
259-
parsed.tick_stream[next_idx] = TabElement3::Fret(x + 1);
227+
parsed.tick_stream.extend([const { TabElement::Rest }; 6]);
228+
parsed.tick_stream[next_idx] = TabElement::Fret(x + 1);
260229
let entry = note_properties.entry(next_idx as u32).or_default();
261230
entry.slurs.push(Slur::stop(slur_cnt));
262231
}
263232
// since we know that with a "hanging bend" the next element in this track is going to be a rest, we can just silently replace it and add the correct note
264-
Some(TabElement3::Rest) => {
265-
let TabElement3::Fret(x) = parsed.tick_stream[last_idx] else {
233+
Some(TabElement::Rest) => {
234+
let TabElement::Fret(x) = parsed.tick_stream[last_idx] else {
266235
let (line, char) =
267236
source_location_from_stream(&parsed, stream_idx as u32);
268237
r.err = Some(BackendError::bend_on_invalid(line, char));
269238
return (None, r);
270239
};
271-
parsed.tick_stream[next_idx] = TabElement3::Fret(x + 1);
240+
parsed.tick_stream[next_idx] = TabElement::Fret(x + 1);
272241
traceln!(
273242
"hanging bend on {stream_idx}, replacing {next_idx} with a Fret"
274243
);
@@ -283,7 +252,7 @@ fn gen_muxml2(
283252

284253
traceln!("added bend with start idx {last_idx} and end idx {next_idx}")
285254
}
286-
TabElement3::Slide => {
255+
TabElement::Slide => {
287256
let last_idx = stream_idx.saturating_sub(6);
288257
traceln!(
289258
depth = 1,
@@ -307,7 +276,6 @@ fn gen_muxml2(
307276
stream_idx += 1;
308277

309278
if stream_proc_cnt == 5 {
310-
stream_proc_cnt = 0;
311279
if note_count > 0 {
312280
measure_processed.push(Muxml2TabElement::CopyTick(stream_idx as u32 - 6));
313281
// TODO: maybe pass the non-rest tick ids here instead?
@@ -316,6 +284,7 @@ fn gen_muxml2(
316284
}
317285
traceln!(depth = 1, "Parsed a tick, a {:?} ", measure_processed.last().unwrap());
318286
note_count = 0;
287+
stream_proc_cnt = 0;
319288
} else {
320289
stream_proc_cnt += 1;
321290
}

src/parser/parser.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::{
22
string_name,
3-
tab_element::{self, tab_element3, TabElement3},
3+
tab_element::{self, tab_element3, TabElement},
44
};
55
use crate::{
66
backend::errors::backend_error::BackendError, debugln, parser::tab_element::TabElementError,
@@ -32,7 +32,7 @@ impl Measure {
3232
pub struct ParseResult {
3333
/// This is not a [Result] because we want to preserve the partial parse state, eg. for fixup or recovery
3434
pub error: Option<BackendError>,
35-
pub tick_stream: Vec<TabElement3>,
35+
pub tick_stream: Vec<TabElement>,
3636
pub measures: Vec<Measure>,
3737
pub base_notes: Vec<char>,
3838
/// The line on which the n-th section begins and the index of the first tick in that section.
@@ -53,7 +53,7 @@ impl ParseResult {
5353
let max_width =
5454
(0..6).map(|x| self.tick_stream[tick * 6 + x].repr_len()).max().unwrap() as usize;
5555
for (s, buf) in bufs.iter_mut().enumerate() {
56-
use tab_element::TabElement3::*;
56+
use tab_element::TabElement::*;
5757
let to_padded = |c: char| format!("{1:<0$}", max_width, c);
5858
match self.tick_stream[tick * 6 + s] {
5959
Fret(x) => buf.push_str(&format!("{x:<0$}", max_width)),
@@ -173,7 +173,7 @@ pub fn parse(lines: &[String]) -> ParseResult {
173173
let elem_idx = r.tick_stream.len() - (6 - s);
174174
let elem = &r.tick_stream[elem_idx];
175175
traceln!(depth = 1, "on string {s} we have {:?}", elem);
176-
if let TabElement3::Rest = elem {
176+
if let TabElement::Rest = elem {
177177
traceln!(depth = 2, "this is a rest so we try to parse the next element");
178178
let len_before = part[s].len();
179179
let next = tab_element3(part[s]).unwrap();

src/parser/tab_element.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
use crate::{backend::errors::backend_error::BackendError, parser::numeric, traceln};
1+
use crate::parser::numeric;
22
use std::cmp::max;
33

44
#[derive(Debug, PartialEq, Clone)]
5-
pub enum TabElement3 {
5+
pub enum TabElement {
66
Fret(u8),
77
Rest,
88
DeadNote,
@@ -19,27 +19,27 @@ pub enum TabElementError {
1919
FretTooLarge,
2020
}
2121
#[inline(always)]
22-
pub fn tab_element3(s: &str) -> Result<(&str, TabElement3), (&str, Option<TabElementError>)> {
22+
pub fn tab_element3(s: &str) -> Result<(&str, TabElement), (&str, Option<TabElementError>)> {
2323
let bytes = s.as_bytes();
2424
match bytes.first() {
25-
Some(b'-') => Ok((&s[1..], TabElement3::Rest)),
26-
Some(b'x') => Ok((&s[1..], TabElement3::DeadNote)),
25+
Some(b'-') => Ok((&s[1..], TabElement::Rest)),
26+
Some(b'x') => Ok((&s[1..], TabElement::DeadNote)),
2727
Some(48..=58) => {
2828
let (res, num) = numeric(s).map_err(|s| (s, Some(TabElementError::FretTooLarge)))?;
29-
Ok((res, TabElement3::Fret(num)))
29+
Ok((res, TabElement::Fret(num)))
3030
}
31-
Some(b'b') => Ok((&s[1..], TabElement3::Bend)),
32-
Some(b'h') => Ok((&s[1..], TabElement3::HammerOn)),
33-
Some(b'p') => Ok((&s[1..], TabElement3::Pull)),
34-
Some(b'r') => Ok((&s[1..], TabElement3::Release)),
35-
Some(b'/') | Some(b'\\') => Ok((&s[1..], TabElement3::Slide)),
36-
Some(b'~') => Ok((&s[1..], TabElement3::Vibrato)),
31+
Some(b'b') => Ok((&s[1..], TabElement::Bend)),
32+
Some(b'h') => Ok((&s[1..], TabElement::HammerOn)),
33+
Some(b'p') => Ok((&s[1..], TabElement::Pull)),
34+
Some(b'r') => Ok((&s[1..], TabElement::Release)),
35+
Some(b'/') | Some(b'\\') => Ok((&s[1..], TabElement::Slide)),
36+
Some(b'~') => Ok((&s[1..], TabElement::Vibrato)),
3737
Some(_) | None => Err((s, None)),
3838
}
3939
}
40-
impl TabElement3 {
40+
impl TabElement {
4141
pub fn repr_len(&self) -> u32 {
42-
use TabElement3::*;
42+
use TabElement::*;
4343
match self {
4444
Fret(x) => max(x, &1).ilog10() + 1,
4545
Bend | HammerOn | DeadNote | Pull | Slide | Rest | Release | Vibrato => 1,

0 commit comments

Comments
 (0)