Adventures In Pitch Shifting

I utilize audio sample playback in a few ways in my Soundb0ard application - I have one shot sample playback, and I have a Looper which uses a form of granular synthesis to time stretch.

Sample files are stored in PCM Wav files which have a header, followed by the audio data stored in an array of numbers, one per sample. Normal playback entails playing those samples back at sample rate at which it was recorded, e.g. 44,100 samples per second.

In order to pitch shift a sample playback, i.e. slow it down or speed it up, you have a few options. You can think of pitch shifting as resampling, e.g. to play a sample back at twice the speed, you could resample at half the original sample rate, i.e. remove half the samples, and then playback the resampled audio at the original sample rate; or to slow down playback to half-speed, you could play every sample twice.

However, what happens if you want a fractional pitch, such as 1.1 x original speed or 0.8? The naive way, which I’ve been using up till now, was to progress through the array at the fractional speed, i.e. instead of moving through the array 1 sample at a time, I would maintain a float read_idx, that would increment at the sample ratio, e.g. 1.1 x and then calculate the playback value as a linear interpolation between the two closest points in the audio data array. This works ok for some ratios, but some can sound a bit too gnarly.

Recently via a reddit thread I came across this wonderful resource - Sean Luke, 2021, Computational Music Synthesis, first edition, available for free at http://cs.gmu.edu/~sean/book/synthesis/

"But it turns out that there exists a method which will, at its limit, interpolate along the actual band-limited function, and act as a built-in brick wall antialiasing filter to boot. This method is windowed sinc interpolation."

Windowed Sinc Interpolation relies on this Sinc Function:

"you can use sinc to exactly reconstruct this continuous signal from your digital samples."

The links on this page can explain the math better, but basically in order to convert the frequency / sample rate, you walk through your original samples as the new sample rate and apply this sinc operation over a window of neighboring samples before and after your current sample, applying and summing the result of the sinc function.

From the Sean Luke book above, i converted this algorithm into code:

My first implementation didn’t work. The pitched signal was recognisable but was amped too high and sounded a lil janky. I think I mixed up some indexes with the value they should be representing.

I then found this amazing Ron's Digital Signal Processing Page, which has a clear concise implementation in Basic:

I implemented this in C++, and the code was clearer to read. After applying the repitch my signal was still clean but no matter what pitch ratio I used, my return signal was always double the original pitch. I must have made a calculation wrong. Possibly to do with handling stereo values.

Lazily I turned to Google Gemini…

> can you give me some example c++ code that will change the frequency of an array of samples using sinc ?
..
<boom>>
> can you expand that example to handle a stereo signal?
<boom>>
> using an interleaved stereo signal, please
<boom>>
> can you improve the algorithm using a hann window?
<boom>>

Ok, quite impressed. I dropped the code into my Looper, and it worked great.

Heres the before, with linear playback:

Heres the after using windowed sinc.

I think it sounds cleaner and better, so i think the implementation works? I’ll play with it a while and see if I prefer it. Here’s the current code:

Job done?
No, there are some performance trade-offs.

I initially implemented it for the granular playback system, which meant only dealing with small arrays of data. However this meant I was doing redundant work, recalculating the same values upon each loop.

I moved the window sinc operation to be run once when you call the RePitch function. This becomes a performance bottleneck as those samples can be large arrays, and you dont want this being run on your audio thread as if it takes too long to run, you’ll experience audio drop outs. I looked to a newer feature of C++ to run the repitch algorithm, using std::async from <future>.

MORE BYTES

Finished a track I’d been working on recently, and decided to put together a wee bandcamp release of things I’ve finished this year. All written and performed with Soundb0ard.

DX100 SysEx data dumper



One of my software synths is based on the DX100. I programmed it by following along with Will Pirkle’s 'Designing Software Synthesizer Plug-Ins in C++', a most awesome book. FM synthesis has a reputation for being notoriously difficult to program, so most people with one of the original Yamaha DX range tended to just modify the presets. Building my own software implementation means I don’t have any presets, so I mostly stuck to randomizing the settings and saving the ones which sounded decent.


More recently I’ve started learning how to create FM patches from scratch, and when you dig in a little, you find it’s not actually that hard to start sculpting decent sounds. With FM synths, oscillators and envelope generators are combined into a unit called an Operator. These Operators can either be used as Carriers, where the sound they generate can be heard, or as Modulators, which modulate the sound of the Carriers, creating interesting timbres. These Operators can have multiple configurations of how they are connected, i.e. which are Carriers and which are Modulators. That makes more sense with a diagram. Here’s the layout of the 4 Operators for the 8 x DX100 algorithms:

The button row of each algorithm are the Carriers, the ones which we can directly hear. The Operators above them are modulating the ones below.

The secret to designing your own is start simple, use one of the first 4 Algorithms, and switch off all but the first Operator, gradually adding modulation from higher Operators. The first 4 algorithms all have only one Carrier, and the other 3 Operators apply modulation in various combinations. From Algorithm 5, you start to get combinations of Carriers, up to Algorithm 8 which is no longer applying FM, but instead is a purely additive synthesis with the 4 Operators acting as Carriers.

As I’ve been designing my own patches, I have become more curious about the original DX presets, some of which have their own kinda cult following, especially the Jazz Organ preset, which is maybe mostly widely down from Robin S’s “Show Me Love”. (See an excellent wee blog post on its history and mix from Mark Fell here.)

I discovered there are many resources online for sharing DX patches, which can be loaded into compatible synths. The DX line of synths use a binary format called SysEx to store and transmit patches. SysEx messages became an unofficial but de facto standard, and you can find lots of SysEx files online. The ones I found were specifically Midi bulk data messages containing 32 Voice VMEM. Specifically this has a 6 byte header, then 32 voices stored in 4096 bytes, and a closing 2 bytes footer.

While searching I found many Sysex librarian programs which allow you to manage and apply the voices but I couldn’t find what I was looking for - a way to just display the settings stored within the DX100 SysEx files. The closest I did find was this dxsyx, a “C++ library for manipulating DX7 SysEx files”, which offers a human readable YAML output, which is exactly what I was looking for, however that library is only the DX7 with its 6 operators, and not compatible with DX100 Sysex format. The original Yamaha DX synth, the DX7, has 6 Operators which are combined into 32 algorithms. The later DX100 and compatible DX21 and DX27, all used 4 Operators organized in 8 algorithms.

I decided to write my own parser, I figured it could be quite a fun exercise! I borrowed quite a lot of code from the before-mentioned dxsyx, a lot of the header checks and the general approach. Quite simple really, read the file into a data array (std::vector<uint8_t>), and peel it off byte by byte, mapping the bytes to the expected Sysex fields. Where my dumper differs from dxsyx is in the parsing of the bytes, which need to be mapped correctly to the values needed for the Voice and Operator values, specific to the synth model. The hardest part was finding an exact specification of the DX100 Sysex format to ensure the binary data I was reading was being mapped to the correct data field.

The DX-100 manuals I could find listed the Sysex VMEM data fields in detail:


But not how the byes were laid out in memory. For that I found a related manual for the Yamaha TX81Z, which “uses the same 4-operator, 8 algorithm FM synthesis as the DX21, DX27 and DX100, and voice data can be transmitted and received between them”
Here’s the binary layout of fields:

With that information, I could loop and parse each of the 32 voices. Most of the data are byte length, but a few are packed and require some bitmasking to extract.
Full code is on my github.

Build:
clang++ -o dx -std=c++20 main.cpp

Usage: ./dx inputfile.syx

Here in my ‘dx100_1.syx’ i found the illustrious ‘Jazz Org’

It seems to work pretty legit. The data still needs some translation for use however. The ‘algorithm’ field is 0 indexed, so in this case its Algorithm 8, which is correct according to Mark’s blog post

Another example is the frequency ratio field, which is crucial in the timbre of FM synthesis. In the data output, the ratio value is an index into a table of frequency values. I had learned this already from the Will Pirkle book. Using the indexes listed above, the frequency ratios from my dump show ratios of 3, 1, 6, and 1, which also agree with Mark’s description.

The values for the envelope length are in “rates”, a value between 31 and 0, where 31 is an instantaneous one, and 0 is a long change. I haven’t yet found a mapping between these envelope rates and milliseconds, so i’ve just been mapping them between 0 and 1000ms.

Applying the values to my own dx software synth, the Jazz Organ preset sounds decently convincing, but some of the other presets sound a little wonky when imported to my synth, so i think i still have a bit more interpretation to play with, most likely around feedback. But yeah, pretty fun wee project! Check it here

Pop music and Magic, 2021



I’ve lived out here in the Sunset for over ten years. When you come to know the neighborhood and start to learn its fog shrouded mysteries, it’s really no surprise how easily magic can happen.

But I didn’t know that back then.

Through media and literature, San Francisco had called out to me, a young man living on the outskirts of Glasgow, Scotland. It began in 1989, when a friend's older brother gave the fifteen-year-old-me a copy of The Electric Kool-Aid Acid Test. I was enchanted with stories of Ken Kesey and The Merry Pranksters, painted and mystical, wired for sound in La Honda. Then there was the writings of Kerouac, specifically The Dharma Bums, with its dexedrine fueled storytelling and midnight road trips; articles in The Face and iD about the burgeoning SF House music and club scene, hanging out on a sunday morning at The End-Up; the crazy tech weird of R. U. Sirius and Mondo 2000. Finally in the spring of 1994, after I swallowed the six Tales Of The City books, swiftly followed by the Channel4 television adaption, I walked, bewitched, into the nearest travel agent and booked myself a flight, my first visit to the City By The Bay. I came back several times over the next few years, staying for extended periods of time, making friends, making art, making magical memories.

Alas, the dot-crash happened, jobs and my visa disappeared, and I had no choice but to leave, my SF life cut too short.

I moved to London in the winter of 2001, a great city in itself, and I fully immersed myself in the music and art scenes, enjoying all it had to offer. I had a good life, a decent job, and a great circle of friends. But I yearned. I couldn't settle. No matter how well things were, I would still find myself dreaming of idyllic bike rides over cascading hills, chimeric shops in the limbic space between North Beach and Chinatown near where Animal Chin went underground. I could picture how the sunlight would make everything shimmer, how the color of the sky changed at dusk, those beautiful reds, pinks and purples. I remembered hitchhiking through Big Sur, gazing out over the vast Pacific ocean.

*Sigh* Best just to move on, accept where I was, no point in looking back or holding regrets. The odds of being able to go back were stacked against me, living 5,351 miles away. And having focused on my record label for most of that time in London meant I was no longer current in the kind of in-demand work that could get me a visa.

But... but.

But Pop music. And Magic.

There was a comic out of the UK back in the ‘00s called Phonogram by Keiron Gillen and Jamie McKelvie. The story was about a group of DJs who used the power of Pop music to cast spells. There was a backup story in one of the issues, in which the lead character, a Phonomancer, explained to a friend how it worked. I paraphrase, "You know that feeling when you're listening to a song and it gives you chills, it makes you feel like you could do anything? That's the key - that energy is Magic. You can channel it and use it".

I mean, of course, Pop Magic is possible. Isn't it? It's all about belief - believe the hype, at least believe your own hype. Magic and Pop - symbolism, the mysticism of romance, rock-n-roll, soda-pop and a late night kiss.

Miles Kurosky knew it.

Miles Kurosky lived in San Francisco and had a band named Beulah. I loved Beulah - still do. Presumably the band is named after Beulah Street, just off Stanyon. I listened to the four Beluah albums on repeat for the whole summer of 2004, perambulating the streets and canals of London's East End, deliberately lost, loving and exploring its psycho-geographic past, yet still dreaming of California.

An idea struck me in early 2010. On Beulah's third album, The Coast Is Never Clear, there is a track by the name of “Gene Autry." The chorus goes like this:



When I get to California,

Gonna write my name in the sand.

I'm gonna lay this body down

and watch the waves roll in.



Well, easy - there's my plan. I use this song in a magical ritual. I fly to California, write my name in the sand while listening to this track, and boom, my spell should be in effect, which would surely provide a path for me to return.

So that's pretty much what I did. I made the arrangements, took a flight, landed, took BART to 16th, walked up 16th, swung right on Guerrero, across Market to Haight, and finally to Fillmore and my hotel. After dropping my luggage, I jumped on the 7 and sat there, head against the window, my mind on fire as it took in the sights and sounds of the City I had been dreaming of for those long years, as the bus lazily weaved its way out to Ocean Beach.

The sun had set by the time I arrived. I climbed up and over the sand dunes at the bottom of Noreiga, my jacket flapping in the wind, the ocean roaring hungrily as it clawed itself up the beach. There wasn't much light when I got away from the orange sodium street lamps, save for the far-off lights of Pacifica. It was a perfect night for Magic. After finding an appropriate stick I could use, I queued up “Gene Autry” on my iPod, took a deep breath, pressed play and got to writing my name in the sand. I wrote it a second time, just for good measure. I yelled into the wind, "I want to live here, I want to come back!".

The wind howled back indifference.

I stayed at the beach a little longer, feeling a little foolish, but at least I had followed through on my plan. I thanked the Ocean and headed back downtown.

But maybe something did happen. A few days later on that trip, I went to visit a friend at his workplace, a music distributor whom I had dealt with for my record label. Just as I was leaving the office I crossed paths with an old boss of mine from the 90s - he was now the engineering manager at this music distributor. We got to catching up. We asked after people we had known together, laughed about some industry stuff, and that was that. I bid my farewell and a few days later I flew back to London, somewhat resigned but content.

When I got back to the UK, however, I kept an eye on job openings with the distributor. A few months later, somewhat incredibly, an opportunity came up under my old manager, which I was totally suitable for. Within a year of that beach “spell” I had successfully made it back to the City, with a visa in hand, and a one bedroom apartment on Taraval and 23rd, less than a mile from where I had scrawled my name on that windy evening.

In retrospect, it doesn't seem so crazy. It just took some intent. One fortuitous event, precariously balanced on another, dependent on a dream inspired by a song and a comic book. I mean, of course it was gonna pan out!

But would it all have happened without that trip to the beach?

Pop music and Magic.

Huh.


Discount Computer Software

I’ve been a big fan of Evel records out of spain for a few years - tons of great releases from artists I love such as William Fields, Deli Kuvveti, NOXIN, Guy Birkin, and many more. So I was super stoked when they approached me last year about putting out a release!

It dropped on a friday, a split release with an amazing Spanish artist named AmorObsoleto!

My tracks are done via my custom live coding software, Soundb0ard

Code Rush - Netscape/Mozilla documentary

I was revisiting the Don Melton episode of Internet History podcast and heard them mention ‘Code Rush’ - I kinda vaguely remember watching this years ago, but quite nutty to revisit now. It’s such a crazy time-capsule, covering the tail end of the Browser wars, as Netscape rush to meet their own deadline to release the source code of Netscape Communicator, and the formation of Mozilla.org.

Riveting!