0
$\begingroup$

I'm developing an Android app which uses USB soundcard for input and output. The audio processes are in the native (C++) side.

The device's bit resolution is 16. I get the audio stream from the device as unsigned char* and have to convert them to float between -1.0f and +1.0f to process.

I do the conversion but it sounds like bit crushing effect if I increase the volume of input.

Here is what I do when converting:

For Input Conversion:

/*** buffer is an array of float ***/
/*** temp_buffer_in is the buffer coming from the device ***/

float divider = (float) std::pow(2, (BIT_RESOLUTION_IN - 1));
int BYTE_RESOLUTION_IN = BIT_RESOLUTION_IN / (sizeof(char) * 8);
int bytes = buffer_size * BYTE_RESOLUTION_IN; //Buffer size in bytes

for (i = 0, j = 0; i < bytes; i += BYTE_RESOLUTION_IN, j++) {

    UnionInteger16 union_int; // Union structure below
    union_int.i = 0;

    for (int k = 0; k < BYTE_RESOLUTION_IN; k++) {
            union_int.c[k] = temp_buffer_in[i + k];
    }

    buffer[j] = (float) union_int.i;

    buffer[j] = buffer[j] / divider;
}

For Output Conversion:

/*** temp_buffer_out is the buffer sent to the device ***/

float multiplier = (float) std::pow(2, (BIT_RESOLUTION_OUT - 1));
int BYTE_RESOLUTION_OUT = BIT_RESOLUTION_OUT / (sizeof(char) * 8);
int bytes = buffer_size * BYTE_RESOLUTION_OUT;

for (i = 0, j = 0; i < bytes; i += BYTE_RESOLUTION_OUT, j++) {

    if (buffer[j] >= 0) {
        buffer[j] = buffer[j] * (multiplier - 1.0f);
    } else {
        buffer[j] = buffer[j] * multiplier;
    }


    UnionInteger16 union_int; // Union structure below
    union_int.i = (int16_t) buffer[j];

    for (int k = 0; k < BYTE_RESOLUTION_OUT; k++) {
        temp_buffer_out[i + k] = union_int.c[k];
    }
}

I use Union for converting unsigned chars to int16_t and then to float. Here is the union structure:

union UnionInteger16 {
    int16_t i;
    uint8_t c[2];
};

Everything looks fine in the code but as I mentioned, the audio sounds like bit crushing when the input volume is increased and when the volume is decreased, the audio starts to disappear. I think I lost the dynamic range of the audio.

Sorry for the long question. I would be grateful if you help me. Thanks in advance.

$\endgroup$
  • $\begingroup$ May I ask why you downvoted the question? $\endgroup$ – Harun Yilmaz May 2 '15 at 15:06
  • $\begingroup$ I don't know why some silly user downvoted it without giving a reason, i upvoted it because it's asked in earnest. It is as much a programming question as a DSP question. probably more likely to get an answer on programming forum as it's simple array type conversion. You can check the float values of the result array to see if they have been bit reduced, rectified, or some similar scenario. $\endgroup$ – com.prehensible May 3 '15 at 9:08
  • $\begingroup$ @ufomorace Thank you for taking your time to upvote and care. Actually I'm logging both input bytes and output bytes without modifying in audio engine and they are the same. I thought it may be about a dithering issue but I'm not reducing the bit depth. I'm currently working hard to find a solution. If I find anything, I will post it here in case anyone else will need it. $\endgroup$ – Harun Yilmaz May 3 '15 at 9:19
0
$\begingroup$

In case anyone has the same problem, I want to tell that the above code works really well. My problem about the distortion of audio caused by wrong buffer size.

But while searching for a solution, I figured out that everyone says that using union may cause undefined behaviour in different CPU structures. It is said to use bitshift operations instead. So I decided to change the code for conversion as below:

Input Conversion

int16_t sample = 0;
    for (int k = 0; k < BYTE_RESOLUTION_IN; k++) {
    sample |= input_buffer[i + k] << (k * 8);
}

Output Conversion

int16_t sample_int16 = (int16_t) temp;
    for (int k = 0; k < BYTE_RESOLUTION_OUT; k++) {
    output_buffer[i + k] = (sample_int16 >> (k * 8)) & 0xFF;
}

And this conversion is made for Little-Endian system. If you have Big-Endian system, you have to change the k value properly.

Have a nice day

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.