Math Piano from Midi
To run this program a C compiler is required to make a LibraryFunction compiled for your operating system. The notebook, mergeNoteP-WC.nb, has the C code and will create the library function. The functions in the C code were first worked out in Mathematica, and are described in the notebooks, PerfectHarmonic.nb, MathPiano.nb, and DualDecay.nb. The C code creates a 32 bit real file on a NumericArray set up in Mathematica, which is initially set to all zeros. The mergeNoteP file translates midi notes to a mathematical piano function described in the notebooks above, and merges them into the NummericArray, which can be interpreted as an Audio file, simply by wrapping it with Audio[ ... ].
The piano music generated is quite different from a real piano which does not have a lot of power in the low frequency notes. When the music is played on a music system with a sub-woofer, the bass notes can be felt as much as heard. The 3+ minutes of music generated by this example was nearly 80MB, so it couldn’t be uploaded with the notebook, because it was too big.
The piano music generated is quite different from a real piano which does not have a lot of power in the low frequency notes. When the music is played on a music system with a sub-woofer, the bass notes can be felt as much as heard. The 3+ minutes of music generated by this example was nearly 80MB, so it couldn’t be uploaded with the notebook, because it was too big.
In[]:=
mergeNoteP=LibraryFunctionLoad["C:\\Users\\Bob\\AppData\\Roaming\\Mathematica\\SystemFiles\\LibraryResources\\Windows-x86-64\\mergeNoteNADP.dll","mergeNoteP",{{LibraryDataType[NumericArray],"Shared"},Real,Real,Real,Real},Integer];
SoundNote input to frequency.
After inserting file name and (loading mergeNote function, SoundNote input above), the whole notebook below can be evaluated.
In[]:=
fileName="http://www.kunstderfuge.com/-/midi.asp?file=20/gottschalk_banjo_15_(c)yogore.mid";
In[]:=
elem=Import[fileName,"Elements"]
Out[]=
{Duration,Header,Metadata,RawData,Sound,SoundNotes,TrackCount}
In[]:=
duration=Import[fileName,elem[[1]]]
Out[]=
206.308
In[]:=
trackCount=Import[fileName,elem[[-1]]]
Out[]=
6
In[]:=
metadata=Import[fileName,elem[[3]]]
Out[]=
{{{0.,TrackNamegottschalk The Banjo, American Sketch, Op15 },{0.,CopyRightNoticeSegundo G. Yogore, 2006, dody@pldtdsl.net},{0.,TextEventsequenced by Segundo G. Yogore, 2006},{0.,TimeSignature{1,2,24,8}},{0.,KeySignature{6,0}},{0.,SetTempo461538},{0.461538,TimeSignature{2,2,24,8}},{186.923,SetTempo400000},{203.723,TimeSignature{6,2,24,8}}},{{0.,21{0}},{0.,TrackNameGrand Piano}},{{0.,21{0}},{0.,TrackNameInstrument17}},{{0.,21{0}},{0.,TrackNameInstrument18}},{{0.,21{0}},{0.,TrackNameInstrument19}},{{0.000961538,CopyRightNotice___________________________________________________KUNSTDERFUGE.COM LARGE CLASSICAL MIDI COLLECTIONONCLASSICAL BY ALESSANDRO SIMONETTO, PROPRIETOR___________________________________________________! Attention: this file is under copyright !(c)onclassical, (c)yogore, 2010___________________________________________________NO ONE MAY REPUBLISH THIS FILE WITHOUT PERMISSIONCOMMERCIAL USES OF THIS FILE IS STRICTLY PROHIBITED___________________________________________________Files & contributor's list: http://kunstderfuge.com/Terms and conditions: http://kunstderfuge.com/notes.htm}}}
In[]:=
(*usingthisstructureitispossibletopreservethemiditrackswhichthencanbemerged*)(*sndata=Import[fileName,elem[[-2]]];Length/@sndatach2={fnotes[#1],#2[[1]],#2[[2]],#4[[2]]}&@@@sndata[[2]];ch3={fnotes[#1],#2[[1]],#2[[2]],#4[[2]]}&@@@sndata[[3]];ch4={fnotes[#1],#2[[1]],#2[[2]],#4[[2]]}&@@@sndata[[4]];ch5={fnotes[#1],#2[[1]],#2[[2]],#4[[2]]}&@@@sndata[[5]];ch6={fnotes[#1],#2[[1]],#2[[2]],#4[[2]]}&@@@sndata[[6]];chAll=Sort[Join[ch2,ch3,ch4,ch5,ch6],#1[[2]]<#2[[2]]&];*)
In[]:=
(*thisstrategyhasMMainterpretationoftempo*)(*mayneedtolearnassembleRawData*)snd=Import[fileName,elem[[-3]]];
In[]:=
snd[[1]][[1]]
Out[]=
SoundNote[F#4,{0.461538,0.530769},Piano,SoundVolume0.894118]
In[]:=
chAll={fnotes[#1],#2[[1]],#2[[2]],#4[[2]]}&@@@snd[[1]];
In[]:=
Histogram[chAll[[All,3]]-chAll[[All,2]],Automatic,FrameTrue,FrameLabel{"Seconds","Number of Notes"},PlotLabel"Distribution of Note Durations"]
Out[]=
In[]:=
mx=Ceiling[44100duration];(*thiscreatesthe32bitrealfilefortheaudio*)na=NumericArray[ConstantArray[0.,mx],"Real32"];(*thefilenaisownedbyM;mergeNoteoperatesonit*)mergeNoteP[na,#1,#2,#3,#4]&@@@chAll;//AbsoluteTiming
Out[]=
{0.892311,Null}
In[]:=
(*createmonauralaudiofromna*)audio0=Audio[na];
In[]:=
(*makeastereofile*)audioS=AudioChannelMix[audio0,"Stereo"]//AudioNormalize;
In[]:=
(*Export[FileNameJoin[{NotebookDirectory[],FileBaseName[fileName]<>".wav"}],audioS]*)
In[]:=
(*LibraryFunctionUnload[mergeNote]*)