We are excited to announce that we just released a course on C++ Real-Time Audio Programming with Bela. This is aimed at beginner to intermediate C++ users, so if you have so far been using Bela with other languages and you are interested in tipping you toes in C++, this is a great occasion. If you know your C++ stuff, you may still want to check out some of the more advanced topics (ARM/NEON assembly, state machines, fixed-point maths, timing, block-based processing).

During the course you will learn:

  • Writing real-time audio code in C++
  • Running that code on embedded hardware
  • Creating musical instruments, audio effects and synth modules
  • Turning digital signal processing theory into working code

New lessons will be coming out twice a week for a few months, covering programming topics such as:

Working in real time, Buffers and arrays, Parameter control, Classes and objects, Analog and digital I/O, Filtering, Circular buffers, Timing in real time, State machines, MIDI, Block-based processing, Threads, Fixed point arithmetic, ARM assembly language

all of this while building audio signal processors that implement:

Oscillators, Samples, Wavetables, Filters, Control voltages, Gates and triggers, Delays and delay-based effects, Metronomes and clocks, Envelopes, ADSR, MIDI, Additive synthesis, Phase vocoders, Impulse reverb

Subscribe to our youtube channel so that you don't miss any of the upcoming classes, and feel free to share this with your friends on Twitter, Facebook and Instagram.

Af a "getting started" lesson 0 last week, the course has fully started today with lesson 1, and the next class will be out this Friday at 5pm.

Note: you will need up-to-date Bela code to follow along with the course, as the example code relies on some of the latest features we added (namely the slider Gui via the GuiController library). Updating your board is covered in lesson 0.

As you'd expect, you can find support here on the forum, using the "Online C++ course" tag.

    6 months later

    This is excellnt for PD users like me. Thank you, that way i might finally find a way into dsp audio c++ coding.

    5 months later
    2 months later

    will try to make some time to finally check this out.
    the

    giuliomoro Af a "getting started" lesson 0 last week

    link redirects this very same forum thread, was it supposed to go to this video?

    2 months later

    This has been such a good course and platform for taking the scary steps from writing simple digital modules and patching things into working fully in C++. I'm happy that all the hard decisions are guided towards (data structures, methods, best libraries to use, etc). It's given me the confidence to build things from scratch that I've been trying to patch for a long time. Thanks for the effort put into making these!

      4 months later

      guttula Thank you for this message of confidence, personally I'll still have to convert to C++, as libpd is too slow for what i need to do. I have loads of Vanilla abstractions simplifying my PD life, just hoping, that i can retain the majority of such in C++.
      Starting that course then.

      4 months later
      2 months later

      Hi

      On “Lecture 3: Wavetables”, we learned we should avoid aliasing by avoiding harmonize we do not support.

      This is how I’ve implemented that
      (For now I’m following You tutorial on Desktop without bela device
      https://github.com/shemeshg/LearningRtAudio/blob/master/libs/TestRtAudio/TestRtAudioLib/Components/OscWaveTableAddative.cpp
      My Bella should arrive soon so it might look a bit different on real Bella
      ):

              for (unsigned int i = 1; i < harmoniesLevels.size(); i++)
              {
                if (((float)gFrequency * (i + 1)) > (sampleRate / 2))
                {
                  break;
                }
                gWavetable[n] += harmoniesLevels[i] * sin(fondamental * (i + 1));
              }

      * This is nice, but it is evaluated for every buffer, (Requires recalculating of the wavetable).

      • In “Lecture 8: Filters” we sow it might be possible to just filter those frequencies,

      Question:

      • What type of filter would you choose,
      • of what degree
      • how would you choose the Cutoff frequency
      • and What Q
        assuming it is the correct path to take?

      One fundamental issue with aliasing is that once you have introduced aliased components in your system, you won't be able to distinguish them from the non-aliased ones and therefore will not be able to filter them out trivially. A common approach in wavetable synthesis is to have several pre-computed tables, each bandlimted for a specific range of frequencies. The more tables you have the more memory you need and the fewer you have the larger the frequencies band will be and therefore the less ideal will be your bandlimited representation at least in some regions of a given frequency band.

      If you are in a memory-constrained application (e.g.: a microcontroller), another approach could be to have a single wavetable that you filter with a bandlimiting filter tuned according to the current frequency of the oscillator before reading from the table. This approach increases the CPU cost (because of the filtering), but reduces the RAM usage. In this case the ideal filter to use is a windowed sync FIR, but that may be too long (and therefore expensive to compute), however if one doesn't mind phase distortion, in practice a steep enough (e.g.: 4th order?) IIR (something like Chebyshev or Elliptic, which have a shorter transition band than Butterworth, are cheaper than an equivalent FIR but introduce phase distortion) would probably still be fine. However, it is unlikely that this would be a useful approach on Bela, as you probably have more than enough RAM to store several large-ish wavetables.

      2 months later

      Lecture 14: ADSR, Is it possible control the curviness/linearity of the ExponentialSegmentRampto?

      In time domain, it is no problem, for example:
      y=x for linear
      y=x(2) for curved, or y=x(2-1) for the opposite

      as I've implemented in time domain here

      https://github.com/shemeshg/LearningRtAudio/blob/lesson12_stateMachine/libs/TestRtAudio/TestRtAudioLib/Components/Envelopes/SimpleAdsrComponent.h

          double AdsrStep::getPowSignedZerowToOne(const double val)
          {
            return pow((double)position * (1.0 / (double)totalFramesLen), rescalePower(val));
          }

      The question is: how do we gradually add more linearity in the discrete domain for the Exp expression?,
      or maybe the opposite should we add more curve to the linear expression?

      The ExponentialSegmentRampto.cpp expression:
      pow(exp(-1/tow),1.0/sampleRate)

      Thanks
      Shemeshg

      Hi Shemeshg,

      It's a good question. In general, with an exponential function you really only get one parameter, which here is expressed as the time constant tau. However, in the ExponentialSegment class you do have a way of manipulating how linear (or not) the segment is: the overshoot ratio.

      The idea is that an exponential function asymptotically approaches its target value but never actually reaches it, so if we want the segment to end we need to aim for something a bit beyond where we actually need to get to, so that we reach the value in a finite time. In various situations in the lecture, we use overshoot ratios of around 1.01 or even 1.001, but other values could be chosen as well.

      If the overshoot ratio is very large (say 10+), then the segment will be nearly linear because you'll only get the very start of the exponential curve before it reaches the target. If it's almost exactly 1, then you will get a lot of curvature. In practice what this is doing is changing the value of tau while keeping the segment length fixed.

      3 months later

      Excellent course. Is there a lecture 22 showing assembly language use for audio?