@@ -32,6 +32,7 @@ namespace pxt.assets.music {
3232 * 5 measures
3333 * 6 number of tracks
3434 * ...tracks
35+ * ...track velocities
3536 *
3637 * track(6 + instrument length + note length bytes)
3738 * 0 id
@@ -83,13 +84,24 @@ namespace pxt.assets.music {
8384 * 0 = normal
8485 * 1 = flat
8586 * 2 = sharp
87+ *
88+ * track velocity
89+ * 0 track id
90+ * 1...velocities
91+ *
92+ * velocty
93+ * 1 byte
8694 */
8795
8896 function encodeSong ( song : Song ) {
8997 const encodedTracks = song . tracks
9098 . filter ( ( track ) => track . notes . length > 0 )
9199 . map ( encodeTrack ) ;
92- const trackLength = encodedTracks . reduce ( ( d , c ) => c . length + d , 0 ) ;
100+ const encodedTrackVelocities = song . tracks
101+ . map ( encodeTrackVelocity )
102+ . filter ( ( v ) : v is Uint8Array => ! ! v ) ;
103+
104+ const trackLength = ( encodedTracks . concat ( encodedTrackVelocities ) ) . reduce ( ( d , c ) => c . length + d , 0 ) ;
93105
94106 const out = new Uint8Array ( 7 + trackLength ) ;
95107 out [ 0 ] = 0 ; // encoding version
@@ -105,6 +117,10 @@ namespace pxt.assets.music {
105117 current += track . length ;
106118 }
107119
120+ for ( const trackVelocity of encodedTrackVelocities ) {
121+ out . set ( trackVelocity , current ) ;
122+ current += trackVelocity . length ;
123+ }
108124 return out ;
109125 }
110126
@@ -181,6 +197,17 @@ namespace pxt.assets.music {
181197 return encodeMelodicTrack ( track ) ;
182198 }
183199
200+ function encodeTrackVelocity ( track : Track ) {
201+ if ( ! track . notes . some ( note => note . velocity !== undefined && note . velocity < 128 ) ) return undefined ;
202+
203+ const out = new Uint8Array ( 1 + track . notes . length ) ;
204+ out [ 0 ] = track . id ;
205+ for ( let i = 0 ; i < track . notes . length ; i ++ ) {
206+ out [ 1 + i ] = track . notes [ i ] . velocity || 0 ;
207+ }
208+ return out ;
209+ }
210+
184211 function encodeMelodicTrack ( track : Track ) {
185212 const encodedInstrument = encodeInstrument ( track . instrument ) ;
186213 const encodedNotes = track . notes . map ( note => encodeNoteEvent ( note , track . instrument . octave , false ) ) ;
@@ -248,14 +275,19 @@ namespace pxt.assets.music {
248275 tracks : [ ]
249276 } ;
250277
278+ const numTracks = buf [ 6 ] ;
251279 let current = 7 ;
252280
253- while ( current < buf . length ) {
281+ for ( let i = 0 ; i < numTracks ; i ++ ) {
254282 const [ track , pointer ] = decodeTrack ( buf , current ) ;
255283 current = pointer ;
256284 res . tracks . push ( track ) ;
257285 }
258286
287+ while ( current < buf . length ) {
288+ current = decodeTrackVelocity ( buf , res . tracks , current ) ;
289+ }
290+
259291 return res ;
260292 }
261293
@@ -296,6 +328,16 @@ namespace pxt.assets.music {
296328 return decodeMelodicTrack ( buf , offset ) ;
297329 }
298330
331+ function decodeTrackVelocity ( buf : Uint8Array , tracks : Track [ ] , offset : number ) : number {
332+ const trackId = buf [ offset ] ;
333+ const track = tracks . find ( t => t . id === trackId ) ;
334+ if ( ! track ) throw new Error ( `Track with id ${ trackId } not found` ) ;
335+ for ( let i = 0 ; i < track . notes . length ; i ++ ) {
336+ track . notes [ i ] . velocity = buf [ offset + i + 1 ] ;
337+ }
338+ return offset + track . notes . length + 1 ;
339+ }
340+
299341 function decodeDrumInstrument ( buf : Uint8Array , offset : number ) : DrumInstrument {
300342 const res : DrumInstrument = {
301343 startFrequency : get16BitNumber ( buf , offset + 1 ) ,
0 commit comments