<?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: Varlen Pavani Neto</title>
    <description>The latest articles on DEV Community by Varlen Pavani Neto (@varlen).</description>
    <link>https://dev.to/varlen</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%2F83388%2Fb8779a06-52eb-4efa-a28a-825f5bccd9e1.png</url>
      <title>DEV Community: Varlen Pavani Neto</title>
      <link>https://dev.to/varlen</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/varlen"/>
    <language>en</language>
    <item>
      <title>Considerations about implementing VueJS systems</title>
      <dc:creator>Varlen Pavani Neto</dc:creator>
      <pubDate>Wed, 01 Dec 2021 19:59:34 +0000</pubDate>
      <link>https://dev.to/varlen/considerations-about-implementing-vuejs-systems-1lol</link>
      <guid>https://dev.to/varlen/considerations-about-implementing-vuejs-systems-1lol</guid>
      <description>&lt;p&gt;When working with VueJS, I feel productive and feel like my code is explicit about what it is doing. It works nicely with current Web Standards and also lets you bring your own tooling if needed.&lt;/p&gt;

&lt;p&gt;In comparison with Angular, Vue gives the developer total freedom on how to architect the application frontend, only being concerned about rendering components on screen (the view, or &lt;em&gt;le vue&lt;/em&gt;). There's no such thing as Modules, Services, no RxJS or anything like Angular provides by default.&lt;/p&gt;

&lt;p&gt;This freedom simplifies the implementation but comes with a cost. If your project is heavy on the logic side of backend or has multiple components, it is necessary to expend some time to keep the house clean, organize everything and define standards to be used with the team.&lt;/p&gt;

&lt;p&gt;It may be a little bit confusing for newcomers to know how to organize your implementation and over time I found myself taking some notes about this, to be able to improve how Vue systems are built. &lt;/p&gt;

&lt;p&gt;Here, I want to share some of my insights, gathered from the experience of working with many distinct VueJS systems, some started by me, some started by others, and also from the experiences shared by coleagues.&lt;/p&gt;




&lt;h2&gt;
  
  
  Do NOT use Vuex without reason
&lt;/h2&gt;

&lt;p&gt;Vuex is the default Global State management solution in Vue. It is part of the study path of any Vue training. It is fair to say that Vuex was inspired in Redux. &lt;/p&gt;

&lt;p&gt;However, it is easy to misunderstand when to really use it. I've seen projects that used Vuex in every single API call, even when that specific store was used by a single component.&lt;/p&gt;

&lt;p&gt;I've seen developers hating Vue mostly because every single API call would yield way more lines of code that needed. That's not Vue fault, but Vuex misusage.&lt;/p&gt;

&lt;p&gt;Some may argue that "I will create it because whenever you create another component that uses it, the state is already there to be used". Well, it is true. However, you cannot predict the future to be really sure that the added complexity of Vuex will pay-off.&lt;/p&gt;

&lt;p&gt;I believe that it is better to supose that YAGNI (you ain't gonna need it). Let the state sit in the component and just move it to Vuex if you really think this is necessary. Prefer props and events to comunicate between components.&lt;/p&gt;

&lt;p&gt;If your team comes from an Angular background or you're reusing parts of a previous system implemented in Angular, you may also ditch Vuex entirely and give a chance to vue-rx, which allows to use subscriptions as a property of a Vue Component.&lt;/p&gt;




&lt;h2&gt;
  
  
  Pure Components and High-Order Components
&lt;/h2&gt;

&lt;p&gt;There are two concepts that come in handy to organize the Vue code. &lt;/p&gt;

&lt;p&gt;First is the &lt;em&gt;Pure Component&lt;/em&gt;. The Pure Component is a component that doesn't have any external API calls (using axios, a service or whatever) or directly access the global state (the Vuex stores, possibly). This is &lt;del&gt;an idea stolen&lt;/del&gt; slightly inspired in Pure Functions, from Functional Programming.&lt;/p&gt;

&lt;p&gt;For instance, suppose that you have a component that renders a table of data with a single text input on top that filters the displayed content. &lt;/p&gt;

&lt;p&gt;Also, suppose that your system have many pages, displaying different domain entities in each page, but using that same table component with different configurations, like column headers.&lt;/p&gt;

&lt;p&gt;If you use a component library like Vuetify, you may use its v-datatable component to do the job. But, at some point you'll probably realize that most code to setup the datable is being repeated across multiple pages.&lt;/p&gt;

&lt;p&gt;At this point it is a good idea to create a Pure Component wrapping the v-datable, let's call it, for example, FilterableTable. Now, all your shared code lies in a single place and you can use the FilterableTable in the pages without repeating all the required configuration.&lt;/p&gt;

&lt;p&gt;The FilteredTable component does not fetch any data and must receive data to be displayed somehow. From this, we notice that we'll need a parent component passing data to the props of FilteredTable and listening to its events.&lt;/p&gt;

&lt;p&gt;This parent component is a High-Order Component. It is a container of Pure Components. This is the right place to fetch data from APIs or consume services and to access and mutate the global state. &lt;/p&gt;

&lt;p&gt;A High-Order Component may have multiple Pure Components and orchestrate them if necessary.&lt;/p&gt;

&lt;p&gt;This separation between Pure Components and High-Order Components allows developers to keep components small and makes it easier to understand and maintain.&lt;/p&gt;




&lt;h2&gt;
  
  
  Don't fear the Props
&lt;/h2&gt;

&lt;p&gt;Props in Vue can be typed and validated. This is extremely useful, specially if the project do not uses typescript, for creating Pure Components and sparing some lines of test code. Trust Vue to do the validation for you.&lt;/p&gt;

&lt;p&gt;Props do give you the possiblity to pass a whole object into a Vue component. This is something that should be done with caution. &lt;/p&gt;

&lt;p&gt;Do not assume that the deep properties are available when your component is created and rendered unless you ensure that manually, otherwise you will face some errors and broken page renderings.&lt;/p&gt;

&lt;p&gt;Vue will try to reach properties that still doesn't exists when creating the component and throw an error.&lt;/p&gt;

&lt;p&gt;One useful pattern to solve this problem without needing to validate every single object property used by your component is to ensure that the component is only created when data exists or after loading with &lt;strong&gt;v-if.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If all the component needs is a small subset of object data, a couple to a few properties, prefer passing these as single props instead of the whole object. This will give you the advantage of validating each property individually.&lt;/p&gt;




&lt;h2&gt;
  
  
  Avoiding Big Components
&lt;/h2&gt;

&lt;p&gt;The number of rows in a component may be used as an indication that the component could use some refactoring and may be simplified. &lt;/p&gt;

&lt;p&gt;There's no fixed value for that but as a rule of thumb, I would say that a component with 100 lines is ok, 300 lines is ok-ish, 600 lines is a yellow light and 1000 has a considerable probability of implementing multiple concerns that should be separated.&lt;/p&gt;

&lt;p&gt;There are some strategies that may be useful to refactor a component into smaller parts.&lt;/p&gt;

&lt;p&gt;First, start by analysing your methods. Sometimes you may have a single method that just changes the value of a state variable (those in data object). In this case, you may replace the method with the attribution itself in the places where the method is called. &lt;/p&gt;

&lt;p&gt;Methods in Vue Components usually are not meant to be used as methods in default object oriented scenarios. The main difference is that Vue Methods are usually used inside the component itself to do a single internal operation and not as a gateway to the external world which would be the case that would justify a method with a single line in object orientation.&lt;/p&gt;

&lt;p&gt;Thus, the use case for methods in Vue is closer to private methods in object oriented languages  and if this detail goes unoticed, it may lead to unecessary creation of methods.&lt;/p&gt;

&lt;p&gt;If a component needs to comunicate with the external world, then the proper way to do it is using props to receive data and events to output data, considering a pure component.&lt;/p&gt;

&lt;p&gt;Specifically if you have a component with let's say, 1000 lines, it certainly could be refactored into a High-Order Component plus a few Pure Components and Mixins.&lt;/p&gt;




&lt;h2&gt;
  
  
  Be aware of Mixins
&lt;/h2&gt;

&lt;p&gt;For last but not least, about mixins I have the same advice from Vuex: Use carefully. &lt;/p&gt;

&lt;p&gt;Even seeming like a great solution for code reuse, they may create unwanted coupling between components if misused, leading to maintainability issues. &lt;/p&gt;

&lt;p&gt;Definetely, avoid having multiple mixins in the same component to avoid name colisions.&lt;/p&gt;

&lt;p&gt;A interesting use case for Mixins is to keep pre-made event handler methods that will be used in a High-Order Component.&lt;/p&gt;

&lt;p&gt;Thank you!&lt;/p&gt;




&lt;p&gt;If you find these insights useful or want to share some more, feel free to leave a comment or reach me out on twitter at varlenneto.&lt;/p&gt;

&lt;p&gt;PS: A big shout out for all people that took their first look on Vue influenced by me. You folks were the inspiration for this post&lt;/p&gt;

</description>
      <category>vue</category>
      <category>javascript</category>
      <category>frontend</category>
      <category>fullstack</category>
    </item>
    <item>
      <title>Productivity on Visual Studio Code - Running scripts from keyboard shortcuts</title>
      <dc:creator>Varlen Pavani Neto</dc:creator>
      <pubDate>Thu, 13 Aug 2020 01:19:58 +0000</pubDate>
      <link>https://dev.to/varlen/productivity-on-visual-studio-code-running-scripts-from-keyboard-shortcuts-481d</link>
      <guid>https://dev.to/varlen/productivity-on-visual-studio-code-running-scripts-from-keyboard-shortcuts-481d</guid>
      <description>&lt;p&gt;Have you ever dealt with some scripts that you need to run over and over again via command line in a project? Some redeploy script, custom compilation or something? &lt;/p&gt;

&lt;p&gt;I was working on a project where it was necessary to recreate the database from scratch in a docker container every few moments and it was really boring to invoke the rebuild script by hand on the command line every time I changed its creation script. Here I share a simple tip that increased my productivity and development experience considerably.&lt;/p&gt;

&lt;p&gt;Instead of typing the command in the CLI or right clicking it everytime it was needed to run it, it is possible to create a task and add a keyboard shortcut to it. &lt;/p&gt;

&lt;p&gt;By doing this, we don't need to access the CLI to invoke the script anymore. &lt;a href="https://github.com/NARKOZ/hacker-scripts/blob/master/fucking_coffee.rb" rel="noopener noreferrer"&gt;It is even possible&lt;/a&gt; to make coffee &lt;a href="https://www.stuff.co.nz/technology/digital-living/99164024/a-programmer-wrote-scripts-to-secretly-automate-his-job" rel="noopener noreferrer"&gt;(taken from here)&lt;/a&gt; with a keyboard shortcut without leaving Visual Studio Code! The only thing is that you will need a compatible coffee machine in your network :)&lt;/p&gt;

&lt;p&gt;To create a task, open Visual Studio Code command pallete and search for&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;&amp;gt; Tasks: Configure Tasks&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Then choose&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;Create tasks.json file from template&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
 and pick one of the available templates, according to your needs. For example, I will use &lt;em&gt;Others&lt;/em&gt; template:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Faa2sod0xahih66e6njj0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Faa2sod0xahih66e6njj0.gif" alt="Creating a task" width="698" height="483"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will create the &lt;strong&gt;.vscode/tasks.json&lt;/strong&gt; file, allowing you to configure tasks.&lt;/p&gt;

&lt;p&gt;It is possible to do all kinds of stuff using Visual Studio Code tasks and you can find the full documentation &lt;a href="https://go.microsoft.com/fwlink/?LinkId=733558" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now edit your tasks.json file to include your script in a object inside the tasks array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my nice task"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shell"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./myscript.sh"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After creating the task, you can version this file in your repository to share this configuration with other developers.&lt;/p&gt;

&lt;p&gt;Now if you open the command pallete again and select &lt;strong&gt;Tasks: Run Task&lt;/strong&gt;, you will be able to see and run your task from there. &lt;/p&gt;

&lt;p&gt;Now, it is necessary to configure the keyboard shortcut.&lt;/p&gt;

&lt;p&gt;Open the command pallete (&lt;strong&gt;Ctrl+Shift+P&lt;/strong&gt; or F1) again, type in "keyboard" and look for &lt;strong&gt;Preferences: Open Keyboard Shortcuts (JSON)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fco3j6fvvig04xhh784zh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fco3j6fvvig04xhh784zh.png" alt="JSON Keyboard configuration" width="768" height="206"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will open the &lt;strong&gt;keybindings.json&lt;/strong&gt; file. You can version or keep this file in a (gist)[gist.github.com]. There, you can define a new keybinding by clicking in the button on the bottom right or type in manually the configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
   "key": "ctrl+k 1",
   "command": "workbench.action.tasks.runTask",
   "args" : "my nice task"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's look what each parameter does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;key&lt;/strong&gt; : This is the sequence of keys that will be used to trigger your script. From the configuration in the example above, it will be necessary to press ctrl and k simultaneously and then press 1 (This is what is called a "chord").&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;command&lt;/strong&gt; : This is the reference (command id) to the internal command of Visual Studio Code that will be triggered by the keypress. Here, it is the command that runs a given task. The full list of commands can be found by opening &lt;strong&gt;Default Keyboard Shortcuts (JSON)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;args&lt;/strong&gt; : This is an argument to the command. In our case, it is the exact name of the custom task.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Save the keybindings file and you're good to go. Try pressing the key sequence that you just configured. &lt;/p&gt;

&lt;p&gt;There's a lot of customization options for keybindings and if you find it useful, I highly recommend checking out the docs on this feature of VSCode as well.&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Editing MIDI files with Python</title>
      <dc:creator>Varlen Pavani Neto</dc:creator>
      <pubDate>Sat, 11 Jul 2020 01:10:25 +0000</pubDate>
      <link>https://dev.to/varlen/editing-midi-files-with-python-2m0g</link>
      <guid>https://dev.to/varlen/editing-midi-files-with-python-2m0g</guid>
      <description>&lt;p&gt;Couple months ago, I was in the house of my band's guitar player doing pre-production of a new song. Our drummer had sent us a MIDI sequence made with MT PowerDrum Kit 2 VST plugin. I wanted to check how the grooves would sound with a sample pack I had.&lt;/p&gt;

&lt;p&gt;I tried to load the samples using Kontakt and...&lt;/p&gt;

&lt;p&gt;The sample pack had some sounds mapped differently from the original plugin. What now?&lt;/p&gt;

&lt;p&gt;I could edit the drum line note by note in my daw, however this is a tedious and error prone process. Besides, if my drummer send me another version, I would need to change everything again. Manually.&lt;/p&gt;

&lt;p&gt;We can create drum lines using one plugin and use it in another. Here I show you how to avoid the repetition and automate the translation between different drum plugins using Python. &lt;/p&gt;




&lt;h1&gt;
  
  
  MIDI and MIDI files
&lt;/h1&gt;

&lt;p&gt;MIDI is communication protocol created way before my existence in this planet. In a nutshell, it empowers musicians by allowing multiple digital musical instruments to work together.&lt;/p&gt;

&lt;p&gt;Usually, MIDI devices used a 5 pin DIN cable. Nowadays, the protocol still exists and is commonly found working over USB, connecting instruments to a computer. &lt;/p&gt;

&lt;p&gt;MIDI uses messages to communicate events like the start or end of a note, its intensity and pitch, a change in tempo, etc.&lt;/p&gt;

&lt;p&gt;These messages can be stored in a MIDI file. These files were famous on the early days of multimedia internet as background music for personal websites and as polyphonic ringtones.&lt;/p&gt;

&lt;p&gt;These files can represent digitally the performance of a song.&lt;/p&gt;




&lt;h1&gt;
  
  
  How to handle MIDI files?
&lt;/h1&gt;

&lt;p&gt;We could search the MIDI protocol specifications and implement the protocol ourselves, however since the idea here is to avoid a lot of manual work, a quick Google search for a library may be enough.&lt;/p&gt;

&lt;p&gt;By googling "python midi library", I found &lt;strong&gt;mido&lt;/strong&gt;. From skimming the docs, we can see that it should provide everything we need for this task. It is available &lt;a href="https://mido.readthedocs.io/en/latest/" rel="noopener noreferrer"&gt;here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pip provides it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install mido
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Thinking about the script
&lt;/h1&gt;

&lt;p&gt;Having our tools chosen, we now need to plan what the code must do.&lt;/p&gt;

&lt;p&gt;The python script must read note sequences in the source MIDI file and map each note from the original plugin into their equivalents of another plugin.&lt;/p&gt;

&lt;p&gt;For that, it is necessary to understand how each VST plugin maps their drum pieces into MIDI notes. For MT PowerDrum Kit 2, there are some files in &lt;a href="https://www.powerdrumkit.com/presets.php" rel="noopener noreferrer"&gt;their website&lt;/a&gt; documenting which note maps each sound.&lt;/p&gt;

&lt;p&gt;The sample pack had these informations in its PDF manual.&lt;/p&gt;

&lt;p&gt;It would be really convenient to do this mapping in a visual way, but I didn't find any tools for doing it, and creating a custom tool would go totally against the purpose of this whole thing. (It could be a nice side project, thou)&lt;/p&gt;

&lt;p&gt;Since, there's no another way to do it, I did it by hand, trying the best match possible between both plugins.&lt;/p&gt;

&lt;p&gt;Each row contains source, destination and description columns.&lt;/p&gt;

&lt;p&gt;If you find yourself doing the exact same mapping, don't waste your time anymore, here it is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;65,44,Hihat Pedal
63,68,Hihat Edge Tight
62,69,Hihat Edge Closed
61,71,Hihat Edge Semi-open
60,72,Hihat Edge Open
58,54,Crash 1 Choke
57,55,Crash 1
55,55,Splash -&amp;gt; Crash
53,53,Ride Bell
52,35,China
51,51,Ride
50,50,Tom 1 - Hi
49,52,Crash 2
48,50,Tom 1 - Hi
47,48,Tom 2 - Mid
46,72,Hihat Edge Open
45,48,Tom 2 - Mid
44,71,Hihat Edge Semi-open
43,47,Tom 3 - Low
42,69,Hihat Edge Closed
41,47,Tom 3 - Low
40,38,Snare
39,38,Snare
38,38,Snare
37,37,Sidestick
36,36,Kick
35,36,Kick
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's the final script, commented line by line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;mido&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MidiFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MidiFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MidiTrack&lt;/span&gt;

&lt;span class="c1"&gt;# Opening the original MIDI sequence
&lt;/span&gt;&lt;span class="n"&gt;input_midi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MidiFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;./Murundu.mid&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Creating the destination file object
&lt;/span&gt;&lt;span class="n"&gt;output_midi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MidiFile&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Copying the time metrics between both files
&lt;/span&gt;&lt;span class="n"&gt;output_midi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ticks_per_beat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input_midi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ticks_per_beat&lt;/span&gt;

&lt;span class="n"&gt;note_map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="c1"&gt;# Load the mapping file
&lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;note_map.csv&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;map_text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;map_text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;elements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;# Each line in the mapping file will be loaded into a
&lt;/span&gt;        &lt;span class="c1"&gt;# dictionary with the original MIDI note as key and
&lt;/span&gt;        &lt;span class="c1"&gt;# another dictionary with target note 
&lt;/span&gt;        &lt;span class="c1"&gt;# and description as value
&lt;/span&gt;        &lt;span class="n"&gt;note_map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elements&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;target_note&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elements&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; 
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;elements&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Now, we iterate the source file and insert mapped notes
# into the destination file
&lt;/span&gt;
&lt;span class="c1"&gt;# Notes are determined by note_on e note_off MIDI messages
# Other types of messages will be copied directly 
# Notes that does not exist in the mapping will not be copied
&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;original_track&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;input_midi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tracks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="n"&gt;new_track&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MidiTrack&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;original_track&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;note_on&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;note_off&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
            &lt;span class="c1"&gt;# mido's API allows to copy a MIDI message
&lt;/span&gt;            &lt;span class="c1"&gt;# changing only some of its parameters
&lt;/span&gt;            &lt;span class="c1"&gt;# Here, we use the mapping dictionary to create
&lt;/span&gt;            &lt;span class="c1"&gt;# the mapped note, keeping its properties like
&lt;/span&gt;            &lt;span class="c1"&gt;# intensity
&lt;/span&gt;
            &lt;span class="n"&gt;origin_note&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;note&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;origin_note&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;note_map&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;new_track&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; 
                    &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;note&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;note_map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;origin_note&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;target_note&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;))&lt;/span&gt;
                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;note_map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;origin_note&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Origin note&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;origin_note&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;not mapped&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;new_track&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# MIDI files are multitrack. Here we append
&lt;/span&gt;    &lt;span class="c1"&gt;# the new track with mapped notes to the output file
&lt;/span&gt;    &lt;span class="n"&gt;output_midi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tracks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_track&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Finally, save the mapped file to disk
&lt;/span&gt;&lt;span class="n"&gt;output_midi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;./Murundu-remap.mid&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>python</category>
      <category>midi</category>
      <category>music</category>
      <category>musicproduction</category>
    </item>
  </channel>
</rss>
