Re: How do I import midi files into Mathematica?
- To: mathgroup at smc.vnet.net
- Subject: [mg125640] Re: How do I import midi files into Mathematica?
- From: markholtuk <markholtuk at googlemail.com>
- Date: Sat, 24 Mar 2012 02:02:37 -0500 (EST)
- Delivered-to: l-mathgroup@mail-archive0.wolfram.com
- References: <jkh5ih$jtf$1@smc.vnet.net>
On Mar 23, 6:34 am, Roger Bagula <roger.bag... at gmail.com> wrote: > I asked this in a Mathematica help group > and came up with an xml conversion of midi > that Mathematica will read, but stripping down the xml tree > is hard and I missed the pauses on the first successful track. > Do anyone else know of a better method to > get a midi track into a times series in Mathematica? This is something that I've been working on recently, so the code is pretty nascent and has only been used on simple one track midi files consisting of four bars of notes. It might be a useful spring for you though. midiIn=Import["file.mid","Byte"]; midiIn={77,84,104,100,0,0,0,6,0,0,0,1,0,96,77,84,114,107,0,0,0,255,0,255,3,7,66,76,95,52,95,67,0,0,255,88,4,4,2,36,8,0,255,88,4,4,2,36,8,0,144,60,95,36,128,60,32,13,144,36,95,11,128,36,32,13,144,48,95,10,128,48,32,13,144,48,127,13,128,48,32,11,144,60,95,13,128,60,32,13,144,48,95,10,128,48,32,12,144,72,95,25,144,48,95,9,128,72,32,27,128,48,32,11,144,48,127,13,128,48,32,11,144,48,95,12,128,48,32,12,144,60,95,12,128,60,32,13,144,48,127,10,128,48,32,13,144,48,127,11,128,48,32,13,144,48,95,13,128,48,32,11,144,60,95,37,128,60,32,12,144,36,95,11,128,36,32,13,144,48,95,12,128,48,32,11,144,48,127,13,128,48,32,11,144,60,95,12,128,60,32,13,144,48,95,11,128,48,32,11,144,72,95,26,144,48,95,9,128,72,32,26,128,48,32,12,144,48,127,13,128,48,32,10,144,48,95,13,128,48,32,12,144,60,95,12,128,60,32,13,144,48,127,10,128,48,32,14,144,48,127,10,128,48,32,13,144,48,95,13,128,48,32,0,255,47,0}; (*This is the imported data from a MIDI file that I have. Execute this rather than the line above so that you can see how it should work. You can also export this to see how it should sound. It's a modern electronic bassline!*) ch=1; (*assuming a range of 1-16*) noteonPos=Position[midiIn,143+ch]; noteoffPos=Position[midiIn,127+ch]; timeEvents=Flatten[Union[noteonPos,noteoffPos]-1]; (*These are timing events since the last timing event.*) realTimeEvents=Accumulate[midiIn[[timeEvents]]]; (*Time events are accumulated to give actual timing events.*) midi=ReplacePart[midiIn,Table[timeEvents[[i]]->realTimeEvents[[i]], {i,Length[timeEvents]}]]; (*The original timing events are replaced by the real timing events*) extractEvents[data_List,{x_}]:=Extract[data,{{x-1},{x},{x+1},{x +2}}]; (*This function is for extracting timing, note event, note number, and velocity for each note on/off evnt*) noteOn=Flatten[{#,extractEvents[midi,#]}]&/@noteonPos; (*This extracts each note on event and prepends with the events position in the imported list*) noteOff=Flatten[{#,extractEvents[midi,#]}]&/@noteoffPos; (*This extracts each note off event and prepends with the events position in the imported list*) notes=Table[{noteOn[[i]],First[Select[noteOff,#[[1]]>noteOn[[i, 1]]&&#[[4]]==noteOn[[i,4]]&]]},{i,Length[noteOn]}]; (*Pair the correct note off messages with each note on message*) Graphics[{Hue[0.8#[[1,5]]/127],Rectangle[#[[1,{2,4}]]+{0,-0.5},#[[2, {2,4}]]+{0,0.5}]}&/@notes,Frame->True,AspectRatio->0.5] (*Show the notes on a grid*) I should point out that the MIDI file that I have used here only contains note on and off events and consists of only one MIDI channel. There are no controller events present. If you want to work with MIDI files that contain more than one channel and events other than note on or off then you will need to significantly change some of this code. Hopefully, this is a start to go on to bigger, better things! I will try to incorporate controller events and multi-channel data myself at some point. Good Luck! Mark