Matt TytelMatt Tytel - personal website
https://tytel.org/
Thu, 21 Apr 2022 13:25:53 +0100Thu, 21 Apr 2022 13:25:53 +0100Jekyll v3.8.6New Synth in the Works<p><a href="https://vital.audio">I’m working on a new synth!</a></p>
Mon, 19 Feb 2018 12:30:00 +0000
https://tytel.org/blog/2018/02/19/new-synth/
https://tytel.org/blog/2018/02/19/new-synth/blogdevblogStickers!<p>I got some stickers printed of the new logo! If you PayPal me $5 at
<a href="mailto:[email protected]">[email protected]</a> and mention the
stickers and include your address I’ll send you one :D</p>
<p><img src="/static/images/blog/stickers.jpg" alt="Helm Stickers" /></p>
<p>Since the synth is free this is a way of generating some (small) amount of
monetary support.</p>
<p>I got these die cut stickers through Sticker Mule. They make super high quality
vinyl stickers that are water/sun/scratch resistant. They can even go through
the dishwasher.</p>
<p>Dimensions are about 3in x 3in.</p>
Mon, 01 Jun 2015 13:30:00 +0100
https://tytel.org/blog/2015/06/01/stickers/
https://tytel.org/blog/2015/06/01/stickers/blogdevbloghelmExperiments with Material Design<p>I’ve done a lot of UI changes with <a href="https://github.com/mtytel/helm">Helm</a> lately based off this
new design idea called <a href="https://www.google.com/design/spec/material-design/">Material Design</a>. You should go check
it out yourself, but the basic idea is you take flat UI design and organize
it in layers like pieces of paper. The result is a combination of bold colors
and skeuomorphic shadows.</p>
<p>The shadows gave me pause, at first it felt like the 90’s again where you slap
a drop shadow on everything. After looking through Google’s examples and
applying many of their ideas to Helm, I have to say that I’m now a born-again
drop shadow believer. They make colors really pop and are a great way to
emphasize how important certain elements are.</p>
<p><img src="/static/images/blog/shadows.png" alt="Helm Shadows" /></p>
<p><img src="/static/images/blog/shadows2.png" alt="Helm Shadows" /></p>
<p>Google’s design doc is pretty funny when they mention <em>how</em> to implement the
shadows. They say you shouldn’t approximate the shadows with gradients or
images. Instead they say, render the shadows with a 3d graphics engine. I
<em>guess</em> I get it, when you have multiple layers overlapping the gradients won’t
look right, but I don’t know many people who can hire a team of developers
to develop a rendering engine just so the shadows look accurate!</p>
<p>After the shadows, the <a href="https://www.google.com/design/spec/style/color.html">color</a> section has been the most
help in designing Helm. If you get overwhelmed with all the combinations of
possible color palettes like I do, then using Google’s method for picking
colors is a good place to start. They hit a good balance of restricting the
colors enough so whatever combination you pick should look decent while also
having enough colors and shades so not every app using this method will look
the same.</p>
<p>If you care about design and want some guidelines to follow I highly recommend
giving the whole <a href="https://www.google.com/design/spec/material-design/">Material Design</a> doc a read. They hit on a
lot of other topics like animation, layout and widgits that all have decent
insight on what looks good and what doesn’t.</p>
Sun, 17 May 2015 13:30:00 +0100
https://tytel.org/blog/2015/05/17/material-design/
https://tytel.org/blog/2015/05/17/material-design/blogdevbloghelmfeaturesRebranding - Helm<p>I’m rebranding Twytch! First the name: Twytch was a little
too similar to the video streaming service ‘Twitch’ and so after playing around
with some logos and names I’ve decided on ‘Helm’. It conveys control, a common
theme in synthesizers, it’s short and easy to remember, and I can’t find other
software that uses the name except for an emacs plugin.</p>
<p>The other part is a new icon/logo. Graphic design is something I spend a lot of
time on but doesn’t come natural to me. After many hours I think I have a logo
I’m happy with. Here’s the development in reverse chronological order.</p>
<h3 id="i-think-its-more-cute-than-cool-and-im-good-with-that"><strong>I think it’s more cute than cool and I’m good with that:</strong></h3>
<p><img src="/static/images/blog/helm_logo6.png" alt="Helm Logo 6" /></p>
<h3 id="got-to-helmet-stage-but-didnt-like-the-shadows-and-square-nose"><strong>Got to ‘helmet’ stage, but didn’t like the shadows and square nose:</strong></h3>
<p><img src="/static/images/blog/helm_logo5.png" alt="Helm Logo 5" /></p>
<h3 id="flipped-it-its-almost-a-helmet-and-less-of-a-plug"><strong>Flipped it, it’s almost a helmet and less of a plug:</strong></h3>
<p><img src="/static/images/blog/helm_logo4.png" alt="Helm Logo 4" /></p>
<h3 id="i-like-the-cuts-of-the-yellow-circle-being-align-with-the-blue-circle"><strong>I like the cuts of the yellow circle being align with the blue circle:</strong></h3>
<p><img src="/static/images/blog/helm_logo3.png" alt="Helm Logo 3" /></p>
<h3 id="getting-away-from-that-phallic-design"><strong>Getting away from that phallic design:</strong></h3>
<p><img src="/static/images/blog/helm_logo2.png" alt="Helm Logo 2" /></p>
<h3 id="trying-a-different-flat-bold-outline-style"><strong>Trying a different flat, bold, outline style:</strong></h3>
<p><img src="/static/images/blog/helm_logo1.png" alt="Helm Logo 1" /></p>
<h3 id="first-design-its-supposed-to-be-a-plug-pretty-phallic-though"><strong>First design, it’s supposed to be a plug. Pretty phallic though:</strong></h3>
<p><img src="/static/images/blog/helm_logo0.png" alt="Helm Logo 0" /></p>
Fri, 08 May 2015 13:30:00 +0100
https://tytel.org/blog/2015/05/08/rebranding-to-helm/
https://tytel.org/blog/2015/05/08/rebranding-to-helm/blogdevbloghelmUnexpected Optimization #2: fixed point arithmetic<p>I’ve wanted to add a ‘unison’ feature to Twytch for a while but without a
significant performance hit. Unison works by having many oscillators per voice
so improving the oscillator CPU usage was a must.</p>
<p>The way many oscillator implementations work is by having a ‘phasor’ which is
a phase value that cycles through the values from 0 to 1. When the phase value
is 0, we are at the beginning of the waveform, 0.5 we’re half way through and
when we get to 1, we’re at the end and we set the value back to 0. Checking if
we have to wrap the phase every sample for every oscillator can get pretty
costly. One way to improve this is by using the modf function instead of a
comparison and an if/else branch but it still is has a relatively large CPU
hit.</p>
<figure class="highlight"><pre><code class="language-c--" data-lang="c++"><span class="kt">int</span> <span class="n">table_size</span> <span class="o">=</span> <span class="mi">2048</span><span class="p">;</span>
<span class="kt">double</span> <span class="n">phase</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span>
<span class="kt">double</span> <span class="n">phase_diff</span> <span class="o">=</span> <span class="p">...;</span> <span class="c1">// Usually we don't know what value this is.</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">samples</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
<span class="n">phase</span> <span class="o">+=</span> <span class="n">phase_diff</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">phase</span> <span class="o">>=</span> <span class="mf">1.0</span><span class="p">)</span>
<span class="n">phase</span> <span class="o">-=</span> <span class="mf">1.0</span><span class="p">;</span>
<span class="c1">// Lookup value with phase. No interpolation for this example.</span>
<span class="kt">int</span> <span class="n">index</span> <span class="o">=</span> <span class="n">phase</span> <span class="o">*</span> <span class="n">table_size</span><span class="p">;</span>
<span class="n">output_buffer</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">lookup</span><span class="p">[</span><span class="n">index</span><span class="p">];</span>
<span class="p">}</span>
<span class="c1">// Alternatively with modf which is slightly more efficient.</span>
<span class="kt">double</span> <span class="n">integral_part</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">samples</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
<span class="n">phase</span> <span class="o">=</span> <span class="n">modf</span><span class="p">(</span><span class="n">phase</span> <span class="o">+</span> <span class="n">phase_diff</span><span class="p">,</span> <span class="o">&</span><span class="n">integral_part</span><span class="p">);</span>
<span class="c1">// Lookup value with phase. No interpolation for this example.</span>
<span class="kt">int</span> <span class="n">index</span> <span class="o">=</span> <span class="n">phase</span> <span class="o">*</span> <span class="n">table_size</span><span class="p">;</span>
<span class="n">output_buffer</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">lookup</span><span class="p">[</span><span class="n">index</span><span class="p">];</span>
<span class="p">}</span></code></pre></figure>
<p>There’s another solution though and it’s using ‘fixed-point’ instead of
‘floating-point’ numbers. Floating point numbers can represent a crazy large
range of numbers but for our phasor implementation we only care about number
between 0 and 1. What we can do is use an unsigned integer type to represent
these values. 0 will still remain the beginning of our waveform, but
UINT_MAX will represent the end of our waveform. Cool thing about integers
is that when we add to our phase and go past UINT_MAX, we get the wrapping
for free! Another benefit is if our wave lookup table is a power of two, we
can get the lookup index by bit shifting our current phase down which is
another (albeit small) performance improvement.</p>
<figure class="highlight"><pre><code class="language-c--" data-lang="c++"><span class="kt">int</span> <span class="n">table_bits</span> <span class="o">=</span> <span class="mi">11</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">shift</span> <span class="o">=</span> <span class="mi">8</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">)</span> <span class="o">-</span> <span class="n">table_bits</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">phase</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">phase_diff</span> <span class="o">=</span> <span class="p">...;</span> <span class="c1">// Usually we don't know what value this is.</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">samples</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// Automatially wraps :D</span>
<span class="n">phase</span> <span class="o">+=</span> <span class="n">phase_diff</span><span class="p">;</span>
<span class="c1">// One bit shift is more efficient than a multiply and cast I believe.</span>
<span class="kt">int</span> <span class="n">index</span> <span class="o">=</span> <span class="n">phase</span> <span class="o">>></span> <span class="n">shift</span><span class="p">;</span>
<span class="n">output_buffer</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">lookup</span><span class="p">[</span><span class="n">index</span><span class="p">];</span>
<span class="p">}</span></code></pre></figure>
<p>After this improvement I’m would say the DSP is at a releasable efficiency.
Comparing Twytch to other similar synths on the commercial market, it’s in the
middle of the pack. The next thing I’ll be focusing on is improving the UI
efficiency as there are a lot of moving parts in Twytch and most of them are
not CPU friendly.</p>
Fri, 01 May 2015 13:30:00 +0100
https://tytel.org/blog/2015/05/01/unexpected-optimization-02/
https://tytel.org/blog/2015/05/01/unexpected-optimization-02/blogdevblogtwytchoptimizationLong Update<p>Whew, it’s been a while and a lot has changed! I’ve decided to make
<a href="https://github.com/mtytel/twytch">Twytch</a> a free and open source project releasing it under GNU. My new
goal is to make a very accessible free synth that runs on most platforms.
Because of this I’ve cut back a lot of the more experimental features like
glitches in place of more established ones like unison and a powerful
modulation system.</p>
<p>The new modulation system is heavily inspired by Bitwig Studio though I don’t
think they were the original creators of this type of system. I’ll talk more
about how it works in a different post.</p>
<p>I’ve made a bunch of changes to the UI and there’s a lot more coming! I find
going back through the iterations entertaining so I’m posting them all here.
The most recent changes are inspired by <a href="https://www.google.com/design/spec/material-design/">Material Design</a>
which has heavy shadow usage. I used to think drop shadows were pretty
outdated, but when combined with a flat UI, it looks really fresh.</p>
<p>Here are the UI screenshots in reverse chronological order:</p>
<h3 id="material-design-attempt-1-and-new-colors-look-at-dem-shadows"><strong>Material design attempt 1 and new colors. Look at dem shadows:</strong></h3>
<p><img src="/static/images/blog/2015-04-23-screenshot.png" alt="Twytch Screenshot 4-23" /></p>
<h3 id="no-more-borders"><strong>No more borders:</strong></h3>
<p><img src="/static/images/blog/2015-04-14-screenshot.png" alt="Twytch Screenshot 4-14" /></p>
<h3 id="trying-out-some-new-colors"><strong>Trying out some new colors:</strong></h3>
<p><img src="/static/images/blog/2015-04-01-screenshot.png" alt="Twytch Screenshot 4-01" /></p>
<h3 id="im-not-sure-if-i-want-this-entire-synth-to-be-purple"><strong>I’m not sure if I want this entire synth to be purple:</strong></h3>
<p><img src="/static/images/blog/2015-03-20-screenshot.png" alt="Twytch Screenshot 3-20" /></p>
<h3 id="prototyping-widgits"><strong>Prototyping widgits:</strong></h3>
<p><img src="/static/images/blog/2015-01-18-screenshot.png" alt="Twytch Screenshot 1-18" /></p>
Thu, 23 Apr 2015 13:30:00 +0100
https://tytel.org/blog/2015/04/23/long-update/
https://tytel.org/blog/2015/04/23/long-update/blogdevblogtwytchUnexpected Optimization #1: avoiding denormals<p>I’ve been noticing a strange spike in CPU usage while playing
with <a href="https://github.com/mtytel/twytch">Twytch</a>. When a synth voice rings out and is not producing sound
anymore, it is killed and reused later to save CPU cycles. However, there’s
a significant increase in CPU usage right before a voice dies. For a while
this was a mystery, but I was recently reading <a href="https://github.com/vinniefalco/DSPFilters">some filter code in another
project</a> that added a very small alternating current to the input
of the filter. In the comment it said “Hack to prevent denormals”.</p>
<p>A <a href="https://en.wikipedia.org/wiki/Denormal_number">denormal</a> is a type of really small floating point number.
Wikipedia give a better explanation, but in short the structure of floating
point numbers cause the gap from 0 to the smallest positive number to be much
larger than the gap between the two smallest positive numbers. Architectures
compensate for this by setting aside some numbers that are more evenly spaced
really close to zero called “denormal numbers” or “subnormal numbers”. The
problem with this in synth development, is that processing subnormal numbers
is much slower than normal floating point numbers. Since we create really
small numbers any time there’s an exponential decay like in an envelope or a
filter, we need to disable denormals.</p>
<p>The alternative to having denormals is flushing those numbers to zero. Since
these numbers are so small these jumps are imperceptible in an audio signal.
All we have to do is slap an environment variable setting and we should be good
to go! (on some machines)</p>
<figure class="highlight"><pre><code class="language-c--" data-lang="c++"><span class="cp">#include <fenv.h>
</span><span class="c1">// ...</span>
<span class="n">fesetenv</span><span class="p">(</span><span class="n">FE_DFL_DISABLE_SSE_DENORMS_ENV</span><span class="p">);</span></code></pre></figure>
Tue, 10 Feb 2015 12:30:00 +0000
https://tytel.org/blog/2015/02/10/unexpected-optimization-01/
https://tytel.org/blog/2015/02/10/unexpected-optimization-01/blogdevblogtwytchoptimizationUnexpected Optimization #0: at() vs operator[]<p>Writing a soft synth requires a lot of optimization. As I develop
<a href="https://github.com/mtytel/twytch">twytch</a> and the synth engine it’s built on, <a href="https://github.com/mtytel/mopo">mopo</a>, I’ll be
posting many of the optimizations I make, especially nonobvious ones. These
could range from simple things like using one-multiply instead of
two-multiply interpolation:</p>
<figure class="highlight"><pre><code class="language-c--" data-lang="c++"><span class="c1">// These lines compute the same value.</span>
<span class="kt">double</span> <span class="n">one_multiply</span> <span class="o">=</span> <span class="n">from</span> <span class="o">+</span> <span class="n">t</span> <span class="o">*</span> <span class="p">(</span><span class="n">to</span> <span class="o">-</span> <span class="n">from</span><span class="p">);</span> <span class="c1">// 1 multiply and 2 adds</span>
<span class="kt">double</span> <span class="n">two_multiply</span> <span class="o">=</span> <span class="n">t</span> <span class="o">*</span> <span class="n">to</span> <span class="o">+</span> <span class="p">(</span><span class="mi">1</span> <span class="o">-</span> <span class="n">t</span><span class="p">)</span> <span class="o">*</span> <span class="n">from</span><span class="p">;</span> <span class="c1">// 2 multiplies and 2 adds</span></code></pre></figure>
<p>Or could be uglier solutions like embedding assembly instructions in C++.
I’m not a C++ optimization expert yet, so some of these things may be more
obvious than others.</p>
<p>This first unexpected optimization concerns accessing values from std::vector.
Consider these two methods of element access:</p>
<figure class="highlight"><pre><code class="language-c--" data-lang="c++"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o"><</span><span class="kt">double</span><span class="o">></span> <span class="n">vect</span> <span class="o">=</span> <span class="p">...;</span>
<span class="kt">double</span> <span class="n">one</span> <span class="o">=</span> <span class="n">vect</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
<span class="kt">double</span> <span class="n">two</span> <span class="o">=</span> <span class="n">vect</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span></code></pre></figure>
<p>There is a significant difference between the two: at() does boundary checking
while operator[] does not. You don’t normally notice this performance
difference, but I was running it once per audio sample for every single
component which totaled in the millions per second.</p>
<p>Now why would I use at() instead of operator[] in
the first place? The way mopo sets up polyphony is that all the module
instances in each voice share a list of input pointers. For example, every
Filter instance in each poice has a pointer to the same std::vector. Using at()
on a pointer to std::vector is much easier to read than using operator[] or
dereferencing first so I first chose the slower but prettier method.</p>
<figure class="highlight"><pre><code class="language-c--" data-lang="c++"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o"><</span><span class="kt">double</span><span class="o">>*</span> <span class="n">pvect</span> <span class="o">=</span> <span class="k">new</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o"><</span><span class="kt">double</span><span class="o">></span><span class="p">();</span>
<span class="n">pvect</span><span class="o">-></span><span class="n">push_back</span><span class="p">(</span><span class="mf">1.0</span><span class="p">);</span>
<span class="kt">double</span> <span class="n">slow</span> <span class="o">=</span> <span class="n">pvect</span><span class="o">-></span><span class="n">at</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// easy to read but slow.</span>
<span class="kt">double</span> <span class="n">fast1</span> <span class="o">=</span> <span class="n">pvect</span><span class="o">-></span><span class="k">operator</span><span class="p">[](</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// fast ugly access 1</span>
<span class="kt">double</span> <span class="n">fast2</span> <span class="o">=</span> <span class="p">(</span><span class="o">*</span><span class="n">pvect</span><span class="p">)[</span><span class="mi">0</span><span class="p">];</span> <span class="c1">// fast ugly access 2</span></code></pre></figure>
<p>Fortunately switching from at() to operator[] an easy thing to fix, and I got a
significant 25% speed boost because of it.</p>
Mon, 19 Jan 2015 12:30:00 +0000
https://tytel.org/blog/2015/01/19/unexpected-optimization-00/
https://tytel.org/blog/2015/01/19/unexpected-optimization-00/blogdevblogtwytchoptimizationStarting Development on Twytch, an open source synthesizer<p>On the 1st day of 2015, I started development on an open source software synth, <a href="https://github.com/mtytel/twytch">Twytch</a>. I’ve decided to keep a devblog after seeing some of the devblog successes in the indie game development world such as <a href="http://willychyr.com/blog/">Willy Chyr’s Relativity</a> and <a href="http://fractgame.com/news">Phosfiend Systems’ Fract OSC</a>.</p>
<p>The goal of Twytch is a mix of granular and subtractive synthesis that focuses on glitching live and sampled audio input. It currently runs as a VST and Audio Unit and hopefully will run as a stand-alone synthesizer in the future. Some of the technologies I’m using are:</p>
<ul>
<li><a href="https://www.juce.com/">JUCE</a>: for cross platform UI development and VST/AU input and output handling</li>
<li><a href="https://github.com/mtytel/mopo">mopo</a>: a modular and polyphonic synthesizer engine I’m working on</li>
</ul>
<p>I started with the code from a past synthesizer I made called <a href="https://www.gnu.org/software/cursynth/">cursynth</a>. It’s this goofy stand-alone ascii synth that runs inside of a terminal with ascii sliders and graphics. From the past weeks of work I have a functioning Audio Unit synthesizer and the beginnings of many of the UI elements. There’s also very cumbersome patch saving and loading, but it works. I’m now at that point in development where you just throw all the controls on the screen and make an ugly UI soup. Have a look:</p>
<p><img src="/static/images/blog/2015-01-18-screenshot.png" alt="Twytch Screenshot" /></p>
Sun, 18 Jan 2015 04:59:06 +0000
https://tytel.org/blog/2015/01/18/twytch-intro/
https://tytel.org/blog/2015/01/18/twytch-intro/blogdevblogtwytchStray Bolts<p>Not born for courts and chains<br />
and pendulums swinging up and down,<br />
through granada’s royal town.<br />
We softly, slowly dance,<br />
listening for murmured murmurs.</p>
<p>Our vanity endows us<br />
though neither foe nor friend allow us,<br />
to hear the force of that murderous deed,<br />
that made love bleed.</p>
<p>To know sometimes we run to madness,<br />
in thoughtless throngs and empty noise.<br />
Shall truth with fiction, our world of bloom<br />
preserve what it first creates?</p>
Sun, 06 Jan 2013 00:00:00 +0000
https://tytel.org/poetry/stray-bolts/
https://tytel.org/poetry/stray-bolts/poems