HN user

sudara

216 karma

Building an additive synth with 10k time domain oscillators (and blogging) over at https://melatonin.dev

Posts22
Comments47
View on HN
melatonin.dev 1mo ago

It's Timbre Time! An interactive comic about additive synthesis

sudara
4pts0
melatonin.dev 9mo ago

Show HN: I built an additive synth with 10k oscillators

sudara
3pts0
melatonin.dev 1y ago

Dev Therapy, part 4: Tending the narrative gardens

sudara
5pts0
twitter.com 2y ago

500 Harmonics, each with a different pitch lfo rate

sudara
3pts0
melatonin.dev 2y ago

Code Signing on Windows with Azure Trusted Signing

sudara
3pts0
github.com 2y ago

An expressive, quasi-Ptolemaic semi-modular synthesizer

sudara
3pts0
melatonin.dev 2y ago

Doing my synthesizer homework: The quirks of MIDI Velocity

sudara
2pts0
melatonin.dev 2y ago

How to code sign Windows installers with an EV cert on GitHub Actions

sudara
2pts0
melatonin.dev 3y ago

Dev Therapy Part II: Recoveries

sudara
3pts0
melatonin.dev 3y ago

Dev Therapy, part I: How to not get stuck (as a solo dev)

sudara
4pts0
letsken.com 3y ago

How to implement a web-based rich text editor in 2023

sudara
3pts0
blog.petersobot.com 3y ago

Reviving an Analog Polysynth with an Arduino, Ghidra, and Python

sudara
11pts2
github.com 3y ago

Pure Data as a plugin, with a new GUI

sudara
192pts54
validatemyplugin.com 4y ago

ValidateMyPlugin – Validate Your Windows, macOS or Linux VST3 and Audio Unit

sudara
3pts0
melatonin.dev 4y ago

How JUCE Components Work

sudara
8pts3
melatonin.dev 4y ago

Dealing with UI jank in the JUCE framework

sudara
4pts0
melatonin.dev 4y ago

How to create LLDB type summaries and synthetic children for your custom types

sudara
4pts0
medium.com 9y ago

Introducing Nextjournal

sudara
1pts0
blog.scoutapp.com 10y ago

Rails Performance and the Root of All Evil

sudara
8pts0
github.com 13y ago

Execute ruby code sometimes (little helpers to encourage variety)

sudara
37pts11
blog.ramenmusic.com 14y ago

Emily White needs no defense. She needs sustainable music businesses.

sudara
2pts0
alonetone.com 18y ago

music distribution without industry or commercialism

sudara
1pts0

Cache locality and specifically the vertical pass was top of my mind when trying to come up with good ways to vectorize. In the end (at least in my vector implementations) the difference between the passes weren't too large. But most of the them ended up having to do things like first convert the incoming row/col to its own float vector.

One main issue I never resolved is in the middle of the main loop, data has to be converted and written back to the source image and the incoming pixels have to be converted and loaded in. Even when doing all rows or cols in bulk (which was always faster somehow than doing batches of 32/64), that seemed pretty brutal.

I also wondered whether it might be more efficient to rotate the entire image before and after the vertical pass, but in my implementations at least, there wasn't a huge difference in the pass timings.

If you take a look at the video in my README, you'll see how bad it is.

Ahh, the video threw me off originally, I think because of the FPS glitches on the full width — but I see it now! Big bands of blue on the left and right edges. I'll have to cook up some examples to reproduce. Also curious what it means (if anything) in the drop shadow context.

I can say there is a huge performance tradeoff in using real division

Makes sense. It would also throw a wrench in my vector implementations, where the expectation is to perform the same operation efficiently across groups of pixels.

and that my library was therefore the best :)

Haha, well it was for me! I don't know Rust, but it helped me figure out my first C++ implementations!

Fixed! Sorry about that. The rustrepo stuff confused me!

My question is — was solving the edge bleed worth the (assumed) performance tradeoff? There were a couple vendor APIs that seemed to have smarter edge bleed options, but they performed worse. I never got around to actually visually comparing the images, though...

Thanks for all the great comments in your repo, they were quite helpful when trying to figure out how Stack Blur worked!

Thanks for the proofread! I had so much text juggling between this and the README that it was guaranteed some things would fall through the cracks! I updated the things you mentioned about `stackSum` and thanks for the catch on the `sumIn` definition.

It couldn't provide this if it was moving every value in the queue.

I actually don't remember anymore what std::deque does under the hood, I did look into it, but the only thing I remember is that it was quite slow!

You'd have to template the code on `radius` instead of passing it in as a runtime parameter so that the compiler could lower the divisions to bitshifts.

Yes, I really like this idea. Especially because radii only really vary between 1-48px for most drop shadow needs. It would be nice to have a handful of the common radii be ripping fast.

Audio Sparklines 5 years ago

This is great, thanks! I looked for existing unicode waveform representations before building, but didn't run into this. The unicode blocks the Julia REPL uses limits the output to magnitude (signed) vs. amplitude (unsigned), but it gets the job done!

Audio Sparklines 5 years ago

OMG, I thought I was already using ×, but that was a different project. Good call!

Audio Sparklines 5 years ago

STK is cool! I'm building a synth plugin, so that's why I'm in JUCE...

I want to hear more about the remote visualizer! I was using Jim Credland's buffer debugger (again, JUCE)[1]. It pops open a window, making it fairly easy to visualize buffers with one caveat: you actually have to tell it about the buffers you care about visualizing and then recompile. This means debugging can't really be on the fly (unless you only always care about the same buffer or two).

The other issue I ran into was viewing audio from my tests. I'd love to hear about the shared memory approach — real waveforms would be ideal!

1. https://github.com/jcredland/juce-toys/blob/master/jcf_debug...

Audio Sparklines 5 years ago

You found the Achilles' heel of the project! I don't mind the fonts being different sizes or not monospaced, but the fact that there's a difference in height in the font rendering between ⎺ and ‾ on different platforms is a bummer. I have a flag in the C++ implementation so they can still be rendered "correctly" in IDEs like Xcode [1].

I felt doomed to Unicode in this case because of the number of places I wanted them to show up (CLion lldb integration, GitHub actions output, terminal). I would have loved to actually render graphics! I actually never thought about how they would render on a blog article, I wouldn't generally wouldn't use them for blogging...

1. https://github.com/sudara/melatonin_audio_sparklines/blob/ma...

Audio Sparklines 5 years ago

Thanks for the constructive feedback! It's nice to have some new ideas.

In the audio contexts I'm working in, it is a feature to have the zero crossings and errors jump out. It's less "pretty" but is as data-dense as I could get just with unicode.

why not use color when available?

You are right, color would increase data density. In both my test context and in my debugger, color is unfortunately unavailable...

Silence should be easy to spot, not crammed behind numbers!

The condensed 0(256) notation is ugly, it's true. However, you can't miss it, and it's information dense. This was the toughest element to design and I tried a few other styles before this, because yes, it's ugly :)

I'm often working with buffers with 256+ zeros, so zeros had to be condensed to stay legible. Simultaneously, it's often necessary to know the exact number of empty samples (they could occur at the start, middle or end of the block). A dash - for a 0 such as in [----0(256)] might have some ambiguity with a quiet part of a signal (it's important to differentiate true zeros) but your post has me thinking!...

Agreed with all of that! Especially the poor sap who is reading the code wondering WTF...

So — my thinking for those two methods is to purposefully encourage being imprecise. We are always so obsessed with being exact in programming. And typically for good reasons. But in some cases, perhaps it doesn't matter if it's 50% of the time or 20% or 10% of the time. Just sometimes, not all of the time.

That being said, you bring up a fantastic point: what the hell does 'sometimes' mean? Half the time? What does rarely mean? It's certainly going to depend on the individual. No answers here, except I'm leaning towards redefining "sometimes" to mean between 15-50% of the time.

"Lifelike responses" — nice.

I like that "action potential" idea – I was trying to think of a good implementation for "do something twice a month per user" — decaying counter is a nice idea.

I'm with you on willy nilly making parts of your UI random — my use case is for changing up the text in greetings, general play with copy, and once in a while showing something like a tip or a "welcome back" message. Basically, small touches that convey a small sense of variety (vs. RANDOMLY DONT SHOW THE NAV!)