Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Added a mu-Law codec to the record over UART feature to provide for 14-bit effective dynamic range in the captured recordings, which matches the dynamic range actually produced by the PDM to PCM conversion as implemented. |
---|---|
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
1d38441bbc47e83d63d6ed9b65b0a8d2 |
User & Date: | rberteig 2015-03-17 00:48:23 |
Context
2015-03-27
| ||
01:04 | Added second sonar driving the blue LED. The GRN sonar is active low during PCM sample processing. The BLU sonar is active low in the main loop. check-in: 1fe01e0ab5 user: rberteig tags: trunk | |
2015-03-17
| ||
00:48 | Added a mu-Law codec to the record over UART feature to provide for 14-bit effective dynamic range in the captured recordings, which matches the dynamic range actually produced by the PDM to PCM conversion as implemented. check-in: 1d38441bbc user: rberteig tags: trunk | |
2015-03-10
| ||
22:54 | Replaced subtracting average sample value with a simple single pole IIR high pass filter rolling off at 20Hz. Added mechanism for dumping scaled 8-bit PCM samples to the UART for analysis on the PC. Tested with recording of room audio. check-in: 5218c33e38 user: rberteig tags: trunk | |
Changes
Changes to LPCWorkspace/PDMSPL/src/main.c.
︙ | ︙ | |||
22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #include <string.h> #include <stdlib.h> #include "splear.h" #include "iap.h" #include "lg2.h" #include "pwm.h" #include "pdmspi.h" /* Systick timer tick rate, to change duty cycle */ #define TICKRATE_HZ 1000 /* 1 ms Tick rate */ /* * SPL parameters | > | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #include <string.h> #include <stdlib.h> #include "splear.h" #include "iap.h" #include "lg2.h" #include "pwm.h" #include "pdmspi.h" #include "mulaw.h" /* Systick timer tick rate, to change duty cycle */ #define TICKRATE_HZ 1000 /* 1 ms Tick rate */ /* * SPL parameters |
︙ | ︙ | |||
209 210 211 212 213 214 215 | //ssq += (pcm-avg)*(pcm-avg); sabs += pcm > 0 ? pcm : -pcm; // Finish SPL and apply it at each complete SPL window interval ++n; if (monitor & PRINT_SAMPLES) { extern void putLineUARTn(const uint8_t *, size_t); | | | | 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | //ssq += (pcm-avg)*(pcm-avg); sabs += pcm > 0 ? pcm : -pcm; // Finish SPL and apply it at each complete SPL window interval ++n; if (monitor & PRINT_SAMPLES) { extern void putLineUARTn(const uint8_t *, size_t); //int s = (pcm + 8192) >> 6; int s = linear14_ulaw(pcm); //s = n & 0xff; sbuf[n & 63] = s <= 0 ? 0 : s >=255 ? 255 : s; if ((n&31) == 31) putLineUARTn(sbuf + (n & 32), 32); } if (n == WINDOWSIZE) { |
︙ | ︙ |
Added LPCWorkspace/PDMSPL/src/mulaw.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | /* * mulaw.c * * Created on: Mar 13, 2015 * Author: Ross * * Good source for g711.c seems to be from pulseaudio sources where * they are deliberately starting with 14-bit samples. The referenced * page also has a complete lookup table set for doing both a-Law and * µ-Law to and from linear coding with lookup tables. 256 entries for * the decoder. 8K entries for aLaw encoder and 16K entries for µ-Law * encoder, so we won't be implementing the encoder with tables. * * https://fossies.org/linux/pulseaudio/src/pulsecore/g711.c */ #include <stdint.h> #if (!defined(USE_TABLE_LOOKUP) || !defined(USE_CLZ_EMULATED)) #define USE_TABLE_LOOKUP //#define USE_CLZ_EMULATED #endif #ifdef USE_TABLE_LOOKUP /* * Table of thresholds for implementing count of leading zeros for computing * the segment number from the biased 14 bit sample value. */ static int16_t seg_uend[8] = {0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF}; static int16_t search( int16_t val, int16_t *table, int size) { int i; for (i = 0; i < size; i++) { if (val <= *table++) return (i); } return (size); } static unsigned int segment14(unsigned short x) { return search(x, seg_uend, 8); } #else #ifdef USE_CLZ_EMULATED #if 0 static unsigned int clz32(unsigned int x) { int n = 0; if (x = 0) return 32; if (!(x & 0xFFFF0000)) { n += 16; x <<= 16; } if (!(x & 0xFF000000)) { n += 8; x <<= 8; } if (!(x & 0xF0000000)) { n += 4; x <<= 4; } if (!(x & 0xC0000000)) { n += 2; x <<= 2; } if (!(x & 0x80000000)) { n += 1; /*x <<= 1;*/ } return n; } #endif static unsigned int clz16(unsigned short x) { int n = 0; if (x = 0) return 16; if (!(x & 0xFF00)) { n += 8; x <<= 8; } if (!(x & 0xF000)) { n += 4; x <<= 4; } if (!(x & 0xC000)) { n += 2; x <<= 2; } if (!(x & 0x8000)) { n += 1; /*x <<= 1;*/ } return n; } static unsigned int segment14(unsigned short x) { int n = clz16(x); return n >= 10 ? 0 : 10-n; #if 0 int n = 0; //if (x = 0) return 0; if (!(x & 0xFE00)) { n += 4; x <<= 4; } if (!(x & 0xF800)) { n += 2; x <<= 2; } if (!(x & 0xF000)) { n += 1; /*x <<= 1;*/ } return 7-n; #endif } #endif #endif #define BIAS (0x84) /* Bias for linear code. */ #define CLIP 8159 /* * linear2ulaw() accepts a 14-bit signed integer and encodes it as u-law data * stored in a unsigned char. This function should only be called with * the data shifted such that it only contains information in the lower * 14-bits. * * In order to simplify the encoding process, the original linear magnitude * is biased by adding 33 which shifts the encoding range from (0 - 8158) to * (33 - 8191). The result can be seen in the following encoding table: * * Biased Linear Input Code Compressed Code * ------------------------ --------------- * 0 0000 001w xyza 000wxyz * 0 0000 01wx yzab 001wxyz * 0 0000 1wxy zabc 010wxyz * 0 0001 wxyz abcd 011wxyz * * 0 001w xyza bcde 100wxyz * 0 01wx yzab cdef 101wxyz * * 0 1wxy zabc defg 110wxyz * 1 wxyz abcd efgh 111wxyz * * Each biased linear code has a leading 1 which identifies the segment * number. The value of the segment number is equal to 7 minus the number * of leading 0's. The quantization interval is directly available as the * four bits wxyz. * The trailing bits (a - h) are ignored. * * Ordinarily the complement of the resulting code word is used for * transmission, and so the code word is complemented before it is returned. * * For further information see John C. Bellamy's Digital Telephony, 1982, * John Wiley & Sons, pps 98-111 and 472-476. */ unsigned char linear14_ulaw( int16_t pcm_val) /* 2's complement (14-bit range) */ { int16_t mask; int16_t seg; unsigned char uval; /* Have calling software do it since its already doing a shift * from 32-bits down to 16-bits. */ /* pcm_val = pcm_val >> 2; */ /* u-law inverts all bits */ /* Get the sign and the magnitude of the value. */ if (pcm_val < 0) { pcm_val = -pcm_val; mask = 0x7F; } else { mask = 0xFF; } if ( pcm_val > CLIP ) pcm_val = CLIP; /* clip the magnitude */ pcm_val += (BIAS >> 2); /* Convert the scaled magnitude to segment number. */ seg = segment14(pcm_val); //seg = search(pcm_val, seg_uend, 8); /* * Combine the sign, segment, quantization bits; * and complement the code word. */ if (seg >= 8) /* out of range, return maximum value. */ return (unsigned char) (0x7F ^ mask); else { uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF); return (uval ^ mask); } } #ifdef TEST_CODE #include <stdio.h> int table() { int x, y; printf("uint8_t _st_14linear2ulaw[0x4000] = {\n "); y = 0; for (x = 0; x < 0x4000; x++) { printf(" 0x%02x,", linear14_ulaw((-0x2000)+x)); y++; if (y == 12) { y = 0; printf("\n "); } } printf("\n};\n"); } int sample(void) { static unsigned int b[8] = {0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF}; int i; for (i=0; i<8; ++i) { printf("%4x %02x %4x %02x\n", b[i], linear14_ulaw(b[i]), 0x3fff & ((-0x2000)+b[i]), linear14_ulaw(b[i]-0x2000)); printf("%4x %02x %4x %02x\n", b[i]+1, linear14_ulaw(b[i]+1), 0x3fff & (b[i]+1-0x2000), linear14_ulaw(b[i]+1-0x2000)); } } int main(int argc, char **argv) { // sample(); table(); } #endif |
Added LPCWorkspace/PDMSPL/src/mulaw.h.
> > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /* * mulaw.h * * Created on: Mar 16, 2015 * Author: Ross */ #ifndef MULAW_H_ #define MULAW_H_ #include <stdint.h> unsigned char linear14_ulaw(int16_t pcm_val); /* 2's complement (14-bit range) */ #endif /* MULAW_H_ */ |