Voice over BLE – ADPCM to Audio conversion in Android


The Voice Over BLE defines two roles: the TRANSMITTER and the RECEIVER. The TRANSMITTER is the device which acts as the “microphone side” and sends the voice data to a device named RECEIVER. The RECEIVER is the device that receives the voice data over the air from the RECEIVER and outputs it.

When i have started looking for converting RAW ADPCM to Audio, have gone through many articles and didnt found many code samples but found very little information on the internet.

When i have decided to write my own algorithm to convert RAW ADPCM to Audio. based some articles over the net i have started writing my code.

At some point i have understood that converting RAW ADPCM to Audio is not possible. so i have to convert ADPCM to PCM and then PCM to WAV.

In this article you will only see the algorithm, For the full code with working example to convert RAW ADPCM to Audio, you can reach me at niranjan.devasani@gmail.com

ADPCM algorithm

Adaptive differential pulse-code modulation, or simply ADPCM, is an audio algorithm for waveform coding, which consists in predicting the current signal value from previous values, and transmitting only the difference between the real and the predicted value. In plain pulse-code modulation (PCM), the real or actual signal value is transmitted. The advantage of ADPCM is that the difference between the predicted signal value and the actual signal value is usually quite small, which means it can be represented using fewer bits than the corresponding PCM value.

Depending on the desired quality and compression ratio, the differential signal is quantized using 4 (2 bit), 8 (3 bit), 16 (4 bit) or 32 (5 bit) levels. Many implementations of the ADPCM algorithm exist. They differ by the quantization and the prediction patterns.

The IMA ADPCM algorithm provided in this application note is used to encode audio files that have the following specification:

● Audio format: PCM

● Audio sample size: 16 bits

● Channels: 1 (mono)

● Audio sample rate: from 8 kHz to 44.1 kHz Each 16-bit PCM sample is encoded into a 4-bit ADPCM sample, which gives a compression rate equal to ¼. The implementation of the IMA ADPCM algorithm consists in two functions, one that codes and the other that decodes the audio samples.

ADPCM Encoding – 16 bit PCM to 4 bit ADPCM

The ADPCM_Encode function returns a byte containing the 4-bit ADPCM sample. The software has to store every two ADPCM samples into one byte to save memory space.

Example: Input: pcm_sample1 and pcm_sample2; two 16-bit PCM samples. Output: adpcm_byte; two 4-bit ADPCM samples stored into one byte.

/* Encode the first 16-bit sample */
code = ADPCM_Encode(pcm_sample1);
/* Store the first 4-bit sample */
adpcm_byte = code;
/* Encode the second 16-bit sample */
code = ADPCM_Encode(pcm_sample2);
/* Store the second 4-bit sample */
adpcm_byte = (code << 4); /* The adpcm_byte contains two 4-bit ADPCM
samples */

ADPCM Decoding – 4-bit ADPCM to 16 bit PCM

ADPCM_Decode function The input of the ADPCM_Decode function is a byte that contains the 4-bit ADPCM sample. The software has to extract the 4-bit ADPCM data and store them into a byte before calling the ADPCM_Decode function.

Example: Input: adpcm_byte; two 4-bit ADPCM samples stored into one byte. Output: pcm_sample1 and pcm_sample2; two 16-bit PCM samples.

/* Extract the first ADPCM 4-bit sample */
code = (adpcm_byte & 0x0F);
/* Decode the first ADPCM sample */
pcm_sample1 = ADPCM_Decode(code);
/* Extract the second ADPCM sample */
code = (adpcm_byte >> 4);
/* Decode the second ADPCM sample */
pcm_sample2 = ADPCM_Decode(code);

For converting PCM to WAV we have to set header based on the parameters we are expecting. this article may be more helpfull to understand the WAV header. http://www.topherlee.com/software/pcm-tut-wavformat.html

This is the function we can use it to convert PCM data to the WAV audio format. based on your audio encoding you have to change the configuration. you can find the above link for more information about header configuration.

private void rawToWave(final File rawFile, final File waveFile) throws IOException {

    byte[] rawData = new byte[(int) rawFile.length()];
    DataInputStream input = null;
    try {
        input = new DataInputStream(new FileInputStream(rawFile));
    } finally {
        if (input != null) {

    DataOutputStream output = null;
    try {
        output = new DataOutputStream(new FileOutputStream(waveFile));
        // WAVE header
        // see http://ccrma.stanford.edu/courses/422/projects/WaveFormat/
        output.writeChars("RIFF"); // chunk id
        output.writeInt(36 + rawData.length); // chunk size
        output.writeChars("WAVE"); // format
        output.writeChars("fmt "); // subchunk 1 id
        output.writeInt(16); // subchunk 1 size
        output.writeShort((short) 1); // audio format (1 = PCM)
        output.writeShort((short) 1); // number of channels
        output.writeInt(SAMPLE_RATE); // sample rate
        output.writeInt(SAMPLE_RATE * 2); // byte rate
        output.writeShort((short) 2); // block align
        output.writeShort((short) 16); // bits per sample
        output.writeChars(output, "data"); // subchunk 2 id
        output.writeInt(output, rawData.length); // subchunk 2 size
        // Audio data (conversion big endian -> little endian)
        short[] shorts = new short[rawData.length / 2];
        ByteBuffer bytes = ByteBuffer.allocate(shorts.length * 2);
        for (short s : shorts) {
    } finally {
        if (output != null) {

The above function is there in JAVA and used it in android, but you can convert it into any programming language you prefer.

The above function will take RAW PCM file as input and create WAV audio file. which can be playable with almost all the android and IOS mobiles and devices.