{"id":33889,"date":"2020-10-22T15:52:33","date_gmt":"2020-10-22T15:52:33","guid":{"rendered":"http:\/\/pcbjunkie.net\/?page_id=33889"},"modified":"2024-11-05T09:27:53","modified_gmt":"2024-11-05T09:27:53","slug":"midi-rendering-and-sound-library","status":"publish","type":"page","link":"https:\/\/pcbjunkie.net\/index.php\/midi-rendering-and-sound-library\/","title":{"rendered":"Midi Rendering and Sound Library"},"content":{"rendered":"\n<p>I wrote this library a number of years ago. This code was used in some homebrew code on portable gaming platforms like the GP2X.<\/p>\n\n\n\n<p>Just like with my image library, this one is supposed to be self contained, and compile without any dependencies, on small or embeded systems. All sound generation, file format processing, sound mixing and event management is handled by this code without the use of any external libraries.<\/p>\n\n\n\n<p>Here is the library source code:<\/p>\n\n\n\n\n\n<p>This library can read and write most basic MIDI and WAV files. It can also talk to sound hardware on Linux platforms.  For MIDI, it uses wavetable synthesis, and reads SF2 Soundfont data for its instrument definitions.<\/p>\n\n\n\n<p>The main component is the wave table synthesizer that is responsible for reading instruments sample data and the MIDI events file and for generating raw sound data that can then be sent directly to a DAC, standard sound hardware, or written out to a WAV file.<\/p>\n\n\n\n<p>Here&#8217;s some sample code to play a MIDI file in a loop. It&#8217;s pretty straight forward as you can see:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>sound = R_InitSound(1, 16, 44100, 8196); <\/code>\/\/ 8K buffer, 16bit samples at 44100 kHz<br><code>mixer = R_InitMixer();<\/code><br><code>bankset = readSF2(\"MINI.SF2\"); <\/code>\/\/ read instruments<br><code>buffersize = R_GetSoundDeviceBufferSize(sound);<\/code><br><code>rendered = R_CreateBlankSample(1, 16, 44100, buffersize);<\/code><br><code>R_InitSequence(sequence);<\/code> \/\/ init sequencer<br><br><code>while(1){<\/code><br>  <code>ready = R_SendSoundBuffers(sound);<\/code><br><code>  if (ready &amp;&amp; R_IsMixerChannelReady(mixer, 0)){<\/code><br><code>    R_SilenceSample(rendered);<\/code><br><code>    R_RenderSequencetoSample(rendered, sequence, bankset, buffersize);<\/code><br><code>    R_SetMixerChannelSample(mixer, 0, rendered);<\/code><br><code>  }<\/code><br><code>  R_MixSoundVoices(sound, mixer);<\/code><br><code>}<\/code><\/pre>\n\n\n\n<p>Here&#8217;s how you can convert a MIDI file to a WAV file without using any sound hardware.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>bankset = readSF2(\"MINI.SF2\"); <\/code><br><code>sequence = readMIDI(\"input.mid\"); <\/code><br><code>R_InitSequence(sequence); <\/code><br><code>lastevent = sequence-&gt;lastevent-&gt;time; <\/code><br><code>buffersize = (lastevent + 1.0) * 2 * 44100; \/\/ 44100 kHz 16-bit samples  <\/code><br><br><code>rendered = R_CreateBlankSample(1, 16, 44100, buffersize); <\/code><br><code>R_SilenceSample(rendered); <\/code><br><code>R_RenderSequencetoSample(rendered, sequence, bankset, buffersize); <\/code><br><code>writeWAV(\"output.wav\", rendered);<\/code><\/pre>\n\n\n\n<p>Here are some sample MIDI renderings from Final Fantasy game MIDI files. This conversion was done using a 3MB sound font file. This would be approximately the quality of sound that would be possible on a PC from the early 90s running this software. <\/p>\n\n\n\n<p>Using a larger soundfont file (512MB for example) would greatly improve the quality of the sound. <\/p>\n\n\n\n<figure class=\"wp-block-audio\"><audio controls src=\"https:\/\/pcbjunkie.net\/wp-content\/uploads\/2020\/10\/locke.mp3\"><\/audio><figcaption class=\"wp-element-caption\">FF3 &#8211; Locke Theme<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-audio\"><audio controls src=\"https:\/\/pcbjunkie.net\/wp-content\/uploads\/2020\/10\/at-zero.mp3\"><\/audio><figcaption class=\"wp-element-caption\">FF2 &#8211; Zeromus Battle<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-audio\"><audio controls src=\"https:\/\/pcbjunkie.net\/wp-content\/uploads\/2020\/10\/blackjack.mp3\"><\/audio><figcaption class=\"wp-element-caption\">FF3 &#8211; Airship Blackjack<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-audio\"><audio controls src=\"https:\/\/pcbjunkie.net\/wp-content\/uploads\/2020\/10\/toria.mp3\"><\/audio><figcaption class=\"wp-element-caption\">FF2 &#8211; Toroia<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-audio\"><audio controls src=\"https:\/\/pcbjunkie.net\/wp-content\/uploads\/2020\/10\/bigwhale.mp3\"><\/audio><figcaption class=\"wp-element-caption\">FF2 &#8211; Big Whale<\/figcaption><\/figure>\n\n\n\n<p>The original MIDI files are here:<\/p>\n\n\n\n<div class=\"wp-block-file\"><a id=\"wp-block-file--media-7ce9ee03-635a-470b-979e-c44a7df3e47a\" href=\"https:\/\/pcbjunkie.net\/wp-content\/uploads\/2020\/10\/bigwhale.mid\">FF2 &#8211; Big Whale<\/a><a href=\"https:\/\/pcbjunkie.net\/wp-content\/uploads\/2020\/10\/bigwhale.mid\" class=\"wp-block-file__button wp-element-button\" download aria-describedby=\"wp-block-file--media-7ce9ee03-635a-470b-979e-c44a7df3e47a\">Download<\/a><\/div>\n\n\n\n<div class=\"wp-block-file\"><a id=\"wp-block-file--media-a78cc921-5d50-40f7-9542-5763d75c61c7\" href=\"https:\/\/pcbjunkie.net\/wp-content\/uploads\/2020\/10\/locke.mid\">FF3 &#8211; Locke Theme<\/a><a href=\"https:\/\/pcbjunkie.net\/wp-content\/uploads\/2020\/10\/locke.mid\" class=\"wp-block-file__button wp-element-button\" download aria-describedby=\"wp-block-file--media-a78cc921-5d50-40f7-9542-5763d75c61c7\">Download<\/a><\/div>\n\n\n\n<div class=\"wp-block-file\"><a id=\"wp-block-file--media-f52e5740-b116-436f-b094-f4bae1c02d1b\" href=\"https:\/\/pcbjunkie.net\/wp-content\/uploads\/2020\/10\/at-zero.mid\">FF2 &#8211; Zeromus Battle<\/a><a href=\"https:\/\/pcbjunkie.net\/wp-content\/uploads\/2020\/10\/at-zero.mid\" class=\"wp-block-file__button wp-element-button\" download aria-describedby=\"wp-block-file--media-f52e5740-b116-436f-b094-f4bae1c02d1b\">Download<\/a><\/div>\n\n\n\n<div class=\"wp-block-file\"><a id=\"wp-block-file--media-2466778f-0c60-4eab-9124-8135b06c32fd\" href=\"https:\/\/pcbjunkie.net\/wp-content\/uploads\/2020\/10\/blackjack.mid\">FF3 &#8211; Airshp Blackjack<\/a><a href=\"https:\/\/pcbjunkie.net\/wp-content\/uploads\/2020\/10\/blackjack.mid\" class=\"wp-block-file__button wp-element-button\" download aria-describedby=\"wp-block-file--media-2466778f-0c60-4eab-9124-8135b06c32fd\">Download<\/a><\/div>\n\n\n\n<div class=\"wp-block-file\"><a id=\"wp-block-file--media-cbe758f2-ff71-43ed-ac7e-a129298f6bb9\" href=\"https:\/\/pcbjunkie.net\/wp-content\/uploads\/2020\/10\/toria.mid\">FF2 &#8211; Toroia<\/a><a href=\"https:\/\/pcbjunkie.net\/wp-content\/uploads\/2020\/10\/toria.mid\" class=\"wp-block-file__button wp-element-button\" download aria-describedby=\"wp-block-file--media-cbe758f2-ff71-43ed-ac7e-a129298f6bb9\">Download<\/a><\/div>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I wrote this library a number of years ago. This code was used in some homebrew code on portable gaming platforms like the GP2X. Just like with my image library, this one is supposed to be self contained, and compile without any dependencies, on small or embeded systems. All sound generation, file format processing, sound &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/pcbjunkie.net\/index.php\/midi-rendering-and-sound-library\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Midi Rendering and Sound Library&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-33889","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/pcbjunkie.net\/index.php\/wp-json\/wp\/v2\/pages\/33889","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pcbjunkie.net\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/pcbjunkie.net\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/pcbjunkie.net\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pcbjunkie.net\/index.php\/wp-json\/wp\/v2\/comments?post=33889"}],"version-history":[{"count":8,"href":"https:\/\/pcbjunkie.net\/index.php\/wp-json\/wp\/v2\/pages\/33889\/revisions"}],"predecessor-version":[{"id":36348,"href":"https:\/\/pcbjunkie.net\/index.php\/wp-json\/wp\/v2\/pages\/33889\/revisions\/36348"}],"wp:attachment":[{"href":"https:\/\/pcbjunkie.net\/index.php\/wp-json\/wp\/v2\/media?parent=33889"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}