<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Nathan Ho (Posts about dsp)</title><link>https://nathan.ho.name/</link><description></description><atom:link href="https://nathan.ho.name/categories/dsp.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>© 2026</copyright><lastBuildDate>Wed, 15 Jul 2026 22:22:11 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>DM Synthesis</title><link>https://nathan.ho.name/posts/dm-synthesis/</link><dc:creator>Nathan Ho</dc:creator><description>&lt;div&gt;&lt;p&gt;A while back, I tried &lt;a class="reference external" href="https://www.youtube.com/watch?v=L-o-qQr2iaw"&gt;recreating the sound of a dialup modem from scratch&lt;/a&gt;, which involved a dive into multiple PDFs of telecommunication standards. (I am &lt;a class="reference external" href="https://freesound.org/people/berdnikov2004/sounds/586442/"&gt;not the first person to do this&lt;/a&gt;.) Very helpful was &lt;a class="reference external" href="https://www.windytan.com/2012/11/the-sound-of-dialup-pictured.html"&gt;Windy Tan’s beautiful analysis&lt;/a&gt; breaking down a spectrogram of a real dialup handshake. A particularly famous bit is the nasal mid-low “whine” at the end of the handshake, and if you’ve ever wondered what that is, you’re hearing line probing signals L1 and L2, which are synthesized using additive synthesis. The exact partial frequency, phases, and amplitudes are specified in section 10.1.2.4 of &lt;a class="reference external" href="https://www.itu.int/rec/T-REC-V.34-199802-I/en"&gt;ITU-T V.34&lt;/a&gt;. They’re at 9 seconds in &lt;a class="reference external" href="https://freesound.org/people/thearchiveguy99/sounds/658932/"&gt;this recording&lt;/a&gt; of a modem by thearchiveguy99 on Freesound:&lt;/p&gt;
&lt;audio controls src="https://nathan.ho.name/audio/dm-synthesis/thearchiveguy99_dialup.mp3"&gt;&lt;/audio&gt;&lt;p&gt;&lt;em&gt;WARNING: Audio files in this post are loud and piercing. Please turn up your speakers to extremely painful levels for optimal telecommunication.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The whine is legendary, but I want to turn your attention to high-frequency gurgles before it, starting at about 4 seconds in, some of them resembling slurping a last bit of soda through a straw in a McDonald’s cup. These tones, specified at a high level in &lt;a class="reference external" href="https://www.itu.int/rec/T-REC-V.8bis-200011-I/en"&gt;ITU-T V.8bis&lt;/a&gt;, are encoded using &lt;em&gt;frequency-shift keying&lt;/em&gt; (FSK) as given in the lower-level &lt;a class="reference external" href="https://www.itu.int/rec/T-REC-V.21-198811-I/en"&gt;ITU-T V.21&lt;/a&gt; spec. In its simplest form, FSK uses a single sine wave to encode a binary signal by modulating its frequency. Following V.21’s description of a “channel 1” signal, at regular intervals of 1/300 seconds, a single bit is transmitted. If the bit is 0, the sine wave’s frequency is set to 1180 Hz. If the bit is 1, the frequency is set to 980 Hz.&lt;/p&gt;
&lt;audio controls src="https://nathan.ho.name/audio/dm-synthesis/fsk.mp3"&gt;&lt;/audio&gt;&lt;p&gt;Yep, that’s a dialup gurgle. The graph below demonstrates this visually (for different parameters — I had to lower the carrier for the 1 bits so that the distinction between the two is obvious). Above we have the audio waveform, below it the data signal.&lt;/p&gt;
&lt;img alt="/images/dm-synthesis/fsk.png" src="https://nathan.ho.name/images/dm-synthesis/fsk.png"&gt;
&lt;p&gt;Designing that dialup imitation made me realize that I really like how FSK sounds purely as a sound design tool. This got me looking into its various siblings, which are known as the “digital modulation” schemes for transmission of digital signals over an analog medium such as radio. In contrast, in “analog modulation” the signal being transmitted is continuous, encompassing familiar techniques like FM, AM, and single-sideband modulation. Today we’re going to honor the long tradition of adapting telecommunications methods for creative use by seeing what kind of sounds we can design by directly listening to signals produced with FSK and related methods. I call this approach Digital Modulation Synthesis, a name I’m not in love with, but I couldn’t think of a better one. It may be abbreviated to the cooler-sounding “DM Synthesis.”&lt;/p&gt;
&lt;p&gt;In telecommunications, modulation is only half the story, and you also need a demodulator which takes the transmission signal and gets the data back. Engineering modulators and demodulators in a way that’s robust to noise is an interesting problem subject to nearly a century of study, but here we’re going to be the weirdos who just want to listen to the modulated signal itself. I will spend no time here discussing the engineering tradeoffs of these digital modulation schemes in a telecommunication settings; those problems are very interesting and deep but not relevant to this post.&lt;/p&gt;
&lt;p&gt;This post is pretty light on math, and the DSP isn’t fancy here, as our concentration is more on sound design and synthesis. All this should be doable in SuperCollider, Pd, Max, etc. with pre-existing units.&lt;/p&gt;
&lt;p&gt;I didn’t research this post as thoroughly as I would have liked, so it’s not impossible that I have misrepresented things from the telecommunications literature. If there are mistakes, sorry about that.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://nathan.ho.name/posts/dm-synthesis/"&gt;Read more…&lt;/a&gt; (17 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>dsp</category><category>synthesis</category><category>telecommunications</category><guid>https://nathan.ho.name/posts/dm-synthesis/</guid><pubDate>Sun, 24 Nov 2024 08:00:00 GMT</pubDate></item><item><title>Audio Effects with Wavesets and K-Means Clustering</title><link>https://nathan.ho.name/posts/wavesets-clustering/</link><dc:creator>Nathan Ho</dc:creator><description>&lt;div&gt;&lt;img alt="/images/waveset-clustering/stay_with_me_5.0.png" src="https://nathan.ho.name/images/waveset-clustering/stay_with_me_5.0.png"&gt;
&lt;p&gt;&lt;audio controls src="https://nathan.ho.name/audio/waveset-clustering/stay_with_me_original.mp3"&gt;&lt;/audio&gt; (original)&lt;/p&gt;
&lt;p&gt;&lt;audio controls src="https://nathan.ho.name/audio/waveset-clustering/stay_with_me_5.0.mp3"&gt;&lt;/audio&gt; (processed)&lt;/p&gt;&lt;p&gt;I would like to congratulate wavesets (not &lt;a class="reference external" href="https://nathan.ho.name/posts/wavelets/"&gt;wavelets&lt;/a&gt;) for entering their 30th year of being largely ignored outside of a very small circle of computer music nerds. Introduced by Trevor Wishart in &lt;a class="citation-reference" href="https://nathan.ho.name/posts/wavesets-clustering/#wishart1994" id="citation-reference-1" role="doc-biblioref"&gt;[Wishart1994]&lt;/a&gt; and popularized by &lt;em&gt;Microsound&lt;/em&gt; &lt;a class="citation-reference" href="https://nathan.ho.name/posts/wavesets-clustering/#roads2002" id="citation-reference-2" role="doc-biblioref"&gt;[Roads2002]&lt;/a&gt; and the &lt;a class="reference external" href="https://composersdesktop.com/"&gt;Composers Desktop Project&lt;/a&gt;, a waveset is defined as a segment of an audio signal between two consecutive upward zero crossings. For simple oscillators like sine and saw waves, wavesets divide the signal into pitch periods, but for general periodic signals there may be any number of wavesets per period. For signals containing noise or multiple pitches at once, waveset segmentation is completely unpredictable.&lt;/p&gt;
&lt;p&gt;Many simple audio effects fall out of this idea. You can reverse individual wavesets, omit every other waveset, repeat each waveset, sort them, whatever.&lt;/p&gt;
&lt;p&gt;I like waveset-based effects best on input signals that are monophonic (having only one pitch) and low in noise. Synthetic signals can make for particularly interesting results. Much as the phase vocoder tends to sound blurry and phasey, waveset transformations also have their own “house style” in the form of highly digital glitches and crackles. These glitches are particularly pronounced when a waveset-based algorithm is fed non-monophonic signals or signals containing strong high-frequency noise. Wavesets are extremely sensitive to any kind of prefiltering applied to the input signal; it’s a good idea to highpass filter the signal to block dc, and it’s fun to add pre-filters as a musical parameter.&lt;/p&gt;
&lt;p&gt;Today, we’re putting a possibly new spin on wavesets by combining them with basic statistical learning. The idea is to perform &lt;a class="reference external" href="https://en.wikipedia.org/wiki/K-means_clustering"&gt;k-means clustering&lt;/a&gt; on waveset features. The steps of the algorithm are as follows:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Segmentation:&lt;/strong&gt; Divide a single-channel audio signal into &lt;span class="math"&gt;\(N\)&lt;/span&gt; wavesets.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Analysis:&lt;/strong&gt; Compute the feature vector &lt;span class="math"&gt;\(\mathbf{x}_i\)&lt;/span&gt; for the &lt;span class="math"&gt;\(i\)&lt;/span&gt;-th waveset. I use just two features: length &lt;span class="math"&gt;\(\ell_i\)&lt;/span&gt;, or number of samples between the zero crossings, and RMS &lt;span class="math"&gt;\(r_i\)&lt;/span&gt; of the waveset’s samples. All the lengths are compiled into a single size-&lt;span class="math"&gt;\(N\)&lt;/span&gt; vector &lt;span class="math"&gt;\(\mathbf{\ell}\)&lt;/span&gt; and the RMSs into &lt;span class="math"&gt;\(\mathbf{r}\)&lt;/span&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Normalization:&lt;/strong&gt; Scale &lt;span class="math"&gt;\(\mathbf{\ell}\)&lt;/span&gt; and &lt;span class="math"&gt;\(\mathbf{r}\)&lt;/span&gt; so that they each have variance 1.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Weighting:&lt;/strong&gt; Scale &lt;span class="math"&gt;\(\mathbf{\ell}\)&lt;/span&gt; by a weighting parameter &lt;span class="math"&gt;\(w\)&lt;/span&gt;, which controls how much the clustering stage emphasizes differences in length vs. differences in amplitude. We’ll talk more about this later, but &lt;span class="math"&gt;\(w = 5\)&lt;/span&gt; seems to work as a start.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clustering:&lt;/strong&gt; Run k-means clustering on the feature vectors &lt;span class="math"&gt;\(\mathbf{x}\)&lt;/span&gt;, producing &lt;span class="math"&gt;\(k\)&lt;/span&gt; clusters.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For each cluster, pick one &lt;em&gt;representative waveset&lt;/em&gt;, the one closest to the centroid of the cluster.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Quantization:&lt;/strong&gt; In the original audio signal, replace each waveset with the representative waveset from its cluster.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Implementation is very lightweight, clocking in at about 30 lines of Python with scikit-learn. There are only two parameters here other than the input audio: &lt;span class="math"&gt;\(w\)&lt;/span&gt; and &lt;span class="math"&gt;\(k\)&lt;/span&gt;. &lt;a class="brackets" href="https://nathan.ho.name/posts/wavesets-clustering/#footnote-1" id="footnote-reference-1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; The length of the input audio signal is important too, so for musical reasons let’s not think in terms of &lt;span class="math"&gt;\(k\)&lt;/span&gt; but rather “clusters per second” &lt;span class="math"&gt;\(c\)&lt;/span&gt;, which is &lt;span class="math"&gt;\(k\)&lt;/span&gt; divided by the signal length in seconds. As we will see, with only two-dimensional control we can produce a tremendous variety of sounds.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://nathan.ho.name/posts/wavesets-clustering/"&gt;Read more…&lt;/a&gt; (11 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>data science</category><category>dsp</category><category>effects</category><category>granular synthesis</category><category>machine learning</category><guid>https://nathan.ho.name/posts/wavesets-clustering/</guid><pubDate>Tue, 09 Apr 2024 12:13:06 GMT</pubDate></item><item><title>Cybernetic Synthesis and Roland Kayn</title><link>https://nathan.ho.name/posts/cybernetic-synthesis/</link><dc:creator>Nathan Ho</dc:creator><description>&lt;div&gt;&lt;a class="reference external image-reference" href="https://rolandkayn.bandcamp.com/album/electronic-symphony-i-iii"&gt;
&lt;img alt="Album cover for Roland Kayn's Electronic Symphony I-III." class="align-right" src="https://nathan.ho.name/images/kayn_electronic_symphony.jpg" style="width: 20em;"&gt;
&lt;/a&gt;
&lt;p&gt;Let’s open this post with music. If you aren’t familiar with the late composer Roland Kayn’s work, listen to one of his &lt;em&gt;Electronic Symphonies&lt;/em&gt;, or at least sample a few minutes. The album cover links to his official Bandcamp.&lt;/p&gt;
&lt;p&gt;I found out about Kayn’s music through &lt;a class="reference external" href="https://llllllll.co/t/cybernetic-music-roland-kayn-feedback-systems-ai/40635"&gt;a thread on Lines&lt;/a&gt;, and it gets only more interesting as I looked into his story. Kayn was an exponent of combining music with &lt;em&gt;cybernetics&lt;/em&gt;, a field I gloss as “the study of feedback systems.” At its heart, it’s a mathematical study; Norbert Wiener’s original text &lt;em&gt;Cybernetics&lt;/em&gt; is chock full of integrals and differential equations. As the field developed, it overlapped significantly with medicine, social sciences, humanities, and especially critical theory. I do hope to read Wiener’s &lt;em&gt;Cybernetics&lt;/em&gt; and &lt;em&gt;The Human Use of Human Beings&lt;/em&gt;, but haven’t gotten around to them, so consider my understanding of the field surface-level — I’m mainly concerned with cybernetics as it relates to Kayn’s music.&lt;/p&gt;
&lt;p&gt;Kayn began making cybernetics-influenced electronic works in university electronic music studios in the 60’s. We don’t know what exact tools, but Pickles’ 2016 dissertation &lt;em&gt;Cybernetics in music&lt;/em&gt; surmises that the equipment back then was something along the lines of tape machines and basic analog processors and generators: oscillators, noise, filters, reverbs, envelope generators, ring modulators. More intriguingly, recordings of his works were entirely real time — a stark contrast to the offline tape-based processes of the contemporary musique concrète movement. Critic Frans van Rossum wrote in 2011 that Kayn worked with a “network of electronic equipment” and a “a system of signals or commands that it can obey and execute” (quote also via Pickles).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;EDIT 2023-12-20:&lt;/em&gt; An earlier version of this post credited the technology to Kayn alone, but I have since been properly schooled: it was Jaap Vink who actually built the system, &lt;a class="reference external" href="https://4columns.org/frere-jones-sasha/jaap-vink"&gt;as Sascha Frere-Jones wrote in 4Columns&lt;/a&gt;. Given the intimacy that cybernetic musicians necessarily have with their tools, his fingerprints are deeply embedded in Kayn’s electronic works. The sources I looked at didn’t make this clear to me, and most don’t even mention Vink by name. Vink referred to himself as a technician, not a composer, and it’s possible that the concealment of his status was his preference.&lt;/p&gt;
&lt;p&gt;That these works were likely made on 60’s equipment, were recorded in real time, &lt;em&gt;and&lt;/em&gt; sound varied and dynamic over long stretches of time should impress anyone familiar with modular synths. The implications that his musical systems had some kinds of self-generating and autonomous properties makes this even more remarkable. Now Kayn’s output is more than just great music, it’s now a puzzle. How did he make this music? Can we recreate part of his process?&lt;/p&gt;
&lt;p&gt;I don’t think we’ll ever get definitive answers. Kayn died in 2011, Vink in January 2023. While there’s a small body of writing about them, little of it is technical. We can only guess, but we have some resources that helps us with the guessing process — the Lines thread I mentioned, and also &lt;a class="reference external" href="https://www.youtube.com/@lasynthesehumaine6932"&gt;La Synthèse Humaine&lt;/a&gt;, a YouTube channel run by musician Émile Zener a.k.a. Gunnar Haslam. He takes direct inspiration from Kayn, and unlike me has extensively studied the cybernetics literature. I won’t take the time to resummarize the &lt;a class="reference external" href="https://llllllll.co/t/cybernetic-music-roland-kayn-feedback-systems-ai/40635"&gt;Lines thread&lt;/a&gt; or Zener’s work — just go check them out for yourself — instead I am interested in expanding on them.&lt;/p&gt;
&lt;section id="making-a-cybernetic-lfo"&gt;
&lt;h2&gt;Making a cybernetic LFO&lt;/h2&gt;
&lt;p&gt;It’s perhaps easiest if I first walk you through a concrete example of building a cybernetic patch. We begin with the simple harmonic oscillator, which can be implemented with the system of ordinary differential equations&lt;/p&gt;
&lt;div class="math"&gt;
\begin{equation*}
\begin{align*}
\dot{a} &amp;amp;= -kb \\
\dot{b} &amp;amp;= ka \\
\end{align*}
\end{equation*}
&lt;/div&gt;
&lt;p&gt;and the following block diagram:&lt;/p&gt;
&lt;img alt="Block diagram of an integrator into an amplifier into another integrator into an inverting amplifier." class="align-center" src="https://nathan.ho.name/images/cybernetic-synthesis/simple_harmonic_oscillator.jpg" style="width: 20em;"&gt;
&lt;p&gt;This comprises two integrator stages in a feedback loop. An integrator is a unit that continuously accumulates the input signal (you can get something like a leaky integrator with a one-pole lowpass filter with a very low cutoff). The triangles are simple amplifiers multiplying by constants; one must be negative and the other positive. There are two outputs, A and B, which produce a sine and cosine wave respectively. The system does need an initial “kick” to generate sine waves, by e.g. initially setting &lt;span class="math"&gt;\(a(0) = 1\)&lt;/span&gt; and &lt;span class="math"&gt;\(b(0) = 0\)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Assume that the oscillator is tuned to oscillate at a slow 1 Hz. It is an “LFO” in the literal sense that it oscillates at a low frequency, but critically we aren’t generating it with an actual oscillator module, and the oscillation is an emergent property of the system that we built. We can turn this into an audible synthesis patch by using the two outputs, A and B, as amplitudes, multiplying them with VCAs by two saw oscillators with static frequencies. Mixing the oscillators together, we have a simple looping alternation between two “notes” even though we have no actual sequencer here.&lt;/p&gt;
&lt;img alt="Block diagram of the above, but the outputs of the two integrators are used to control VCAs applied to oscillators." class="align-center" src="https://nathan.ho.name/images/cybernetic-synthesis/with_vcas.jpg" style="width: 20em;"&gt;
&lt;audio controls src="https://nathan.ho.name/audio/cybernetic/simple_harmonic_oscillator.mp3"&gt;&lt;/audio&gt;&lt;p&gt;However, the oscillators and VCA’s aren’t part of a loop, and their output does not influence the rest of the system. For reasons that I’ll justify later, we loop in their VCAs by running an envelope follower on the output of the VCAs, and using it to modulate the coefficients of other VCAs that are in the loop.&lt;/p&gt;
&lt;img alt="Similar block diagram as before, but the outputs of the oscillator VCAs are routed back to modulated each other's frequencies and the amplifiers in the core SHO feedback loop." class="align-center" src="https://nathan.ho.name/images/cybernetic-synthesis/cybernetic_oscillator.jpg" style="width: 20em;"&gt;
&lt;audio controls src="https://nathan.ho.name/audio/cybernetic/cybernetic_oscillator.mp3"&gt;&lt;/audio&gt;&lt;p&gt;(I’m misusing notation here a bit; the arrows into the loop VCAs are not actually setting the gain, but wiggling around the gain it had in the previous diagram. The intentions of this diagram are more romantic than schematic — the point is to illustrate the closing of loops, not to specify an exact algorithm.)&lt;/p&gt;
&lt;p&gt;This isn’t an actual simple harmonic oscillator anymore, but it mimics the core behavior of one. However, if we start changing any parameter, the core behavior of the “LFO” starts changing too. Everything interacts with everything, and nothing is isolated or purely upstream or purely downstream.&lt;/p&gt;
&lt;p&gt;We’ll return to this patch and expand it into something more compelling in sound design terms. Let’s go theoretical for a bit and explain what we’re actually trying to do here.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://nathan.ho.name/posts/cybernetic-synthesis/"&gt;Read more…&lt;/a&gt; (9 min remaining to read)&lt;/p&gt;&lt;/section&gt;&lt;/div&gt;</description><category>algorithmic composition</category><category>dsp</category><category>electronic music</category><category>musicology</category><category>sound design</category><category>synthesis</category><guid>https://nathan.ho.name/posts/cybernetic-synthesis/</guid><pubDate>Wed, 20 Dec 2023 00:41:04 GMT</pubDate></item><item><title>Audio Effects with Cepstral Processing</title><link>https://nathan.ho.name/posts/cepstrum/</link><dc:creator>Nathan Ho</dc:creator><description>&lt;p&gt;Much like the previously discussed &lt;a class="reference external" href="https://nathan.ho.name/posts/wavelets/"&gt;wavelet transforms&lt;/a&gt;, the cepstrum is a frequency-domain method that I see talked about a lot in the scientific research literature, but only occasionally applied to the creative arts. The cepstrum is sometimes described as “the FFT of the FFT” (although this is an oversimplification since there are nonlinear operations sandwiched in between those two transforms, and the second is really the Discrete Cosine Transform). In contrast to wavelets, the cepstrum is very popular in audio processing, most notably in the ubiquitous mel-frequency cepstral coefficients (MFCCs). Some would not consider the MFCCs a true “cepstrum,” others would say the term “cepstrum” is broad enough to encompass them. I have no strong opinion.&lt;/p&gt;
&lt;p&gt;In almost all applications of the cepstrum, it is used solely for analysis and generally isn’t invertible. This is the case for MFCCs, where the magnitude spectrum is downsampled in the conversion to the mel scale, resulting in a loss of information. Resynthesizing audio from the cepstral descriptors commonly used in the literature is an underdetermined problem, usually tackled with machine learning or other complex optimization methods.&lt;/p&gt;
&lt;p&gt;However, it is actually possible to implement audio effects in the MFCC domain with perfect reconstruction. You just have to keep around all the information that gets discarded, resulting in this signal chain:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Take the STFT. The following steps apply for each frame.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Compute the power spectrum (square of magnitude spectrum) and the phases.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Compute a bank of bandpass filters on the power spectrum, equally spaced on the mel-frequency scale. This is the mel spectrum, and it downsamples the magnitude spectrum, losing information.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Upsample the mel spectrum back up to full spectral envelope. Divide the magnitude spectrum by the envelope to produce the &lt;em&gt;residual spectrum&lt;/em&gt;. (You have to add a little epsilon to the envelope to prevent zero division.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Compute the logarithm and then the Discrete Cosine Transform of the mel spectrum to produce the MFCCs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Perform any processing desired.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Invert step 5: take the inverse DCT and then the exponent to produce the mel spectrum.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Invert step 4: upsample the mel spectrum to the spectral envelope, and multiply it by the residual spectrum to produce the power spectrum.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Recombine the power spectrum with the phases to produce the complex spectrum.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inverse FFT, then overlap-add to resynthesize the signal.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It’s a lot of steps, but as an extension of the basic MFCC algorithm, it’s not that much of a leap. I would not be surprised if someone has done this before, storing all residuals when computing the MFCCs so the process can be inverted, but I had difficulty finding prior work on this for the particular application of musical effects. Something similar is done in MFCC-based vocoders, where the “residual spectrum” instead replaced with speech parameters such as pitch, but I haven’t seen this done on general, non-speech signals.&lt;/p&gt;
&lt;p&gt;I will be testing on the following mono snippet of Ed Sheeran’s “Perfect.” (If you plan on doing many listening tests on a musical signal, never use a sample of music you enjoy.)&lt;/p&gt;
&lt;audio controls src="https://nathan.ho.name/audio/cepstral/NoOp.mp3"&gt;&lt;/audio&gt;&lt;p&gt;As for the parameters: mono, 48 kHz sample rate, 2048-sample FFT buffer with Hann window and 50% overlap, 30-band mel spectrum from 20 Hz to 20 kHz.&lt;/p&gt;
&lt;section id="cepstral-eq"&gt;
&lt;h2&gt;Cepstral EQ&lt;/h2&gt;
&lt;p&gt;Because of the nonlinearities involved in the signal chain, merely multiplying the MFCCs by a constant can do some pretty strange things. Zeroing out all MFCCs has the effect of removing the spectral envelope and whitening the signal. The effect on vocal signals is pronounced, turning Ed into a bumblebee.&lt;/p&gt;
&lt;audio controls src="https://nathan.ho.name/audio/cepstral/Whiten.mp3"&gt;&lt;/audio&gt;&lt;p&gt;Multiplying all MFCCs by 2 has a subtle, hollower quality, acting as an expander for the spectral envelope.&lt;/p&gt;
&lt;audio controls src="https://nathan.ho.name/audio/cepstral/Deepen.mp3"&gt;&lt;/audio&gt;&lt;p&gt;MFCCs are signed and can also be multiplied by negative values, which inverts the phase of a cosine wave component. The effect on the signal is hard to describe:&lt;/p&gt;
&lt;audio controls src="https://nathan.ho.name/audio/cepstral/SignFlip.mp3"&gt;&lt;/audio&gt;&lt;p&gt;We can apply any MFCC envelope desired. Here’s a sine wave:&lt;/p&gt;
&lt;audio controls src="https://nathan.ho.name/audio/cepstral/PartialSignFlip.mp3"&gt;&lt;/audio&gt;&lt;/section&gt;
&lt;section id="cepstral-frequency-shifting"&gt;
&lt;h2&gt;Cepstral frequency shifting&lt;/h2&gt;
&lt;p&gt;Technically this would be “quefrency shifting.” This cyclically rotates the MFCCs to brighten the signal:&lt;/p&gt;
&lt;audio controls src="https://nathan.ho.name/audio/cepstral/ShiftUp.mp3"&gt;&lt;/audio&gt;&lt;p&gt;And here’s the downward equivalent:&lt;/p&gt;
&lt;audio controls src="https://nathan.ho.name/audio/cepstral/ShiftDown.mp3"&gt;&lt;/audio&gt;&lt;/section&gt;
&lt;section id="cepstral-frequency-scaling"&gt;
&lt;h2&gt;Cepstral frequency scaling&lt;/h2&gt;
&lt;p&gt;Resampling the MFCCs sounds reminiscent of formant shifting. This is related to the time-scaling property of the Fourier transform: if you resample the spectrum, you’re also resampling the signal. Here’s upward scaling:&lt;/p&gt;
&lt;audio controls src="https://nathan.ho.name/audio/cepstral/ScaleUp.mp3"&gt;&lt;/audio&gt;&lt;p&gt;Here’s downward scaling:&lt;/p&gt;
&lt;audio controls src="https://nathan.ho.name/audio/cepstral/ScaleDown.mp3"&gt;&lt;/audio&gt;&lt;/section&gt;
&lt;section id="cepstral-time-based-effects"&gt;
&lt;h2&gt;Cepstral time-based effects&lt;/h2&gt;
&lt;p&gt;Here’s what happens when we freeze the MFCCs every few frames:&lt;/p&gt;
&lt;audio controls src="https://nathan.ho.name/audio/cepstral/Latch.mp3"&gt;&lt;/audio&gt;&lt;p&gt;Lowpass filtering the MFCCs over time tends to slur speech:&lt;/p&gt;
&lt;audio controls src="https://nathan.ho.name/audio/cepstral/Smooth.mp3"&gt;&lt;/audio&gt;&lt;/section&gt;
&lt;section id="stray-thoughts"&gt;
&lt;h2&gt;Stray thoughts&lt;/h2&gt;
&lt;p&gt;I have barely scratched the surface of cepstral effects here, opting only to explore the most mathematically straightforward operations. That the MFCCs produce some very weird and very musical effects, even with such simple transformations, is encouraging.&lt;/p&gt;
&lt;p&gt;In addition to playing with additional types of effects, it is also worthwhile to adjust the trasforms being used. The DCT as the space for the spectral envelope could be improved on. One (strange) possibility that came to mind is messing with the Multiresolution Analysis of the mel spectrum; I have no idea if that would sound interesting or not, but it’s worth a shot.&lt;/p&gt;
&lt;p&gt;It’s possible to bypass the MFCCs and just do the DCT of the log-spectrogram. I experimented with this and found that I couldn’t get it to sound as musical as the mel-based equivalent. I believe this is because the resolution of the FFT isn’t very perceptually salient. The mel scale is in fact doing a lot of heavy lifting here.&lt;/p&gt;
&lt;/section&gt;</description><category>dsp</category><category>effects</category><category>frequency transforms</category><guid>https://nathan.ho.name/posts/cepstrum/</guid><pubDate>Fri, 24 Nov 2023 02:02:56 GMT</pubDate></item><item><title>Making Synthesized Sounds More Acoustic</title><link>https://nathan.ho.name/posts/acoustic-sounds/</link><dc:creator>Nathan Ho</dc:creator><description>&lt;p&gt;I have been experimenting a lot with finding ways to get more acoustic sounds out of synthesizers. These sounds don’t need to be perfect recreations of any particular real instrument, but I want a piece of the complexity and depth that those have, and also to investigate “Pinocchio” synth patches that fall short of becoming a real boy in hopefully interesting ways.&lt;/p&gt;
&lt;p&gt;Computer music types often jump to physical modeling, a field that I adore and have casually researched. But with the exception of &lt;a class="reference external" href="https://nathan.ho.name/posts/exploring-modal-synthesis/"&gt;modal synthesis&lt;/a&gt;, most physical modeling paradigms take considerable software engineering tenacity to get good results — especially the finite difference models, but waveguides too. I do intend to explore them further, but also I believe that some cool sounds can come out of chains of completely ordinary oscillators and effects. In my experiments, I’ve come across a bunch of little tricks that can help lend some more realism to those kinds of synth patches. Many of these also apply to sophisticated physical models too (after all, physical models can’t deliver you from having to do sound design).&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;In general, randomize everything a little bit and modulate everything with a slow, smooth random LFOs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Real percussive envelopes have a &lt;em&gt;very&lt;/em&gt; tall initial spike. Inspecting the waveform of an unprocessed xylophone hit, I was surprised by how loud the transient of a typical percussive instrument is compared to its resonating tail.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The high dynamic range can make such sounds tough to bring up in the mix, and can often be addressed by adding clipping or similar distortion that only gets driven during the initial transient. This improves “bite” as well. However, acoustic sounds by nature have higher dynamic range, and clipping and compression can take away from that. Find a balance that works for you.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Key tracking (modifying synth parameters based on register) is essential. No acoustic instrument has the same physics in every register, and some have very limited pitch range in the first place. I usually at least key track amplitude and the cutoff of a lowpass filter. Don’t get discouraged if something sounds good in one octave but bad if you transpose it. You may even need an entirely different patches for different octaves.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In a tonal percussive synth, it’s essential that partials decay at different rates. A rule of thumb for damped physical resonators is that the decay time is roughly proportional to the inverse of the square of frequency. For example, going up an octave will multiply the decay time by about 0.25. This is not only true of partials within a note, but even of different keys of many mallet instruments. (In a piano, different registers have different physical constructions including different numbers of strings per key, which I believe is specifically compensating for this phenomenon.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Synthesized drums made using oscillators benefit from some subtle stereo detuning.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can spruce up standard ADSR or percussive envelopes by using multiple little spikes in sequence, a bit like an 808 clap envelope. These spikes can be obvious or subtle.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add little noise bursts and puffs to every sharp transient. Delay the noise bursts relative to each other a little bit and randomize all properties slightly. Even if the bursts are subtle, the effect will add up tremendously. Noise doesn’t need to be white or pink; crackly impulsive noise is fun too, and more metallic noise is possible using banks of bandpass filters or inharmonic FM.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adding a little puff of noise before the transient can sound really nice for reed instruments, and I’ve gotten a pretty decent thumb piano sound with it by simulating the thumb scraping against the key. Watch yourself, Four Tet.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add “box tone” to every sound source using a bunch of random peaking filters that boost different bands by +-2 dB (maybe more if you’re feeling adventurous!). Wiggle the parameters around slowly if desired, which is pretty ad hoc but might mimic physical changes in temperature, posture, grip of the instrument, etc. Box tone is a good idea in general to compensate for the relative cleanliness of an all-digital signal path. You can even use multiple layers of wiggly EQ with gentle nonlinearities sandwiched between them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is an obvious one, but almost all acoustic instruments have resonating bodies, so reverb can make or break the realism of a sound. Use slightly different subtle reverbs on every instrument, and prefer “weird” and metallic reverbs with short decay times. I often just use a bank of parallel comb filters; you can also use short multitap delays. The lush Alesis/Lexicon sound has its place in mixing, but I find that sound a little too smooth to work as an instrument body. Obviously, reverb on master is pretty essential if your instruments are in a concert hall.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inharmonic modal synthesis (either with actual resonance or with decaying sine waves) can be enhanced with parallel ring modulation with one or more sine waves. This greatly multiplies the number of partials. I like to add a decay on the “modulator” sine waves. This works best for a grungy junk percussion sound, banging on pots and pans that aren’t carefully tuned by instrument builders.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It’s not just the patch, it’s the sequencing. Humanize velocity; don’t just completely randomize it, make the velocity follow the musical phrasing. Also, louder playing is correlated with higher timing accuracy, and conversely softer playing benefits from humanization in arrival times.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;String players performing in &lt;em&gt;detache&lt;/em&gt; style tend to crescendo a little bit when they anticipate the bow change for the next note. I’ve never played winds, but I wouldn’t be surprised if they did something similar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For instruments that comprise a different physical source for every pitch (pianos, mallet instruments, pipe organs, harmonicas), try detuning each key by a tiny, fixed amount to emulate imperfections in the instrument. You can use a lookup table, but my favorite approach is to use the pitch to seed a random number generator; I use the Hasher UGen in SuperCollider a lot for this. Timbral parameters can be similarly randomized in this manner.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Haas effect panning: delay one channel and put it through a random EQ that’s sloped for high-frequency loss.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SuperCollider’s PitchShift is really great for adding a weird metallic “splash” which I mix back into the signal, sometimes fairly subtly. In general, find weird effects and use them in parallel at a low volume to simulate little imperfections that add up.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The notion that bass &lt;em&gt;has&lt;/em&gt; to be mono is a total myth, and only matters today if your music is being pressed to vinyl. (Trust me, nobody is summing your stereo channels.) Low instruments can absolutely have stereo image and using that can make a mix sound less electronic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If simulating an ensemble, some instruments will be further away than others, which can be mimicked with higher wet-dry ratio in a reverb and some high-frequency loss. This helps particularly for homogeneous ensembles like string orchestras.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wind and string instruments require significant dexterity or physical exertion to reach the higher notes in their registers. To mimic this, random detuning should be more dramatic for higher notes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Winds and strings playing legato are typically done with rapid portamento, which sounds fine. Realism can be further improved by briefly fading in some noise and/or high passing the source, simulating instability as the instrument physically transitions between consecutive notes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Saw and pulse waves are pretty obviously synthetic and often need considerable massaging to sound remotely acoustic. Consider other sources if you aren’t getting success with those. Breakpoint synthesis (GENDY) is a favorite of mine.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Common mixing advice states that you should avoid putting effects or processing on anything unless necessary as demonstrated by A/B test. This is a wise idea for recordings, but in mostly synthesized music, a long chain of subtle effects can create an “imperfection cascade” that help get an extra 5% of realism. This only really helps if the sounds are already good enough to stand on their own.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unisons of multiple instruments can sound more realistic as a whole than exposed instruments, since they can mask each other’s imperfections, especially if those instruments are very different from each other.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Slow parameter fluctuations happen not only for individual instruments, but for the entire ensemble, especially for a homogeneous group like a string quartet. Create an automation and map it to the intensity parameter of many instruments, which also fluctuate individually.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;</description><category>dsp</category><category>physical modeling</category><category>sound design</category><category>synthesis</category><guid>https://nathan.ho.name/posts/acoustic-sounds/</guid><pubDate>Mon, 16 Oct 2023 15:54:17 GMT</pubDate></item><item><title>An Intro to Wavelets for Computer Musicians</title><link>https://nathan.ho.name/posts/wavelets/</link><dc:creator>Nathan Ho</dc:creator><description>&lt;div&gt;&lt;p&gt;&lt;em&gt;I wasn’t able to get this post fully complete in time for my self-imposed monthly deadline. I have decided to put it up in an incomplete state and clean it up in early September. I hope it is informative even in its current condition, which gets increasingly sketchy towards the end. Open during construction.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Among DSP types, those unfamiliar with wavelets often view them as a mysterious dark art, vaguely rumored to be “superior” to FFT in some way but for reasons not well understood. Computer musicians with a penchant for unusual and bizarre DSP (for instance, people who read niche blogs devoted to the topic) tend to get particularly excited about wavelets purely for their novelty. Is the phase vocoder too passé for you? Are you on some kind of Baudelairean hedonic treadmill where even the most eldritch Composers Desktop Project commands bore you?&lt;/p&gt;
&lt;p&gt;Well, here it is: my introduction to wavelets, specifically written for those with a background in audio signal processing. I’ve been writing this post on and off for most of 2023, and while I am in no way a wavelet expert, I finally feel ready to explain them. I’ve found that a lot of wavelet resources are far too detailed, containing information mainly useful to people wishing to invent new wavelets rather than people who just want to implement and use them. After you peel back those layers, wavelets are surprisingly not so scary! Maybe not easy, but I do think it’s possible to explain wavelets in an accessible and pragmatic way. The goal here is not to turn you into a wavelet guru, but to impart basic working knowledge (with some theory to act as a springboard to more comprehensive resources).&lt;/p&gt;
&lt;p&gt;Before we go further, I have to emphasize an important fact: while wavelets have found many practical uses in image processing and especially biomedical signal processing, &lt;em&gt;wavelets are not that common in audio&lt;/em&gt;. I’m not aware of any widely adopted and publicly documented audio compression codec that makes use of wavelets. For both audio analysis alone and analysis-resynthesis, the short-time Fourier transform and the phase vocoder are the gold standard. The tradeoffs between time and frequency resolution are generally addressable with multiresolution variants of the STFT.&lt;/p&gt;
&lt;p&gt;There is no one “wavelet transform” but a huge family of methods. &lt;a class="reference external" href="https://scholar.google.com/scholar?hl=en&amp;amp;as_sdt=0,5&amp;amp;q=%22wavelet+transform%22++variant"&gt;New ones are developed all the time&lt;/a&gt;. To limit the scope of this post, I will introduce the two “classical” wavelet transforms: the Continuous Wavelet Transform (CWT) and Multiresolution Analysis (MRA). I’ll also go over popular choices of individual wavelets and summarize their properties. There are other wavelet transforms, some of more musically fertile than CWT or MRA, but you can’t skip the fundamentals before moving on to those. My hope is that demystifying wavelet basics will empower more DSP-savvy artists to learn about these curious creatures.&lt;/p&gt;
&lt;nav class="contents" id="table-of-contents" role="doc-toc"&gt;
&lt;p class="topic-title"&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#top"&gt;Table of Contents&lt;/a&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#preliminaries" id="toc-entry-1"&gt;Preliminaries&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#crash-course-on-hilbert-spaces" id="toc-entry-2"&gt;Crash course on Hilbert spaces&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#continuous-wavelet-transform" id="toc-entry-3"&gt;Continuous Wavelet Transform&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#mother-wavelet" id="toc-entry-4"&gt;Mother wavelet&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#time-shifting-the-mother-wavelet" id="toc-entry-5"&gt;Time-shifting the mother wavelet&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#scaling-the-mother-wavelet" id="toc-entry-6"&gt;Scaling the mother wavelet&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#definition-of-the-cwt" id="toc-entry-7"&gt;Definition of the CWT&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#inverse-continuous-wavelet-transform" id="toc-entry-8"&gt;Inverse Continuous Wavelet Transform&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#discrete-time-continuous-wavelet-transform" id="toc-entry-9"&gt;Discrete-Time Continuous Wavelet Transform&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#quantizing-frequency" id="toc-entry-10"&gt;Quantizing frequency&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#downsampling-dt-cwt-bands" id="toc-entry-11"&gt;Downsampling DT-CWT bands&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#multiresolution-analysis-fast-wavelet-transform" id="toc-entry-12"&gt;Multiresolution Analysis (Fast Wavelet Transform)&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#analysis-with-mra" id="toc-entry-13"&gt;Analysis with MRA&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#implementation-details" id="toc-entry-14"&gt;Implementation details&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#connecting-mra-to-the-cwt-part-1-the-intuition" id="toc-entry-15"&gt;Connecting MRA to the CWT, part 1: the intuition&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#connecting-mra-to-the-cwt-part-2-the-math" id="toc-entry-16"&gt;Connecting MRA to the CWT, part 2: the math&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#specific-wavelets" id="toc-entry-17"&gt;Specific wavelets&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#morlet-wavelet-gabor-wavelet" id="toc-entry-18"&gt;Morlet wavelet (Gabor wavelet)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#haar-wavelet" id="toc-entry-19"&gt;Haar wavelet&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#shannon-wavelet" id="toc-entry-20"&gt;Shannon wavelet&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#daubechies-wavelets" id="toc-entry-21"&gt;Daubechies wavelets&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#mexican-hat-wavelet-ricker-wavelet" id="toc-entry-22"&gt;Mexican hat wavelet (Ricker wavelet)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#others" id="toc-entry-23"&gt;Others&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#conclusion" id="toc-entry-24"&gt;Conclusion&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#acknowledgements" id="toc-entry-25"&gt;Acknowledgements&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#footnotes" id="toc-entry-26"&gt;Footnotes&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="https://nathan.ho.name/posts/wavelets/#references" id="toc-entry-27"&gt;References&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/nav&gt;
&lt;p&gt;&lt;a href="https://nathan.ho.name/posts/wavelets/"&gt;Read more…&lt;/a&gt; (41 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>dsp</category><category>mathematics</category><guid>https://nathan.ho.name/posts/wavelets/</guid><pubDate>Wed, 30 Aug 2023 07:00:00 GMT</pubDate></item><item><title>Correlated Granular Synthesis</title><link>https://nathan.ho.name/posts/correlated-granular-synthesis/</link><dc:creator>Nathan Ho</dc:creator><description>&lt;div&gt;&lt;p&gt;Decades after Curtis Roads’ &lt;em&gt;Microsound&lt;/em&gt;, granular synthesis is making appearances here and there in the commercial plugin market. While it’s nice to see a wider audience for left-field sound design, I have my quibbles with some of the products out there. From what I’ve heard, so many of these products’ demos are covered in reverb in obvious compensation for something, showing that the plugins seem most suited for background textures and transitional moments. In place of sound, the developers seem to prioritize graphics — does watching 3D particles fly around in a physics simulation inspire the process of music production, or distract from it?&lt;/p&gt;
&lt;p&gt;Finally, and most importantly, so many granular “synths” are in fact samplers based on buffer playback. The resulting sound is highly dependent on the sampled source, almost more so than the granular transformations. Sample-based granular (including sampling live input such as in Ableton Live’s Grain Delay) is fun and I’ve done it, but in many ways it’s become the default approach to granular. This leaves you and me, the sound design obsessives, with an opportunity to explore an underutilized alternative to sampled grains: synthesized grains.&lt;/p&gt;
&lt;p&gt;This post introduces a possibly novel approach to granular synthesis that I call Correlated Granular Synthesis. The intent is specifically to design an approach to granular that can produce musical results with synthesized grains. Sample-based granular can also serve as a backend, but the idea is to work with the inherent “unflattering” quality of pure synthesis instead of piggybacking off the timbres baked into the average sample.&lt;/p&gt;
&lt;p&gt;Correlated Granular Synthesis is well suited for randomization in algorithmic music context. Here’s a random sequence of grain clouds generated with this method:&lt;/p&gt;
&lt;p&gt;&lt;audio controls src="https://nathan.ho.name/audio/correlated_granular_synthesis_result.mp3"&gt;&lt;/audio&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="https://nathan.ho.name/posts/correlated-granular-synthesis/"&gt;Read more…&lt;/a&gt; (10 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>data science</category><category>dsp</category><category>electronic music</category><category>granular synthesis</category><category>statistics</category><category>synthesis</category><guid>https://nathan.ho.name/posts/correlated-granular-synthesis/</guid><pubDate>Sun, 04 Jun 2023 19:00:00 GMT</pubDate></item><item><title>Audio Texture Resynthesis</title><link>https://nathan.ho.name/posts/texture-resynthesis/</link><dc:creator>Nathan Ho</dc:creator><description>&lt;div&gt;&lt;img alt="Spectrograms of the audio signals later in the post." class="align-center" src="https://nathan.ho.name/images/texture_resynthesis.png"&gt;
&lt;p&gt;&lt;em&gt;Left: spectrogram of a child singing. Right: spectrogram of resynthesized audio.&lt;/em&gt;&lt;/p&gt;
&lt;section id="background"&gt;
&lt;h2&gt;Background&lt;/h2&gt;
&lt;p&gt;I was alerted to audio texture resynthesis methods by a student of mine who was interested in the collaborative work of researcher Vincent Lostanlen, musician Florian Hecker, and several others &lt;a class="citation-reference" href="https://nathan.ho.name/posts/texture-resynthesis/#lostanlen2019" id="citation-reference-1" role="doc-biblioref"&gt;[Lostanlen2019]&lt;/a&gt; &lt;a class="citation-reference" href="https://nathan.ho.name/posts/texture-resynthesis/#lostanlen2021" id="citation-reference-2" role="doc-biblioref"&gt;[Lostanlen2021]&lt;/a&gt; &lt;a class="citation-reference" href="https://nathan.ho.name/posts/texture-resynthesis/#anden2019" id="citation-reference-3" role="doc-biblioref"&gt;[Andén2019]&lt;/a&gt; &lt;a class="citation-reference" href="https://nathan.ho.name/posts/texture-resynthesis/#muradeli2022" id="citation-reference-4" role="doc-biblioref"&gt;[Muradeli2022]&lt;/a&gt;. Their efforts are built on an analysis method called “Joint Time-Frequency Scattering” (JTFS) based on the Continuous Wavelet Transform. In an attempt to understand the work better, I binged a wavelet transform textbook, &lt;a class="brackets" href="https://nathan.ho.name/posts/texture-resynthesis/#footnote-1" id="footnote-reference-1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; implemented a simplified version of JTFS-based resynthesis, and and briefly exchanged emails with Lostanlen. His helpful answers gave me the impression is that while JTFS is a powerful analysis technique, resynthesis was more of a side project and there are ways to accomplish similar effects that are more efficient and easier to code without compromising too much on musicality.&lt;/p&gt;
&lt;p&gt;Audio texture resynthesis has some history in computer music literature &lt;a class="citation-reference" href="https://nathan.ho.name/posts/texture-resynthesis/#schwartz2010" id="citation-reference-5" role="doc-biblioref"&gt;[Schwartz2010]&lt;/a&gt;, and some researchers have used resynthesis to help understand how the human brain processes audio &lt;a class="citation-reference" href="https://nathan.ho.name/posts/texture-resynthesis/#mcdermott2011" id="citation-reference-6" role="doc-biblioref"&gt;[McDermott2011]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After some experimentation with these methods, I found that it’s not too hard to build a simple audio texture resynthesizer that exhibits clear musical potential. In this blog post, I’ll walk through a basic technique for making such a system yourself. There won’t be any novel research here, just a demonstration of a minimum viable resynthesizer and my ideas on how to expand on it.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="algorithm"&gt;
&lt;h2&gt;Algorithm&lt;/h2&gt;
&lt;p&gt;The above-mentioned papers have used fancy techniques including the wavelet transform and auditory filter banks modeled after the human ear. However, I was able to get decent results with a standard STFT spectrogram, then using phase reconstruction to get time-domain audio samples. The full process looks like this:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Compute a magnitude spectrogram &lt;span class="math"&gt;\(S\)&lt;/span&gt; of the time-domain input signal &lt;span class="math"&gt;\(x\)&lt;/span&gt;. A fairly high overlap is advised.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Compute any number of feature vectors &lt;span class="math"&gt;\(F_1(S),\, F_2(S),\, \ldots,\, F_n(S)\)&lt;/span&gt; and define their concatenation as &lt;span class="math"&gt;\(F(S)\)&lt;/span&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Initialize a randomized magnitude spectrogram &lt;span class="math"&gt;\(\hat{S}\)&lt;/span&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use gradient descent on &lt;span class="math"&gt;\(\hat{S}\)&lt;/span&gt; to minimize the error &lt;span class="math"&gt;\(E(\hat{S}) = ||F(S) - F(\hat{S})||\)&lt;/span&gt; (using any norm such as the squared error).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use phase reconstruction such as the Griffin-Lim algorithm on &lt;span class="math"&gt;\(\hat{S}\)&lt;/span&gt; to produce a resynthesized signal &lt;span class="math"&gt;\(\hat{x}\)&lt;/span&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The cornerstone of making this algorithm work well is that we choose an &lt;span class="math"&gt;\(F(S)\)&lt;/span&gt; that’s differentiable (or reasonably close). This means that the gradient &lt;span class="math"&gt;\(\nabla E\)&lt;/span&gt; can be computed with automatic differentiation (classical backpropagation). As such, this algorithm is best implemented in a differentiable computing environment like PyTorch or Tensorflow.&lt;/p&gt;
&lt;p&gt;The features &lt;span class="math"&gt;\(F(S)\)&lt;/span&gt;, as well as their relative weights, greatly affect the sound. If &lt;span class="math"&gt;\(F(S)\)&lt;/span&gt; is highly time-dependent then the resynthesized signal will mimic the original in evolution. On the other hand, if &lt;span class="math"&gt;\(F(S)\)&lt;/span&gt; does a lot of pooling across the time axis then the resynthesized signal will mostly ignore the large-scale structure of the input signal. I’m mostly interested in the latter case, where &lt;span class="math"&gt;\(F(S)\)&lt;/span&gt; significantly “remixes” the input signal and disregards the overall structure of the original.&lt;/p&gt;
&lt;p&gt;We will represent &lt;span class="math"&gt;\(S\)&lt;/span&gt; as a 2D tensor where the first dimension is frequency and the second is time. As a matrix, each row is an FFT bin, and each column a frame.&lt;/p&gt;
&lt;p&gt;If using a fancy alternative to the magnitude spectrogram such CWT or cochlear filter banks, you may have to do gradient descent all the way back to the time-domain samples &lt;span class="math"&gt;\(x\)&lt;/span&gt;. These analysis methods break down to linear frequency transforms that produce complex numbers followed by computing the absolute value of each bin, so differentiability is maintained.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://nathan.ho.name/posts/texture-resynthesis/"&gt;Read more…&lt;/a&gt; (8 min remaining to read)&lt;/p&gt;&lt;/section&gt;&lt;/div&gt;</description><category>data science</category><category>dsp</category><category>effects</category><category>machine learning</category><category>machine listening</category><category>projects</category><guid>https://nathan.ho.name/posts/texture-resynthesis/</guid><pubDate>Tue, 25 Apr 2023 19:58:19 GMT</pubDate></item><item><title>Negative Compression</title><link>https://nathan.ho.name/posts/negative-compression/</link><dc:creator>Nathan Ho</dc:creator><description>&lt;div&gt;&lt;p&gt;One blog post I’ve been meaning to write for a while is a comprehensive review of the design of dynamic range compressors and limiters, both digital and analog. Textbook compressor designs can be easily found, but like reverbs there are lots of weird little tricks from both hardware and software designs that supposedly define the distinctive musical character of different compressors. It may be a while before I finish that post because, while I’ve read a lot about the DSP of compressors, I don’t feel yet qualified to write on design. I haven’t yet designed a compressor plugin that I’m happy with, nor done a lot of compressor wine tasting, and the musical and psychoacoustic aspects of compressors are to me at least as important as the signal math.&lt;/p&gt;
&lt;p&gt;Nevertheless, there’s a weird corner of compressor design that I feel inspired to talk about, and it’s called negative compression. It’s a feature of a few commercial compressors; I’m not sure which was the first, but I first learned about the concept from &lt;a class="reference external" href="https://klanghelm.com/contents/products/DC1A.php"&gt;Klanghelm DC1A&lt;/a&gt;. Negative comp is the source of considerable confusion – just watch the &lt;a class="reference external" href="https://gearspace.com/board/so-much-gear-so-little-time/919446-negative-compression-ratios.html"&gt;Gearspace pundits&lt;/a&gt; go at it.&lt;/p&gt;
&lt;p&gt;The brief description is that a standard compressor, upon receiving a signal with increasing amplitude, will reach a point where the output amplitude will increase at a slower rate. If the compressor is a perfect limiter, the output amplitude will hit a hard limit and refuse to increase. A negative compressor takes it further – the output signal will eventually get quieter over time as the amplitude increases. If you feed a percussive signal into a negative compressor and drive it hard enough, it will punch a hole in the signal’s amplitude, and can split a transient in two. It can be a pretty bizarre effect, and seems underutilized.&lt;/p&gt;
&lt;p&gt;This explanation should be enough for most, but you know this blog. We do the math here. In this post, I will explain the basic mathematics of compressors to demystify negative compression, propose variants of negative compressors, and demonstrate how to do negative compression in SuperCollider.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://nathan.ho.name/posts/negative-compression/"&gt;Read more…&lt;/a&gt; (6 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>dsp</category><category>dynamic range compression</category><category>effects</category><category>supercollider</category><guid>https://nathan.ho.name/posts/negative-compression/</guid><pubDate>Thu, 23 Feb 2023 17:59:46 GMT</pubDate></item><item><title>A Closer Look at Clarence Barlow's ISIS</title><link>https://nathan.ho.name/posts/clarence-barlow-isis/</link><dc:creator>Nathan Ho</dc:creator><description>&lt;div&gt;&lt;p&gt;In 2005, Clarence Barlow published a paper on &lt;em&gt;Intra-Samplar Interpolating Sinusoids&lt;/em&gt; (ISIS), an audio analysis-synthesis algorithm. It did not make much of a splash, with the paper having only 7 citations in Google Scholar. Nevertheless, it produces some interesting sounds, so let’s dive into it.&lt;/p&gt;
&lt;p&gt;First, some context. The precursor to ISIS is a technique Barlow calls &lt;em&gt;spectastics&lt;/em&gt;. In this method, the short-time Fourier transform is computed of an audio signal, and at each frame, the magnitude spectrum is resampled logarithmically to 12EDO and used as a probability distribution to select a pitch. The pitch sequence forms an extremely rapid melody, which can be synthesized or played on a robotic instrument. Barlow describes the spectasized melody as “remarkably like the original sound recording.”&lt;/p&gt;
&lt;p&gt;In ISIS, this concept is taken to an extreme by making the “melody” a constant amplitude sine wave whose frequency is changed every sample. Given a digital signal that doesn’t exceed ±1, we can interpolate between any two successive samples with a partial cycle of a sine wave. An image helps here; the dots show the sampled digital signal.&lt;/p&gt;
&lt;img alt="Graph showing equally sampled points interpolated by a sine wave with rapidly varying frequency." class="align-center" src="https://nathan.ho.name/images/isis_interpolation_example.png"&gt;
&lt;p&gt;For example, if the samples are 0 and 1, as seen in the first two samples in the image, we can interpolate with a quarter sine wave with a period of 4 samples and a frequency of 1/4th the sample rate. There are actually infinitely many ways to do this interpolation. For example, from 0 to 1 we can also have a sine wave that completes 5/4ths of a cycle. We can even assume that the initial phase of the sine wave is &lt;span class="math"&gt;\(\pi\)&lt;/span&gt; and the final phase &lt;span class="math"&gt;\(5\pi/2\)&lt;/span&gt;, or have the sine wave going backwards with phase ramping from 0 to &lt;span class="math"&gt;\(-3\pi/2\)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;To resolve the ambiguity, ISIS restricts the frequency to be always nonnegative so the phase never goes backward, and always assumes the phase at every sample point is in the range &lt;span class="math"&gt;\([-\pi/2, \pi/2]\)&lt;/span&gt; modulo &lt;span class="math"&gt;\(2\pi\)&lt;/span&gt;. There are other approaches, such as picking the minimum possible nonnegative frequency or the frequency of minimum absolute value, which may produce interesting alternative sounds. I won’t get into these (this is a relatively low-effort post), but feel free to try them out.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://nathan.ho.name/posts/clarence-barlow-isis/"&gt;Read more…&lt;/a&gt; (7 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>dsp</category><category>effects</category><category>electronic music</category><guid>https://nathan.ho.name/posts/clarence-barlow-isis/</guid><pubDate>Sun, 15 Jan 2023 22:37:23 GMT</pubDate></item></channel></rss>