├── Makefile ├── README.md ├── mdc_common.c ├── mdc_decode.c ├── mdc_decode.h ├── mdc_encode.c ├── mdc_encode.h ├── mdc_test.c └── mdc_types.h /Makefile: -------------------------------------------------------------------------------- 1 | 2 | mdc_test: mdc_test.c mdc_decode.o mdc_encode.o 3 | cc -g -o mdc_test mdc_test.c mdc_decode.o mdc_encode.o 4 | ./mdc_test 5 | 6 | mdc_decode.o: mdc_decode.c mdc_decode.h mdc_common.c 7 | cc -c mdc_decode.c 8 | 9 | mdc_encode.o: mdc_encode.c mdc_encode.h mdc_common.c 10 | cc -c mdc_encode.c 11 | 12 | clean: 13 | rm -f mdc_decode.o mdc_encode.o mdc_test 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mdc-encode-decode 2 | Software modem for a specific data burst format 3 | 4 | This library supports decoding and encoding of Motorola's MDC1200 format. (All trademarks property of their respective owners) 5 | 6 | GPL license applies, so all redistribution must include source code for your product. Commercial license terms are available 7 | for closed-source products, contact the author (matthew@eeph.com) 8 | -------------------------------------------------------------------------------- /mdc_common.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * mdc_common.c 3 | * Author: Matthew Kaufman (matthew@eeph.com) 4 | * 5 | * Copyright (c) 2011 Matthew Kaufman All rights reserved. 6 | * 7 | * This file is part of Matthew Kaufman's MDC Encoder/Decoder Library 8 | * 9 | * The MDC Encoder/Decoder Library is free software; you can 10 | * redistribute it and/or modify it under the terms of version 2 of 11 | * the GNU General Public License as published by the Free Software 12 | * Foundation. 13 | * 14 | * If you cannot comply with the terms of this license, contact 15 | * the author for alternative license arrangements or do not use 16 | * or redistribute this software. 17 | * 18 | * The MDC Encoder/Decoder Library is distributed in the hope 19 | * that it will be useful, but WITHOUT ANY WARRANTY; without even the 20 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 21 | * PURPOSE. See the GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License 24 | * along with this software; if not, write to the Free Software 25 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 26 | * USA. 27 | * 28 | * or see http://www.gnu.org/copyleft/gpl.html 29 | * 30 | -*/ 31 | 32 | 33 | 34 | 35 | static mdc_u16_t _flip(mdc_u16_t crc, mdc_int_t bitnum) 36 | { 37 | mdc_u16_t crcout, i, j; 38 | 39 | j = 1; 40 | crcout = 0; 41 | 42 | for (i=1<<(bitnum-1); i; i>>=1) 43 | { 44 | if (crc & i) 45 | crcout |= j; 46 | j<<= 1; 47 | } 48 | return (crcout); 49 | } 50 | 51 | 52 | static mdc_u16_t _docrc(mdc_u8_t *p, int len) 53 | { 54 | mdc_int_t i, j; 55 | mdc_u16_t c; 56 | mdc_int_t bit; 57 | mdc_u16_t crc = 0x0000; 58 | 59 | for (i=0; i>=1) 66 | { 67 | bit = crc & 0x8000; 68 | crc<<= 1; 69 | if (c & j) 70 | bit^= 0x8000; 71 | if (bit) 72 | crc^= 0x1021; 73 | } 74 | } 75 | 76 | crc = _flip(crc, 16); 77 | crc ^= 0xffff; 78 | crc &= 0xFFFF; 79 | 80 | return(crc); 81 | } 82 | 83 | -------------------------------------------------------------------------------- /mdc_decode.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * mdc_decode.c 3 | * Decodes a specific format of 1200 BPS XOR-precoded MSK data burst 4 | * from input audio samples. 5 | * 6 | * Author: Matthew Kaufman (matthew@eeph.com) 7 | * 8 | * Copyright (c) 2005, 2010 Matthew Kaufman All rights reserved. 9 | * 10 | * This file is part of Matthew Kaufman's MDC Encoder/Decoder Library 11 | * 12 | * The MDC Encoder/Decoder Library is free software; you can 13 | * redistribute it and/or modify it under the terms of version 2 of 14 | * the GNU General Public License as published by the Free Software 15 | * Foundation. 16 | * 17 | * If you cannot comply with the terms of this license, contact 18 | * the author for alternative license arrangements or do not use 19 | * or redistribute this software. 20 | * 21 | * The MDC Encoder/Decoder Library is distributed in the hope 22 | * that it will be useful, but WITHOUT ANY WARRANTY; without even the 23 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 24 | * PURPOSE. See the GNU General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU General Public License 27 | * along with this software; if not, write to the Free Software 28 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 29 | * USA. 30 | * 31 | * or see http://www.gnu.org/copyleft/gpl.html 32 | * 33 | -*/ 34 | 35 | #include 36 | #include "mdc_decode.h" 37 | #include "mdc_common.c" 38 | 39 | mdc_decoder_t * mdc_decoder_new(int sampleRate) 40 | { 41 | mdc_decoder_t *decoder; 42 | mdc_int_t i; 43 | 44 | decoder = (mdc_decoder_t *)malloc(sizeof(mdc_decoder_t)); 45 | if(!decoder) 46 | return (mdc_decoder_t *) 0L; 47 | 48 | // decoder->hyst = 3.0/256.0; - deprecated (zerocrossing) 49 | // decoder->incr = (1200.0 * TWOPI) / ((mdc_float_t)sampleRate); 50 | 51 | if(sampleRate == 8000) 52 | { 53 | decoder->incru = 644245094; 54 | } else if(sampleRate == 16000) 55 | { 56 | decoder->incru = 322122547; 57 | } else if(sampleRate == 22050) 58 | { 59 | decoder->incru = 233739716; 60 | } else if(sampleRate == 32000) 61 | { 62 | decoder->incru = 161061274; 63 | } else if(sampleRate == 44100) 64 | { 65 | decoder->incru = 116869858; 66 | } else if(sampleRate == 48000) 67 | { 68 | decoder->incru = 107374182; 69 | } else 70 | { 71 | // WARNING: lower precision than above 72 | decoder->incru = 1200 * 2 * (0x80000000 / sampleRate); 73 | } 74 | 75 | decoder->good = 0; 76 | decoder->indouble = 0; 77 | decoder->level = 0; 78 | 79 | 80 | for(i=0; idu[i].thu = i * 2 * (0x80000000 / MDC_ND); 83 | decoder->du[i].xorb = 0; 84 | decoder->du[i].invert = 0; 85 | decoder->du[i].shstate = -1; 86 | decoder->du[i].shcount = 0; 87 | #ifdef MDC_FOURPOINT 88 | decoder->du[i].nlstep = i; 89 | #endif 90 | } 91 | 92 | decoder->callback = (mdc_decoder_callback_t)0L; 93 | 94 | return decoder; 95 | } 96 | 97 | static void _clearbits(mdc_decoder_t *decoder, mdc_int_t x) 98 | { 99 | mdc_int_t i; 100 | for(i=0; i<112; i++) 101 | decoder->du[x].bits[i] = 0; 102 | } 103 | 104 | #ifdef MDC_ECC 105 | static void _gofix(unsigned char *data) 106 | { 107 | int i, j, b, k; 108 | int csr[7]; 109 | int syn; 110 | int fixi,fixj; 111 | int ec; 112 | 113 | syn = 0; 114 | for(i=0; i<7; i++) 115 | csr[i] = 0; 116 | 117 | for(i=0; i<7; i++) 118 | { 119 | for(j=0; j<=7; j++) 120 | { 121 | for(k=6; k > 0; k--) 122 | csr[k] = csr[k-1]; 123 | 124 | csr[0] = (data[i] >> j) & 0x01; 125 | b = csr[0] + csr[2] + csr[5] + csr[6]; 126 | syn <<= 1; 127 | if( (b & 0x01) ^ ((data[i+7] >> j) & 0x01) ) 128 | { 129 | syn |= 1; 130 | } 131 | ec = 0; 132 | if(syn & 0x80) ++ec; 133 | if(syn & 0x20) ++ec; 134 | if(syn & 0x04) ++ec; 135 | if(syn & 0x02) ++ec; 136 | if(ec >= 3) 137 | { 138 | syn ^= 0xa6; 139 | fixi = i; 140 | fixj = j-7; 141 | if(fixj < 0) 142 | { 143 | --fixi; 144 | fixj += 8; 145 | } 146 | if(fixi >= 0) 147 | data[fixi] ^= 1<du[x].bits[k]; 172 | ++lbc; 173 | } 174 | } 175 | 176 | for(i=0; i<14; i++) 177 | { 178 | data[i] = 0; 179 | for(j=0; j<8; j++) 180 | { 181 | k = (i*8)+j; 182 | 183 | if(lbits[k]) 184 | data[i] |= 1<du[x].shstate == 2) 200 | { 201 | decoder->extra0 = data[0]; 202 | decoder->extra1 = data[1]; 203 | decoder->extra2 = data[2]; 204 | decoder->extra3 = data[3]; 205 | 206 | for(k=0; kdu[k].shstate = -1; 208 | 209 | decoder->good = 2; 210 | decoder->indouble = 0; 211 | 212 | } 213 | else 214 | { 215 | if(!decoder->indouble) 216 | { 217 | decoder->good = 1; 218 | decoder->op = data[0]; 219 | decoder->arg = data[1]; 220 | decoder->unitID = (data[2] << 8) | data[3]; 221 | 222 | switch(data[0]) 223 | { 224 | /* list of opcode that mean 'double packet' */ 225 | case 0x35: 226 | case 0x55: 227 | decoder->good = 0; 228 | decoder->indouble = 1; 229 | decoder->du[x].shstate = 2; 230 | decoder->du[x].shcount = 0; 231 | _clearbits(decoder, x); 232 | break; 233 | default: 234 | for(k=0; kdu[k].shstate = -1; // only in the single-packet case, double keeps rest going 236 | break; 237 | } 238 | } 239 | else 240 | { 241 | // any subsequent good decoder allowed to attempt second half 242 | decoder->du[x].shstate = 2; 243 | decoder->du[x].shcount = 0; 244 | _clearbits(decoder, x); 245 | } 246 | } 247 | 248 | } 249 | else 250 | { 251 | 252 | decoder->du[x].shstate = -1; 253 | } 254 | 255 | if(decoder->good) 256 | { 257 | if(decoder->callback) 258 | { 259 | (decoder->callback)( (int)decoder->good, 260 | (unsigned char)decoder->op, 261 | (unsigned char)decoder->arg, 262 | (unsigned short)decoder->unitID, 263 | (unsigned char)decoder->extra0, 264 | (unsigned char)decoder->extra1, 265 | (unsigned char)decoder->extra2, 266 | (unsigned char)decoder->extra3, 267 | decoder->callback_context); 268 | decoder->good = 0; 269 | 270 | } 271 | } 272 | } 273 | 274 | 275 | static int _onebits(mdc_u32_t n) 276 | { 277 | int i=0; 278 | while(n) 279 | { 280 | ++i; 281 | n &= (n-1); 282 | } 283 | return i; 284 | } 285 | 286 | static void _shiftin(mdc_decoder_t *decoder, int x) 287 | { 288 | int bit = decoder->du[x].xorb; 289 | int gcount; 290 | 291 | switch(decoder->du[x].shstate) 292 | { 293 | case -1: 294 | decoder->du[x].synchigh = 0; 295 | decoder->du[x].synclow = 0; 296 | decoder->du[x].shstate = 0; 297 | // deliberately fall through 298 | case 0: 299 | decoder->du[x].synchigh <<= 1; 300 | if(decoder->du[x].synclow & 0x80000000) 301 | decoder->du[x].synchigh |= 1; 302 | decoder->du[x].synclow <<= 1; 303 | if(bit) 304 | decoder->du[x].synclow |= 1; 305 | 306 | gcount = _onebits(0x000000ff & (0x00000007 ^ decoder->du[x].synchigh)); 307 | gcount += _onebits(0x092a446f ^ decoder->du[x].synclow); 308 | 309 | if(gcount <= MDC_GDTHRESH) 310 | { 311 | //printf("sync %d %x %x \n",gcount,decoder->du[x].synchigh, decoder->du[x].synclow); 312 | decoder->du[x].shstate = 1; 313 | decoder->du[x].shcount = 0; 314 | _clearbits(decoder, x); 315 | } 316 | else if(gcount >= (40 - MDC_GDTHRESH)) 317 | { 318 | //printf("isync %d\n",gcount); 319 | decoder->du[x].shstate = 1; 320 | decoder->du[x].shcount = 0; 321 | decoder->du[x].xorb = !(decoder->du[x].xorb); 322 | decoder->du[x].invert = !(decoder->du[x].invert); 323 | _clearbits(decoder, x); 324 | } 325 | return; 326 | case 1: 327 | case 2: 328 | decoder->du[x].bits[decoder->du[x].shcount] = bit; 329 | decoder->du[x].shcount++; 330 | if(decoder->du[x].shcount > 111) 331 | { 332 | _procbits(decoder, x); 333 | } 334 | return; 335 | 336 | default: 337 | return; 338 | } 339 | } 340 | 341 | #ifdef MDC_FOURPOINT 342 | 343 | static void _nlproc(mdc_decoder_t *decoder, int x) 344 | { 345 | mdc_float_t vnow; 346 | mdc_float_t vpast; 347 | 348 | switch(decoder->du[x].nlstep) 349 | { 350 | case 3: 351 | vnow = ((-0.60 * decoder->du[x].nlevel[3]) + (.97 * decoder->du[x].nlevel[1])); 352 | vpast = ((-0.60 * decoder->du[x].nlevel[7]) + (.97 * decoder->du[x].nlevel[9])); 353 | break; 354 | case 8: 355 | vnow = ((-0.60 * decoder->du[x].nlevel[8]) + (.97 * decoder->du[x].nlevel[6])); 356 | vpast = ((-0.60 * decoder->du[x].nlevel[2]) + (.97 * decoder->du[x].nlevel[4])); 357 | break; 358 | default: 359 | return; 360 | } 361 | 362 | decoder->du[x].xorb = (vnow > vpast) ? 1 : 0; 363 | if(decoder->du[x].invert) 364 | decoder->du[x].xorb = !(decoder->du[x].xorb); 365 | _shiftin(decoder, x); 366 | } 367 | #endif 368 | 369 | int mdc_decoder_process_samples(mdc_decoder_t *decoder, 370 | mdc_sample_t *samples, 371 | int numSamples) 372 | { 373 | mdc_int_t i, j; 374 | mdc_sample_t sample; 375 | #ifndef MDC_FIXEDMATH 376 | mdc_float_t value; 377 | #else 378 | mdc_int_t value; 379 | #endif 380 | 381 | if(!decoder) 382 | return -1; 383 | 384 | for(i = 0; idu[j].thu; 422 | decoder->du[j].thu += decoder->incru; 423 | if(decoder->du[j].thu < lthu) // wrapped 424 | { 425 | if(value > 0) 426 | decoder->du[j].xorb = 1; 427 | else 428 | decoder->du[j].xorb = 0; 429 | if(decoder->du[j].invert) 430 | decoder->du[j].xorb = !(decoder->du[j].xorb); 431 | _shiftin(decoder, j); 432 | } 433 | } 434 | 435 | #elif defined(MDC_FOURPOINT) 436 | 437 | #ifdef MDC_FIXEDMATH 438 | #error "fixed-point math not allowed for fourpoint strategy" 439 | #endif 440 | 441 | for(j=0; jdu[j].th += (5.0 * decoder->incr); 444 | mdc_u32_t lthu = decoder->du[j].thu; 445 | decoder->du[j].thu += 5 * decoder->incru; 446 | // if(decoder->du[j].th >= TWOPI) 447 | if(decoder->du[j].thu < lthu) // wrapped 448 | { 449 | decoder->du[j].nlstep++; 450 | if(decoder->du[j].nlstep > 9) 451 | decoder->du[j].nlstep = 0; 452 | decoder->du[j].nlevel[decoder->du[j].nlstep] = value; 453 | 454 | _nlproc(decoder, j); 455 | 456 | //decoder->du[j].th -= TWOPI; 457 | } 458 | } 459 | 460 | #else 461 | #error "no decode strategy chosen" 462 | #endif 463 | } 464 | 465 | 466 | 467 | if(decoder->good) 468 | return decoder->good; 469 | 470 | return 0; 471 | } 472 | 473 | int mdc_decoder_get_packet(mdc_decoder_t *decoder, 474 | unsigned char *op, 475 | unsigned char *arg, 476 | unsigned short *unitID) 477 | { 478 | if(!decoder) 479 | return -1; 480 | 481 | if(decoder->good != 1) 482 | return -1; 483 | 484 | if(op) 485 | *op = decoder->op; 486 | 487 | if(arg) 488 | *arg = decoder->arg; 489 | 490 | if(unitID) 491 | *unitID = decoder->unitID; 492 | 493 | decoder->good = 0; 494 | 495 | return 0; 496 | } 497 | 498 | int mdc_decoder_get_double_packet(mdc_decoder_t *decoder, 499 | unsigned char *op, 500 | unsigned char *arg, 501 | unsigned short *unitID, 502 | unsigned char *extra0, 503 | unsigned char *extra1, 504 | unsigned char *extra2, 505 | unsigned char *extra3) 506 | { 507 | if(!decoder) 508 | return -1; 509 | 510 | if(decoder->good != 2) 511 | return -1; 512 | 513 | if(op) 514 | *op = decoder->op; 515 | 516 | if(arg) 517 | *arg = decoder->arg; 518 | 519 | if(unitID) 520 | *unitID = decoder->unitID; 521 | 522 | if(extra0) 523 | *extra0 = decoder->extra0; 524 | if(extra1) 525 | *extra1 = decoder->extra1; 526 | if(extra2) 527 | *extra2 = decoder->extra2; 528 | if(extra3) 529 | *extra3 = decoder->extra3; 530 | 531 | decoder->good = 0; 532 | 533 | return 0; 534 | } 535 | 536 | int mdc_decoder_set_callback(mdc_decoder_t *decoder, mdc_decoder_callback_t callbackFunction, void *context) 537 | { 538 | if(!decoder) 539 | return -1; 540 | 541 | decoder->callback = callbackFunction; 542 | decoder->callback_context = context; 543 | 544 | return 0; 545 | } 546 | -------------------------------------------------------------------------------- /mdc_decode.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * mdc_decode.h 3 | * header for mdc_decode.c 4 | * 5 | * Author: Matthew Kaufman (matthew@eeph.com) 6 | * 7 | * Copyright (c) 2005, 2010 Matthew Kaufman All rights reserved. 8 | * 9 | * This file is part of Matthew Kaufman's MDC Encoder/Decoder Library 10 | * 11 | * The MDC Encoder/Decoder Library is free software; you can 12 | * redistribute it and/or modify it under the terms of version 2 of 13 | * the GNU General Public License as published by the Free Software 14 | * Foundation. 15 | * 16 | * If you cannot comply with the terms of this license, contact 17 | * the author for alternative license arrangements or do not use 18 | * or redistribute this software. 19 | * 20 | * The MDC Encoder/Decoder Library is distributed in the hope 21 | * that it will be useful, but WITHOUT ANY WARRANTY; without even the 22 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 23 | * PURPOSE. See the GNU General Public License for more details. 24 | * 25 | * You should have received a copy of the GNU General Public License 26 | * along with this software; if not, write to the Free Software 27 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 28 | * USA. 29 | * 30 | * or see http://www.gnu.org/copyleft/gpl.html 31 | * 32 | -*/ 33 | 34 | #ifndef _MDC_DECODE_H_ 35 | #define _MDC_DECODE_H_ 36 | 37 | // #define MDC_FIXEDMATH // if you want this, define before mdc_types.h 38 | 39 | #include "mdc_types.h" 40 | 41 | #define MDC_GDTHRESH 5 // "good bits" threshold 42 | 43 | #define MDC_ECC 44 | 45 | #define MDC_FOURPOINT // recommended 4-point method, requires high sample rates (16000 or higher) 46 | #undef MDC_ONEPOINT // alternative 1-point method 47 | 48 | #ifdef MDC_FOURPOINT 49 | #define MDC_ND 5 // recommended for four-point method 50 | #endif 51 | 52 | #ifdef MDC_ONEPOINT 53 | #define MDC_ND 4 // recommended for one-point method 54 | #endif 55 | 56 | typedef void (*mdc_decoder_callback_t)( int frameCount, // 1 or 2 - if 2 then extra0-3 are valid 57 | unsigned char op, 58 | unsigned char arg, 59 | unsigned short unitID, 60 | unsigned char extra0, 61 | unsigned char extra1, 62 | unsigned char extra2, 63 | unsigned char extra3, 64 | void *context); 65 | 66 | typedef struct 67 | { 68 | // mdc_float_t th; 69 | mdc_u32_t thu; 70 | // mdc_int_t zc; - deprecated 71 | mdc_int_t xorb; 72 | mdc_int_t invert; 73 | #ifdef MDC_FOURPOINT 74 | #ifdef MDC_FIXEDMATH 75 | #error "fixed-point math not allowed for fourpoint strategy" 76 | #endif // MDC_FIXEDMATH 77 | mdc_int_t nlstep; 78 | mdc_float_t nlevel[10]; 79 | #endif // MDC_FOURPOINT 80 | #ifdef PLL 81 | mdc_u32_t plt; 82 | #endif 83 | mdc_u32_t synclow; 84 | mdc_u32_t synchigh; 85 | mdc_int_t shstate; 86 | mdc_int_t shcount; 87 | mdc_int_t bits[112]; 88 | } mdc_decode_unit_t; 89 | 90 | typedef struct { 91 | mdc_decode_unit_t du[MDC_ND]; 92 | // mdc_float_t hyst; 93 | // mdc_float_t incr; 94 | mdc_u32_t incru; 95 | #ifdef PLL 96 | mdc_u32_t zthu; 97 | mdc_int_t zprev; 98 | mdc_float_t vprev; 99 | #endif 100 | mdc_int_t level; 101 | mdc_int_t good; 102 | mdc_int_t indouble; 103 | mdc_u8_t op; 104 | mdc_u8_t arg; 105 | mdc_u16_t unitID; 106 | mdc_u8_t extra0; 107 | mdc_u8_t extra1; 108 | mdc_u8_t extra2; 109 | mdc_u8_t extra3; 110 | mdc_decoder_callback_t callback; 111 | void *callback_context; 112 | } mdc_decoder_t; 113 | 114 | 115 | 116 | /* 117 | mdc_decoder_new 118 | create a new mdc_decoder object 119 | 120 | parameters: int sampleRate - the sampling rate in Hz 121 | 122 | returns: an mdc_decoder object or null if failure 123 | 124 | */ 125 | mdc_decoder_t * mdc_decoder_new(int sampleRate); 126 | 127 | /* 128 | mdc_decoder_process_samples 129 | process incoming samples using an mdc_decoder object 130 | 131 | parameters: mdc_decoder_t *decoder - pointer to the decoder object 132 | mdc_sample_t *samples - pointer to samples (in format set in mdc_types.h) 133 | int numSamples - count of the number of samples in buffer 134 | 135 | returns: 0 if more samples are needed 136 | -1 if an error occurs 137 | 1 if a decoded single packet is available to read (if no callback set) 138 | 2 if a decoded double packet is available to read (if no callback set) 139 | */ 140 | 141 | int mdc_decoder_process_samples(mdc_decoder_t *decoder, 142 | mdc_sample_t *samples, 143 | int numSamples); 144 | 145 | 146 | /* 147 | mdc_decoder_get_packet 148 | retrieve last successfully decoded data packet from decoder object 149 | 150 | parameters: mdc_decoder_t *decoder - pointer to the decoder object 151 | unsigned char *op - pointer to where to store "opcode" 152 | unsigned char *arg - pointer to where to store "argument" 153 | unsigned short *unitID - pointer to where to store "unit ID" 154 | 155 | returns: -1 if error, 0 otherwise 156 | */ 157 | 158 | int mdc_decoder_get_packet(mdc_decoder_t *decoder, 159 | unsigned char *op, 160 | unsigned char *arg, 161 | unsigned short *unitID); 162 | 163 | /* 164 | mdc_decoder_get_double_packet 165 | retrieve last successfully decoded double-length packet from decoder object 166 | 167 | parameters: mdc_decoder_t *decoder - pointer to the decoder object 168 | unsigned char *op - pointer to where to store "opcode" 169 | unsigned char *arg - pointer to where to store "argument" 170 | unsigned short *unitID - pointer to where to store "unit ID" 171 | unsigned char *extra0 - pointer to where to store 1st extra byte 172 | unsigned char *extra1 - pointer to where to store 2nd extra byte 173 | unsigned char *extra2 - pointer to where to store 3rd extra byte 174 | unsigned char *extra3 - pointer to where to store 4th extra byte 175 | 176 | returns: -1 if error, 0 otherwise 177 | */ 178 | 179 | int mdc_decoder_get_double_packet(mdc_decoder_t *decoder, 180 | unsigned char *op, 181 | unsigned char *arg, 182 | unsigned short *unitID, 183 | unsigned char *extra0, 184 | unsigned char *extra1, 185 | unsigned char *extra2, 186 | unsigned char *extra3); 187 | 188 | 189 | /* 190 | mdc_decoder_set_callback 191 | set a callback function to be called upon successful decode 192 | if this is set, the functions mdc_decoder_get_packet and mdc_decoder_get_double_packet 193 | will no longer be functional, instead the callback function is called immediately when 194 | a successful decode happens (from within the context of mdc_decoder_process_samples) 195 | 196 | the callback function will be passed the (void *)context that is set here 197 | 198 | returns: -1 if error, 0 otherwise 199 | */ 200 | 201 | int mdc_decoder_set_callback(mdc_decoder_t *decoder, mdc_decoder_callback_t callbackFunction, void *context); 202 | 203 | #endif 204 | -------------------------------------------------------------------------------- /mdc_encode.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * mdc_encode.c 3 | * Encodes a specific format from 1200 BPS MSK data burst 4 | * to output audio samples. 5 | * 6 | * 9 October 2010 - typedefs for easier porting 7 | * 27 July 2016 - additional reduced-amplitude sin tables 8 | * 9 | * Author: Matthew Kaufman (matthew@eeph.com) 10 | * 11 | * Copyright (c) 2005, 2010 Matthew Kaufman All rights reserved. 12 | * 13 | * This file is part of Matthew Kaufman's MDC Encoder/Decoder Library 14 | * 15 | * The MDC Encoder/Decoder Library is free software; you can 16 | * redistribute it and/or modify it under the terms of version 2 of 17 | * the GNU General Public License as published by the Free Software 18 | * Foundation. 19 | * 20 | * If you cannot comply with the terms of this license, contact 21 | * the author for alternative license arrangements or do not use 22 | * or redistribute this software. 23 | * 24 | * The MDC Encoder/Decoder Library is distributed in the hope 25 | * that it will be useful, but WITHOUT ANY WARRANTY; without even the 26 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 27 | * PURPOSE. See the GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with this software; if not, write to the Free Software 31 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 32 | * USA. 33 | * 34 | * or see http://www.gnu.org/copyleft/gpl.html 35 | * 36 | -*/ 37 | 38 | #include 39 | #include "mdc_encode.h" 40 | #include "mdc_common.c" 41 | 42 | #if defined(MDC_SAMPLE_FORMAT_U8) 43 | 44 | #if defined(MDC_ENCODE_FULL_AMPLITUDE) 45 | 46 | static mdc_sample_t sintable[] = { 47 | 127, 130, 133, 136, 139, 142, 145, 148, 151, 154, 157, 160, 163, 166, 169, 172, 48 | 175, 178, 180, 183, 186, 189, 191, 194, 196, 199, 201, 204, 206, 209, 211, 213, 49 | 215, 218, 220, 222, 224, 226, 227, 229, 231, 233, 234, 236, 237, 239, 240, 241, 50 | 242, 244, 245, 246, 247, 247, 248, 249, 250, 250, 251, 251, 251, 252, 252, 252, 51 | 252, 252, 252, 252, 251, 251, 251, 250, 250, 249, 248, 247, 247, 246, 245, 244, 52 | 242, 241, 240, 239, 237, 236, 234, 233, 231, 229, 227, 226, 224, 222, 220, 218, 53 | 215, 213, 211, 209, 206, 204, 201, 199, 196, 194, 191, 189, 186, 183, 180, 178, 54 | 175, 172, 169, 166, 163, 160, 157, 154, 151, 148, 145, 142, 139, 136, 133, 130, 55 | 127, 124, 121, 118, 115, 112, 109, 106, 103, 100, 97, 94, 91, 88, 85, 82, 56 | 79, 76, 74, 71, 68, 65, 63, 60, 58, 55, 53, 50, 48, 45, 43, 41, 57 | 39, 36, 34, 32, 30, 28, 27, 25, 23, 21, 20, 18, 17, 15, 14, 13, 58 | 12, 10, 9, 8, 7, 7, 6, 5, 4, 4, 3, 3, 3, 2, 2, 2, 59 | 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 6, 7, 7, 8, 9, 10, 60 | 12, 13, 14, 15, 17, 18, 20, 21, 23, 25, 27, 28, 30, 32, 34, 36, 61 | 39, 41, 43, 45, 48, 50, 53, 55, 58, 60, 63, 65, 68, 71, 74, 76, 62 | 79, 82, 85, 88, 91, 94, 97, 100, 103, 106, 109, 112, 115, 118, 121, 124 }; 63 | 64 | #else 65 | 66 | 67 | static mdc_sample_t sintable[] = { 68 | 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 69 | 160, 162, 164, 166, 168, 170, 172, 172, 174, 176, 178, 180, 182, 182, 184, 186, 70 | 188, 190, 190, 192, 194, 194, 196, 198, 198, 200, 200, 202, 202, 204, 204, 206, 71 | 206, 206, 208, 208, 208, 210, 210, 210, 212, 212, 212, 212, 212, 212, 212, 212, 72 | 212, 212, 212, 212, 212, 212, 212, 212, 212, 210, 210, 210, 208, 208, 208, 206, 73 | 206, 206, 204, 204, 202, 202, 200, 200, 198, 198, 196, 194, 194, 192, 190, 190, 74 | 188, 186, 184, 182, 182, 180, 178, 176, 174, 172, 172, 170, 168, 166, 164, 162, 75 | 160, 158, 156, 154, 152, 150, 148, 146, 144, 142, 140, 138, 136, 134, 132, 130, 76 | 128, 126, 124, 122, 120, 118, 116, 114, 112, 110, 108, 106, 104, 102, 100, 98, 77 | 96, 94, 92, 90, 88, 86, 84, 82, 80, 78, 76, 76, 74, 72, 70, 68, 78 | 68, 66, 64, 64, 62, 60, 60, 58, 56, 56, 54, 54, 52, 52, 50, 50, 79 | 48, 48, 48, 46, 46, 46, 44, 44, 44, 44, 44, 42, 42, 42, 42, 42, 80 | 42, 42, 42, 42, 42, 42, 44, 44, 44, 44, 44, 46, 46, 46, 48, 48, 81 | 48, 50, 50, 52, 52, 54, 54, 56, 56, 58, 60, 60, 62, 64, 64, 66, 82 | 68, 68, 70, 72, 74, 76, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 83 | 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126 }; 84 | 85 | #endif 86 | 87 | #elif defined(MDC_SAMPLE_FORMAT_U16) 88 | 89 | #if defined(MDC_ENCODE_FULL_AMPLITUDE) 90 | 91 | static mdc_sample_t sintable[] = { 92 | 32768, 33552, 34337, 35120, 35902, 36682, 37460, 38235, 93 | 39007, 39775, 40538, 41297, 42051, 42799, 43542, 44277, 94 | 45006, 45728, 46441, 47147, 47843, 48531, 49209, 49877, 95 | 50535, 51182, 51819, 52443, 53056, 53657, 54245, 54820, 96 | 55381, 55930, 56464, 56984, 57489, 57980, 58455, 58915, 97 | 59359, 59787, 60199, 60594, 60972, 61334, 61678, 62005, 98 | 62314, 62606, 62879, 63134, 63371, 63590, 63790, 63971, 99 | 64134, 64278, 64402, 64508, 64595, 64662, 64710, 64739, 100 | 64749, 64739, 64710, 64662, 64595, 64508, 64402, 64278, 101 | 64134, 63971, 63790, 63590, 63371, 63134, 62879, 62606, 102 | 62314, 62005, 61678, 61334, 60972, 60594, 60199, 59787, 103 | 59359, 58915, 58455, 57980, 57489, 56984, 56464, 55930, 104 | 55381, 54820, 54245, 53657, 53056, 52443, 51819, 51182, 105 | 50535, 49877, 49209, 48531, 47843, 47147, 46441, 45728, 106 | 45006, 44277, 43542, 42799, 42051, 41297, 40538, 39775, 107 | 39007, 38235, 37460, 36682, 35902, 35120, 34337, 33552, 108 | 32768, 31983, 31198, 30415, 29633, 28853, 28075, 27300, 109 | 26528, 25760, 24997, 24238, 23484, 22736, 21993, 21258, 110 | 20529, 19807, 19094, 18388, 17692, 17004, 16326, 15658, 111 | 15000, 14353, 13716, 13092, 12479, 11878, 11290, 10715, 112 | 10154, 9605, 9071, 8551, 8046, 7555, 7080, 6620, 113 | 6176, 5748, 5336, 4941, 4563, 4201, 3857, 3530, 114 | 3221, 2929, 2656, 2401, 2164, 1945, 1745, 1564, 115 | 1401, 1257, 1133, 1027, 940, 873, 825, 796, 116 | 787, 796, 825, 873, 940, 1027, 1133, 1257, 117 | 1401, 1564, 1745, 1945, 2164, 2401, 2656, 2929, 118 | 3221, 3530, 3857, 4201, 4563, 4941, 5336, 5748, 119 | 6176, 6620, 7080, 7555, 8046, 8551, 9071, 9605, 120 | 10154, 10715, 11290, 11878, 12479, 13092, 13716, 14353, 121 | 15000, 15658, 16326, 17004, 17692, 18388, 19094, 19807, 122 | 20529, 21258, 21993, 22736, 23484, 24238, 24997, 25760, 123 | 26528, 27300, 28075, 28853, 29633, 30415, 31198, 31983 }; 124 | 125 | #else 126 | 127 | static mdc_sample_t sintable[] = { 128 | 32768, 33314, 33861, 34407, 34952, 35495, 36037, 36577, 37115, 37650, 38182, 38710, 39236, 39757, 40274, 40787, 129 | 41295, 41797, 42294, 42786, 43271, 43750, 44223, 44688, 45147, 45598, 46041, 46476, 46903, 47322, 47731, 48132, 130 | 48523, 48905, 49278, 49640, 49992, 50334, 50665, 50985, 51295, 51593, 51880, 52155, 52419, 52671, 52910, 53138, 131 | 53354, 53557, 53747, 53925, 54090, 54243, 54382, 54508, 54622, 54722, 54809, 54882, 54942, 54989, 55023, 55043, 132 | 55050, 55043, 55023, 54989, 54942, 54882, 54809, 54722, 54622, 54508, 54382, 54243, 54090, 53925, 53747, 53557, 133 | 53354, 53138, 52910, 52671, 52419, 52155, 51880, 51593, 51295, 50985, 50665, 50334, 49992, 49640, 49278, 48905, 134 | 48523, 48132, 47731, 47322, 46903, 46476, 46041, 45598, 45147, 44688, 44223, 43750, 43271, 42786, 42294, 41797, 135 | 41295, 40787, 40274, 39757, 39236, 38710, 38182, 37650, 37115, 36577, 36037, 35495, 34952, 34407, 33861, 33314, 136 | 32768, 32222, 31675, 31129, 30584, 30041, 29499, 28959, 28421, 27886, 27354, 26826, 26300, 25779, 25262, 24749, 137 | 24241, 23739, 23242, 22750, 22265, 21786, 21313, 20848, 20389, 19938, 19495, 19060, 18633, 18214, 17805, 17404, 138 | 17013, 16631, 16258, 15896, 15544, 15202, 14871, 14551, 14241, 13943, 13656, 13381, 13117, 12865, 12626, 12398, 139 | 12182, 11979, 11789, 11611, 11446, 11293, 11154, 11028, 10914, 10814, 10727, 10654, 10594, 10547, 10513, 10493, 140 | 10486, 10493, 10513, 10547, 10594, 10654, 10727, 10814, 10914, 11028, 11154, 11293, 11446, 11611, 11789, 11979, 141 | 12182, 12398, 12626, 12865, 13117, 13381, 13656, 13943, 14241, 14551, 14871, 15202, 15544, 15896, 16258, 16631, 142 | 17013, 17404, 17805, 18214, 18633, 19060, 19495, 19938, 20389, 20848, 21313, 21786, 22265, 22750, 23242, 23739, 143 | 24241, 24749, 25262, 25779, 26300, 26826, 27354, 27886, 28421, 28959, 29499, 30041, 30584, 31129, 31675, 32222 }; 144 | 145 | #endif 146 | 147 | #elif defined(MDC_SAMPLE_FORMAT_S16) 148 | 149 | #if defined(MDC_ENCODE_FULL_AMPLITUDE) 150 | static mdc_sample_t sintable[] = { 151 | 0, 784, 1569, 2352, 3134, 3914, 4692, 5467, 152 | 6239, 7007, 7770, 8529, 9283, 10031, 10774, 11509, 153 | 12238, 12960, 13673, 14379, 15075, 15763, 16441, 17109, 154 | 17767, 18414, 19051, 19675, 20288, 20889, 21477, 22052, 155 | 22613, 23162, 23696, 24216, 24721, 25212, 25687, 26147, 156 | 26591, 27019, 27431, 27826, 28204, 28566, 28910, 29237, 157 | 29546, 29838, 30111, 30366, 30603, 30822, 31022, 31203, 158 | 31366, 31510, 31634, 31740, 31827, 31894, 31942, 31971, 159 | 31981, 31971, 31942, 31894, 31827, 31740, 31634, 31510, 160 | 31366, 31203, 31022, 30822, 30603, 30366, 30111, 29838, 161 | 29546, 29237, 28910, 28566, 28204, 27826, 27431, 27019, 162 | 26591, 26147, 25687, 25212, 24721, 24216, 23696, 23162, 163 | 22613, 22052, 21477, 20889, 20288, 19675, 19051, 18414, 164 | 17767, 17109, 16441, 15763, 15075, 14379, 13673, 12960, 165 | 12238, 11509, 10774, 10031, 9283, 8529, 7770, 7007, 166 | 6239, 5467, 4692, 3914, 3134, 2352, 1569, 784, 167 | 0, -784, -1569, -2352, -3134, -3914, -4692, -5467, 168 | -6239, -7007, -7770, -8529, -9283, -10031, -10774, -11509, 169 | -12238, -12960, -13673, -14379, -15075, -15763, -16441, -17109, 170 | -17767, -18414, -19051, -19675, -20288, -20889, -21477, -22052, 171 | -22613, -23162, -23696, -24216, -24721, -25212, -25687, -26147, 172 | -26591, -27019, -27431, -27826, -28204, -28566, -28910, -29237, 173 | -29546, -29838, -30111, -30366, -30603, -30822, -31022, -31203, 174 | -31366, -31510, -31634, -31740, -31827, -31894, -31942, -31971, 175 | -31981, -31971, -31942, -31894, -31827, -31740, -31634, -31510, 176 | -31366, -31203, -31022, -30822, -30603, -30366, -30111, -29838, 177 | -29546, -29237, -28910, -28566, -28204, -27826, -27431, -27019, 178 | -26591, -26147, -25687, -25212, -24721, -24216, -23696, -23162, 179 | -22613, -22052, -21477, -20889, -20288, -19675, -19051, -18414, 180 | -17767, -17109, -16441, -15763, -15075, -14379, -13673, -12960, 181 | -12238, -11509, -10774, -10031, -9283, -8529, -7770, -7007, 182 | -6239, -5467, -4692, -3914, -3134, -2352, -1569, -784 }; 183 | #else 184 | static mdc_sample_t sintable[] = { 185 | 186 | 0, 546, 1093, 1639, 2184, 2727, 3269, 3809, 4347, 4882, 5414, 5942, 6468, 6989, 7506, 8019, 187 | 8527, 9029, 9526, 10018, 10503, 10982, 11455, 11920, 12379, 12830, 13273, 13708, 14135, 14554, 14963, 15364, 188 | 15755, 16137, 16510, 16872, 17224, 17566, 17897, 18217, 18527, 18825, 19112, 19387, 19651, 19903, 20142, 20370, 189 | 20586, 20789, 20979, 21157, 21322, 21475, 21614, 21740, 21854, 21954, 22041, 22114, 22174, 22221, 22255, 22275, 190 | 22282, 22275, 22255, 22221, 22174, 22114, 22041, 21954, 21854, 21740, 21614, 21475, 21322, 21157, 20979, 20789, 191 | 20586, 20370, 20142, 19903, 19651, 19387, 19112, 18825, 18527, 18217, 17897, 17566, 17224, 16872, 16510, 16137, 192 | 15755, 15364, 14963, 14554, 14135, 13708, 13273, 12830, 12379, 11920, 11455, 10982, 10503, 10018, 9526, 9029, 193 | 8527, 8019, 7506, 6989, 6468, 5942, 5414, 4882, 4347, 3809, 3269, 2727, 2184, 1639, 1093, 546, 194 | 0, -546, -1093, -1639, -2184, -2727, -3269, -3809, -4347, -4882, -5414, -5942, -6468, -6989, -7506, -8019, 195 | -8527, -9029, -9526, -10018, -10503, -10982, -11455, -11920, -12379, -12830, -13273, -13708, -14135, -14554, -14963, -15364, 196 | -15755, -16137, -16510, -16872, -17224, -17566, -17897, -18217, -18527, -18825, -19112, -19387, -19651, -19903, -20142, -20370, 197 | -20586, -20789, -20979, -21157, -21322, -21475, -21614, -21740, -21854, -21954, -22041, -22114, -22174, -22221, -22255, -22275, 198 | -22282, -22275, -22255, -22221, -22174, -22114, -22041, -21954, -21854, -21740, -21614, -21475, -21322, -21157, -20979, -20789, 199 | -20586, -20370, -20142, -19903, -19651, -19387, -19112, -18825, -18527, -18217, -17897, -17566, -17224, -16872, -16510, -16137, 200 | -15755, -15364, -14963, -14554, -14135, -13708, -13273, -12830, -12379, -11920, -11455, -10982, -10503, -10018, -9526, -9029, 201 | -8527, -8019, -7506, -6989, -6468, -5942, -5414, -4882, -4347, -3809, -3269, -2727, -2184, -1639, -1093, -546 }; 202 | 203 | #endif 204 | 205 | #elif defined(MDC_SAMPLE_FORMAT_FLOAT) 206 | 207 | #if defined(MDC_ENCODE_FULL_AMPLITUDE) 208 | static mdc_sample_t sintable[] = { 209 | 0.000000, 0.024541, 0.049068, 0.073565, 0.098017, 0.122411, 0.146730, 0.170962, 210 | 0.195090, 0.219101, 0.242980, 0.266713, 0.290285, 0.313682, 0.336890, 0.359895, 211 | 0.382683, 0.405241, 0.427555, 0.449611, 0.471397, 0.492898, 0.514103, 0.534998, 212 | 0.555570, 0.575808, 0.595699, 0.615232, 0.634393, 0.653173, 0.671559, 0.689541, 213 | 0.707107, 0.724247, 0.740951, 0.757209, 0.773010, 0.788346, 0.803208, 0.817585, 214 | 0.831470, 0.844854, 0.857729, 0.870087, 0.881921, 0.893224, 0.903989, 0.914210, 215 | 0.923880, 0.932993, 0.941544, 0.949528, 0.956940, 0.963776, 0.970031, 0.975702, 216 | 0.980785, 0.985278, 0.989177, 0.992480, 0.995185, 0.997290, 0.998795, 0.999699, 217 | 1.000000, 0.999699, 0.998795, 0.997290, 0.995185, 0.992480, 0.989177, 0.985278, 218 | 0.980785, 0.975702, 0.970031, 0.963776, 0.956940, 0.949528, 0.941544, 0.932993, 219 | 0.923880, 0.914210, 0.903989, 0.893224, 0.881921, 0.870087, 0.857729, 0.844854, 220 | 0.831470, 0.817585, 0.803208, 0.788346, 0.773010, 0.757209, 0.740951, 0.724247, 221 | 0.707107, 0.689541, 0.671559, 0.653173, 0.634393, 0.615232, 0.595699, 0.575808, 222 | 0.555570, 0.534998, 0.514103, 0.492898, 0.471397, 0.449611, 0.427555, 0.405241, 223 | 0.382683, 0.359895, 0.336890, 0.313682, 0.290285, 0.266713, 0.242980, 0.219101, 224 | 0.195090, 0.170962, 0.146730, 0.122411, 0.098017, 0.073565, 0.049068, 0.024541, 225 | 0.000000, -0.024541, -0.049068, -0.073565, -0.098017, -0.122411, -0.146730, -0.170962, 226 | -0.195090, -0.219101, -0.242980, -0.266713, -0.290285, -0.313682, -0.336890, -0.359895, 227 | -0.382683, -0.405241, -0.427555, -0.449611, -0.471397, -0.492898, -0.514103, -0.534998, 228 | -0.555570, -0.575808, -0.595699, -0.615232, -0.634393, -0.653173, -0.671559, -0.689541, 229 | -0.707107, -0.724247, -0.740951, -0.757209, -0.773010, -0.788346, -0.803208, -0.817585, 230 | -0.831470, -0.844854, -0.857729, -0.870087, -0.881921, -0.893224, -0.903989, -0.914210, 231 | -0.923880, -0.932993, -0.941544, -0.949528, -0.956940, -0.963776, -0.970031, -0.975702, 232 | -0.980785, -0.985278, -0.989177, -0.992480, -0.995185, -0.997290, -0.998795, -0.999699, 233 | -1.000000, -0.999699, -0.998795, -0.997290, -0.995185, -0.992480, -0.989177, -0.985278, 234 | -0.980785, -0.975702, -0.970031, -0.963776, -0.956940, -0.949528, -0.941544, -0.932993, 235 | -0.923880, -0.914210, -0.903989, -0.893224, -0.881921, -0.870087, -0.857729, -0.844854, 236 | -0.831470, -0.817585, -0.803208, -0.788346, -0.773010, -0.757209, -0.740951, -0.724247, 237 | -0.707107, -0.689541, -0.671559, -0.653173, -0.634393, -0.615232, -0.595699, -0.575808, 238 | -0.555570, -0.534998, -0.514103, -0.492898, -0.471397, -0.449611, -0.427555, -0.405241, 239 | -0.382683, -0.359895, -0.336890, -0.313682, -0.290285, -0.266713, -0.242980, -0.219101, 240 | -0.195090, -0.170962, -0.146730, -0.122411, -0.098017, -0.073565, -0.049068, -0.024541 }; 241 | #else 242 | static mdc_sample_t sintable[] = { 243 | 0.000000, 0.016688, 0.033366, 0.050024, 0.066652, 0.083239, 0.099777, 0.116254, 244 | 0.132661, 0.148989, 0.165227, 0.181365, 0.197394, 0.213304, 0.229085, 0.244729, 245 | 0.260225, 0.275564, 0.290737, 0.305736, 0.320550, 0.335171, 0.349590, 0.363798, 246 | 0.377788, 0.391550, 0.405076, 0.418357, 0.431387, 0.444158, 0.456660, 0.468888, 247 | 0.480833, 0.492488, 0.503847, 0.514902, 0.525647, 0.536076, 0.546181, 0.555958, 248 | 0.565399, 0.574500, 0.583255, 0.591659, 0.599706, 0.607393, 0.614713, 0.621663, 249 | 0.628238, 0.634435, 0.640250, 0.645679, 0.650719, 0.655368, 0.659621, 0.663477, 250 | 0.666934, 0.669989, 0.672640, 0.674886, 0.676726, 0.678158, 0.679181, 0.679795, 251 | 0.680000, 0.679795, 0.679181, 0.678158, 0.676726, 0.674886, 0.672640, 0.669989, 252 | 0.666934, 0.663477, 0.659621, 0.655368, 0.650719, 0.645679, 0.640250, 0.634435, 253 | 0.628238, 0.621663, 0.614713, 0.607393, 0.599706, 0.591659, 0.583255, 0.574500, 254 | 0.565399, 0.555958, 0.546181, 0.536076, 0.525647, 0.514902, 0.503847, 0.492488, 255 | 0.480833, 0.468888, 0.456660, 0.444158, 0.431387, 0.418357, 0.405076, 0.391550, 256 | 0.377788, 0.363798, 0.349590, 0.335171, 0.320550, 0.305736, 0.290737, 0.275564, 257 | 0.260225, 0.244729, 0.229085, 0.213304, 0.197394, 0.181365, 0.165227, 0.148989, 258 | 0.132661, 0.116254, 0.099777, 0.083239, 0.066652, 0.050024, 0.033366, 0.016688, 259 | 0.000000, -0.016688, -0.033366, -0.050024, -0.066652, -0.083239, -0.099777, -0.116254, 260 | -0.132661, -0.148989, -0.165227, -0.181365, -0.197394, -0.213304, -0.229085, -0.244729, 261 | -0.260225, -0.275564, -0.290737, -0.305736, -0.320550, -0.335171, -0.349590, -0.363798, 262 | -0.377788, -0.391550, -0.405076, -0.418357, -0.431387, -0.444158, -0.456660, -0.468888, 263 | -0.480833, -0.492488, -0.503847, -0.514902, -0.525647, -0.536076, -0.546181, -0.555958, 264 | -0.565399, -0.574500, -0.583255, -0.591659, -0.599706, -0.607393, -0.614713, -0.621663, 265 | -0.628238, -0.634435, -0.640250, -0.645679, -0.650719, -0.655368, -0.659621, -0.663477, 266 | -0.666934, -0.669989, -0.672640, -0.674886, -0.676726, -0.678158, -0.679181, -0.679795, 267 | -0.680000, -0.679795, -0.679181, -0.678158, -0.676726, -0.674886, -0.672640, -0.669989, 268 | -0.666934, -0.663477, -0.659621, -0.655368, -0.650719, -0.645679, -0.640250, -0.634435, 269 | -0.628238, -0.621663, -0.614713, -0.607393, -0.599706, -0.591659, -0.583255, -0.574500, 270 | -0.565399, -0.555958, -0.546181, -0.536076, -0.525647, -0.514902, -0.503847, -0.492488, 271 | -0.480833, -0.468888, -0.456660, -0.444158, -0.431387, -0.418357, -0.405076, -0.391550, 272 | -0.377788, -0.363798, -0.349590, -0.335171, -0.320550, -0.305736, -0.290737, -0.275564, 273 | -0.260225, -0.244729, -0.229085, -0.213304, -0.197394, -0.181365, -0.165227, -0.148989, 274 | -0.132661, -0.116254, -0.099777, -0.083239, -0.066652, -0.050024, -0.033366, -0.016688 }; 275 | 276 | #endif 277 | 278 | #else 279 | #error "no known sample format defined" 280 | #endif 281 | 282 | mdc_encoder_t * mdc_encoder_new(int sampleRate) 283 | { 284 | mdc_encoder_t *encoder; 285 | 286 | encoder = (mdc_encoder_t *)malloc(sizeof(mdc_encoder_t)); 287 | if(!encoder) 288 | return (mdc_encoder_t *) 0L; 289 | 290 | encoder->loaded = 0; 291 | encoder->preamble_set = 0; 292 | 293 | if(sampleRate == 8000) 294 | { 295 | encoder->incru = 644245094; 296 | encoder->incru18 = 966367642; 297 | } else if(sampleRate == 16000) 298 | { 299 | encoder->incru = 322122547; 300 | encoder->incru18 = 483183820; 301 | } else if(sampleRate == 22050) 302 | { 303 | encoder->incru = 233739716; 304 | encoder->incru18 = 350609575; 305 | } else if(sampleRate == 32000) 306 | { 307 | encoder->incru = 161061274; 308 | encoder->incru18 = 241591910; 309 | } else if(sampleRate == 44100) 310 | { 311 | encoder->incru = 116869858; 312 | encoder->incru18 = 175304788; 313 | } else if(sampleRate == 48000) 314 | { 315 | encoder->incru = 107374182; 316 | encoder->incru18 = 161061274; 317 | } else 318 | { 319 | // WARNING: lower precision than above 320 | encoder->incru = 1200 * 2 * (0x80000000 / sampleRate); 321 | encoder->incru18 = 1800 * 2 * (0x80000000 / sampleRate); 322 | } 323 | 324 | return encoder; 325 | } 326 | 327 | int mdc_encoder_set_preamble(mdc_encoder_t *encoder, 328 | int preambleLength) 329 | { 330 | if(!encoder) 331 | return -1; 332 | 333 | if(preambleLength < 0) 334 | return -1; 335 | 336 | encoder->preamble_set = preambleLength; 337 | 338 | return 0; 339 | } 340 | 341 | static mdc_u8_t * _enc_leader(mdc_u8_t *data) 342 | { 343 | data[0] = 0x55; 344 | data[1] = 0x55; 345 | data[2] = 0x55; 346 | data[3] = 0x55; 347 | data[4] = 0x55; 348 | data[5] = 0x55; 349 | data[6] = 0x55; 350 | 351 | data[7] = 0x07; 352 | data[8] = 0x09; 353 | data[9] = 0x2a; 354 | data[10] = 0x44; 355 | data[11] = 0x6f; 356 | 357 | return &(data[12]); 358 | } 359 | 360 | static mdc_u8_t * _enc_str(mdc_u8_t *data) 361 | { 362 | mdc_u16_t ccrc; 363 | mdc_int_t i, j; 364 | mdc_int_t k; 365 | mdc_int_t m; 366 | mdc_int_t csr[7]; 367 | mdc_int_t b; 368 | mdc_int_t lbits[112]; 369 | 370 | ccrc = _docrc(data, 4); 371 | 372 | data[4] = ccrc & 0x00ff; 373 | data[5] = (ccrc >> 8) & 0x00ff; 374 | 375 | data[6] = 0; 376 | 377 | for(i=0; i<7; i++) 378 | csr[i] = 0; 379 | 380 | for(i=0; i<7; i++) 381 | { 382 | data[i+7] = 0; 383 | for(j=0; j<=7; j++) 384 | { 385 | for(k=6; k > 0; k--) 386 | csr[k] = csr[k-1]; 387 | csr[0] = (data[i] >> j) & 0x01; 388 | b = csr[0] + csr[2] + csr[5] + csr[6]; 389 | data[i+7] |= (b & 0x01) << j; 390 | } 391 | } 392 | 393 | k=0; 394 | m=0; 395 | for(i=0; i<14; i++) 396 | { 397 | for(j=0; j<=7; j++) 398 | { 399 | b = 0x01 & (data[i] >> j); 400 | lbits[k] = b; 401 | k += 16; 402 | if(k > 111) 403 | k = ++m; 404 | } 405 | } 406 | 407 | k = 0; 408 | for(i=0; i<14; i++) 409 | { 410 | data[i] = 0; 411 | for(j=7; j>=0; j--) 412 | { 413 | if(lbits[k]) 414 | data[i] |= 1<loaded) 435 | return -1; 436 | 437 | encoder->state = 0; 438 | 439 | dp = _enc_leader(encoder->data); 440 | 441 | dp[0] = op; 442 | dp[1] = arg; 443 | dp[2] = (unitID >> 8) & 0x00ff; 444 | dp[3] = unitID & 0x00ff; 445 | 446 | _enc_str(dp); 447 | 448 | encoder->loaded = 26; 449 | 450 | return 0; 451 | } 452 | 453 | int mdc_encoder_set_double_packet(mdc_encoder_t *encoder, 454 | unsigned char op, 455 | unsigned char arg, 456 | unsigned short unitID, 457 | unsigned char extra0, 458 | unsigned char extra1, 459 | unsigned char extra2, 460 | unsigned char extra3) 461 | { 462 | mdc_u8_t *dp; 463 | 464 | if(!encoder) 465 | return -1; 466 | 467 | if(encoder->loaded) 468 | return -1; 469 | 470 | encoder->state = 0; 471 | 472 | dp = _enc_leader(encoder->data); 473 | 474 | dp[0] = op; 475 | dp[1] = arg; 476 | dp[2] = (unitID >> 8) & 0x00ff; 477 | dp[3] = unitID & 0x00ff; 478 | 479 | dp = _enc_str(dp); 480 | 481 | dp[0] = extra0; 482 | dp[1] = extra1; 483 | dp[2] = extra2; 484 | dp[3] = extra3; 485 | 486 | _enc_str(dp); 487 | 488 | encoder->loaded = 40; 489 | 490 | return 0; 491 | } 492 | 493 | static mdc_sample_t _enc_get_samp(mdc_encoder_t *encoder) 494 | { 495 | mdc_int_t b; 496 | mdc_int_t ofs; 497 | 498 | mdc_u32_t lthu = encoder->thu; 499 | encoder->thu += encoder->incru; 500 | 501 | 502 | if(encoder->thu < lthu) // wrap 503 | { 504 | encoder->ipos++; 505 | if(encoder->ipos > 7) 506 | { 507 | encoder->ipos = 0; 508 | if(encoder->preamble_count == 0) 509 | encoder->bpos++; 510 | else 511 | encoder->preamble_count--; 512 | 513 | if(encoder->bpos >= encoder->loaded) 514 | { 515 | encoder->state = 0; 516 | return sintable[0]; 517 | } 518 | } 519 | 520 | b = 0x01 & (encoder->data[encoder->bpos] >> (7-(encoder->ipos))); 521 | 522 | if(b != encoder->lb) 523 | { 524 | encoder->xorb = 1; 525 | encoder->lb = b; 526 | } 527 | else 528 | encoder->xorb = 0; 529 | } 530 | 531 | if(encoder->xorb) 532 | encoder->tthu += encoder->incru18; 533 | else 534 | encoder->tthu += encoder->incru; 535 | 536 | ofs = (int)(encoder->tthu >> 24); 537 | 538 | return sintable[ofs]; 539 | } 540 | 541 | int mdc_encoder_get_samples(mdc_encoder_t *encoder, 542 | mdc_sample_t *buffer, 543 | int bufferSize) 544 | { 545 | mdc_int_t i; 546 | 547 | if(!encoder) 548 | return -1; 549 | 550 | if(!(encoder->loaded)) 551 | return 0; 552 | 553 | if(encoder->state == 0) 554 | { 555 | encoder->tthu = 0; 556 | encoder->thu = 0; 557 | encoder->bpos = 0; 558 | encoder->ipos = 0; 559 | encoder->state = 1; 560 | encoder->xorb = 1; 561 | encoder->lb = 0; 562 | encoder->preamble_count = encoder->preamble_set; 563 | } 564 | 565 | i = 0; 566 | while((i < bufferSize) && encoder->state) 567 | { 568 | buffer[i++] = _enc_get_samp(encoder); 569 | } 570 | 571 | #ifdef FILL_FINAL 572 | while(istate == 0) 579 | encoder->loaded = 0; 580 | return i; 581 | } 582 | 583 | -------------------------------------------------------------------------------- /mdc_encode.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * mdc_encode.h 3 | * header for mdc_encode.c 4 | * 5 | * 9 October 2010 - typedefs for easier porting 6 | * 7 | * Author: Matthew Kaufman (matthew@eeph.com) 8 | * 9 | * Copyright (c) 2005 Matthew Kaufman All rights reserved. 10 | * 11 | * This file is part of Matthew Kaufman's MDC Encoder/Decoder Library 12 | * 13 | * The MDC Encoder/Decoder Library is free software; you can 14 | * redistribute it and/or modify it under the terms of version 2 of 15 | * the GNU General Public License as published by the Free Software 16 | * Foundation. 17 | * 18 | * If you cannot comply with the terms of this license, contact 19 | * the author for alternative license arrangements or do not use 20 | * or redistribute this software. 21 | * 22 | * The MDC Encoder/Decoder Library is distributed in the hope 23 | * that it will be useful, but WITHOUT ANY WARRANTY; without even the 24 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 25 | * PURPOSE. See the GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this software; if not, write to the Free Software 29 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 30 | * USA. 31 | * 32 | * or see http://www.gnu.org/copyleft/gpl.html 33 | * 34 | -*/ 35 | 36 | #ifndef _MDC_ENCODE_H_ 37 | #define _MDC_ENCODE_H_ 38 | 39 | #include "mdc_types.h" 40 | 41 | //#define FILL_FINAL // fills the end of the last block with zeros, rather than returning fewer samples than requested 42 | 43 | //#define MDC_ENCODE_FULL_AMPLITUDE // encode at 100% amplitude (default is 68% amplitude for recommended deviation) 44 | 45 | typedef struct { 46 | mdc_int_t loaded; 47 | mdc_int_t bpos; 48 | mdc_int_t ipos; 49 | mdc_int_t preamble_set; 50 | mdc_int_t preamble_count; 51 | mdc_u32_t thu; 52 | mdc_u32_t tthu; 53 | mdc_u32_t incru; 54 | mdc_u32_t incru18; 55 | mdc_int_t state; 56 | mdc_int_t lb; 57 | mdc_int_t xorb; 58 | mdc_u8_t data[14+14+5+7]; 59 | } mdc_encoder_t; 60 | 61 | 62 | /* 63 | mdc_encoder_new 64 | create a new mdc_encoder object 65 | 66 | parameters: int sampleRate - the sampling rate in Hz 67 | 68 | returns: an mdc_encoder object or null if failure 69 | 70 | */ 71 | mdc_encoder_t * mdc_encoder_new(int sampleRate); 72 | 73 | /* 74 | mdc_encoder_set_preamble(mdc_encoder_t *encoder, 75 | int preambleLength) 76 | 77 | parameters: mdc_encoder_t *encoder - pointer to the encoder object 78 | int preambleLength - length of additional preamble (in bytes) - preamble time is 6.66 msec * preambleLength 79 | 80 | returns: -1 for error, 0 otherwise 81 | */ 82 | 83 | int mdc_encoder_set_preamble(mdc_encoder_t *encoder, 84 | int preambleLength); 85 | 86 | 87 | /* 88 | mdc_encoder_set_packet 89 | set up a normal-length MDC packet for transmission 90 | 91 | parameters: mdc_encoder_t *encoder - pointer to the encoder object 92 | unsigned char op - the "opcode" 93 | unsigned char arg - the "argument" 94 | unsigned short unitID - the "unit ID" 95 | 96 | returns: -1 for error, 0 otherwise 97 | 98 | */ 99 | int mdc_encoder_set_packet(mdc_encoder_t *encoder, 100 | unsigned char op, 101 | unsigned char arg, 102 | unsigned short unitID); 103 | 104 | /* 105 | mdc_encoder_set_double_packet 106 | set up a double-length MDC packet for transmission 107 | 108 | parameters: mdc_encoder_t *encoder - pointer to the encoder object 109 | unsigned char op - the "opcode" 110 | unsigned char arg - the "argument" 111 | unsigned short unitID - the "unit ID 112 | unsigned char extra0 - the 1st "extra byte" 113 | unsigned char extra1 - the 2nd "extra byte" 114 | unsigned char extra2 - the 3rd "extra byte" 115 | unsigned char extra3 - the 4th "extra byte" 116 | 117 | returns: -1 for error, 0 otherwise 118 | 119 | */ 120 | int mdc_encoder_set_double_packet(mdc_encoder_t *encoder, 121 | unsigned char op, 122 | unsigned char arg, 123 | unsigned short unitID, 124 | unsigned char extra0, 125 | unsigned char extra1, 126 | unsigned char extra2, 127 | unsigned char extra3); 128 | 129 | 130 | /* 131 | mdc_encoder_get_samples 132 | get generated output audio samples from encoder 133 | 134 | parameters: mdc_encoder_t *encoder - the pointer to the encoder object 135 | mdc_sample_t *buffer - the sample buffer to write into 136 | int bufferSize - the size (in samples) of the sample buffer 137 | 138 | returns: -1 for error, otherwise returns the number of samples written 139 | into the buffer (will be equal to bufferSize unless the end has 140 | been reached, in which case the last block may be less than 141 | bufferSize and all subsequent calls will return zero, until 142 | a new packet is loaded for transmission 143 | 144 | */ 145 | int mdc_encoder_get_samples(mdc_encoder_t *encoder, 146 | mdc_sample_t *buffer, 147 | int bufferSize); 148 | 149 | #endif 150 | 151 | -------------------------------------------------------------------------------- /mdc_test.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * functiontest.c 3 | * Functional test for mdc_decode and mdc_encode 4 | * 5 | * 24 May 2011 - Initial implementation 6 | * 7 | * Author: Matthew Kaufman (matthew@eeph.com) 8 | * 9 | * Copyright (c) 2011 Matthew Kaufman All rights reserved. 10 | * 11 | * This file is part of Matthew Kaufman's MDC Encoder/Decoder Library 12 | * 13 | * The MDC Encoder/Decoder Library is free software; you can 14 | * redistribute it and/or modify it under the terms of version 2 of 15 | * the GNU General Public License as published by the Free Software 16 | * Foundation. 17 | * 18 | * If you cannot comply with the terms of this license, contact 19 | * the author for alternative license arrangements or do not use 20 | * or redistribute this software. 21 | * 22 | * The MDC Encoder/Decoder Library is distributed in the hope 23 | * that it will be useful, but WITHOUT ANY WARRANTY; without even the 24 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 25 | * PURPOSE. See the GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this software; if not, write to the Free Software 29 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 30 | * USA. 31 | * 32 | * or see http://www.gnu.org/copyleft/gpl.html 33 | * 34 | -*/ 35 | 36 | #include 37 | #include 38 | 39 | #include "mdc_encode.h" 40 | #include "mdc_decode.h" 41 | 42 | void run(mdc_encoder_t *encoder, mdc_decoder_t *decoder, int expect); 43 | 44 | void testCallback(int numFrames, unsigned char op, unsigned char arg, unsigned short unitID, unsigned char extra0, unsigned char extra1, unsigned char extra2, unsigned char extra3, void *context); 45 | 46 | 47 | 48 | int main() 49 | { 50 | mdc_encoder_t *encoder; 51 | mdc_decoder_t *decoder; 52 | int rv; 53 | 54 | encoder = mdc_encoder_new(16000); 55 | decoder = mdc_decoder_new(16000); 56 | 57 | if(!decoder) 58 | { 59 | fprintf(stderr,"mdc_decoder_new() failed\n"); 60 | exit(-1); 61 | } 62 | 63 | if(!encoder) 64 | { 65 | fprintf(stderr,"mdc_encoder_new() failed\n"); 66 | exit(-1); 67 | } 68 | 69 | rv = mdc_encoder_set_packet(encoder, 0x12, 0x34, 0x5678); 70 | 71 | if(rv) 72 | { 73 | fprintf(stderr,"mdc_encoder_set_packet() failed\n"); 74 | exit(-1); 75 | } 76 | 77 | run(encoder, decoder, 1); 78 | 79 | rv = mdc_encoder_set_double_packet(encoder, 0x55, 0x34, 0x5678, 0x0a, 0x0b, 0x0c, 0x0d); 80 | 81 | if(rv) 82 | { 83 | fprintf(stderr,"mdc_encoder_set_packet() failed\n"); 84 | exit(-1); 85 | } 86 | 87 | printf("1: "); 88 | run(encoder, decoder, 2); 89 | 90 | rv = mdc_encoder_set_double_packet(encoder, 0x55, 0x34, 0x5678, 0x0a, 0x0b, 0x0c, 0x0d); 91 | printf("2: "); 92 | run(encoder, decoder, 2); 93 | rv = mdc_encoder_set_double_packet(encoder, 0x55, 0x34, 0x5678, 0x0a, 0x0b, 0x0c, 0x0d); 94 | printf("3: "); 95 | run(encoder, decoder, 2); 96 | rv = mdc_encoder_set_double_packet(encoder, 0x55, 0x34, 0x5678, 0x0a, 0x0b, 0x0c, 0x0d); 97 | printf("4: "); 98 | run(encoder, decoder, 2); 99 | rv = mdc_encoder_set_double_packet(encoder, 0x55, 0x34, 0x5678, 0x0a, 0x0b, 0x0c, 0x0d); 100 | printf("5: "); 101 | run(encoder, decoder, 2); 102 | rv = mdc_encoder_set_double_packet(encoder, 0x55, 0x34, 0x5678, 0x0a, 0x0b, 0x0c, 0x0d); 103 | printf("6: "); 104 | run(encoder, decoder, 2); 105 | rv = mdc_encoder_set_double_packet(encoder, 0x55, 0x34, 0x5678, 0x0a, 0x0b, 0x0c, 0x0d); 106 | printf("7: "); 107 | run(encoder, decoder, 2); 108 | rv = mdc_encoder_set_double_packet(encoder, 0x55, 0x34, 0x5678, 0x0a, 0x0b, 0x0c, 0x0d); 109 | printf("8: "); 110 | run(encoder, decoder, 2); 111 | rv = mdc_encoder_set_double_packet(encoder, 0x55, 0x34, 0x5678, 0x0a, 0x0b, 0x0c, 0x0d); 112 | printf("9: "); 113 | run(encoder, decoder, 2); 114 | /* additional tests for callback mode */ 115 | 116 | rv = mdc_decoder_set_callback(decoder, testCallback, (void*) 0x555); 117 | 118 | rv = mdc_encoder_set_packet(encoder, 0x12, 0x34, 0x5678); 119 | 120 | if(rv) 121 | { 122 | fprintf(stderr,"mdc_encoder_set_packet() failed\n"); 123 | exit(-1); 124 | } 125 | 126 | run(encoder, decoder, -1); 127 | 128 | rv = mdc_encoder_set_double_packet(encoder, 0x55, 0x34, 0x5678, 0x0a, 0x0b, 0x0c, 0x0d); 129 | 130 | if(rv) 131 | { 132 | fprintf(stderr,"mdc_encoder_set_packet() failed\n"); 133 | exit(-1); 134 | } 135 | 136 | run(encoder, decoder, -2); 137 | 138 | 139 | 140 | 141 | fprintf(stderr,"mdc functional test overall success\n"); 142 | exit(0); 143 | } 144 | 145 | int callbackFound; 146 | 147 | #define NUMSAMPLES 1024 148 | 149 | void run(mdc_encoder_t *encoder, mdc_decoder_t *decoder, int expect) 150 | { 151 | int rv, rv2, rv3; 152 | int cont = 10; 153 | int msgFound = 0; 154 | 155 | callbackFound = 0; 156 | 157 | while(cont) 158 | { 159 | mdc_sample_t buffer[NUMSAMPLES]; 160 | 161 | rv = mdc_encoder_get_samples(encoder, buffer, NUMSAMPLES); 162 | 163 | if(rv < 0) 164 | { 165 | fprintf(stderr,"mdc_encoder_get_samples() failed\n"); 166 | exit(-1); 167 | } 168 | else if(rv == 0) 169 | { 170 | int i; 171 | --cont; 172 | for(i = 0; i