ITU-T G.711 C source code to Java JNI
Bit of backstory, I'm developing a Java softphone with a variety of audio
codecs, and after some answers here and there, I've learned that it's
better to do the audio decoding in native code due to speed.
So my first big step is to implement the PCMU G.711 audio codec in C and
link it into my Java application, which already has a Java-based PCMU
implementation.
I could rewrite it in C, but I want to have a bit of standardization, so
I'm pulling the ITU-T G.191 Software Tools Library source code
(http://www.itu.int/rec/T-REC-G.191/en). This is done with the intention
that I will also use the G.191 STL for other G-series codecs.
This is how they've written the u-law encoder:
void ulaw_compress(lseg, linbuf, logbuf)
long lseg;
short *linbuf;
short *logbuf;
{
long n; /* samples's count */
short i; /* aux.var. */
short absno; /* absolute value of linear (input) sample */
short segno; /* segment (Table 2/G711, column 1) */
short low_nibble; /* low nibble of log companded sample */
short high_nibble; /* high nibble of log companded sample */
for (n = 0; n < lseg; n++)
{
/*
--------------------------------------------------------------------
*/
/* Change from 14 bit left justified to 14 bit right justified */
/* Compute absolute value; adjust for easy processing */
/*
--------------------------------------------------------------------
*/
absno = linbuf[n] < 0 /* compute 1's complement in case of */
? ((~linbuf[n]) >> 2) + 33/* negative samples */
: ((linbuf[n]) >> 2) + 33;/* NB: 33 is the difference value */
/* between the thresholds for */
/* A-law and u-law. */
if (absno > (0x1FFF)) /* limitation to "absno" < 8192 */
absno = (0x1FFF);
/* Determination of sample's segment */
i = absno >> 6;
segno = 1;
while (i != 0)
{
segno++;
i >>= 1;
}
/* Mounting the high-nibble of the log-PCM sample */
high_nibble = (0x0008) - segno;
/* Mounting the low-nibble of the log PCM sample */
low_nibble = (absno >> segno) /* right shift of mantissa and */
& (0x000F); /* masking away leading '1' */
low_nibble = (0x000F) - low_nibble;
/* Joining the high-nibble and the low-nibble of the log PCM sample */
logbuf[n] = (high_nibble << 4) | low_nibble;
/* Add sign bit */
if (linbuf[n] >= 0)
logbuf[n] = logbuf[n] | (0x0080);
}
}
From Java to JNI, I will be passing a byte[] array of PCM linear data and
be returning a byte[] array of encoded PCMU data. Assuming I convert Java
byte[] to jbyte* to char* to short* for the ITU-T's above method, I
thought that it was supposed to take a 16-bit code word and compress it
down to an 8-bit code word.
In the above example, both linbuf (in) and logbuf (out) are short arrays.
I understand most of what is going on, but shouldn't each short (signed
16-bit number) in the linbuf short* array be compressed into a char
(signed 8-bit number) and put into logbuf as a char* array?
So when I get the returned encoded short* array, can I just cast the
logbuf short* array to a char* array and then in JNI return it back as a
Java byte[] array?
If you're familiar with JNI and can quickly write up some pseudo code that
would show me where to begin with the conversions, I'd greatly appreciate
it!
No comments:
Post a Comment