<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Programming on Matias Di Bernardo</title><link>https://dibernardo.netlify.app/categories/programming/</link><description>Recent content in Programming on Matias Di Bernardo</description><generator>Hugo -- gohugo.io</generator><language>en</language><copyright>Matías Di Bernardo</copyright><lastBuildDate>Thu, 26 Jun 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://dibernardo.netlify.app/categories/programming/index.xml" rel="self" type="application/rss+xml"/><item><title>Acoustic modal response optimization for small rooms with genetic algorithms</title><link>https://dibernardo.netlify.app/p/acoustic-modal-response-optimization-for-small-rooms-with-genetic-algorithms/</link><pubDate>Thu, 26 Jun 2025 00:00:00 +0000</pubDate><guid>https://dibernardo.netlify.app/p/acoustic-modal-response-optimization-for-small-rooms-with-genetic-algorithms/</guid><description>&lt;img src="https://dibernardo.netlify.app/p/acoustic-modal-response-optimization-for-small-rooms-with-genetic-algorithms/port3.PNG" alt="Featured image of post Acoustic modal response optimization for small rooms with genetic algorithms" />&lt;p>This work was developed in the context of the course &lt;em>Instruments and Acoustic Measurements&lt;/em> at UNTREF Argentina.&lt;/p>
&lt;h3 id="introduction">&lt;strong>Introduction&lt;/strong>
&lt;/h3>&lt;p>Control rooms and critical listening environments often suffer from uneven low-frequency acoustic responses. These irregularities, caused by a clustered distribution of vibrational modes, produce “colorations” that hamper accurate sound evaluation. Traditionally, criteria such as those by Bonello, Bolt and Louden have been used to optimize the geometry of rectangular rooms and improve modal distribution. However, these methodologies do not consider the influence of complex boundaries nor the positions of source and listener.&lt;/p>
&lt;p>This work presents an open-source tool developed in &lt;strong>Python/FEniCS&lt;/strong> that addresses these limitations. The software uses geometric optimization by brute force over finite element models (FEM) to find room dimensions and contours that provide a more uniform modal distribution.&lt;/p>
&lt;h3 id="theoretical-framework-and-classical-criteria">&lt;strong>Theoretical Framework and Classical Criteria&lt;/strong>
&lt;/h3>&lt;p>Low-frequency behavior in an enclosure is dominated by standing waves, or normal modes, which are characterized by pressure nodes and antinodes. Axial, tangential and oblique modes — whose frequencies depend on the room dimensions — can produce coloration problems when they cluster.&lt;/p>
&lt;p>Classical design criteria, such as those of &lt;strong>Bolt&lt;/strong>, &lt;strong>Bonello&lt;/strong> and &lt;strong>Louden&lt;/strong>, focus on avoiding modal clustering and propose optimal geometric ratios for rectangular rooms. However, these approaches have a major limitation: they do not consider crucial factors such as the position of the sound source and the receiver, and they are restricted to simple geometries.&lt;/p>
&lt;h3 id="methodology-and-software-development">&lt;strong>Methodology and Software Development&lt;/strong>
&lt;/h3>&lt;p>The developed tool combines a two-stage optimization process.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Initial Search:&lt;/strong> First, the software performs a rapid search on rectangular parallelepipeds using the classical modal superposition (MS) method to identify the most promising initial geometric proportions.&lt;/li>
&lt;li>&lt;strong>Refinement and Optimization:&lt;/strong> Then, it refines the search by generating random planar contours with enforced symmetry and applies the &lt;strong>Frequency-Domain Finite Element Method (FD-FEM)&lt;/strong> to evaluate the acoustic merit of complex geometries. This method is more accurate than modal superposition for non-rectangular geometries.&lt;/li>
&lt;/ol>
&lt;p>&lt;img src="https://dibernardo.netlify.app/p/acoustic-modal-response-optimization-for-small-rooms-with-genetic-algorithms/geom.PNG"
width="663"
height="353"
srcset="https://dibernardo.netlify.app/p/acoustic-modal-response-optimization-for-small-rooms-with-genetic-algorithms/geom_hu10103050829635732771.PNG 480w, https://dibernardo.netlify.app/p/acoustic-modal-response-optimization-for-small-rooms-with-genetic-algorithms/geom_hu14036568945277152459.PNG 1024w"
loading="lazy"
alt="Geometry generator showing a valid geometry (left) and an INVALID one (right)"
class="gallery-image"
data-flex-grow="187"
data-flex-basis="450px"
>&lt;/p>
&lt;p>To quantify acoustic performance, a combined figure of merit is used: the &lt;strong>Mean Sound Field Deviation (MSFD)&lt;/strong>. This metric integrates two key parameters:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Magnitude Deviation (MD):&lt;/strong> Measures how flat the frequency response is at a specific position.&lt;/li>
&lt;li>&lt;strong>Spatial Deviation (SD):&lt;/strong> Measures the variation of magnitude across the listening area.&lt;/li>
&lt;/ul>
&lt;p>The tool includes a graphical user interface (GUI) in &lt;strong>PyQt5&lt;/strong> that allows the user to define dimensions, margins, and source/receiver positions, and to visualize results and optimized geometries.&lt;/p>
&lt;p>&lt;img src="https://dibernardo.netlify.app/p/acoustic-modal-response-optimization-for-small-rooms-with-genetic-algorithms/gui.PNG"
width="927"
height="911"
srcset="https://dibernardo.netlify.app/p/acoustic-modal-response-optimization-for-small-rooms-with-genetic-algorithms/gui_hu10660350233230319476.PNG 480w, https://dibernardo.netlify.app/p/acoustic-modal-response-optimization-for-small-rooms-with-genetic-algorithms/gui_hu7665759294953434962.PNG 1024w"
loading="lazy"
alt="Screenshot of the program GUI"
class="gallery-image"
data-flex-grow="101"
data-flex-basis="244px"
>&lt;/p>
&lt;h3 id="results-and-conclusions">&lt;strong>Results and Conclusions&lt;/strong>
&lt;/h3>&lt;p>Case studies on three reference control-room volumes showed &lt;strong>MSFD improvements of up to 5 dB&lt;/strong> compared to the baseline design. The results demonstrate that:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Impact of Margins:&lt;/strong> As the available design space for optimization increases, better results are obtained, improving the overall response by up to 3 dB. This improvement is observed mainly in the Magnitude Deviation (MD).&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="https://dibernardo.netlify.app/p/acoustic-modal-response-optimization-for-small-rooms-with-genetic-algorithms/margenes.PNG"
width="769"
height="521"
srcset="https://dibernardo.netlify.app/p/acoustic-modal-response-optimization-for-small-rooms-with-genetic-algorithms/margenes_hu7235455855802676823.PNG 480w, https://dibernardo.netlify.app/p/acoustic-modal-response-optimization-for-small-rooms-with-genetic-algorithms/margenes_hu1596749676858920027.PNG 1024w"
loading="lazy"
alt="Optimization result varying the margins"
class="gallery-image"
data-flex-grow="147"
data-flex-basis="354px"
>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Complex Geometries:&lt;/strong> Increasing the number of walls in a complex geometry produces solutions superior to simple rectangular parallelepipeds, with a mean difference of 1.3 dB in the merit factor. The optimization process does not yield a single solution but a variety of geometries that present a minimum MSFD.&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="https://dibernardo.netlify.app/p/acoustic-modal-response-optimization-for-small-rooms-with-genetic-algorithms/complex.PNG"
width="1056"
height="484"
srcset="https://dibernardo.netlify.app/p/acoustic-modal-response-optimization-for-small-rooms-with-genetic-algorithms/complex_hu17276317947581166062.PNG 480w, https://dibernardo.netlify.app/p/acoustic-modal-response-optimization-for-small-rooms-with-genetic-algorithms/complex_hu260113823065011408.PNG 1024w"
loading="lazy"
alt="Optimization result varying the number of walls to generate"
class="gallery-image"
data-flex-grow="218"
data-flex-basis="523px"
>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Comparison with Traditional Criteria:&lt;/strong> A complex optimized geometry outperformed rooms dimensioned according to classic criteria by Bolt, Louden and Cox. Although these criteria are effective and computationally free, the software’s ability to model complex geometries and consider the locations of sources and receivers provides a superior condition.&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="https://dibernardo.netlify.app/p/acoustic-modal-response-optimization-for-small-rooms-with-genetic-algorithms/compare.PNG"
width="882"
height="437"
srcset="https://dibernardo.netlify.app/p/acoustic-modal-response-optimization-for-small-rooms-with-genetic-algorithms/compare_hu6871012066806431324.PNG 480w, https://dibernardo.netlify.app/p/acoustic-modal-response-optimization-for-small-rooms-with-genetic-algorithms/compare_hu17032096468667991809.PNG 1024w"
loading="lazy"
alt="Comparison between classical literature results and our optimizers solution"
class="gallery-image"
data-flex-grow="201"
data-flex-basis="484px"
>&lt;/p>
&lt;p>The study concludes that the software is an effective tool for modal acoustic optimization. Future improvements are suggested, such as implementing more advanced optimization algorithms — for example, genetic algorithms — to reduce computation time and increase process efficiency.&lt;/p>
&lt;p>A detailed analysis of the development of this algorithm is available in the following &lt;a class="link" href="https://drive.google.com/file/d/1bFloyBC-lmMt_NCkeMwyjXit8-o1ZzsZ/view?usp=sharing" target="_blank" rel="noopener"
>paper&lt;/a>.&lt;/p></description></item><item><title>Automatic Workout Routine Generator</title><link>https://dibernardo.netlify.app/p/automatic-workout-routine-generator/</link><pubDate>Wed, 17 Apr 2024 00:00:00 +0000</pubDate><guid>https://dibernardo.netlify.app/p/automatic-workout-routine-generator/</guid><description>&lt;h1 id="automatic-workout-routine-generator">Automatic Workout Routine Generator
&lt;/h1>&lt;p>This project was the final project asignment for the Algoritmos y Programación II on UNTREF. The idea of the application is to function as a smart workout planification, where the user input certain criterias and the program establish the best workout routine to maximice the users preference. The program was written in the Go programming language.&lt;/p>
&lt;h2 id="data-management">Data Management
&lt;/h2>&lt;p>This course does not focues on databases, so we choose to use a CSV to simulate a database. This file contains all the information of the different routines and the differente attributes. This serve as a presistency file wheras all the logic is handle by the program.&lt;/p>
&lt;p>Different exercises are categorized by tematics. There are two entities on the program that are represented as structs in Go, this are the Exercise and the Routines.&lt;/p>
&lt;h3 id="exercise">Exercise
&lt;/h3>&lt;p>All the exercises have the following attributes:&lt;/p>
&lt;ul>
&lt;li>Name: Name of the exercise.&lt;/li>
&lt;li>Description: Detailed description of the exercise.&lt;/li>
&lt;li>Duration: Estimated duration of the exercise.&lt;/li>
&lt;li>Calories: Number of calories burned during the exercise.&lt;/li>
&lt;li>Type: Type of exercise (e.g., cardio, strength, flexibility).&lt;/li>
&lt;li>Muscle Group: Muscle group targeted by the exercise.&lt;/li>
&lt;li>Points: Points assigned to the exercise for each of its types.&lt;/li>
&lt;li>Difficulty: Difficulty level of the exercise.&lt;/li>
&lt;/ul>
&lt;h3 id="routines">Routines
&lt;/h3>&lt;p>All the routines are a collection of exercises. This are paresed as a linked list of exercise. Aside from this, the routins have the following attributes:&lt;/p>
&lt;ul>
&lt;li>Name: Name of the routine.&lt;/li>
&lt;li>Exercises: String that stores the IDs of the exercises in the routine, separated by commas.&lt;/li>
&lt;li>AvailableExercises: Linked list of the exercises available for creating the routine.&lt;/li>
&lt;/ul>
&lt;h2 id="algorithm">Algorithm
&lt;/h2>&lt;p>The idea is to maximice different parameters, for example, maximum calories burnt in the least ammount of time, or the minimum duration for this muscle group or type of exercise. To find the best solutions based on the existing data we propose a dynamic programming algorithm that searches for all the posiblities from the data and find the maximum or minimum according to the specifications of the user. The DP apprach uses memory to avoid recalculation combinantions that already were computed, with this optimization the algorithm is fast enough that can generate the routines in miliseconds (with the test dataset under evaluation).&lt;/p>
&lt;h2 id="user-interface">User Interface
&lt;/h2>&lt;p>At the moment, the programm is designed to be used form the terminal as a CLI application. The user can crear an exersice and a rutine, list the avaliable optionas, and generate a custom routine base on the specifications that he choose.&lt;/p>
&lt;p>This is the first iteration of the project and it is fully functional but we plan to create a custom GUI to be user friendly, but for this proposse it will be better to use a different framework and use this GO application as the backend for a web or app service.&lt;/p>
&lt;h2 id="conclusions">Conclusions
&lt;/h2>&lt;p>With this project I solidify my knowledege on programming topics like data structurs and algorithms because we used the theory seen in class and applied it to a real case scenario. Also it help me to get used to the Go langeage and it became a leangauge that I really enjoy coding on it. The code for this project is avaliable on this &lt;a class="link" href="https://github.com/MatiasDiBernardo/Workout-routine-generator" target="_blank" rel="noopener"
>repository&lt;/a>.&lt;/p></description></item><item><title>Z-Plane Visualizer</title><link>https://dibernardo.netlify.app/p/z-plane-visualizer/</link><pubDate>Sat, 12 Aug 2023 00:00:00 +0000</pubDate><guid>https://dibernardo.netlify.app/p/z-plane-visualizer/</guid><description>&lt;img src="https://dibernardo.netlify.app/p/z-plane-visualizer/frontz.PNG" alt="Featured image of post Z-Plane Visualizer" />&lt;p>On the &lt;em>Procesamiento Digital de Señales&lt;/em> (Digital Signal Processing) course at UNTREF, we explore the Z-Plane for filtering design with discrete variables. During the class, the professor introduced a tool built in MATLAB that visualizes the magnitude and phase plots in relation to the positions of zeros and poles on the Z-Plane. Inspired by this, I decided to recreate this tool in Python.&lt;/p>
&lt;p>Leveraging my experience with the PyGame library, I was able to build a real-time application that allows for the movement of poles and zeros, enabling users to see how the transfer function changes in real time.&lt;/p>
&lt;h2 id="how-it-works">How It Works
&lt;/h2>&lt;p>First, I map the pixel positions on the Z-Plane to coordinates according to the unit circle representation. Then, I construct the transfer function, where each zero $z_{n}$ is a term in the numerator, and each pole $z_{i}$ is a term in the denominator. With the transfer function $H(z)$, I can plot both the magnitude and phase plots, which are also mappings from the normalized response into a space within the app.&lt;/p>
$$
H(z) = \frac{\sum_{n=0}^{N} (z - z_{n})}{\sum_{i=0}^{N} (z - z_{i})}
$$&lt;p>Each frame recalculates the transfer function. The program performs efficiently because I store the zeros and poles in arrays, enabling faster computations with the help of numpy, which is already highly optimized. This allows real-time visualizations of the changes and provides a more intuitive understanding of the behavior of the Z-Plane. The following code snippet shows how the transfer function is computed using complex exponentials:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">e&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">w&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">root&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="n">j&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">w&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">root&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">transfer_function&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">zeros&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">poles&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">w&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">linspace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">pi&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">pi&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">RES&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">zero&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">zeros&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">num&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">w&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">zero&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">pole&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">poles&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">den&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">w&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">pole&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">H_z&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">num&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">den&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">mag&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">abs&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">H_z&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ang&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">angle&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">H_z&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">mag&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ang&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>This project is designed as educational material, providing students with a practical tool to better understand the interactions between poles and zeros in the Z-Plane. It is not intended as a professional filter design tool.&lt;/p>
&lt;h2 id="functionality">Functionality
&lt;/h2>&lt;p>The application has the following functionality:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>Display and move poles/zeros&lt;/strong>: The user can select and choose the position of zero or pole in the Z plane. With the symmetry option active, all the poles and zeros selected or moved are attached to their symmetric par with respect to the imaginary axes.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Order&lt;/strong>: The order of the poles/zeros can be modified with the mouse wheel up to increse or down to decrease. It supports up to order 4. The color of the zero/pole change with the order.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Information&lt;/strong>: Holding the cursor over a pole or zero displays information about the position, symmetry and order.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Zoom&lt;/strong>: With the plus and minus symbols, the user can zoom in and out of the Z plane.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Delete&lt;/strong>: The trash bin symbol clears all the poles and zeros from the plane, and the user can also delete specific poles or zeros by pressing right click on them.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Magnitude Graph&lt;/strong>: The magnitude spectrum displayed in the app is normalized. This decision helps to keep the focus on the shape of the magnitude and it makes sure that the graph is visually meaningful for the user. The downside is that the difference in peak values is not captured.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Phase Graph&lt;/strong>: The phase is displayed unwrapped between $-\pi$ and $\pi$.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="demo">Demo
&lt;/h2>&lt;p>Here is a quick demo of the app in action:&lt;/p>
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
&lt;iframe src="https://player.vimeo.com/video/1045497647" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="vimeo video" webkitallowfullscreen mozallowfullscreen allowfullscreen>&lt;/iframe>
&lt;/div>
&lt;p>The source code for this project can be found on this &lt;a class="link" href="https://github.com/MatiasDiBernardo/Z-Plane_Visualizer" target="_blank" rel="noopener"
>repo&lt;/a>.&lt;/p></description></item><item><title>AI learns to play 2048 game</title><link>https://dibernardo.netlify.app/p/ai-learns-to-play-2048-game/</link><pubDate>Fri, 17 Feb 2023 00:00:00 +0000</pubDate><guid>https://dibernardo.netlify.app/p/ai-learns-to-play-2048-game/</guid><description>&lt;img src="https://dibernardo.netlify.app/p/ai-learns-to-play-2048-game/game_img.jpg" alt="Featured image of post AI learns to play 2048 game" />&lt;p>I used this project as an introduction to Reinforcement Learning. Having mostly worked with supervised and unsupervised learning, I wanted to start with a small, simple project to quickly grasp the main ideas and create something fun. I followed this &lt;a class="link" href="https://youtu.be/L8ypSXwyBds" target="_blank" rel="noopener"
>YouTube video&lt;/a> as a reference, which explains how to use Reinforcement Learning (RL) to train a model capable of playing the snake game. To make it more challenging, I applied the same network to the 2048 game.&lt;/p>
&lt;h2 id="code">Code
&lt;/h2>&lt;p>The code has three main components:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>The Game&lt;/strong>: Implements the game logic and the graphical user interface (GUI).&lt;/li>
&lt;li>&lt;strong>Agent&lt;/strong>: Controls the gameplay.&lt;/li>
&lt;li>&lt;strong>AI Model&lt;/strong>: A neural network that learns how to play and guides the agent.&lt;/li>
&lt;/ul>
&lt;h3 id="game-state">Game State
&lt;/h3>&lt;p>I modeled the game state as a 4x4 matrix representing the board. The actions in the game are represented by a vector, with the following possibilities:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Left&lt;/strong>: [1, 0, 0, 0]&lt;/li>
&lt;li>&lt;strong>Right&lt;/strong>: [0, 1, 0, 0]&lt;/li>
&lt;li>&lt;strong>Up&lt;/strong>: [0, 0, 1, 0]&lt;/li>
&lt;li>&lt;strong>Down&lt;/strong>: [0, 0, 0, 1]&lt;/li>
&lt;/ul>
&lt;h3 id="reward">Reward
&lt;/h3>&lt;p>The RL model works with rewards to quantify when the agent performs well or poorly. Initially, I defined the following rewards:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>+10 points&lt;/strong>: When the agent doubles the points. This is crucial because, in 2048, points increase exponentially.&lt;/li>
&lt;li>&lt;strong>-10 points&lt;/strong>: When the game is lost. This serves as a straightforward negative reward.&lt;/li>
&lt;/ul>
&lt;p>Initially, the model showed slow improvement. To address this, I added an additional reward:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>+2 points&lt;/strong>: When points are increased. This reward incentivizes actions that maximize board clearance and progress.&lt;/li>
&lt;/ul>
&lt;h2 id="how-the-model-works">How the Model Works
&lt;/h2>&lt;p>The model is a simple linear neural network. It takes the game state as input and predicts the best next action to maximize the reward.&lt;/p>
&lt;p>Rewards are managed using a technique called Q-Learning. A &lt;em>Q Value&lt;/em> represents the quality of a decision based on the loss function. The loss function is derived from the &lt;em>Bellman Equation&lt;/em>:&lt;/p>
$$
NewQ(s, a) = Q(s, a) + \alpha [R(s, a) + \lambda \, \text{max}Q'(s', a') - Q(s, a)]
$$&lt;p>Where:&lt;/p>
&lt;ul>
&lt;li>$Q(s, a)$: The &lt;em>Q Value&lt;/em> for a specific state and action.&lt;/li>
&lt;li>$\alpha$: Learning rate.&lt;/li>
&lt;li>$R(s, a)$: Reward for a specific state and action.&lt;/li>
&lt;li>$\lambda$: Discount rate.&lt;/li>
&lt;li>$\text{max}Q&amp;rsquo;(s&amp;rsquo;, a&amp;rsquo;)$: Maximum expected future reward.&lt;/li>
&lt;/ul>
&lt;h2 id="experiments-and-results">Experiments and Results
&lt;/h2>&lt;h3 id="random-test-as-a-baseline">Random Test as a Baseline
&lt;/h3>&lt;p>To establish a baseline, I tested the average score achievable by taking random actions. After 1,000 iterations, the average score was &lt;strong>170&lt;/strong>, far below the 2048 points needed to win the game.&lt;/p>
&lt;h3 id="initial-results">Initial Results
&lt;/h3>&lt;p>My initial attempts were discouraging. The model performed worse than random movements. Here are some early results:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Game 1,000&lt;/strong> | Score: 208 | Record: 416 | Mean Score: 200 | Reward: 640&lt;/li>
&lt;li>&lt;strong>Game 1,000&lt;/strong> | Score: 116 | Record: 346 | Mean Score: 161 | Reward: 310&lt;/li>
&lt;li>&lt;strong>Game 1,000&lt;/strong> | Score: 112 | Record: 348 | Mean Score: 146 | Reward: 320&lt;/li>
&lt;/ol>
&lt;p>In these attempts, the agent developed a suboptimal strategy of filling the board before increasing points.&lt;/p>
&lt;h3 id="improvements">Improvements
&lt;/h3>&lt;p>After experimenting with the reward parameters, I focused on the exploration phase. Initially, the &lt;em>exploration games&lt;/em> parameter, which randomly picks moves, was set to 25 games. Increasing this parameter allowed the agent to explore more strategies, leading to better results:&lt;/p>
&lt;ol start="4">
&lt;li>&lt;strong>Game 1,000&lt;/strong> | Score: 478 | Record: 478 | Mean Score: 230&lt;/li>
&lt;li>&lt;strong>Game 1,000&lt;/strong> | Score: 514 | Record: 964 | Mean Score: 382&lt;/li>
&lt;/ol>
&lt;p>As the model improved, I extended the training to more games:&lt;/p>
&lt;ol start="6">
&lt;li>&lt;strong>Game 3,796&lt;/strong> | Score: 770 | Record: 1,366 | Mean Score: 469&lt;/li>
&lt;li>&lt;strong>Game 4,852&lt;/strong> | Score: 631 | Record: 1,462 | Mean Score: 483&lt;/li>
&lt;/ol>
&lt;p>Finally, with 200 exploration games and 5,000 training games, the results were as follows:&lt;/p>
&lt;ol start="8">
&lt;li>&lt;strong>Game 5,000&lt;/strong> | Score: 840 | Record: 1,678 | Mean Score: 512&lt;/li>
&lt;/ol>
&lt;p>Although the model didn&amp;rsquo;t beat the game, I was satisfied with the progress. I believe that with longer training (the final run lasted 4 hours) and additional network layers, it would be possible to win the game using this architecture.&lt;/p>
&lt;h2 id="demo">Demo
&lt;/h2>&lt;p>Here is a demo of the application, showcasing the agent&amp;rsquo;s learning process:&lt;/p>
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
&lt;iframe src="https://player.vimeo.com/video/1045495533" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="vimeo video" webkitallowfullscreen mozallowfullscreen allowfullscreen>&lt;/iframe>
&lt;/div>
&lt;p>I implemented keybindings to control the game&amp;rsquo;s speed, providing three options:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Fast&lt;/strong>: For rapid training.&lt;/li>
&lt;li>&lt;strong>Slow&lt;/strong>: To observe and analyze the agent&amp;rsquo;s progress and mistakes.&lt;/li>
&lt;li>&lt;strong>Medium&lt;/strong>: Rarely used.&lt;/li>
&lt;/ul>
&lt;p>The complete code for this project is available in this &lt;a class="link" href="https://github.com/MatiasDiBernardo/RF_2048-game" target="_blank" rel="noopener"
>repository&lt;/a>.&lt;/p></description></item><item><title>Time Scale Modification Algorithms</title><link>https://dibernardo.netlify.app/p/time-scale-modification-algorithms/</link><pubDate>Sat, 11 Feb 2023 00:00:00 +0000</pubDate><guid>https://dibernardo.netlify.app/p/time-scale-modification-algorithms/</guid><description>&lt;img src="https://dibernardo.netlify.app/p/time-scale-modification-algorithms/tsm.PNG" alt="Featured image of post Time Scale Modification Algorithms" />&lt;p>Time scale modifications algorithms are used to speed up or slow down the reproduction velocity of an audio. When you change the sample rate of an audio, the velocity changes but it also changes the pitch (when the audio is speed up it sounds highier pitch). There are different algorithms that change the velocity of the audio but mantain the pitch.&lt;/p>
&lt;p>The main reference for this study is the following article, where all the different algorithms are describe in detail.&lt;/p>
&lt;blockquote>
&lt;p>A Review of Time-Scale Modification of Music Signals.&lt;br>
— &lt;cite>Jonathan Driedger and Meinard Müller&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>&lt;/cite>&lt;/p>
&lt;/blockquote>
&lt;h2 id="algorithm-comparison">Algorithm comparison
&lt;/h2>&lt;p>There are two main algorithms, the &lt;em>Overlap-and-add&lt;/em> (OLA) and the &lt;em>Phase Vocoder&lt;/em> (PV). Both achieve good results under different signals and conditions. For this, a final implementation using &lt;em>Harmonic Percussion Separation&lt;/em> (HPS) combines both algorithms and achiving the best results.&lt;/p>
&lt;h3 id="ola">OLA
&lt;/h3>&lt;p>This method works on time domain and overlap sections of the audio (windows) and rearange it to achive a certain desire change on speed. This method works well for percussive signals, but it introduces artifacts when used with harmonic or tonal signals.&lt;/p>
&lt;h3 id="pv">PV
&lt;/h3>&lt;p>This method works on frequency domain, and it combines chunks of audio in the frequency domain to achieve the desire change in time. This uses the phase vocoder principle to propagate the phase between the windows, this grantice the continuity of when applied to harmonic signals. On the contrary, it does not work for percussive signals becouse the phase propagation process eliminate the transients in the signals.&lt;/p>
&lt;p>I created visualizations using &lt;em>Manim&lt;/em> to enhance my class presentation. The first video demonstrates how the PV algorithm aligns windows to ensure smooth transitions in the generated signal over time. To achieve this, a Gaussian window is applied, which maintains continuity and smoothness, even at the start and end of the sequence.&lt;/p>
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
&lt;iframe src="https://player.vimeo.com/video/1045495557" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="vimeo video" webkitallowfullscreen mozallowfullscreen allowfullscreen>&lt;/iframe>
&lt;/div>
&lt;p>The second video showcases the effects of applying the PV algorithm to a signal containing transients.&lt;/p>
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
&lt;iframe src="https://player.vimeo.com/video/1045495634" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="vimeo video" webkitallowfullscreen mozallowfullscreen allowfullscreen>&lt;/iframe>
&lt;/div>
&lt;p>As predicted by theory, the transients vanish because the PV algorithm disrupts the vertical phase alignment. While these examples utilize idealized signals, they effectively demonstrate the key strengths and limitations of the algorithm.&lt;/p>
&lt;h3 id="hps">HPS
&lt;/h3>&lt;p>To use both methods with their ideal signals, the HPS algorithms is used. This algorithm separete the signal into the harmonics and the percussive parts. It works by comparing the continuty of the signal in the STFT representation and using a filter to compare vertical versus horizontal presence on the spectrogram. With a threshold, a binary mask can be define over the spectrogram to separete the percussive parts from the harmoincs sections.&lt;/p>
&lt;h2 id="results">Results
&lt;/h2>&lt;p>We succesfully implement all the algorithms and compare them, verifying the theortical contents presented on the referenca article. In the process, we develope the toolkit to use this algorithms with the python programming language. All the code is avaliable on this &lt;a class="link" href="https://github.com/MatiasDiBernardo/TSM_Toolkit" target="_blank" rel="noopener"
>repo&lt;/a>&lt;/p>
&lt;h2 id="academic-presentation">Academic Presentation
&lt;/h2>&lt;p>The study was preseented with my classmates on the &lt;em>JAAS&lt;/em> (Jornadas de Acustica, Audio y Sonido). The main ideas and conclusions were preseneted on the conference. In the following repoert there is all the details and anlysis done for this proyect (in spanish).&lt;/p>
&lt;blockquote>
&lt;p>ALGORITMOS DE MODIFICACIÓN DE ESCALA TEMPORAL.&lt;br>
— &lt;cite>Matías Di Bernardo; Matías Vereertbruhggen; Sebastían Carro &lt;sup id="fnref:2">&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref">2&lt;/a>&lt;/sup>&lt;/cite>&lt;/p>
&lt;/blockquote>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>A Review of Time-Scale Modification of Music Signal &lt;a class="link" href="https://www.researchgate.net/publication/295082364_A_Review_of_Time-Scale_Modification_of_Music_Signals" target="_blank" rel="noopener"
>paper&lt;/a>.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:2">
&lt;p>JAAS 2023 - Algoritmos de Modificación de Escala Temporal &lt;a class="link" href="https://drive.google.com/file/d/12kPB3qBjczyx7X2XV3ZpBDo1GDO2u4qR/view?usp=sharing" target="_blank" rel="noopener"
>paper&lt;/a>.&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description></item></channel></rss>