HNHacker News
TopNewBestAskShowJobs

m-hilgendorf

113 karma · joined October 14, 2019

personal: mike at hilgendorf . audio work: mike at tangram . dev

Software engineer at tangram.dev, formerly at JITX, Ambidio. Currently a generalist, formerly audio/DSP specialist.

submissionscomments
m-hilgendorf··on SIMD programming in pure Rust
People should be aware though that without `-C target_feature=+<feature>` in your rustc flags the compiler may emit function calls to stubs for the intrinsic. So people should make sure they're passing the appropriate target features, especially when benchmarking.

[0] https://godbolt.org/z/85nx44zcE

edited: I tested gcc/clang and they just straight up fail to compile without -msse3. The generated code without optimizations is also pretty bonkers!

m-hilgendorf··on Testing Generative AI for Circuit Board Design
imo, it's the same reason that Grace Hopper designed COBOL to write programs instead of math notation.

What natural language processing does is just make a much smarter (and dumber, in many ways) parser that can make an attempt to infer the intent, as well as be instructed how to recover from mistakes.

Personally I'm a skeptic since I've seen some hilariously bad hallucinations in generated code (and unlike a human engineer who will say "idk but I think this might work" instead of "yessir this is the solution!"). If you have to double check every output manually it's not that much better than learning yourself. However, at least with programming tasks, LLMs are fantastic at giving wrong answers with the right vocabulary - which makes it possible to check and find a solution through authoritative sources and references instead of blindly analyzing a problem or paying a human a lot of money to tell you the answer to your query.

For example, I don't use LLMs to give me answers. I use them to help explore a design space, particularly by giving me the vocabulary to ask better questions. And that's the real value of a conversational model today.

m-hilgendorf··on What Are You Building? Share Your Projects
I had need for a special purpose lock that solved this problem: There are `N` task sharing a single resource. It is incorrect for the `n`th task to acquire a lock on it until after the `n - 1`th task has released its lock. When the `N - 1`th task releases its lock the `0`th task may acquire the lock again.

I couldn't find any lock off the shelf that solved this, or a clean way to hack it with a fair mutex. So I wrote my own, and I'm pretty sure it's correct (1).

It's like a ticket lock, except the total number of tickets is known up front so every task can get one ticket. To acquire a lock is one CAS, where the lock is acquired iff the "current" value of the lock matches the ticket value of the task, if so we swap in a magic LOCK value. When the writer releases the lock it writes (ticket + 1) % num_tickets back to current so the lock can be acquired by the next task.

There's a deadlock condition though - if one task is cancelled while any other task is outstanding, no other task may acquire the lock, even if the cancelled task didn't acquire it!

To deal with that, the lock is poisoned with a magic POISON value. Then when any other task attempts to acquire the lock, but its value is POISON, then an error is returned and those tasks may be cancelled accordingly.

It's be possible to support adding/removing tasks concurrently by replacing the tickets with a circularly linked list of atomic pointers, so when one task is cancelled the "next" of the "prev" item can be atomically swapped, but I don't have a use case for that and it's annoying enough to write in Rust that I didn't want to bother with it.

(1) The code for this is here: https://github.com/m-hilgendorf/sequex/. I call it "sequex" for sequence-mutex. It could also be called a round-robin lock or something like that.

---

You could do this with just a ticket lock, where you take a ticket up front N times and then give one ticket to each task. When a task's ticket comes up it acquires the lock, but before releasing the lock, it takes another ticket. That's where I started, but I found this implementation cleaner.

m-hilgendorf··on JITX – The Fastest Way to Design Circuit Boards
As a former employee (2019-2021) it's heartwarming to see the comments shift from where they were five years ago to where they are today. The idea was proven out!

Keep up the excellent work, seeing the autorouter come to fruition and demoed on the homepage is a massive accomplishment and mind blowing.

m-hilgendorf··on Wddbfs – Mount a SQLite database as a filesystem
NFSv4 is stateful, and while it's true that the server has to support stateless reads for bad clients, most clients are ok with keeping the state ids that are returned after an open. Whether you have to step through the object byte-by-byte isn't inherent to the protocol, it depends on how you've stored the data.
m-hilgendorf··on Wddbfs – Mount a SQLite database as a filesystem
I've implemented both in the last 6 months and the only reason I would expect anyone to use NFS over FUSE is for MacOS without macfuse/fuse-t. fuse-t is a cool project that provides (iirc) the high level fuse interface (libfuse) via NFS on MacOS. Compare to macfuse, which implements the low level interface (/dev/fuse) via a kext.

FUSE is much, much easier to work with. The protocol (even v4) should also be less chatty, and if performance is your goal there are projects like ExtFuse that can move some caching into the kernel via eBPF which I don't think would be possible with NFS.

If you poke around other user space file systems (sshfs, cephfs, objectivefs, etc) they're all FUSE.

m-hilgendorf··on How to write a great README
It can also make your project inaccessible if you rely too heavily on images.

Personally I don't like too many images in a README. It's not a SHOWME. That's for your product page.

m-hilgendorf··on Crystal 1.9.1
For 3 I think it's Typescript and Dart. There's also stanza (1) which is a lot like Python but it's not being used outside of one startup (disclaimer: I used to work there). Ultimately I think optional typing on top of a garbage collected language is the answer.

(1) https://lbstanza.org/

m-hilgendorf··on JITX (YC S18) launches general availability and announces Series A from Sequoia
We have some code examples, for anyone that wants to see what a software-driven design looks like!

https://docs.jitx.com/tutorials/quickstart-1.html

https://docs.jitx.com/getting-started/example-design.html

m-hilgendorf··on Ask HN: Are there any companies that are doing interesting work in hardware?
I was about to shill!

Disclaimer: I'm an engineer at JITX. The core technology is a programming language for designs. It's a low level language for describing schematics and circuit boards, the kicker is that it's fully parametric and embedded into a high level language, which is stanza. The pitch I would give is that we're trying to do for hardware what GCC or NodeJS did for software engineering - everyone is hand coding assembly and manually checking it, we're building a compiler and set of libraries for getting things right and doing it fast.

I wouldn't just call it AI to automate circuit board design. We're definitely working on it and hiring folks for the tough optimization problems, but a lot of what we do is allow engineers to encode their expertise as reusable software components. I would say we're language and algorithm designers first, married to hardware designers.

For example, one of the cooler projects we did early in the pandemic was a mechanical keyboard designer that takes the JSON output of Keyboard Layout Editor and compiled it into a working circuit board and generated enclosure. I have it sitting in my office right now.

I may be overly biased but it's an awesome place to work. There are tons of interesting problems and great people. We have hardware experts designing boards, coming up with checks (think unit tests for hardware to automate design review), software folks doing our front end (a language server, custom VS Code extension to view circuit boards in a text editor), component selection, automatic placement, topological routing, web front end and backend, interesting and challenging DevOps, even real world compiler engineering - you name it. Every week is like the best course you've taken in CS - there so much to learn.

We're well funded and hiring. Since I joined in 2019 we've more than tripled in size and hiring! And frankly there's not many people working on this crucial problem. My email is in my profile if this sounds interesting to anyone.

m-hilgendorf··on Coding Up an IoT PCB Design
We've actually got some decent (imho) support for this in our standard library, OCDB (1).

The function call is a little deceivingly simple, it queries a parts database for one that fits the constraints like value/rating/stock and the part/footprint are parameterized by global design variables/rules under the hood.

(1) https://github.com/JITx-Inc/open-components-database/blob/1f...

m-hilgendorf··on I’m porting the TypeScript type checker tsc to Go
Rust encourages you to use an adjacent list/matrix for your graph representation, which is preferable almost all of the time for graph algorithms. It's a little unwieldy if the graph needs to be mutable during the core algorithms, but almost all algorithms in practice assume it will be stable.
m-hilgendorf··on I’m porting the TypeScript type checker tsc to Go
> 1) prototyping something where I don't want to spend time writing types

It doesn't compile to JS, but this is one of the canonical use cases for Stanza 's (1) "optional" type system

(1) http://lbstanza.org/optional_typing.html

m-hilgendorf··on Dear sir, you have built a compiler
Lucky for us, the language we embed the DSL(1) within has a REPL!

(1) http://lbstanza.org/

m-hilgendorf··on Dear sir, you have built a compiler
At my company (JITX) we've fully committed to compiler architectures in our stack, which makes sense since we're developing an embedded DSL for circuit boards.

It's remarkable how many problems are easier when you just accept it's some kind of compiler problem that needs parsing into a tree you can walk with a pass to spit out the required data. For example in audio networks, you can write a buffer allocation and latency compensation solver as a compiler pass over an AST that represents the network topology, collected by walking the network graph objects. It's way easier to write and test than using the same objects as the network itself.

I will say one of the downsides (if not tackled early) is incremental and streaming data through the architecture. It's a lot easier to write a batch parser than interactive one - which can hurt if you need partial compilation in the future.

m-hilgendorf··on How will MIDI 2.0 change music? (2020)
I think JSON makes a lot of sense. It's just orders of magnitude more complex to parse into useful data structures than MIDI1, or any other part of MIDI2.

Since MIDI is already going the opposite direction of say AES67 and reinventing wheels is ok, a custom binary encoding would have made more sense to me. Something that can be encoded in a C89 struct without a ton of trouble or doesn't need much thought put into an allocator on bare metal devices to get the handshake working.

I believe it's not strictly JSON though, I don't have the docs in front of me but iirc strings have a max length. So that's good.

m-hilgendorf··on How will MIDI 2.0 change music? (2020)
MIDI 2.0 is transport agnostic so it doesn't necessarily require USB, however USB is going to be the best solution for connecting many MIDI devices for awhile.

The big underlying change is that MIDI 2 is duplex, which allows for device discovery, property exchange, and profile configuration. What that buys you is an arbitrary protocol for exchanging information about what things are connected to each other on the same network of devices. It should allow for a lot of cool features, like supplanting Mackie Control and Eucon with an open (or at least trivially open) protocol. One thing I think we'll see with these is more support for microtonal or arbitrary pitch systems that MIDI currently can't realize.

Jitter compensation is built into the protocol too so it should resolve some of the timing issues with USB.

Having read through the spec and written the data structures out for it already I'm not sold that it's overly complex. The additional annoyance is that it mandates JSON parsing but that isn't a tall order these days.

m-hilgendorf··on Information Theory: A Tutorial Introduction
The edition with Weaver's introduction is also very good, especially if you would like the context and ramifications of Shannon's theory.

https://pure.mpg.de/rest/items/item_2383164/component/file_2...

m-hilgendorf··on My Favorite One Liners
On MacOS

   ./very-long-task.sh && say 'success' || say 'fail'
I use it when I need to context switch and leave something running. `espeak` is an alternative for `say` on Linuxes.
m-hilgendorf··on Reflections on the Lack of Adoption of Domain Specific Languages [pdf]
I have my own ideas about making CI/CD for DSLs easier. I don't think transpiling is necessarily the right approach, since not every language has a valid transpilation targe (here's my bias showing - consider a hardware description language, there can't really be a transpilation target).

One of the problems in designing generic tools for language development is they have to be far more abstract than the author might realize at first. The notion of evaluation is a big one, as in what it means to evaluate a chunk of code, what its results are, its intermediate products, and when the evaluation takes place (is it compile time, run time, parse time, etc). I think the next generation of tools are going to inspect these subtleties a lot more than traditional tools, since it has a big impact on usage when languages have heavy macro or other compile/parse time evaluation.

m-hilgendorf··on Reflections on the Lack of Adoption of Domain Specific Languages [pdf]
I think this is a great point, but I'd counter (disclaimer: I work on developer tools for a DSL).

It's a great time to create language tools. The language server/debug adapter protocols make it possible to develop a rich backend for your language of choice and a thin client to integrate into many editors, rather than extending a single editor/IDE platform. You don't really need to build an entire IDE to create a rich IDE experience, or tie that experience to a particular platform.

I'd also add that you can get really far without linters/static analysis tools. A DSL doesn't necessarily need them to be useful. That said, there are language agnostic linters you can use to add support for your own language.

I will say though that there needs to be richer/better language agnostic tools. There are a few for linting, debugging, static analysis, etc, but there's a need for things like auto formatting, CI/CD/general automation, build systems, and package managers. There are a many but it's tough to know which horse to pick.

m-hilgendorf··on Convolution Is Fancy Multiplication
I was introduced to convolution in a undergraduate signals/systems course in continuous time where it's basically magic that you memorize to pass your course. I think a better introduction would be through discrete convolution by reexamining polynomial multiplication (which is convolution through a different lens - the coefficients of the product of two polynomials is the convolution of their coefficients).

That serves as a less magical introduction to the operator. You can then point out that the polynomials whose coefficients one convolves can be considered power series, which has a nice interlude into the Z transform and its usefulness as an analytical tool when working with convolutions (and then on to the Fourier transform, etc).

m-hilgendorf··on The compositor is evil
> The only people doing real heavyweight real-time audio are music producers

I wouldn't discount the amount of people using voice assist and rely on noise reduction/echo cancellation in their meetings, or the near future where we have SMPTE 2098 renderers running on HTPCs.

I really think we're only a few years away from seeing a lot more realtime DSP in consumer applications. Conferencing, gaming, and content consumption all benefit immensely, and it would good for us all to start thinking about the latency penalty on audio-centric HCI like we do for video.

m-hilgendorf··on Home Studio Setup Costs Compared – 1980s And Now
I strongly disagree, and I say that as a classically trained musician. You can do pretty much everything with a mouse and (QWERTY) keyboard today. We've worked really hard to democratize content creation and lower the barrier to entry, we don't need to raise it by reinforcing the notion that you need a physical aptitude for playing instruments to create art with sound.

The computer can be an entry point for one's journey just the same as an acoustic guitar or piano. You can use that as your platform to learn theory as well as (if not better than) a piano or guitar.

But to get elitist for a moment, there's no better way to learn music aside from private lessons. That's true of any instrument, including the DAW.

m-hilgendorf··on Generics and Compile-Time in Rust
You can, it's how com-rs [0] works and we're co-opting it in vst3-sys [1] for non-Windows targets. It's painful, unsurprisingly. There are some people working on better abstractions, but I hand-coded a VST3 plugin using those macros just for the FFI-safe COM bindings and it is verbose and particularly unsafe [2]

I'm in disagreement with the parent, dynamic dispatch through vtables is only a zero-cost abstraction across FFI boundaries. Personally I'd ballpark about 33% of the value-add of traits are shared interfaces on different types.

The real money is in associated types and trait bounds. The latter is still a serious type-checking requirement at compile time, and the former requires RTTI to support dynamically in some form - both of which have costs at compile and runtime.

All that said, there may be an argument that the features GP is talking about are covered currently by enum variants (many of the use cases one would have for base classes with associated member variables are done that way, for example), and if you could show how performance and ergonomics improved by increasing the semantic complexity of dyn trait objects - you'd have a strong argument to add it to the language. Just my two cents.

[0] https://github.com/microsoft/com-rs/

[1] https://github.com/RustAudio/vst3-sys

[2] https://github.com/RustAudio/vst3-sys/blob/master/examples/p...

m-hilgendorf··on Rust/WinRT Public Preview
While we've been hacking on the vst3-sys crate [0], we wound up forking the mentioned com-rs crate to support COM APIs on non-win32 targets (notably, there's some stuff with endianness of the IIDs, the calling convention of the generated vtables) as well as usability (the com-rs crate only supports up to 5 interfaces implemented at once). We're still chasing down some issues with order mattering when implementing the interfaces. Even without those small changes, it's an impressive piece of macro programming that is very close to being usable for general purpose, ABI-stable rust crates.

As a little dose of irony, clippy doesn't like the com-rs crate too much.

[0] https://github.com/RustAudio/vst3-sys.git

m-hilgendorf··on Why Do FM Frequencies End in an Odd Decimal? (2015)
Some of my favorite radio stations broadcast(ed) below 88MHz. 87.7 and 87.9 are favorites of college and low budget FM broadcast.
m-hilgendorf··on Rust Survey 2019 Results
When people want better docs, do they mean better doc tooling or better doc writing? Because personally, I'm a huge fan of cargo-doc and its integration to the ecosystem. Just yesterday I found out about #![deny(missing_docs)] - which combined with executing code snippets in cargo test - enforces really good documentation discipline and ensuring that everything is doc'd, and that docs don't become stale.
m-hilgendorf··on Ask HN: Which open source project's C++ code is pleasure to read?
JUCE:

https://juce.com/discover/stories/coding-standards

https://github.com/WeAreROLI/JUCE

m-hilgendorf··on PID Without a PhD (2016) [pdf]
No, because a Markov process only depends on current state. All Markov processes are stateful systems, but not all stateful systems are Markov processes.

For example, an exponential moving average:

    s_n+1 = a x_n + (1 - a) s_n 
      y_n = s_n

    where a, x, s, y in Reals
The next state depends on all past state, including initial conditions.

Conceptually, stateful systems are the notion "where I am going depends on where I am." Markov processes are stateful systems where "where I am going depends on where I am, but not upon where I came from."

Page 1 of 2Next →