This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Unable to decode ADPCM from Thingy 52

Hi guys,

I have a setup to receive the microphone data from the Thingy 52 on an nrf52840 evaluation board. Currently I recive the 131 audio packages ADPCM encodet. In the second step I implemented the iOS Swift example (https://github.com/NordicSemiconductor/IOS-Nordic-Thingy/blob/develop/IOSThingyLibrary/Classes/Services/SoundService/ThingySoundService.swift) to C to decode to PCM:

/** Intel ADPCM step variation table */
int8_t indexTable[] = { -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8 };

    /** ADPCM step size table */
int16_t stepTable[] = { 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28,
						31, 34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143,
						157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494, 544,
						598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878,
						2066, 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, 5894,
						6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, 15289, 16818,
						18500, 20350, 22385, 24623, 27086, 29794, 32767 };

#define min(a,b) (((a)<(b))?(a):(b))
#define max(a,b) (((a)>(b))?(a):(b))




static void decodeAdpcm(uint8_t* currentFrame, int16_t* output, uint16_t sample)
{
    //Achtung, man muss sich hier sicher sein, dass man auch die vollen 131 byte bekommt

	// A ADPCM frame on Thingy ia 131 bytes long:
    // 2 bytes - predicted value
    // 1 byte  - index
    // 128 bytes - 256 4-bit samples convertable to 16-bit PCM
    // Read 16-bit predicted value

	//var valuePredicted: Int32 = Int32(Int16(currentFrame[1])    | Int16(currentFrame[0]) << 8)
	int16_t val_0 = ((int16_t)currentFrame[0])  & 0x00FF;
	int16_t val_1 =  ((int16_t)(currentFrame[1]))& 0x00FF;
	int32_t  valuePredicted = 0;
    valuePredicted = ((int32_t)(val_1 |  ((val_0 << 8)& 0xFF00))) & 0x0000FFFF;
    if(valuePredicted > 32767 || valuePredicted < -32767){
    	NRF_LOG_ERROR("Start value out of range");
    }
    // Read the first index
    //var index = Int(currentFrame[2])
    int8_t index = (int8_t)(currentFrame[2]);
    if(index > 80){ NRF_LOG_ERROR("Something seems to be wrong with ADPCM Data ( To high)");}
    if(index < 0){ NRF_LOG_ERROR("Something seems to be wrong with ADPCM Data( Less Zeros)");}
    uint8_t nextValue = 0;// value to be read from the frame
	uint8_t bufferStep = 0; //false   // should the first f second touple be read from nextValue as index delta
	uint8_t delta = 0;     // index delta; each following frame is calculated based on the previous using an index
	uint8_t sign  = 0;
	int16_t step = stepTable[index];
	int16_t value;
	int32_t diff;
    for(int i = 0; i < 128 * 2; i++) { // 3 bytes have already been eaten

    	if (bufferStep == 1) {
            delta = nextValue & 0x0F;
        } else {
            nextValue = currentFrame[3 + i / 2];
            delta = (nextValue >> 4) & 0x0F;
        }
        bufferStep = !bufferStep;

        index += indexTable[delta];
        index = min(max(index, 0), 88); // index must be <0, 88>

        sign  = delta & 8;    // the first bit of delta is the sign
        delta = delta & 7;    // the rest is a value

        diff = ((int32_t)(step >> 3))& 0x0000FFFF;
        if ((delta & 4) > 0) {
            diff += ((int32_t)(step))& 0x0000FFFF;
        }
        if ((delta & 2) > 0) {
            diff += ((int32_t)(step >> 1))& 0x0000FFFF;
        }
        if ((delta & 1) > 0) {
            diff += ((int32_t)(step >> 2))& 0x0000FFFF;
        }
        if (sign > 0) {
            valuePredicted -= diff;
        } else {
            valuePredicted += diff;
        }

      //let value: Int16 =      Int16(min( Int32     (Int16.max), max(  Int32    (Int16.min), valuePredicted)))
       value =  (int16_t)(min((int32_t)32767   , max((int32_t)-32767   , valuePredicted)));

        step = stepTable[index];

        output[sample] = value;
        sample++;
    }

}

When I play the File with Matlab I can hear a very distorted version of the sound. Some of the packages are decoded properly and the other packages contain only 32767.

If I zomm in you can see the pattern. The red 'x' shows the start of a new package:

I dont get the clou why the one package is decoded prpperly and the next one only contains 32767. Maybe I did something wrong in the translation from Swift to C?

Thanks a lot for your help!

Peter

Related