0

I have char pAudioBuffer buffer which i got from function ffmpeg:

int len = avcodec_decode_audio3(av_codec_context,
            (int16_t *) pAudioBuffer, &out_size, &packet);

I know that audio format is two bytes per sample, i need to convert every two bytes to short value, i have tried to use code snippet below, but i often got zero instead of short value:

int shortBufIndex = 0;
for (int i = 0; i < (out_size); i += 2) {
    char b1 = pAudioBuffer[i];
    char b2 = pAudioBuffer[i + 1];
    short sample = atoi(&b1) + atoi(&b2);
    shortBuffer[shortBufIndex] = sample;
    shortBufIndex++;
    LOGI("BUFFER_ITEM='%d'", sample);
}

What i'm doing wrong, how to convert every two bytes in char buffer to short and and back.

UPDATE:

system's byte order is LITTLE_ENDIAN i have test it like this: Endianness of Android NDK

How can i convert every two bytes in buffer to sample of short type and back. Please can you provide any code sample.

UPDATE

I have tried to access to short as pairs, here is my fixed code, but it not work, i don't hear any sound:

    int shortBufIndex = 0;
    for (int i = 0; i < (out_size); i += 2) {
        char * byte = (char *) pAudioBuffer[i];
        short * sample = byte;
        shortBuffer[shortBufIndex] = sample;
}

What i'm doing wrong? I need conversion like this: byte array to short array and back again in java but in c.

Community
  • 1
  • 1
testCoder
  • 7,155
  • 13
  • 56
  • 75
  • 1
    Why don't you just pass `shortBuffer` instead of `pAudiBuffer` to the ffmpeg API? – alk Dec 15 '12 at 17:48
  • @alk How can i accomplish that, is it simply replace `pAudioBuffer` with `shortBuffer`. – testCoder Dec 15 '12 at 17:52
  • I have tried to use shortBuffer instead of pAudioBuffer but when i pass it to AudioTrack i hearing some noise, i cannot use that approach. – testCoder Dec 15 '12 at 18:56
  • There might be an endian issue here. If the endianess used by ffmpeg and your system differs, you could use `ntohs()` to convert each element of `shortBuffer`after it had been filled by the call to `avcodec_decode_audio3` like so: `size_t size = out_size/2; for (size_t i = 0; i < size; ++i) shortBuffer[i] = ntohs(shortBuffer[i]);` – alk Dec 16 '12 at 09:36
  • @alk when i try to use `ntohs` i hearing only noise, but when i use short without `ntohs` i hearing sometimes noise (periodically). It seems not work. – testCoder Dec 16 '12 at 11:57

3 Answers3

2

The use of atoi() with the address of the variables is entirely mistaken and incorrect. That is for converting the ASCII representation of a value into a number. In your case, you don't really have a buffer of "characters" but rather a buffer of byte values, which under the history of C is commonly implemented with the char type rather than something more recent and definitive such as int8_t.

To convert between a character buffer and a short buffer, you first need to answer the critical question if the encoding of the character buffer is in the system's native endian order, or opposite to it.

If it is in native endian order, then in a language such as C all you have to do is cast the pointer type to a short, and access the data as pairs of bytes.

However, if it is in opposite order, you will have to access the two bytes and combine them (shift + add) in opposite order from usual. There may be macros for doing this which you can use, though doing it by hand has the advantage of making the functionality fully evident.

Chris Stratton
  • 39,853
  • 6
  • 84
  • 117
  • How to define is buffer in system's native endian order? – testCoder Dec 15 '12 at 17:57
  • 1) identify what the system's native endian order is (by built-in defines or by testing it), 2) check the documentation of the library function you are using as to what it expects. – Chris Stratton Dec 15 '12 at 18:03
  • `and access the data as pairs of bytes` - how? Can you provide code example. – testCoder Dec 15 '12 at 18:55
  • If it is in native endian order and aligned, just cast and assign to short pointer and access with that. However remember that you only add one (instead of two) to the offset per value, because a short pointer points to pairs of bytes (the compiler does a hidden multiply by two when adding an offset to a short pointer, by four when adding to a 32-bit int's pointer, etc). – Chris Stratton Dec 16 '12 at 15:45
1

Na. you have to write

short sample = b1<<8|b2;

or, depending of your endian-situation, you have to swap b1 and b2

pbhd
  • 4,384
  • 1
  • 20
  • 26
1
short *pshBuf = (short*)pCharBuf;

It works. I am using the same in my live projects as well.

Suman
  • 4,221
  • 7
  • 44
  • 64