By 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.