@@ -6,7 +6,7 @@ pub mod settings;
66use crate :: backend:: errors:: backend_error:: BackendError ;
77use crate :: parser:: parser;
88use crate :: parser:: parser:: { source_location_from_stream, ParseResult } ;
9- use crate :: parser:: tab_element:: TabElement3 ;
9+ use crate :: parser:: tab_element:: TabElement ;
1010use 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+
5669impl 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+
177155fn 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 }
0 commit comments