Software Development KitBy convention and without declaration, the audio format is G.711 a-law.
This is the structure that holds the APP13 audio data:
#define M_APP13 0xed
#define M_MXAUDIO M_APP13 /* mobotix audio record */
typedef struct{
/* 0 */ u8 ff_0; /* Marker-leadin, 0xff */
/* 1 */ u8 au_marker; /* app13-Marker M_MXAUDIO */
/* 2 */ u8 len_hi, len_lo; /* Length of APP13 block (2 bytes) */
/* 4 */ u32 dur_us; /* duration of block in us, little-endian */
/* 8 */ u64 start_us; /* time (GMT) of first sample
* in us since 1970, little-endian */
/* 16 */ u8 au_samples[0]; /* array of up to 64k - sizeof(jh_mxm_audio_hdr_t) */
/* the number of samples is computed as
* ((len_hi << 8) + len_lo) - (sizeof(jh_mxm_audio_hdr_t) - 2)
* (because the marker is not included in the length, we
* need to subtract 2 */
} jh_mxm_audio_hdr_t;
start_us is a sample of the system clock that may
show drifts or other errors. Therefore 8000 samples may not
exactly amount to 1 second. The audio rendering software should
correct these slight drifts.
According to the standard, all samples are XORed by 0x55. To convert them into 12-bit signed values, you may use the following routine:
/************************************************************/
/* a-law code/decode */
/************************************************************/
static int a3_to_s12_tab[256] = {
-672, -640, -736, -704, -544, -512, -608, -576,
-928, -896, -992, -960, -800, -768, -864, -832,
-336, -320, -368, -352, -272, -256, -304, -288,
-464, -448, -496, -480, -400, -384, -432, -416,
-2688, -2560, -2944, -2816, -2176, -2048, -2432, -2304,
-3712, -3584, -3968, -3840, -3200, -3072, -3456, -3328,
-1344, -1280, -1472, -1408, -1088, -1024, -1216, -1152,
-1856, -1792, -1984, -1920, -1600, -1536, -1728, -1664,
-42, -40, -46, -44, -34, -32, -38, -36,
-58, -56, -62, -60, -50, -48, -54, -52,
-10, -8, -14, -12, -2, 0, -6, -4,
-26, -24, -30, -28, -18, -16, -22, -20,
-168, -160, -184, -176, -136, -128, -152, -144,
-232, -224, -248, -240, -200, -192, -216, -208,
-84, -80, -92, -88, -68, -64, -76, -72,
-116, -112, -124, -120, -100, -96, -108, -104,
672, 640, 736, 704, 544, 512, 608, 576,
928, 896, 992, 960, 800, 768, 864, 832,
336, 320, 368, 352, 272, 256, 304, 288,
464, 448, 496, 480, 400, 384, 432, 416,
2688, 2560, 2944, 2816, 2176, 2048, 2432, 2304,
3712, 3584, 3968, 3840, 3200, 3072, 3456, 3328,
1344, 1280, 1472, 1408, 1088, 1024, 1216, 1152,
1856, 1792, 1984, 1920, 1600, 1536, 1728, 1664,
42, 40, 46, 44, 34, 32, 38, 36,
58, 56, 62, 60, 50, 48, 54, 52,
10, 8, 14, 12, 2, 0, 6, 4,
26, 24, 30, 28, 18, 16, 22, 20,
168, 160, 184, 176, 136, 128, 152, 144,
232, 224, 248, 240, 200, 192, 216, 208,
84, 80, 92, 88, 68, 64, 76, 72,
116, 112, 124, 120, 100, 96, 108, 104
};
#define a3_to_s12(x) (a3_to_s12_tab[x])
static inline int s12_to_a3(int x) {
/* 12 bit + sign amplitude -> a-law code
positive cases:
0000 0000 00ab cde* -> 100a bcde ; first 32 codes are linear !
0000 0000 01ab cd** -> 1010 abcd
0000 0000 1abc d*** -> 1011 abdc
0000 0001 abcd **** -> 1100 abdc
0000 001a bcd* **** -> 1101 abdc
0000 01ab cd** **** -> 1110 abdc
0000 1abc d*** **** -> 1111 abdc
negative cases:
0001 0000 0000 **** _> 0111 1111 ; "-4096 -> +4095"
otherwise MSB = 0; |x| is treated as positive
*/
int sign7;
sign7 = ((~x) >> 5) & 0x80;
/* force code 0x1000 (and some smaller ones) to 0x0FF0, as the a-law-code
is symmetrical (has "-0") */
if (!sign7) x = (((u32)((x + 0x0FF0))) >> 20) -x;
if (x < 64) return (0x55 ^ (sign7 ^ (x >> 1)));
if (x & 0xC00) {sign7 += (2 << 4); x >>= 2;}
if (x & 0x300) {sign7 += (2 << 4); x >>= 2;}
if (x & 0x080) {sign7 += (1 << 4); x >>= 1;}
return (0x55 ^ (sign7 + 32 + ((x & 0x03C) >> 2)));
}
In order to avoid distortions, the PCM data have to further pass through a sin(x)/x filter (contained in telco codecs).
Copyright (c) 2005-2007, MOBOTIX AG. All rights reserved.