FAUST generates C/C++ code that is really hard to read, so it’s not really a good way to understand how to implement code in C. I will say the best way to understand how to write DSP code in C, FAUST, or any other language, is to learn the underlying mathematical concepts first. I’ve found this especially true for things like filters. By the time filters are implemented, all the coefficients are fully derived and what you are left with are a bunch of arithmetic + trig operations with magic variables that don’t make much sense. Audio DSP code for the most part is actually surprisingly simple in terms of structure. As a colleague of mine once said, “it’s all multiplies and adds”.

Personally, I really enjoy writing in C for my audio-related work because it is simple and portable. Software typically has a very short shelf life before it crumbles out of neglect, but I believe that this is unacceptable for the computer musician. We need tools that can sustain our creativity for many decades, and can even be run for future generations of computer musicians to study and improve on. Because it really sucks having to learn a new thing every few years. I want to actually try to master something, yknow? It’s a very tall order, but when I write a tool or component in clean unfancy C89 C or C99 C, I feel like I have a chance at that kind of sustainability. I’d really like to see a push for more of this kind of thinking in the digital art world. Our ecosystems for so creation are so brittle right now…

I’ve always found that when I write things in C, I always come up with more elegant solutions. C gives you very little in terms of data structures and algorithms, so it’s up to you to make good thoughtful design decisions, and I quite like that.

I’ve always found C++ to be this huge complicated beast. I never feel like I can write anything small and simple in it, and I like writing small and simple things. It’s one of those weird languages where codebases have to agree on which features to use and which features not to use. Sometimes they can be difficult to compile because I’ll have a C++ compiler that is out of date. Also, no one is able to give a straight answer on how to learn C++ in 2019? You don’t really need any of that fancy stuff to do audio DSP. C is a language that allows you to build things without any of the nonsense (you get to build that nonsense yourself. heh.).

9 Likes

Btw @PaulBatchelor there was talk and some action toward putting a ‘proper’ forth on the aleph for control, menus etc… Never happened and I guess the moment’s well and truly passed :grinning:.

However the fact that forths are not garbage collected but (reputedly) permit complex metaprogramming (I’ve written quite a bit of lisp) made me think semi-seriously about using a forth on the blackfin to make its DSP programming more interactive (everything about aleph programming is very much plan, plan, plan, deep dive)…

Wouldn’t have thought at that time about using a forth to glue together ugens. However this sounds like a brilliant approach and the sporthlings are very inspiring!

Have you done any work glueing sporth to external sequencers/controllers or for processing instrument sounds?

2 Likes

Admittedly, Sporth isn’t really a true Forth. It only uses the Forth-like syntax for notating an underlying audio graph data structure. Initially, I chose to model Sporth syntax after Forth because I read somewhere that Forth parsers were very easy to build. It being a very expressive way to build complex modular patches was a happy accident.

Sporth is designed to be easy to embed into other places, and I’ve done a few proof-of-concept experiments integrating it into other music environments, including ChucK, PD, Protrekkr, and LMMS. I’ve also built my own sequencers for Sporth, which includes a music tracker: https://github.com/PaulBatchelor/spigot

In Sporth, everything is signal based, so sequencing is limited to monophonic voices or layered monophonic voices for polyphony. Sequencers need to be able to convert discrete note-like data into a continuous audio-rate signal in order for it to be read by Sporth.

While I haven’t explored it as thoroughly, Sporth can (and has) been used to process external audio. The Chorth (Chuck + Sporth) UGen, for example, overrides the “in” ugen in Sporth to read from a mono input signal from ChucK. This small example here shows a sawtooth oscillator in ChucK being processed by a reverb inside of Sporth: https://github.com/PaulBatchelor/Sporth/blob/master/util/chorth/in.ck

These are all very initial proof-of-concept experiments with Sporth. Personally, I don’t find myself using these too often, but there is still much to explore here. If anyone here is interested enough to help maintain some of these efforts, send me a PM.

3 Likes

I’ve been given the chance to study algorithms relating to pitch perception this summer through an undergraduate research project — I’m super excited to finally have the time to get into the gritty details of digital sound. I’m familiar with the maths involved (however I certainly won’t claim I know everything about DSP), although I’m a bit confused about choosing the right library / framework to build from. I’m set on using C++ on macOS.

I’ll be studying the performance of a number of pitch tracking algorithms and maybe get to implement a weird hybridation of granular and additive synthesis I dreamt up. I only really need the basics — If I can read and write from sample buffers then I can write the algorithms, although having filters and existing implementations of a few standard pitch tracking algorithms would be nice.

From what I’ve gathered, JUCE, STK, and SDL could fulfil my needs. What I’m not too sure about is code reusability / portability and expected lifespan. If anyone wants to share their experiences or thoughts on the matter it would be much appreciated!

2 Likes

Starting by building your code as max/msp externals might be a great way to abstract away the audio management and routing side of the code while you focus on the algorithms and control structures. Eric Lyon’s excellent book on the subject is a great help though a little dated now — the style and manner of coding for max/msp hasn’t changed, only a few types and constants to support 64-bit, which the author provides as supplementary info via his website.

6 Likes

You’ll probably spend a lot of time just experimenting with the algorithm, for this a rapid prototyping environment like Matlab or Octave would be helpful. This step won’t produce anything real-time, but it will allow you to make a lot of decisions up front without the overhead of C++.

When you’re ready to make something interactive/realtime, I’ll second @equipoise’s recommendation to create a Max external. For historical reasons Max community likes C rather than C++ but if you’re going to make an app, best to embed a C++ delegate object in the “C” max object (it works) and then you’ll have something you can port anywhere else.

You may actually be fine with the Max implementation, especially as this is an academic project. You can create a simple GUI in Max or hook up controllers, and you already have real-time audio.

If you want to develop something with a nicer/custom UI, say for commercial development or just to go beyond what Max allows, then you’d use something like JUCE to create AU/VST etc.

for very basic, easily implemented pitch tracking (just a starting point… you may find more “updated” methods for comparison): http://audition.ens.fr/adc/pdf/2002_JASA_YIN.pdf (note: it’s not perfect and parameters will always need tweaking for your test cases/source material. but still pretty good for an easily implemented algorithm).

3 Likes

existing implementations of a few standard pitch tracking algorithms

hm i dunno if that sounds like a likely thing to encounter off the shelf.

my favorite, (update to yin, i think? bit simpler?):
http://www.katjaas.nl/helmholtz/helmholtz.html

important bit on “special normalized autocorrelation”
[ http://miracle.otago.ac.nz/tartini/papers/Philip_McLeod_PhD.pdf ]

using matlab or scipy or something good idea,

same good practices in DSP as anywhere else. use abstraction judiciously - in this case FFT should be a well contained wrapper. kissfft is convenient for testing.

pitch tracking is one case where test suite makes sense. especially since you want to do something comparative anyway

3 Likes

If I can read and write from sample buffers then I can write the algorithms, although having filters and existing implementations of a few standard pitch tracking algorithms would be nice.

A friend and colleague of mine wrote a paper that studies a few pitch tracking algorithms. You should definitely give it a read if you haven’t already: https://ccrma.stanford.edu/~kermit/website/scpitch.html

Soundpipe has adopted a pitch tracking algorithm originally written by Miller Puckette, adapted from the ptrack opcode in Csound. It is a very portable opcode written in c99-compliant C code. It is also the main pitch tracker used by AudioKit. You can study the code here:

(PSA: if anyone can make this better/faster, please consider contributing it to AK. They would be very very grateful!)

My advice to you would to make sure your algorithms can rendered offline to an audio file. Why? Because debugging audio DSP code is a slow and tedious process… you will need all the help you can get. Tracking down nils and trying to figure out why your filter is exploding is such a tedious experience. Getting things to work inside of a command-line program makes testing a whole lot easier. From there, it is a trivial process to get things up and running on a realtime system.

For the library to use, I highly recommend using libsndfile. It’s so simple and straight forward to use. Here is some sample code to get you started:

In fact, this is the very same sample code I started out with when I started to learn how to do audio programming as an undergrad.

10 Likes

Looks very promising and indeed simpler, probably a better choice than YIN these days.

The point of these “classic algorithms” isn’t necessarily how good they perform in an unmodified state, but that they’re good pedagogical starting points to being thinking about the issues of pitch tracking in general. that is, after getting one of them to work, you’ll be in a much better shape to read other papers; you’ll have a good framework in which to think about modifications or even creating your own algorithm from scratch.

at some point you’ll need your own ideas because you’ll always have different assumptions, goals, materials in mind than did the authors. everything is specific to some degree.

also a great point. But it also highlights the need for a Matlab (or Octave/scipy) reference that also works on file I/O. You can make sure everywhere along the block diagram your Matlab/C input and output files are identical (although you may run into problems with how each deals with floating point characteristics – may not get them exactly “identical” on the level of bits).

I know this sounds like a lot of overhead and duplication – you’re putting in significantly more effort up front, but it will really save you in debugging.

4 Likes

teleporting this discussion over here - this looks totally useful to me rn & not something I’ve heard of before. anyone else have experience w/ using audio APIs in a C environment as opposed to writing low level maths ?

also, are there any good places to find example code and algorithms for audio processes ?

the situation is: stating to get my handle on using C/C++, but still far away from understanding & implementing low/mid-level audio processes.

i’m a bit confused. the STK is a pretty classic library and seems like a good starting place for your questions… e.g the STK tutorial?

note that STK is implemented directly in C++ though; not sure this is the right thread for it.

STK source (c++)
CSound source
SuperCollider source (c++, but the inner loops are basic)
PD source
musicdsp.org

or a book by
boulanger/lazzarini
richard moore
will pirkle (c++)

e.g., all the stuff already mentioned in this thread and similar threads:
https://llllllll.co/t/lower-level-audio-programming
https://llllllll.co/t/dsp-book-recommendations

of course… learning a specific library is a pretty different thing from learning the math behind the algorithms yourself.

2 Likes

The Soundpipe library was built with that in mind (I am the author):

If you stick to just rendering audio files, Soundpipe by itself has everything you need.

2 Likes

ahhh didn’t know about this thread, probably mis-migrated & that would be a decent lookthrough as well

Per @zebra’s suggestion, I moved things over here :wink:

1 Like

A big turning point for me was being able to jump into some of these codebases. It is more about pyschology than understanding, IMO. Being able to say “fuck it, lets jump in and try and see how this works” is a very useful mindset to have at any level. It also is helpful to look read random bits of code, as it helps you learn to skim code to get the gist of things. The more you do it, the more confidence you will get in jumping in.

If you aren’t sure if you are ready or not to jump into things, you are ready. Just download some code, open a file, and start going line by line to see what you can understand. 90% comprehension? Great. 10%? Great! Nothing at all? Also great. There is something to be said about just the physical act of moving eyeballs across code.

I have looked at the source code for the projects listed above at varying degrees. For those interested in doing some code spelunking, here are my thoughts on them below. If any one wants to contribute their own person thoughts and experiences, feel free:

STK:

I have spent minimal time looking at this code, but it seems fairly readable. The core codebase is very small, and written in a style of C++ which I call “C+”. Code basically reads like C with classes.

Csound:

I have spent a considerable amount of time examining the source code to Csound, and adapting some of the algorithms for soundpipe. There is a treasure trove of great DSP algorithms there, but it definitely took me a while to get used to reading. It has a range of coding styles. A lot of the older code can be cryptic to read, and the style should not be emulated. If you get the Audio Programming Book, I recommend reading John ffitches chapter on Opcode design (this is what I did to learn). His tutorial has code samples that boil away some of the weird bits of the production code that you don’t really need to understand. Opcodes can be in a variety of places, depending on what decade they were made. I would recommend grepping for the opcode in quoates to find the dictionary entry in the code, then finding the compute code that way.

SuperCollider:

I actually know the least about this one. I’ve had some SC friends of mine tell me that SC did a major refactoring effort a while back. Looking at the code, I certainly believe it. It is written in what looks to me like clean enough C++ code (I do not really know C++ code, so I can’t really speak much on this). C++ is one of those languages that keeps evolving, so I have no idea of it is “modern C++” or not. Like Csound, SC has a rich ecosystem of good DSP algorithms. C++ has a tendency for code to be more coupled together, so my biased opinion is that it is could be harder to extract DSP code from SC than from Csound? But what do I know here.

PD:

I am only a casual PD user, mostly using it as a prototying environment. I managed to learn enough PD guts to get a fork of PD vanilla embedded as a sort of PD file player without the use of the libpd. I have also managed to implement some undocumented features in some of my custom PD objects by looking at standard PD object code.

Look at PD vanilla source code, if you are going to look at PD. It is actually a pretty small codebase, so you could definitely digest a sizeable chunk of it if you wanted to. Many people will tell you that PD source code is hard to read, but honestly it is not too bad if you are just interested in looking at external code. There is a lot of similar-looking code you can use as a rosetta tablet. Similar to Csound, PD has a lot of old-school looking code and design choices. Both Csound and PD were written for very different kinds of computers that we use today! So just take in things with a grain of salt.

11 Likes

VCV Rack (https://github.com/VCVRack/Rack), is another open source project in C++ worth exploring the source code – seems very well written and organized.

4 Likes

! these are all solid suggestions !

1 Like

agreed, it’s a really clean project. i didn’t include it cause the stuff actually included in Rack engine is pretty minimal (momstly in these headers.)

some great building blocks though (FIR, IIR, minblep) as well as some stuff that is wrapping heavy libraries (speex resampler.)

super nice infrastructure

ooooo made me realize - was thinking about stealing functionality from some mutable instruments source code but it looks like the audible instruments source is basically a bunch of handy wrappers for their modules - might be pretty easy to wrap that into a max external (though I suppose that would be the less learning things route)

this is kinda what i mean. most actual VCVR functionality is not in the framework, it’s in the modules. some of them are by the framework author (andrew belt) and many are not.

the biggest one by AB is Fundamental

and, less extensively, his ports of Eseries and Befaco

they’re all worth looking at

the Audible Instruments stuff is interesting case. it’s not in fact a wrapper around Mutable Instruments source (which is well worth looking at itself; emilie is a great developer); rather, AB appears to have ported (most of) the functionality from MI, using the VCVR framework components instead of the MI conponents (makes sense since the latter are highly focused on STM32 processors.) there are significant differences; like, at first glance VCVR Clouds seems to have a pretty different interpretation of the “quality” parameter.

(all of AB’s code is highly dependent on building blocks from VCVR. e.g., the Fundamental VCF module defines sample update loop and UI, but the routines to actually compute the filter coefficients (viz, the hard part) are in the dsp headers linked above.)

maybe worth noting that some of this gets definitely into C++ specific language features (templates) and libraries (algorithm), though nothing super crazy

5 Likes