Built using Jetpack Compose, Oboe library, C++, Kotlin, and modern architecture guidelines.
Android Wavetable Synthesizer Tutorial Series
- App Architecture (this one)
- UI with Jetpack Compose
- Calling C++ Code From Kotlin with JNI
- Playing Back Audio on Android with C++
- Wavetable Synthesis Algorithm in C++
Recently, thanks to my employer Loudly, I went to droidcon Berlin 2022 and learned a lot about modern Android development. That is, “modern” as of 2022 😉
Figure 1. At droidcon Berlin 2022, I was lucky to meet Manuel Vivo of Google and listen to his talk on the modern Android app architecture. And I was happy to get some German pretzels too!
Recent developments on this platform, especially, the brand-new Compose UI framework, inspired me to write a synthesizer app for Android.
What kind of synthesizer? A wavetable synthesizer, of course!
We’ve built one in Python, another one in Rust, and another one in C++ as an audio plugin. So why not Android?
The goal of the app is to build a wavetable synthesizer on Android with basic controls. You can see them in the user interface (UI) of the app.
Figure 2. Graphical user interface of the synthesizer app we are going to build.
The secondary goal is to use cutting-edge Android tools and practices like
- Kotlin programming language,
- Jetpack Compose UI framework,
- Oboe audio library,
- and modern Android architecture guidelines.
What Will You Learn?
Thanks to this tutorial, you will learn
- How wavetable synthesis can be implemented in an app,
- Kotlin basics in a fun and easy way, including Kotlin Coroutines,
- Android development basics,
- Jetpack Compose framework basics,
- Interfacing Kotlin code with C++,
- Controlling audio output on Android,
- How to implement Android architecture guidelines.
Who Is This Tutorial For?
This tutorial is for:
- Complete Android beginners who want to learn app development basics in an enjoyable way,
- People who want to learn wavetable synthesis and how to implement it,
- Android developers who want to learn the audio side of Android apps,
- Kotlin developers who want to understand coroutines,
- Android developers who want to see a modern Android architecture in action,
- Android developers who want to learn Jetpack Compose,
- C++ developers who want to learn how to interface with Android audio-wise and UI-wise.
Full Source Code
The complete source code is available on GitHub.
Before we start with the project setup, I want to discuss the architecture of our app.
How can one come up with an architecture at the very beginning?
The answer is: one doesn’t.
Figure 3. Boromir knows what he’s saying 😉.
The architecture is something that should be kind of a sketch in our minds or on paper that only guides us in the right direction during implementation.
To keep the architecture flexible, I always try to follow advice from “Software Architecture” by Robert C. Martin and abstract out the details.
In practice, this means using interfaces when we’re unsure how we will implement certain functionalities.
So here I will show you the architecture of the completed app. The initial idea was similar but still different from the end product.
Android architecture guidelines encourage developers to build their apps in layers.
Figure 4. Officially recommended app architecture by Google (source).
In general, I prefer the ports and adapters approach. As a result, our app is a mix of the two.
Figure 5. Architecture of our wavetable synthesizer Android app. <I> marks an interface.
We can observe that our app consists of 7 parts:
- UI layer, which defines how our app will look.
- ViewModel layer which holds the UI state (e.g., sliders’ values) and communicates changes to the
- A very small and very “dirty” (i.e., concrete, non-abstract)
MainActivityto plug our app to the Android ecosystem, initialize the app, and connect everything.
- Kotlin-side wavetable synthesizer representation, which can be a gateway to the native C++ synthesizer or a dummy class for testing purposes.
- Java Native Interface (JNI) code that allows interfacing Kotlin and C++.
- C++-side wavetable synthesizer that contains actual business logic regarding the synthesizer.
WavetableSynthesizerC++ class delegates its functionalities to a handful of smaller classes that aren’t shown in the diagram.
- Sound playback layer that is conveniently abstracted behind an interface so that it can be easily replaced in the future. In our app, we will implement the
AudioPlayerinterface using the Oboe library from Google.
Actually, this architecture could be used for any synthesizer that doesn’t use keys or MIDI. For example, with more sliders, we could build a frequency modulation (FM) synthesizer. But let’s leave that for another occasion! 😉
Finally, I want to list all the tools and libraries that I’m using with their respective versions.
- Android Studio Chipmunk 2021.2.1 Patch 1
- CMake 3.18.1
- Jetpack Compose 1.1.1
- Kotlin 1.8.0
- C++ 20
- Oboe 1.6.1
The remaining dependencies can be found in the build.gradle file.
Part 1 Summary
In this introductory part of the tutorial, we discussed the goals of the project and the architecture of our wavetable synthesizer Android app. Following this tutorial in full or in parts will allow you to learn a handful of modern technologies in an easy and enjoyable way. You can code it yourself or you can download the source code from GitHub. Have fun!
If you want to check out my guidelines on what knowledge is needed to write sound-processing software, download my free audio plugin developer checklist.
Up next: implementing the UI in Jetpack Compose!
Comments powered by Talkyard.