<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Srgy Surkv</title>
    <description>The latest articles on DEV Community by Srgy Surkv (@surikov).</description>
    <link>https://dev.to/surikov</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F219821%2Fe8538af6-b62b-4c70-a174-46426423af1c.jpeg</url>
      <title>DEV Community: Srgy Surkv</title>
      <link>https://dev.to/surikov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/surikov"/>
    <language>en</language>
    <item>
      <title>Automatic music creation without artificial intelligence</title>
      <dc:creator>Srgy Surkv</dc:creator>
      <pubDate>Tue, 02 Apr 2024 07:03:37 +0000</pubDate>
      <link>https://dev.to/surikov/automatic-music-creation-without-artificial-intelligence-4nlp</link>
      <guid>https://dev.to/surikov/automatic-music-creation-without-artificial-intelligence-4nlp</guid>
      <description>&lt;p&gt;Automatic creation of music according to specified parameters.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open in browser - &lt;a href="https://surikov.github.io/rockdice/main.html"&gt;https://surikov.github.io/rockdice/main.html&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Sources - &lt;a href="https://github.com/surikov/rockdice"&gt;https://github.com/surikov/rockdice&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Android version - &lt;a href="https://play.google.com/store/apps/details?id=rockdice.chord.progression"&gt;https://play.google.com/store/apps/details?id=rockdice.chord.progression&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Uses Web Audio API, TypeScript, Android WebView, wavetable synthesis, and basic music theory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Description of application
&lt;/h2&gt;

&lt;p&gt;In the main window, you can use the slider to select the progression. The sequence of chords determines the mood of the melody (minor on the left, major on the right, jazz seventh chord in the middle). &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjaioe7z0xb9rzh29u8zz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjaioe7z0xb9rzh29u8zz.png" alt="Image description" width="800" height="841"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Round switches allow you to select riffs for the standard 4 layers of melody.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Drums - set the rhythm&lt;/li&gt;
&lt;li&gt;Bass – harmonic basis and rhythm&lt;/li&gt;
&lt;li&gt;The leader creates a melodic pattern.&lt;/li&gt;
&lt;li&gt;Pad – counterpoint, long notes that show the function of a chord.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The blue button with a die selects random values.&lt;/p&gt;

&lt;p&gt;The application modulates selected fragments to the specified chords. If you turn the switches and listen to a few melodies, you can be convinced that with any combination of chords and instruments, the sound of the result is quite “human”.&lt;/p&gt;

&lt;h3&gt;
  
  
  Similar projects
&lt;/h3&gt;

&lt;p&gt;The first synthesizers had built-in functions for auto-generating arrangements. An example of performance on a Cassio MT-100 from the 1980s - &lt;a href="https://www.youtube.com/watch?v=Aepm6V4yvhw"&gt;https://www.youtube.com/watch?v=Aepm6V4yvhw&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Modern Captain Plugins Epic app, suitable only for professionals - &lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=ZuB_t1DBwp8"&gt;https://www.youtube.com/watch?v=ZuB_t1DBwp8&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The BandLab SongStarter web application does not support any settings, it simply generates melodies in one style - &lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=EDRPy8KtY0c"&gt;https://www.youtube.com/watch?v=EDRPy8KtY0c&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Settings
&lt;/h3&gt;

&lt;p&gt;When you click on the gear, the settings window opens. You can edit volume by layers, speed, change chords, transpose:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzweo11e4bdau3nxdwwbe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzweo11e4bdau3nxdwwbe.png" alt="Image description" width="400" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For each track you can choose a riff from the list:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzzsydddih6d5t61tn6sm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzzsydddih6d5t61tn6sm.png" alt="Image description" width="400" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also choose a chord progression:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmsm402up3h7fewoe4e9q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmsm402up3h7fewoe4e9q.png" alt="Image description" width="400" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  History/Undo
&lt;/h3&gt;

&lt;p&gt;The ability to undo a previous action and return to a previous state is a typical requirement for any application. When you click on the button with the Cancel icon (top right), a window opens with the history of selecting melodies:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx66h9f06vqsp48ogce7n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx66h9f06vqsp48ogce7n.png" alt="Image description" width="400" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Publishing and exporting
&lt;/h3&gt;

&lt;p&gt;Like any music application, RockDice allows you to export the created melody to a MIDI file or Wav file (buttons on the bottom panel). The resulting files can be edited in other music applications. Example of tracks imported into BandLab MixEditor (any track can be forked and opened in the editor):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.bandlab.com/sss1024/tracks"&gt;https://www.bandlab.com/sss1024/tracks&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk8dqsbjazpqs8g3dswwo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk8dqsbjazpqs8g3dswwo.png" alt="Image description" width="400" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Collaboration
&lt;/h3&gt;

&lt;p&gt;The link to the melody opens in the application exactly as the author sent it.&lt;/p&gt;

&lt;p&gt;Clicking the button with the standard Share icon opens a preview window. In it you can send a link to the melody by email, instant messenger or social networks:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fstdor3m0o7zbwmns54c7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fstdor3m0o7zbwmns54c7.png" alt="Image description" width="400" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most social networks correctly recognize a link with a description and image of the selected tools:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7kr0f8mnovwg9j9ofx7i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7kr0f8mnovwg9j9ofx7i.png" alt="Image description" width="400" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation Description
&lt;/h2&gt;

&lt;p&gt;How it's done.&lt;/p&gt;

&lt;h3&gt;
  
  
  Playing sound
&lt;/h3&gt;

&lt;p&gt;The WebAudioFont library is used to play sound:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/surikov/webaudiofont"&gt;https://github.com/surikov/webaudiofont&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The library contains more than 2000 digitized instruments and basic filters for sound processing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;10-band equalizer to customize tone&lt;/li&gt;
&lt;li&gt;echo for surround sound&lt;/li&gt;
&lt;li&gt;dynamic compressor to highlight voices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Documentation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://surikov.github.io/webaudiofont/npm/src/docs/index.html"&gt;https://surikov.github.io/webaudiofont/npm/src/docs/index.html&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Modulation of fragments
&lt;/h3&gt;

&lt;p&gt;For selected (or manually entered) chords, extractMode calculates the root note and scale, see below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/surikov/rockdice/blob/main/ts/code/zvoogharmonizer.ts#L1156"&gt;https://github.com/surikov/rockdice/blob/main/ts/code/zvoogharmonizer.ts#L1156&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For music playing, about two hundred riffs with different instruments were added to the project; you can see them in the folder&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/surikov/rockdice/tree/main/patterns"&gt;https://github.com/surikov/rockdice/tree/main/patterns&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each pattern, in addition to notes, also contains a description of the mode and tonic.&lt;/p&gt;

&lt;p&gt;The selected riffs in the morphSchedule function are transposed to the root of the selected chords and modulated according to the scale of the chord progression, see below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/surikov/rockdice/blob/main/ts/code/zvoogharmonizer.ts#L377"&gt;https://github.com/surikov/rockdice/blob/main/ts/code/zvoogharmonizer.ts#L377&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Transposing a melody involves moving all notes the same number of semitones. Simply put, make the sound higher or lower.&lt;/li&gt;
&lt;li&gt;Modulation of a melody is a shift of the scale by certain steps. In a simple way - from minor to major, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Music instrument's Features
&lt;/h3&gt;

&lt;p&gt;When playing musical fragments, the specifics of performance on specific instruments are taken into account. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When playing guitar with distortion, you typically use both open string strumming and palm muted strumming. Those. There is only one instrument, but for a realistic sound you need two separate sets of samples for &lt;a href="https://surikov.github.io/webaudiofontdata/sound/0300_LesPaul_sf2.html"&gt;open&lt;/a&gt; and &lt;a href="https://surikov.github.io/webaudiofontdata/sound/0290_LesPaul_sf2.html"&gt;muted&lt;/a&gt; strings&lt;/li&gt;
&lt;li&gt;on an acoustic guitar, hitting the strings down and up is noticeably different, see &lt;a href="https://surikov.github.io/webaudiofont/examples/strum.html"&gt;example&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;sets of notes of similar chords (for example G and Gm) can be pressed on completely different frets, this must be taken into account when modulating fragments&lt;/li&gt;
&lt;li&gt;and so on.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a result, the generated music sounds less monotonous.&lt;/p&gt;

&lt;h3&gt;
  
  
  Application State's storage
&lt;/h3&gt;

&lt;p&gt;Selected chords, fragments and other settings are saved in the browser's localStorage, see &lt;a href="https://github.com/surikov/rockdice/blob/main/ts/code/zvoogapp.ts#L2376"&gt;readObjectFromlocalStorage&lt;/a&gt;. As a result, when you reopen the application, its state is restored to the same state as in the last session.&lt;/p&gt;

&lt;p&gt;When creating a link for publication, all data is encoded into a long, very long URL, example&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mzxbox.ru/RockDice/share.php?seed=%7B%22drumsSeed%22%3A21%2C%22bassSeed%22%3A12%2C%22leadSeed%22%3A6%2C%22padSeed%22%3A12%2C%22drumsVolume%22%3A111%2C%22bassVolume%22%3A99%2C%22leadVolume%22%3A66%2C%22padVolume%22%3A77%2C%22chords%22%3A%5B%22Cm%22%2C%222%2F1%22%2C%22Ebm%22%2C%222%2F1%22%5D%2C%22tempo%22%3A130%2C%22mode%22%3A%22Ionian%22%2C%22tone%22%3A%22D%23%22%2C%22version%22%3A%22v2.83%22%2C%22comment%22%3A%22%22%2C%22ui%22%3A%22web%22%7D"&gt;https://mzxbox.ru/RockDice/share.php?seed=%7B%22drumsSeed%22%3A21%2C%22bassSeed%22%3A12%2C%22leadSeed%22%3A6%2C%22padSeed%22%3A12%2C%22drumsVolume%22%3A111%2C%22bassVolume%22%3A99%2C%22leadVolume%22%3A66%2C%22padVolume%22%3A77%2C%22chords%22%3A%5B%22Cm%22%2C%222%2F1%22%2C%22Ebm%22%2C%222%2F1%22%5D%2C%22tempo%22%3A130%2C%22mode%22%3A%22Ionian%22%2C%22tone%22%3A%22D%23%22%2C%22version%22%3A%22v2.83%22%2C%22comment%22%3A%22%22%2C%22ui%22%3A%22web%22%7D&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Link markup
&lt;/h3&gt;

&lt;p&gt;Published links comply with the Open Graph and Twitter Cards protocols.&lt;/p&gt;

&lt;p&gt;These protocols are supported by most social networking systems. networks. Essentially, this is a requirement that the page being linked to include a description of the page and a preview image.&lt;/p&gt;

&lt;p&gt;The image and page for publication are generated dynamically by a regular PHP script, see.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/surikov/rockdice/blob/main/server/share.php"&gt;https://github.com/surikov/rockdice/blob/main/server/share.php&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All information for the preview is in the tags&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;meta name="twitter:card" content="summary" /&amp;gt;&lt;br&gt;
&amp;lt;meta property="og:title" content="&amp;lt;?php echo $line; ?&amp;gt;" /&amp;gt;&lt;br&gt;
&amp;lt;meta property="og:url" content="https://mzxbox.ru/RockDice/share.php?seed=&amp;lt;?php echo $encoded; ?&amp;gt;" /&amp;gt;&lt;br&gt;
&amp;lt;meta property="og:image" content="https://mzxbox.ru/RockDice/picture.php?drums=&amp;lt;?php echo $drums; ?&amp;gt;&amp;amp;prog=&amp;lt;?php echo urlencode($line); ?&amp;gt;&amp;amp;bass=&amp;lt;?php echo $bass; ?&amp;gt;&amp;amp;lead=&amp;lt;?php echo $lead; ?&amp;gt;&amp;amp;pad=&amp;lt;?php echo $pad; ?&amp;gt;" /&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Scripts are hosted on regular hosting at a price of approximately 200 rubles per month.&lt;/p&gt;

&lt;h3&gt;
  
  
  Android
&lt;/h3&gt;

&lt;p&gt;To create a mobile version, you can use the WebView component.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.android.com/reference/android/webkit/WebView"&gt;https://developer.android.com/reference/android/webkit/WebView&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Essentially, it's regular Chrome built into an Activity. Web pages are opened locally from application resources, files and digitized tools are also downloaded locally.&lt;/p&gt;

&lt;p&gt;In terms of functionality, the mobile version is no different from the web version. Here is the compiled application (not updated for a long time):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://play.google.com/store/apps/details?id=rockdice.chord.progression"&gt;https://play.google.com/store/apps/details?id=rockdice.chord.progression&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvsrd2k5i1dj052leqlfy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvsrd2k5i1dj052leqlfy.png" alt="Image description" width="315" height="700"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;WebView has some minor limitations that should be taken into account.&lt;/p&gt;

&lt;p&gt;For example, access to the file system for saving melodies in MIDI and Wav files. In a large browser, it is enough to create a blob with binary data of the correct MIME type and open a link to it, for example&lt;/p&gt;

&lt;p&gt;&lt;code&gt;let blob: Blob = new Blob([dataview], { type: 'audio/wav' });&lt;br&gt;
let ourl = URL.createObjectURL(blob);&lt;br&gt;
let a = document.createElement("a");&lt;br&gt;
document.body.appendChild(a);&lt;br&gt;
a.href = ourl;&lt;br&gt;
a.download = 'rockdice';&lt;br&gt;
a.click();&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The browser correctly recognizes the file type and displays the normal save dialog with the correct extension.&lt;/p&gt;

&lt;p&gt;For an embedded WebView, you will need to create a save function using Android, embed it in the application's JavaScript via &lt;a href="https://developer.android.com/reference/android/webkit/WebView#addJavascriptInterface(java.lang.Object,%20java.lang.String)"&gt;addJavascriptInterface&lt;/a&gt;, and access it from the web page.&lt;/p&gt;

&lt;p&gt;It is also necessary that published links to melodies open not in the phone’s browser, but in the mobile version of the application. To do this, you need to configure a filter in the AndroidManifest.xml of the application:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;intent-filter&amp;gt;&lt;br&gt;
    &amp;lt;action android:name="android.intent.action.VIEW" /&amp;gt;&lt;br&gt;
    &amp;lt;category android:name="android.intent.category.DEFAULT" /&amp;gt;&lt;br&gt;
    &amp;lt;category android:name="android.intent.category.BROWSABLE" /&amp;gt;&lt;br&gt;
    &amp;lt;data&lt;br&gt;
        android:host="surikov.github.io"&lt;br&gt;
        android:pathPrefix="/rockdice/main.html"&lt;br&gt;
        android:scheme="https"&lt;br&gt;
        /&amp;gt;&lt;br&gt;
&amp;lt;/intent-filter&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can do without the mobile version, because Chrome on phones is no different from Chrome on a computer.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>music</category>
      <category>midi</category>
      <category>android</category>
    </item>
    <item>
      <title>How to use MIDI for web in short</title>
      <dc:creator>Srgy Surkv</dc:creator>
      <pubDate>Wed, 28 Aug 2019 10:12:16 +0000</pubDate>
      <link>https://dev.to/surikov/how-to-use-midi-for-web-in-short-2i2d</link>
      <guid>https://dev.to/surikov/how-to-use-midi-for-web-in-short-2i2d</guid>
      <description>&lt;p&gt;MIDI player&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;a href="https://github.com/nfroidure/midifile"&gt;MIDI parser&lt;/a&gt; to read notes from MIDI file&lt;/li&gt;
&lt;li&gt;Use &lt;a href="https://www.npmjs.com/package/webaudiofont"&gt;WebAudioFont&lt;/a&gt; to play musical instruments in a browser&lt;/li&gt;
&lt;li&gt;See &lt;a href="https://surikov.github.io/webaudiofont/examples/midiplayer.html"&gt;result&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;MIDI keyboard&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;a href="https://reactjs.org/"&gt;React&lt;/a&gt; to draw piano keyboard&lt;/li&gt;
&lt;li&gt;Use &lt;a href="https://www.google.com/chrome/"&gt;Chrome&lt;/a&gt; to read MIDI events from hardware keyboard&lt;/li&gt;
&lt;li&gt;Use &lt;a href="https://www.npmjs.com/package/midi-sounds-react"&gt;midi-sounds-react&lt;/a&gt; to play sound&lt;/li&gt;
&lt;li&gt;See &lt;a href="https://surikov.github.io/midi-sounds-react-examples/examples/midi-sounds-example10/build/"&gt;result&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;MIDI editor&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;a href="https://threejs.org/"&gt;three.js&lt;/a&gt; to create catchy UI&lt;/li&gt;
&lt;li&gt;Use &lt;a href="https://www.npmjs.com/package/webaudiofont"&gt;WebAudioFont&lt;/a&gt; to play music&lt;/li&gt;
&lt;li&gt;See &lt;a href="https://surikov.github.io/riffshare/parse.html?riff=78-0000575a-a2724328-0e0d06080c0e1011020e-001101110211031104110511061107114010411042104310441045104610479080338133823383338433853386338733a044a144a244a344a444a544a644a744-004051840005020040006071b40006110040006100c40006091840006111340007020c40025020040027020c40035020040037020c40045020040047020c40055020040057020c40065020040066031a40067020c40075020040077020c40085020040086031840087020c40095020040097020c400a6031a400b50200400b7020c400c50200400c6031b400c7020c400d50200400d7020c400e40313400e50200400e6031f400e7020c400f50200400f7020c40104051640105020740106110740106111340106072240106011a40107020740125020740127020740135020740137020740145020740147020740155020740157020740165020740166032140167020740175020740177020740185020740186031f401870207401950207401970207401a50207401a60321401a70207401b50207401b70207401c50207401c60322401c70207401d50207401d70207401e4031a401e50207401e60326401e70207401f50207401f7020740204111d40205020a40206201640206200a40206202940206011d40207020a40225020a40227020a40235020a40237020a40245020a40247020a40255020a40257020a40265020a40267020a40275020a40277020a40285020a40287020a40295020a40297020a402a5020a402a7020a402b5020a402b7020a402c5020a402c7020a402d5020a402d7020a402e5020a402e7020a402f5020a402f7020a40305020a40307020a40325020a40327020a40335020a40337020a40345020a40347020a40355020a40357020a40365020a40367020a40375020a40377020a40385020a40387020a40395020a40397020a403a5020a403a7020a403b5020a403b7020a403c5020a403c7020a403d5020a403d7020a403e5020a403e7020a403f5010a403f7010a40"&gt;result&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>midi</category>
      <category>music</category>
      <category>javascript</category>
      <category>react</category>
    </item>
  </channel>
</rss>
