top | item 47080873

Show HN: A small, simple music theory library in C99

57 points| lowsun | 10 days ago |github.com

18 comments

order

OptionOfT|10 days ago

As someone who only has used C in conjunction with Rust...

Given that it is 2026, what are some of the thoughts that go into choosing C99 vs C23, which I presume has more quality-of-life features?

jcalvinowens|10 days ago

Requiring C23 for a library header is a great way to guarantee nobody will use your code for long time.

I still write nearly ANSI compliant C for simple embedded things. Because somebody might need to figure out how to rebuild it in twenty years, and making that person's life harder for some syntactic sugar isn't worth it.

Even C99 can be a problem: for example, C99 designated initializers are not supported in C++. If your header needs to support C++ you can't use them (C++ forces you to initialize every field in the structure in order if you do it that way).

rabf|10 days ago

Very few people are using C for `quality-of-life features`. I'm fairly certain I've never even seen any C23 code, is it supported by many compilers or C tooling? One of the great things about C is that it is fairly easy to write code that runs everywhere and for a library that is especially important. There are many who just stick to C89.

fallingmeat|10 days ago

known quantity. UBs well understood. tooling.

firmretention|10 days ago

Yes, you sit at that piano every Sunday morning and play Mahler for Maris. But you hate Mahler. Besides Maris, who doesn't?

randomNumber7|10 days ago

What is the purpose of this and how would I use it (as someone who actually knows a lot about music theory and C programming)?

lowsun|10 days ago

Well, this library provides the core functions for classical, Western music theory (scales, keys, intervals, etc.). So any ideas that needs to understand or generate these structures could use them. Some examples off the top of my head:

- Music theory education tools - Music generation (and the outputs could be transformed to MIDI format for example) - Piano chord finder

and similar.

saivishwak|10 days ago

Love the point of 100% test coverage.

ceteia|10 days ago

Nitpicking:

https://github.com/thelowsunoverthemoon/mahler.c/blob/4ebfe8...

Should that type have been mah_acci instead of int? mah_acci doesn't seem to be used anywhere.

Also, have you considered using (edit) designated initializer syntax for some of the function calls that take in structs as arguments?

https://cppreference.com/w/c/language/struct_initialization....

    struct mah_scale scale = mah_get_scale(
        (struct mah_note) {
            .tone=MAH_C,
            .acci=MAH_NATURAL,
            .pitch=4
        },
        &MAH_BLUES_SCALE, notes,
        MAH_ASCEND,
        NULL
    );

lowsun|10 days ago

Ah yes, that is by design. This is because it supports more than a double sharp / double flat (eg triple sharp, quad sharp, etc). The enums are there just for the most common values so it's easier to read.

As for second, that's a good point! Would definitely make readability better, thanks.