Copyright (C) 2015-2020 Dennis Sheirer
This fork is maintained for use with my fork of sdrtrunk and focuses on practical codec maintenance:
- Lint and code quality — visibility narrowing, dead code removal, encapsulation of internal implementation details, and general cleanup throughout the AMBE/IMBE codec paths
- Removed unused code — debug wave-generation utilities, the unused
ambepluspackage, and internal tables and classes not reachable from the sdrtrunk API. The old code is still in the repo history, just not in the production version. - Build compatibility — updated for current Gradle and JDK toolchains; I use JDK 26
- Reduced allocation pressure — instance-field reuse for hot-path buffers (noise samples, phase arrays, DFT bin scalars); eliminated per-frame array allocations in spectral amplitude interpolation, enum lookups, and overlap-add synthesis
- Tuning - AMBE frames are no longer decoded twice
- Bug fixes — fixed off-by-one in voiced band counting that inflated phase noise injection
- Codec correctness fixes — unvoiced band scaling now guards zero-energy FFT bands to prevent NaN audio output, and voiced phase handling uses consistent normalization to keep overlap-add synthesis stable across frame transitions
- Output calibration — final AMBE output is trimmed slightly before clipping so routine high-energy frames stay below the hard limiter more often without changing gain decoding or spectral amplitude math
- Voiced synthesis performance — replaced per-sample
Math.cos()calls with incremental phasor rotation, reducing transcendental function calls from O(samples × harmonics) to O(harmonics) per frame. At 50 voice frames/sec, 160 samples/frame, and up to 56 harmonics, this moves the hot path from ~448,000Math.cos()calls/sec to ~22,000 setup calls/sec, with the inner loop handled by multiply/add rotation. Audio quality is preserved or improved under A/B testing.
In short, this fork has been radically pruned to just what sdrtrunk requires and tuned to be faster than the original. Vectorization of the synthesis loop is difficult given the data-dependent branching on voicing decisions, but eliminating trigonometry from the inner loop and replacing it with fused multiply-add phasor rotation is a significant win on any hardware.
The original patent notice and upstream usage notes remain below.
Audio conversion library for decoding MBE encoded audio frames.
Decodes IMBE 144-bit and AMBE 72-bit encoded 20 millisecond audio frames to 8 kHz 16-bit mono PCM encoded audio.
PATENT NOTICE
This source code is provided for educational purposes only. It is a written description of how certain voice encoding/decoding algorithms could be implemented. Executable objects compiled or derived from this package may be covered by one or more patents. Readers are strongly advised to check for any patent restrictions or licensing requirements before compiling or using this source code.
Note: this patent notice is verbatim from the mbelib library README at (https://github.com/szechyjs/mbelib)
YOU DO NOT HAVE TO INSTALL THE JAVA JDK. The instructions for creating the JMBE library have changed starting with version 1.0.7.
- Download the latest JMBE Creator for your operating system from the Releases page.
- Unzip the JMBE Creator
- Open a command/console window and run the JMBE Creator application
- Windows: (unzip directory)/bin/creator.bat
- Linux/OSX: (unzip directory)/bin/creator
- When the program finishes, it will display the location of your JMBE library.
- Move the library to a permanent location
Note: for sdrtrunk use the menu item View > Preferences and then use the JMBE Audio Library section to tell sdrtrunk where your compiled JMBE library is located.
- Follow the same instructions for downloading the source code above. Use the following command to build the API:
WINDOWS:
gradlew.bat api
LINUX:
./gradlew api
-
Add the API library jar to your project.
-
Add the following code to your program
IAudioCodecLibrary audioCodecLibrary = null; try { URLClassLoader childClassLoader = new URLClassLoader(new URL[]{path.toUri().toURL()}, this.getClass().getClassLoader()); Class classToLoad = Class.forName("jmbe.JMBEAudioLibrary", true, childClassLoader); Object instance = classToLoad.getDeclaredConstructor().newInstance(); if(instance instanceof IAudioCodecLibrary) { audioCodecLibrary = (IAudioCodecLibrary)instance; } catch (Exception e) { //error handling } -
To convert 18-byte IMBE audio frames:
IAudioCodec audioCodec = library.getAudioConverter("IMBE"); float[] convertedAudio = audioCodec.getAudio(byte[] imbeFrameData); -
To convert 9-byte AMBE audio and tone frames:
IAudioCodec audioCodec = library.getAudioConverter("AMBE"); float[] convertedAudio = audioCodec.getAudio(byte[] ambeFrameData); -
To convert 9-byte AMBE audio frames and tone frames along with tone frame metadata:
IAudioCodec audioCodec = library.getAudioConverter("AMBE"); IAudioWithMetadata convertedAudio = audioCodec.getAudioWithMetadata(byte[] ambeFrameData);
-
Install the Java 8 (or higher) Java Development Kit (JDK). Note: this is different from the Java Runtime Environment (JRE) that most users have installed on their computers.
- Liberica OpenJDK: (https://bell-sw.com/)
- Oracle: (http://www.oracle.com/technetwork/java/javase/downloads/index.html)
-
Download the source code branch from GitHub:
- Version 1.0.6 (current): (https://github.com/DSheirer/jmbe/archive/v1.0.6.zip)
- Version 0.3.4 (previous): (https://github.com/DSheirer/jmbe/archive/v0.3.4.zip)
-
Setup the JAVA_HOME and PATH environment variables
-
Verify that JAVA_HOME points to the Java Development Kit (JDK) version 8 or higher. At a command prompt type:
- > echo %JAVA_HOME%
This should respond with the directory where you have installed the JDK.
-
Verify that your computer is using the correct version of the Java compiler. At a command prompt type:
- > javac -version
This should respond with the java version.
-
Unzip the source code file with a tool like 7-Zip or using the Windows File Manager (right-click on file)
-
Using the command prompt, change to the directory where you downloaded and unzipped the source code (jmbe-master.zip in this example):
- > cd C:\Users\Denny\Downloads\jmbe-1.0.6
-
Run the build script
- > gradlew.bat build
-
The build script will compile the source code and create the library. The first time that you run the build script, it may download some additional files needed for installing the gradle build tool and some java libraries needed for compiling the jmbe library code.
-
The compiled JMBE library will be located in a sub-folder named '\codec\build\libs', for example:
- > C:\Users\Denny\Downloads\jmbe-master\codec\build\libs\jmbe-1.0.6.jar
-
Follow the instructions for the application that will use the JMBE library.
Note: for sdrtrunk use the menu item View > Preferences and then use the JMBE Audio Library section to tell sdrtrunk where your compiled JMBE library is located.
- Setup the JAVA_HOME and PATH environment variables
(https://askubuntu.com/questions/175514/how-to-set-java-home-for-java)
-
Verify that JAVA_HOME points to the Java Development Kit (JDK) version 8 or higher. Open a terminal and type:
- > echo
$JAVA_HOME$
- > echo
This should respond with the directory where you have installed the JDK.
-
Verify that your computer is using the correct version of the Java compiler. At a command prompt type:
- > javac -version
This should respond with the java version.
-
Unzip the source code file with a tool like 7-Zip or ark using the File Manager (right-click on file)
-
In the terminal window, change to the directory where you downloaded and unzipped the source code (jmbe-master.zip in this example):
- > denny@denny-desktop:~$ cd Downloads\jmbe-1.0.6
-
Run the build script
- > ./gradlew build
-
The build script will compile the source code and create the library. The first time that you run the build script, it may download some additional files needed for installing the gradle build tool and some java libraries needed for compiling the jmbe library code.
-
The compiled JMBE library will be located at:
- > ~\Downloads\jmbe-master\codec\build\libs\jmbe-1.0.6.jar
-
Follow the instructions for the application that will use the JMBE library.