...an audio engine for Android, using either OpenSL (compatible with Android 4.1 and up) or AAudio (Android 8.0 and up) as the drivers for low latency audio performance. The engine has been written for both MikroWave and Kosm to provide fast live audio synthesis.
MWEngine provides an architecture that allows you to work with audio within a musical context. It is easy to build upon the base classes and create your own noise generating mayhem. A few keywords describing the out-of-the-box possibilities are:
- tempo-based sequencing with support for alternative time signatures
- on-the-fly audio synthesis
- multi-channel audio output
- effect chains operating on individual input/output channels
- sample playback with real time pitch shifting
- bouncing output to WAV files, either live (during a performance) or "offline"
Also note that MWEngine's underlying audio drivers are the same as Google Oboe uses, MWEngine and Oboe are merely abstraction layers to solve the same problem, only in different ways. Additionally, MWEngine provides a complete audio processing environment.
The Issue Tracker is your point of contact
Bug reports, feature requests, questions and discussions are welcome on the GitHub Issue Tracker, please do not send e-mails through the development website. However, please search before posting to avoid duplicates, and limit to one issue per post.
Please vote on feature requests by using the Thumbs Up/Down reaction on the first post.
Though the library is written in C++ (and can be used solely within this context), the library can be built using JNI (Java Native Interface) which makes its API expose itself to Java, while still executing in a native layer outside of the Dalvik/ART VM. In other words : high performance of the engine is ensured by the native layer operations, while ease of development is ensured by delegating application logic / UI to the realm of the Android Java SDK.
Whether you intend to use MWEngine for its sample based playback or to leverage its built-in synthesizer and audio processing, you are not required to write any additional C++ code. If you however intend to create your own DSP or synthesis routines (which is fun to do!) you must write them in C++, but can rely on SWIG for making them usable in Java.
It is important to note that when a Java object finalizes (i.e. all its references are broken and is garbage collected), the destructors of the native objects are invoked, which can lead to unpredictable results if you happen to overlook this! As such, audio engine objects such as effects processors or events that are created on the Java side, must also hold strong references during their lifecycle. Basically, follow the same principles you'd use in Java, but be aware that ignoring these will have a particularly violent result with a very unfriendly stack trace.
If you intend to use Android Studio you can open the build.gradle file to setup the project and its dependencies accordingly by following the on-screen steps.
For CLI builds:
You will need both the Android SDK and the Android NDK. Additionally, you will need SWIG (available on most package managers like Brew for OS X or apt-get on Linux)
You will need Gradle to run the build scripts. All aforementioned utilities are available on all major Operating Systems.
If you are using Android Studio, creating a project from the supplied build.gradle file should suffice to get you to build both the native and Java code as well as enabling building, debugging and packaging directly both from its IDE.
When NDK builds fail, be aware that ndk-build doesn't like it when paths contain spaces (yeah...)
In case the Java build fails due to missing classes, see below to compile the audio engine as a library using CLI.
After making sure you have all the correct tools (see Environment setup):
The makefile (/src/main/cpp/Android.mk) will by default compile the library with all available modules. The SWIG interface file (/src/main/cpp/mwengine.i) includes all the engine's actors that will be exposed to Java.
Those of a Unix-bent can run the build.sh-file in the root folder of the repository whereas Windows users can run the build.bat-file that resides in the same directory, just make sure "ndk-build" and "swig" are globally available through the PATH settings of your system (or adjust the shell scripts accordingly).
After compiling the C++ code, the SWIG wrappers will generate the nl.igorski.lib.audio.mwengine-namespace, making the code available to Java.
You can create the .APK package and deploy it instantly onto an attached device / emulator by using Gradle e.g. :
gradle installDebug
To create a signed release build, add the following into the Gradle's properties file inside your home folder (~/.gradle/gradle.properties) and replace the values accordingly:
RELEASE_STORE_FILE={path_to_.keystore_file}
RELEASE_STORE_PASSWORD={password_for_.keystore}
RELEASE_KEY_ALIAS={alias_for_.keystore}
RELEASE_KEY_PASSWORD={password_for_.keystore}
You can now build and sign a releasable APK by running:
gradle build
The contents of this repository should result in a stable application. If you experience issues with the setup, consult the Troubleshooting Wiki page.
You can view the Wiki (which documents all of the engine's actors as well as a variety of real world use cases) here:
https://github.com/igorski/MWEngine/wiki
Note that you can also view the contents of the header files to get more details about the inner workings of each class.
The library comes with unit tests (/src/main/cpp/tests/), written using the Googletest C++ testing framework (distributed with NDK 10). To run the tests, simply execute the test.sh (sorry Unix-only shell at the moment)-script with a device attached. This will also build the library prior to running the tests by calling the build script described above. Note: adb must be available in your global path settings.
Note on unit testing: To build the application for unit testing observe that there is a separate makefile for the unit test mode (see Application_test.mk). In short: this file sets the compiler preprocesser MOCK_ENGINE which replaces the OpenSL driver with a mocked driver so the engine can be unit tested "offline".
The repository contains an example Activity that is ready to deploy onto any Android device/emulator supporting ARM-, ARMv7-, x86- architecture and running Android 4.1 or higher. The example will demonstrate how to quickly get a musical sequence going using the library.
To install the demo: first build the library as described above, and then run the build script to deploy the .APK onto an attached device/emulator (note that older emulated devices can only operate at a sample rate of 8 kHz!).
The AAudio implementation has been built using (in Google's words): "a Preview release of the AAudio library. The API might change in backward-incompatible ways in future releases. It is not recommended for production use." so use it at your own peril. To use AAudio instead of OpenSL:
- change the desired driver in global.h from type 0 (OpenSL) to 1 (AAudio)
- update the Android.mk file to include all required adapters and libraries (simply set BUILD_AAUDIO to 'true')
- update target in project.properties to android-26
Once AAudio is a stable library, MWEngine will allow on-the-fly switching between OpenSL and AAudio drivers.
(!) MWEngine does not support recording from the device inputs using AAudio just yet, (igorski#70) references this feature.
MWEngine has received welcome contributions (either suggestions on improving the API or proposal of new features, solving of bugs, etc.) from the following developers :
- Andrey Stavrinov (@hypeastrum)
- Toufik Zitouni & Robert Avellar (Tize)
- Koert Gaaikema (@koertgaaikema)
- Matt Logan (@mattlogan)
- Thomas Flasche (@harthorst)
- Rickard Östergård (@rckrdstrgrd)
- Aran Arunakiri