From b1024fba9543ce7e76c8de15ff396a4d3f173dbe Mon Sep 17 00:00:00 2001 From: Jared Szechy Date: Sun, 21 Aug 2011 03:36:53 -0400 Subject: [PATCH] version 1.4.1 --- CHANGELOG | 43 +++++++++- DSD_Author.pgp | 52 +++++------ Makefile | 14 ++- README | 95 ++++++++++---------- configure | 0 dmr_data.c | 13 +-- dmr_voice.c | 14 ++- dsd.h | 57 +++++++++--- dsd_audio.c | 12 ++- dsd_file.c | 93 ++++++++++++++++++-- dsd_frame.c | 63 ++++++++++---- dsd_frame_sync.c | 219 ++++++++++++++++++++++++++++++++++------------- dsd_main.c | 106 ++++++++++++++++++----- dsd_mbe.c | 6 +- dsd_serial.c | 8 +- dsd_symbol.c | 26 +++++- dsd_upsample.c | 163 +++++++---------------------------- nxdn_const.h | 66 ++++++++++++++ nxdn_data.c | 36 ++++++++ nxdn_voice.c | 59 +++++++++++++ p25_lcw.c | 36 ++++---- p25p1_hdu.c | 4 + x2tdma_data.c | 13 +-- x2tdma_voice.c | 15 +++- 24 files changed, 818 insertions(+), 395 deletions(-) mode change 100644 => 100755 configure create mode 100644 nxdn_const.h create mode 100644 nxdn_data.c create mode 100644 nxdn_voice.c diff --git a/CHANGELOG b/CHANGELOG index f25297d..da71e08 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,44 @@ +1.4.1 + New features: + Several new sync types for existing formats now recognized: + Decodes voice from NXDN 4800 (6.25kHz) signals + Decodes voice from NXDN 9600 (12.5kHz) repeater output + Decodes voice from DMR/MotoTRBO simplex/repeater input + Decodes voice from X2-TDMA simplex/repeater input + + Fixed bugs: + renamed "input:" to "inlvl:" to reduce confusion. This value + indicates the audio input level, NOT the "decode success + rate". Voice decode errors are indicated by the errorbars "=". + +1.4 + New features: + Decodes voice from NXDN 9600 (12.5 kHz) simplex/repeater input + NXDN96 frames enabled by default + Improved resistance to NXDN96 sync false positives + + Fixed bugs: + .wav file header updated after playing .imb/.amb data files + .imb/.amb files now have correct tgid in filename + +1.3.1 New features: + Support for ProVoice EA sync + CTRL-C is now caught so .wav files can be properly closed + DSD now shows mbelib version as well as it's own version + -R resume option now triggers on any TSDU so control channels can be left + in conventional scanlists. + Auto output gain now has 0.5 second hold time for faster error burst recovery + (was 1.5 seconds) + Audio output upsampling function simplified and improved + + Fixed bugs: + DSD_Author.pgp now has correct public key (was copy of mbelib_Author key) + TGID and SRC are now cleared after TDULC or TDU. + Voice error counter is now reset in noCarrier() + TGID and SRC were not displaying for X2-TDMA frames + Fixed buffer issue in resumeScan() + Fixed error in .wav file headers preventing playback on some apps + 1.3 New features: Decodes voice from ProVoice signals (requires -fp option) algid and kid are now shown in hex notation @@ -17,7 +58,7 @@ Fixed bugs: nac was showing wrong ID - p25 metadata (lcinfo, mfid, lfcormat, mi, keyid, algid, lsd) are now + P25 metadata (lcinfo, mfid, lfcormat, mi, keyid, algid, lsd) are now printed out in the correct bit order (MSB -> LSB), was reversed. fixed serveral bugs in dsd_upsample.c, with improved quality diff --git a/DSD_Author.pgp b/DSD_Author.pgp index 2303a46..cdc0327 100644 --- a/DSD_Author.pgp +++ b/DSD_Author.pgp @@ -1,30 +1,30 @@ -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1.4.10 -mQENBEufusYBCADN1SNkRkQzdLM02MCjen8KQmfuA38MrQIV0dZLpPJcn1+hsvZZ -KWvpUiWCNw1ClGRsJAT5cjonndi1PV7tpzQz+CyMqSP5OwR40eTJBoZhl74hdmU8 -QvcKkJ32khSsOXMo60NHk5iIMDELzOGqq57NHhbunj6NtYog2mR5+WT37JLCvF/q -dvYl2KkRwEHD76/b/O1CyheiiqNMGBb13zPN0qO/PRlENSgViLcDh9qVj4ETNNS6 -zMlP4D4pa07iED4Ua31wiXI04ReznnmvMqzQb8uFbg7d98F3bZpsbNURbmsFHMhj -c9qw65nzaMa3OHfZ3Qwl4XRlNqEzZrclIZADABEBAAG0DW1iZWxpYiBBdXRob3KJ -ATgEEwECACIFAkufusYCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEE+Y -6GPqXv4sI/4H/RsumInT5GtDdBTgxt3lERqc5GF8tI5CAQX9DUMMkKxQ306Fgb4M -ISYdepgL6BlbtSyMdKpKsDLScNA6YXER4gMU1nhhyBulqj41kAfsVbG8hiTBy5Ri -FTo36HrC//Zj1MlaTCB8Rl6B6IftAHIb1U+Gda3WnLDe+R5Pym/76TqeYx23PnJl -V+qfrkjbNyOb2bttyko2iccm9DSq/I1OF0Ufz3P60ssUwHW/b2S6WOXRxiZIq0sz -8pAweUFCxIMWo+XYlSpRtwpebfx+JoHJKdW1cSCgY9jwVsOZO1zxc8P+jr3ByiIR -ZPd0PfBt/AHuC6Hmw9nC12e49+4qsHkj50S5AQ0ES5+6xgEIALf60WjqHm552FIX -KqmG0TIrXpCsYoTWzDdO5j0Ro6fmg9U48BqDH5aS4YRvuyPE7q6DGYEnXF5EIPtU -FhUk4FMmez5eMg91UW4Qjqx8M3reoBROYocM5Nfbc9w7St8+3oRS6rUBIh/B6o4O -kEjkoW3R7O3uFpC53Oi9IVhx/joWxhi430RrUTig5CQzuPFTAHd3xJVE6Pv44nsY -/PsOhBLu2Z3kRkvjcGbsGDlAl2bDEobzQdsqXDD8gJkF5W4IeBKvRC54SE0FSm57 -G1gadhZ7vT4DWQZvYYKXR+AE7FTcopoAFHdapYokOGLHCguabyeZ5q7+s7J4nddL -p5yq8ikAEQEAAYkBHwQYAQIACQUCS5+6xgIbDAAKCRBPmOhj6l7+LPi6B/sEkDkm -Qs/aTz9HDANBAbTuDZTY4WBbkPdFos3xxC2Z/TH5m4bfHEkvNk5WD+j+vYB3exAc -uBi7ZiqibRpap4kiAiKKCRXOyvmEmrjKB5wOWbRpkdTeEdPcpsQ4dDDw1ZUKwzjN -1jI/9GOgq49nAGdlU59f3IdPut6oQNq9vrtanTq2xHVN/rOhV9GLE6gLX1YWkpIH -zYSUheGPsnv4sWRsQDTB7xmF+6RZzjmauKNwsGFscX1TenOWtUbYb9qFCwvNMOSk -51sEaD6PK6wWTXMqQlgjaoGqh1ZaePgT0QTh1W/bvOD0fL5NEToJl2h/lBSvO+ez -R9B++dt5JX9BMxAH -=puA7 +mQENBEufuqsBCADAtWFE1qE3xqJE4xggUn6id0fVulM7y+rSH1VPxo7Ps9duc/O9 +VegEx8+N5KphDROS4RgHxMiS1O8Qy5Hpq4gEp6RvLNj3s+0DMwqRZoA0tBCkNmvF +K7sF+GncrOu/NZkDIZ8emN9NWWeWynWJvuM2H5HQA9yCq+YTFae5sgyr3APC3xh4 +OkTuVMcclGTJdVrISlNBDpo/AZLJ/nV0SgITpiZVsI4RSNiQPP1kX+2fIDEAwtxN +3HIDyegDoX36cOItsb05zHkLxoUoZnWoxMvV3rwnqXg5cr6PWfiwgqWd0avl1sg6 +abpR6MKV68OCpTkqMrDIXJJrM2sTz+ZB2bBtABEBAAG0CkRTRCBBdXRob3KJATgE +EwECACIFAkufuqsCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEPqiY10/ +HX/Q11UH/0ZutGQWLZyZD5ZqVdBeYEf6IKhKhaC2vD/+5zUJ2cIgT5xJVTPCKN7X +sygBANJc9GyPRYRvQecdcTHR5B+wUKCPeibv9iQuU3v7Uqb5edXEh2b4jOMWNvHJ +l3lqBdUefuQdbc2xXCPgn+GkyexXEBsVF3hCzWV9r4bCpY57iWUYZZT0wAbN81hz +jPKCCRmF+gZUUufxyhUGq/+eAKeUll6lgG5Ms2YKOlUMphfMav45qgWZHj1DASOV +wPsiIVUaC6+GtHTTzHYRL05ydxxduX+yyKDO1emCE4fx1n3jdwToHLRrC1ui+AJM +Q1s+bp+bGmMYaYaKc/JtNHcN8mbWyCK5AQ0ES5+6qwEIAJvPrnv2QO5Be3FRsnYL +qbA1h/Lj0SjnuimaiNOzCYFIYtusLpyWjwWUnOEXdw5FoExqUStOHJ557SDG/zFB +qy+DsNC9ncSRZ5U2tUQUtt50m2lpYvoy/sVf3oN+IsyZ5hZpiAwrxlyMC/aoGR3C +6ZlLkZ42azNCmEmoBniIxQ+XwhwkLMRsOnqLoFyXB9CcDFIXeEhZkVWZT0B5+20f +yGSBDJ6VcIAASoaIyvSwU9l/DT7D/s0J8WnZQZmRdrsZ3Ikj0Sv/4D2MJnCVJTSw +DHq5Sf7DmUq/WD0iWRLEXWmPt9w3WxP4imhtmIpICxCDoeQUTkqFpOTf29sVcpPt +838AEQEAAYkBHwQYAQIACQUCS5+6qwIbDAAKCRD6omNdPx1/0O8ECADAcPORjGFl +RnIrsgiVMp82GQ7hnZZxktU1WVVx8EsPTT1DD79nIoeKI+UcenzuOGyTX7DGcy+P +rWntUbt2ZygPTbP5Wu6zd845y9EzjxQ5q0vDF4oAefQptwqGDVeO/KBv9cZLbnih +VEjQELgC/rVB7nd5p83EL5vb8qL/Eiu65stxwZ3QOT9pp2bsAPk6LJWWnVqJroKI +Pc6KWG7n6mMJPbhFmE8Ld2lcNlSKQwLHIxDocL2GAqh5S5hJeGg2oLMFpy0g2Ron +643w0zPfpKC15TlnkJDCIgtRlHovrs42Qkypz9y3e8yOL9O0RLYIKbuKw4mNR3cT +OdeV+TjfiZ5I +=2oe6 -----END PGP PUBLIC KEY BLOCK----- diff --git a/Makefile b/Makefile index 8825fde..31cc335 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ # PERFORMANCE OF THIS SOFTWARE. CC = gcc -CFLAGS = -O2 +CFLAGS = -O2 -Wall INCLUDES = -I. -I/usr/local/include -I/usr/include LIBS = -L/usr/local/lib -lm -lmbe INSTALL=install @@ -24,7 +24,7 @@ DEST_BASE=/usr/local DEST_INC=${DEST_BASE}/include DEST_LIB=${DEST_BASE}/lib DEST_BIN=${DEST_BASE}/bin -OBJS = dsd_main.o dsd_symbol.o dsd_dibit.o dsd_frame_sync.o dsd_file.o dsd_audio.o dsd_serial.o dsd_frame.o dsd_mbe.o dsd_upsample.o p25p1_hdu.o p25p1_ldu1.o p25p1_ldu2.o p25p1_tdulc.o p25_lcw.o x2tdma_voice.o x2tdma_data.o dstar.o nxdn96.o dmr_voice.o dmr_data.o provoice.o +OBJS = dsd_main.o dsd_symbol.o dsd_dibit.o dsd_frame_sync.o dsd_file.o dsd_audio.o dsd_serial.o dsd_frame.o dsd_mbe.o dsd_upsample.o p25p1_hdu.o p25p1_ldu1.o p25p1_ldu2.o p25p1_tdulc.o p25_lcw.o x2tdma_voice.o x2tdma_data.o dstar.o nxdn_voice.o nxdn_data.o dmr_voice.o dmr_data.o provoice.o all: dsd @@ -84,8 +84,14 @@ x2tdma_data.o: x2tdma_data.c x2tdma_const.h dsd.h config.h dstar.o: dstar.c dstar_const.h dsd.h config.h $(CC) $(CFLAGS) $(INCLUDES) -c dstar.c -o dstar.o -nxdn96.o: nxdn96.c nxdn96_const.h dsd.h config.h - $(CC) $(CFLAGS) $(INCLUDES) -c nxdn96.c -o nxdn96.o +nxdn48_voice.o: nxdn48_voice.c nxdn_const.h dsd.h config.h + $(CC) $(CFLAGS) $(INCLUDES) -c nxdn48_voice.c -o nxdn48_voice.o + +nxdn_voice.o: nxdn_voice.c nxdn_const.h dsd.h config.h + $(CC) $(CFLAGS) $(INCLUDES) -c nxdn_voice.c -o nxdn_voice.o + +nxdn_data.o: nxdn_data.c nxdn_const.h dsd.h config.h + $(CC) $(CFLAGS) $(INCLUDES) -c nxdn_data.c -o nxdn_data.o dmr_voice.o: dmr_voice.c dmr_const.h dsd.h config.h $(CC) $(CFLAGS) $(INCLUDES) -c dmr_voice.c -o dmr_voice.o diff --git a/README b/README index 9709a75..909f404 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -Digital Speech Decoder 1.3 +Digital Speech Decoder 1.4 Copyright (C) 2010 DSD Author GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0) @@ -16,10 +16,10 @@ PERFORMANCE OF THIS SOFTWARE. DSD is able to decode several digital voice formats from discriminator tap audio and synthesize the decoded speech. Speech - synthesis requires mbelib, which is a separate package. DSD 1.3 + synthesis requires mbelib, which is a separate package. DSD 1.4.1 requires mbelib 1.1 or later. - Supported formats in version 1.3: + Supported formats in version 1.4.1: P25 Phase 1 Widely deployed radio standard used in public safety and amateur radio. @@ -46,19 +46,18 @@ PERFORMANCE OF THIS SOFTWARE. DMR/MOTOTRBO "Digital Mobile Radio" Eurpoean two slot TDMA standard. MOTOTRBO is a popular implementation of this standard. - Support includes decoding and synthesis of speech and - the ability to save and replay .amb data files. + Support includes decoding and synthesis of speech and + the ability to save and replay .amb data files. + + NXDN Digital radio standard used by NEXEDGE and IDAS brands. + Supports both 9600 baud (12.5 kHz) and + 4800 baud (6.25 kHz) digital voice. + + Support includes decoding and synthesis of speech and + the ability to save and replay .amb data files. Development (no speech) support only: - NXDN (9600) Digital radio standard used by NEXEDGE and IDAS brands. - - Development support only. DSD recognizes frames and can - extract the voice bits but speech is not yet decoded. - The issue is likely either an unusual interleave pattern - or a pseudo-random bit mask initialized by a "color code" - Note: not enabled by default, use -fn to enable. - D-STAR Amateur radio digital voice standard Development support only. DSD recognized frames and can @@ -66,9 +65,9 @@ PERFORMANCE OF THIS SOFTWARE. D-STAR likely uses a version of AMBE not yet supported by mbelib. The voice bit interleave pattern also needs to be determined. - Note: not enabled by default, use -fn to enable. + Note: not enabled by default, use -fd to enable. - Unsupported formats in version 1.3 considered for future development: + Unsupported formats in version 1.4 considered for future development: P25 Phase 2 This is not yet a published standard. Full support is expected once the standard is published and there are @@ -78,10 +77,7 @@ PERFORMANCE OF THIS SOFTWARE. OpenSKY It is possible that the four slot version uses a vocoder supported by mbelib. The two slot version does not. - NXDN (4800) This should be supportable as soon as we have .wav files - or access to a radio programmed in this format. - - Supported demodulation optimizations in version 1.3: + Supported demodulation optimizations in version 1.4: C4FM Continuous envelope 2 or 4 level FSK with relatively sharp transitions between symbols. Used by most P25 @@ -147,19 +143,19 @@ Display modes Errorbars mode output for P25 Phase 1 looks like this: -Sync: -p25p1 mod: C4FM input: 39% nac: 5C2 src: 0 tg: 32464 TDULC -Sync: -p25p1 mod: C4FM input: 39% nac: 5C2 src: 0 tg: 32464 TDULC -Sync: -p25p1 mod: C4FM input: 39% nac: 5C2 src: 0 tg: 32464 TDULC -Sync: -p25p1 mod: C4FM input: 39% nac: 5C2 src: 0 tg: 32464 TDULC -Sync: -p25p1 mod: C4FM input: 38% nac: 5C2 src: 0 tg: 32464 TDU -Sync: -p25p1 mod: C4FM input: 38% nac: 5C2 src: 0 tg: 32464 HDU -Sync: -p25p1 mod: C4FM input: 42% nac: 5C2 src: 0 tg: 32464 LDU1 e: -Sync: (-p25p1) mod: C4FM input: 39% nac: 5C2 src: 52610 tg: 32464 (LDU2) e: -Sync: -p25p1 mod: C4FM input: 38% nac: 5C2 src: 52610 tg: 32464 LDU1 e: -Sync: -p25p1 mod: C4FM input: 39% nac: 5C2 src: 52610 tg: 32464 LDU2 e: -Sync: -p25p1 mod: C4FM input: 39% nac: 5C2 src: 52610 tg: 32464 LDU1 e: -Sync: -p25p1 mod: C4FM input: 39% nac: 5C2 src: 52610 tg: 32464 LDU2 e: -Sync: -p25p1 mod: C4FM input: 39% nac: 5C2 src: 52610 tg: 32464 LDU1 e: +Sync: -P25p1 mod: C4FM inlvl: 39% nac: 5C2 src: 0 tg: 32464 TDULC +Sync: -P25p1 mod: C4FM inlvl: 39% nac: 5C2 src: 0 tg: 32464 TDULC +Sync: -P25p1 mod: C4FM inlvl: 39% nac: 5C2 src: 0 tg: 32464 TDULC +Sync: -P25p1 mod: C4FM inlvl: 39% nac: 5C2 src: 0 tg: 32464 TDULC +Sync: -P25p1 mod: C4FM inlvl: 38% nac: 5C2 src: 0 tg: 32464 TDU +Sync: -P25p1 mod: C4FM inlvl: 38% nac: 5C2 src: 0 tg: 32464 HDU +Sync: -P25p1 mod: C4FM inlvl: 42% nac: 5C2 src: 0 tg: 32464 LDU1 e: +Sync: (-P25p1) mod: C4FM inlvl: 39% nac: 5C2 src: 52610 tg: 32464 (LDU2) e: +Sync: -P25p1 mod: C4FM inlvl: 38% nac: 5C2 src: 52610 tg: 32464 LDU1 e: +Sync: -P25p1 mod: C4FM inlvl: 39% nac: 5C2 src: 52610 tg: 32464 LDU2 e: +Sync: -P25p1 mod: C4FM inlvl: 39% nac: 5C2 src: 52610 tg: 32464 LDU1 e: +Sync: -P25p1 mod: C4FM inlvl: 39% nac: 5C2 src: 52610 tg: 32464 LDU2 e: +Sync: -P25p1 mod: C4FM inlvl: 39% nac: 5C2 src: 52610 tg: 32464 LDU1 e: "Sync" indicates the frame type detected and whether the polarity is positive or negative. DSD automatically detects and handles either @@ -179,7 +175,7 @@ Sync: -p25p1 mod: C4FM input: 39% nac: 5C2 src: 52610 tg: 32464 LDU1 e: "mod" indicates the current demodulation optimizations. - "input" indicates the audio input level. QPSK signals tend to appear + "inlvl" indicates the audio input level. QPSK signals tend to appear much "wider" than C4FM from a discriminator tap so it is important to set your input gain using a QPSK signal if you plan to montir them. It is not necessary nor desirable to get to 100%, in fact your sound @@ -189,7 +185,7 @@ Sync: -p25p1 mod: C4FM input: 39% nac: 5C2 src: 52610 tg: 32464 LDU1 e: "nac" is the P25 Phase 1 Network Access Code. This is a 12 bit field in each P25 Phase 1 header. It should not be confused with the 16 - bit System ID used in non-p25 trunking control channels. + bit System ID used in non-P25 trunking control channels. "src" is the radio id of the trasmitting subscriber unit. @@ -207,10 +203,10 @@ Sync: -p25p1 mod: C4FM input: 39% nac: 5C2 src: 52610 tg: 32464 LDU1 e: Errorbars mode output for X2-TDMA looks like this: -Sync: -X2-TDMA mod: QPSK input: 59% src: 17211 tg: 197 [SLOT0] slot1 VOICE e: -Sync: -X2-TDMA mod: QPSK input: 47% src: 17211 tg: 197 [SLOT0] slot1 VOICE e: -Sync: -X2-TDMA mod: QPSK input: 43% src: 17211 tg: 197 [SLOT0] slot1 VOICE e: -Sync: (-X2-TDMA) mod: QPSK input: 28% src: 17211 tg: 197 [SLOT0] slot1 VOICE e: +Sync: -X2-TDMA mod: QPSK inlvl: 59% src: 17211 tg: 197 [SLOT0] slot1 VOICE e: +Sync: -X2-TDMA mod: QPSK inlvl: 47% src: 17211 tg: 197 [SLOT0] slot1 VOICE e: +Sync: -X2-TDMA mod: QPSK inlvl: 43% src: 17211 tg: 197 [SLOT0] slot1 VOICE e: +Sync: (-X2-TDMA) mod: QPSK inlvl: 28% src: 17211 tg: 197 [SLOT0] slot1 VOICE e: DMR/MOTOTRBO display is similar except it does not yet show source and talkgroup information. @@ -303,10 +299,10 @@ Display Options information displayed in Errorbars mode: -e Show Frame Info and errorbars (default) - -pe Show p25 encryption sync bits - -pl Show p25 link control bits - -ps Show p25 status bits and low speed data - -pt Show p25 talkgroup info + -pe Show P25 encryption sync bits + -pl Show P25 link control bits + -ps Show P25 status bits and low speed data + -pt Show P25 talkgroup info -q Don't show Frame Info/errorbars -s Datascope (disables other display options) -t Show symbol timing during sync @@ -439,7 +435,8 @@ Scanner control options: -B Serial port baud rate (default=115200) -C Serial port for scanner control (default=/dev/ttyUSB0) - -R Resume scan after TDULC frames or any PDU + -R Resume scan after TDULC frames or any PDU or TSDU + On some P25 systems Packet Data Units (PDU) are sent on the same frequencies used for voice traffic. If done constantly this can @@ -453,7 +450,8 @@ Decoder options -fa Auto-detect frame type (default) -f1 Decode only P25 Phase 1 -fd Decode only D-STAR* (no audio) - -fn Decode only NXDN96* (no audio) + -fi Decode only NXDN48* (6.25 kHz) / IDAS* + -fn Decode only NXDN96 (12.5 kHz) -fp Decode only ProVoice* -fr Decode only DMR/MOTOTRBO -fx Decode only X2-TDMA @@ -465,10 +463,13 @@ Decoder options -xx Expect non-inverted X2-TDMA signal -xr Expect inverted DMR/MOTOTRBO signal + * denotes frame types that cannot be auto-detected. - NXDN and D-STAR are not enabled by default as they are for development - testing only and have shorter frame sync patterns that are prone to - false triggering. + ProVoice and NXDN48 not auto-detected as use different symbol + rates (9600 and 2400) than most formats (4800). D-STAR is not + enabled by default as voice decode does not work and it has a + short sync word that is prone to false triggering. It is included + for development/testing only. MBE speech synthesis is broken down into two main types of sounds, "Voiced" and "Unvoiced". Voiced speech bands are synthesized with diff --git a/configure b/configure old mode 100644 new mode 100755 diff --git a/dmr_data.c b/dmr_data.c index 1e809d0..ab47f10 100644 --- a/dmr_data.c +++ b/dmr_data.c @@ -206,7 +206,7 @@ processDMRdata (dsd_opts * opts, dsd_state * state) printf ("%s ", syncbits); #endif - if (strcmp (sync, DMR_DATA_SYNC) == 0) + if ((strcmp (sync, DMR_BS_DATA_SYNC) == 0) || (strcmp (sync, DMR_MS_DATA_SYNC) == 0)) { if (state->currentslot == 0) { @@ -217,17 +217,6 @@ processDMRdata (dsd_opts * opts, dsd_state * state) sprintf (state->slot1light, "[slot1]"); } } - else if (strcmp (sync, DMR_VOICE_SYNC) == 0) - { - if (state->currentslot == 0) - { - sprintf (state->slot0light, "[SLOT0]"); - } - else - { - sprintf (state->slot1light, "[SLOT1]"); - } - } if (opts->errorbars == 1) { diff --git a/dmr_voice.c b/dmr_voice.c index 329b50e..b567e22 100644 --- a/dmr_voice.c +++ b/dmr_voice.c @@ -32,6 +32,7 @@ processDMRvoice (dsd_opts * opts, dsd_state * state) char syncdata[25]; char cachdata[13]; int mutecurrentslot; + int msMode; #ifdef DMR_DUMP int k; @@ -40,6 +41,7 @@ processDMRvoice (dsd_opts * opts, dsd_state * state) #endif mutecurrentslot = 0; + msMode = 0; dibit_p = state->dibit_buf_p - 144; for (j = 0; j < 6; j++) @@ -193,7 +195,7 @@ processDMRvoice (dsd_opts * opts, dsd_state * state) sync[24] = 0; syncdata[24] = 0; - if (strcmp (sync, DMR_DATA_SYNC) == 0) + if ((strcmp (sync, DMR_BS_DATA_SYNC) == 0) || (strcmp (sync, DMR_MS_DATA_SYNC) == 0)) { mutecurrentslot = 1; if (state->currentslot == 0) @@ -205,7 +207,7 @@ processDMRvoice (dsd_opts * opts, dsd_state * state) sprintf (state->slot1light, "[slot1]"); } } - else if (strcmp (sync, DMR_VOICE_SYNC) == 0) + else if ((strcmp (sync, DMR_BS_VOICE_SYNC) == 0) || (strcmp (sync, DMR_MS_VOICE_SYNC) == 0)) { mutecurrentslot = 0; if (state->currentslot == 0) @@ -217,6 +219,10 @@ processDMRvoice (dsd_opts * opts, dsd_state * state) sprintf (state->slot1light, "[SLOT1]"); } } + if ((strcmp (sync, DMR_MS_VOICE_SYNC) == 0) || (strcmp (sync, DMR_MS_DATA_SYNC) == 0)) + { + msMode = 1; + } if ((j == 0) && (opts->errorbars == 1)) { @@ -318,7 +324,7 @@ processDMRvoice (dsd_opts * opts, dsd_state * state) sync[24] = 0; syncdata[24] = 0; - if (strcmp (sync, DMR_DATA_SYNC) == 0) + if ((strcmp (sync, DMR_BS_DATA_SYNC) == 0) || (msMode == 1)) { if (state->currentslot == 0) { @@ -329,7 +335,7 @@ processDMRvoice (dsd_opts * opts, dsd_state * state) sprintf (state->slot0light, " slot0 "); } } - else if (strcmp (sync, DMR_VOICE_SYNC) == 0) + else if (strcmp (sync, DMR_BS_VOICE_SYNC) == 0) { if (state->currentslot == 0) { diff --git a/dsd.h b/dsd.h index f737dc1..c96515d 100644 --- a/dsd.h +++ b/dsd.h @@ -18,6 +18,7 @@ #include "config.h" #include #include +#include #include #define __USE_XOPEN #include @@ -36,6 +37,12 @@ #include #include +/* + * global variables + */ +int exitflag; + + typedef struct { int onesymbol; @@ -71,7 +78,8 @@ typedef struct int frame_dstar; int frame_x2tdma; int frame_p25p1; - int frame_nxdn; + int frame_nxdn48; + int frame_nxdn96; int frame_dmr; int frame_provoice; int mod_c4fm; @@ -100,6 +108,7 @@ typedef struct float *audio_out_temp_buf_p; int audio_out_idx; int audio_out_idx2; + int wav_out_bytes; int center; int jitter; int synctype; @@ -155,19 +164,35 @@ typedef struct /* * Frame sync patterns */ -#define INV_FRAME_SYNC "333331331133111131311111" -#define FRAME_SYNC "111113113311333313133333" -#define X2TDMA_VOICE_SYNC "113131333331313331113311" -#define X2TDMA_DATA_SYNC "331313111113131113331133" -#define DSTAR_SYNC "313131313133131113313111" -#define INV_DSTAR_SYNC "131313131311313331131333" -#define INV_NXDN96_SYNC "313133113131111333" -#define NXDN96_SYNC "131311331313333111" -#define DMR_DATA_SYNC "313333111331131131331131" -#define DMR_VOICE_SYNC "131111333113313313113313" -#define INV_PROVOICE_SYNC "31313111333133133311331133113311" -#define PROVOICE_SYNC "13131333111311311133113311331133" +#define INV_P25P1_SYNC "333331331133111131311111" +#define P25P1_SYNC "111113113311333313133333" +#define X2TDMA_BS_VOICE_SYNC "113131333331313331113311" +#define X2TDMA_BS_DATA_SYNC "331313111113131113331133" +#define X2TDMA_MS_DATA_SYNC "313113333111111133333313" +#define X2TDMA_MS_VOICE_SYNC "131331111333333311111131" + +#define DSTAR_SYNC "313131313133131113313111" +#define INV_DSTAR_SYNC "131313131311313331131333" + +#define NXDN_MS_DATA_SYNC "313133113131111333" +#define INV_NXDN_MS_DATA_SYNC "131311331313333111" +#define NXDN_MS_VOICE_SYNC "313133113131113133" +#define INV_NXDN_MS_VOICE_SYNC "131311331313331311" +#define INV_NXDN_BS_DATA_SYNC "131311331313333131" +#define NXDN_BS_DATA_SYNC "313133113131111313" +#define INV_NXDN_BS_VOICE_SYNC "131311331313331331" +#define NXDN_BS_VOICE_SYNC "313133113131113113" + +#define DMR_BS_DATA_SYNC "313333111331131131331131" +#define DMR_BS_VOICE_SYNC "131111333113313313113313" +#define DMR_MS_DATA_SYNC "311131133313133331131113" +#define DMR_MS_VOICE_SYNC "133313311131311113313331" + +#define INV_PROVOICE_SYNC "31313111333133133311331133113311" +#define PROVOICE_SYNC "13131333111311311133113311331133" +#define INV_PROVOICE_EA_SYNC "13313133113113333311313133133311" +#define PROVOICE_EA_SYNC "31131311331331111133131311311133" /* * function prototypes @@ -189,6 +214,7 @@ void openMbeInFile (dsd_opts * opts, dsd_state * state); void closeMbeOutFile (dsd_opts * opts, dsd_state * state); void openMbeOutFile (dsd_opts * opts, dsd_state * state); void openWavOutFile (dsd_opts * opts, dsd_state * state); +void closeWavOutFile (dsd_opts * opts, dsd_state * state); void printFrameInfo (dsd_opts * opts, dsd_state * state); void processFrame (dsd_opts * opts, dsd_state * state); void printFrameSync (dsd_opts * opts, dsd_state * state, char *frametype, int offset, char *modulation); @@ -199,6 +225,8 @@ void initOpts (dsd_opts * opts); void initState (dsd_state * state); void usage (); void liveScanner (dsd_opts * opts, dsd_state * state); +void cleanupAndExit (dsd_opts * opts, dsd_state * state); +void sigfun (int sig); int main (int argc, char **argv); void playMbeFiles (dsd_opts * opts, dsd_state * state, int argc, char **argv); void processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char ambe_fr[4][24], char imbe7100_fr[7][24]); @@ -207,7 +235,8 @@ void resumeScan (dsd_opts * opts, dsd_state * state); int getSymbol (dsd_opts * opts, dsd_state * state, int have_sync); void upsample (dsd_state * state, float invalue); void processDSTAR (dsd_opts * opts, dsd_state * state); -void processNXDN96 (dsd_opts * opts, dsd_state * state); +void processNXDNVoice (dsd_opts * opts, dsd_state * state); +void processNXDNData (dsd_opts * opts, dsd_state * state); void processP25lcw (dsd_opts * opts, dsd_state * state, char *lcformat, char *mfid, char *lcinfo); void processHDU (dsd_opts * opts, dsd_state * state); void processLDU1 (dsd_opts * opts, dsd_state * state); diff --git a/dsd_audio.c b/dsd_audio.c index 0ba069b..9ae6d8b 100644 --- a/dsd_audio.c +++ b/dsd_audio.c @@ -41,14 +41,14 @@ processAudio (dsd_opts * opts, dsd_state * state) *state->aout_max_buf_p = max; state->aout_max_buf_p++; state->aout_max_buf_idx++; - if (state->aout_max_buf_idx > 74) + if (state->aout_max_buf_idx > 24) { state->aout_max_buf_idx = 0; state->aout_max_buf_p = state->aout_max_buf; } // lookup max history - for (i = 0; i < 75; i++) + for (i = 0; i < 25; i++) { maxbuf = state->aout_max_buf[i]; if (maxbuf > max) @@ -157,6 +157,7 @@ writeSynthesizedVoice (dsd_opts * opts, dsd_state * state) int n; short aout_buf[160]; short *aout_buf_p; + ssize_t result; aout_buf_p = aout_buf; state->audio_out_temp_buf_p = state->audio_out_temp_buf; @@ -175,18 +176,21 @@ writeSynthesizedVoice (dsd_opts * opts, dsd_state * state) state->audio_out_temp_buf_p++; } - write (opts->wav_out_fd, aout_buf, 320); + result = write (opts->wav_out_fd, aout_buf, 320); fflush (opts->wav_out_f); + state->wav_out_bytes += 320; } void playSynthesizedVoice (dsd_opts * opts, dsd_state * state) { + ssize_t result; + if (state->audio_out_idx > opts->delay) { // output synthesized speech to sound card - write (opts->audio_out_fd, (state->audio_out_buf_p - state->audio_out_idx), (state->audio_out_idx * 2)); + result = write (opts->audio_out_fd, (state->audio_out_buf_p - state->audio_out_idx), (state->audio_out_idx * 2)); state->audio_out_idx = 0; } diff --git a/dsd_file.c b/dsd_file.c index 9918fc7..28cef9f 100644 --- a/dsd_file.c +++ b/dsd_file.c @@ -125,7 +125,7 @@ readAmbe2250Data (dsd_opts * opts, dsd_state * state, char *ambe_d) } } b = fgetc (opts->mbe_in_f); - ambe_d[48] = b; + ambe_d[48] = (b & 1); return (0); } @@ -173,6 +173,7 @@ closeMbeOutFile (dsd_opts * opts, dsd_state * state) int sum, i, j; int talkgroup; struct tm timep; + int result; if (opts->mbe_out_f != NULL) { @@ -187,11 +188,6 @@ closeMbeOutFile (dsd_opts * opts, dsd_state * state) strptime (opts->mbe_out_file, "%s.amb", &timep); } - for (i = 0; i < 17; i++) - { - tgid[i] = 0; - } - if (state->tgcount > 0) { for (i = 0; i < 16; i++) @@ -203,6 +199,7 @@ closeMbeOutFile (dsd_opts * opts, dsd_state * state) } tgid[i] = (char) (((float) sum / (float) state->tgcount) + 48.5); } + tgid[16] = 0; talkgroup = (int) strtol (tgid, NULL, 2); } else @@ -216,7 +213,16 @@ closeMbeOutFile (dsd_opts * opts, dsd_state * state) strftime (datestr, 31, "%Y-%m-%d-%H%M%S", &timep); sprintf (newfilename, "nac%X-%s-tg%i%s", state->nac, datestr, talkgroup, ext); sprintf (shell, "mv %s %s", opts->mbe_out_file, newfilename); - system (shell); + result = system (shell); + + state->tgcount = 0; + for (i = 0; i < 25; i++) + { + for (j = 0; j < 16; j++) + { + state->tg[i][j] = 48; + } + } } } @@ -273,6 +279,7 @@ openWavOutFile (dsd_opts * opts, dsd_state * state) return; } opts->wav_out_fd = fileno (opts->wav_out_f); + state->wav_out_bytes = 0; fprintf (opts->wav_out_f, "RIFF"); // total length @@ -310,7 +317,7 @@ openWavOutFile (dsd_opts * opts, dsd_state * state) fputc (0, opts->wav_out_f); fputc (0, opts->wav_out_f); - // bytes/sample + // block align fputc (2, opts->wav_out_f); fputc (0, opts->wav_out_f); @@ -325,7 +332,75 @@ openWavOutFile (dsd_opts * opts, dsd_state * state) fputc (0, opts->wav_out_f); fputc (0, opts->wav_out_f); fputc (0, opts->wav_out_f); - fputc (127, opts->wav_out_f); + fputc (0, opts->wav_out_f); fflush (opts->wav_out_f); } + +void +closeWavOutFile (dsd_opts * opts, dsd_state * state) +{ + + int length; + + if (opts->wav_out_f != NULL) + { + rewind (opts->wav_out_f); + length = state->wav_out_bytes; + + fprintf (opts->wav_out_f, "RIFF"); + // total length + fputc (((36 + length) & 0xff), opts->wav_out_f); + fputc ((((36 + length) >> 8) & 0xff), opts->wav_out_f); + fputc ((((36 + length) >> 16) & 0xff), opts->wav_out_f); + fputc ((((36 + length) >> 24) & 0xff), opts->wav_out_f); + + fprintf (opts->wav_out_f, "WAVE"); + fprintf (opts->wav_out_f, "fmt "); + + // length of format chunk + fputc (16, opts->wav_out_f); + fputc (0, opts->wav_out_f); + fputc (0, opts->wav_out_f); + fputc (0, opts->wav_out_f); + + // always 0x1 + fputc (1, opts->wav_out_f); + fputc (0, opts->wav_out_f); + + // channels + fputc (1, opts->wav_out_f); + fputc (0, opts->wav_out_f); + + // sample rate + fputc (64, opts->wav_out_f); + fputc (31, opts->wav_out_f); + fputc (0, opts->wav_out_f); + fputc (0, opts->wav_out_f); + + // bytes per second + fputc (128, opts->wav_out_f); + fputc (62, opts->wav_out_f); + fputc (0, opts->wav_out_f); + fputc (0, opts->wav_out_f); + + // block align + fputc (2, opts->wav_out_f); + fputc (0, opts->wav_out_f); + + // bits/sample + fputc (16, opts->wav_out_f); + fputc (0, opts->wav_out_f); + + // data chunk header + fprintf (opts->wav_out_f, "data"); + + // length of data + fputc ((length & 0xff), opts->wav_out_f); + fputc (((length >> 8) & 0xff), opts->wav_out_f); + fputc (((length >> 16) & 0xff), opts->wav_out_f); + fputc (((length >> 24) & 0xff), opts->wav_out_f); + + fflush (opts->wav_out_f); + } +} diff --git a/dsd_frame.c b/dsd_frame.c index 3cccfee..393ac17 100644 --- a/dsd_frame.c +++ b/dsd_frame.c @@ -26,7 +26,7 @@ printFrameInfo (dsd_opts * opts, dsd_state * state) level = (int) (((float) state->max / (float) 32768) * (float) 100); if (opts->verbose > 0) { - printf ("input: %2i%% ", level); + printf ("inlvl: %2i%% ", level); } if (state->nac != 0) { @@ -65,6 +65,7 @@ processFrame (dsd_opts * opts, dsd_state * state) if ((state->synctype == 8) || (state->synctype == 9)) { + state->rf_mod = 2; state->nac = 0; state->lastsrc = 0; state->lasttg = 0; @@ -73,7 +74,7 @@ processFrame (dsd_opts * opts, dsd_state * state) if (opts->verbose > 0) { level = (int) (((float) state->max / (float) 32768) * (float) 100); - printf ("input: %2i%% ", level); + printf ("inlvl: %2i%% ", level); } } state->nac = 0; @@ -82,7 +83,30 @@ processFrame (dsd_opts * opts, dsd_state * state) openMbeOutFile (opts, state); } sprintf (state->fsubtype, " VOICE "); - processNXDN96 (opts, state); + processNXDNVoice (opts, state); + return; + } + else if ((state->synctype == 16) || (state->synctype == 17)) + { + state->rf_mod = 2; + state->nac = 0; + state->lastsrc = 0; + state->lasttg = 0; + if (opts->errorbars == 1) + { + if (opts->verbose > 0) + { + level = (int) (((float) state->max / (float) 32768) * (float) 100); + printf ("inlvl: %2i%% ", level); + } + } + state->nac = 0; + if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) + { + openMbeOutFile (opts, state); + } + sprintf (state->fsubtype, " DATA "); + processNXDNData (opts, state); return; } else if ((state->synctype == 6) || (state->synctype == 7)) @@ -95,7 +119,7 @@ processFrame (dsd_opts * opts, dsd_state * state) if (opts->verbose > 0) { level = (int) (((float) state->max / (float) 32768) * (float) 100); - printf ("input: %2i%% ", level); + printf ("inlvl: %2i%% ", level); } } state->nac = 0; @@ -117,7 +141,7 @@ processFrame (dsd_opts * opts, dsd_state * state) if (opts->verbose > 0) { level = (int) (((float) state->max / (float) 32768) * (float) 100); - printf ("input: %2i%% ", level); + printf ("inlvl: %2i%% ", level); } } if ((state->synctype == 11) || (state->synctype == 12)) @@ -140,8 +164,6 @@ processFrame (dsd_opts * opts, dsd_state * state) else if ((state->synctype >= 2) && (state->synctype <= 5)) { state->nac = 0; - state->lastsrc = 0; - state->lasttg = 0; if (opts->errorbars == 1) { printFrameInfo (opts, state); @@ -173,7 +195,7 @@ processFrame (dsd_opts * opts, dsd_state * state) if (opts->verbose > 0) { level = (int) (((float) state->max / (float) 32768) * (float) 100); - printf ("input: %2i%% ", level); + printf ("inlvl: %2i%% ", level); } } if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) @@ -211,7 +233,6 @@ processFrame (dsd_opts * opts, dsd_state * state) printFrameInfo (opts, state); printf (" HDU\n"); } - state->cur_mp->repeat = 0; if (opts->mbe_out_dir[0] != 0) { closeMbeOutFile (opts, state); @@ -280,14 +301,15 @@ processFrame (dsd_opts * opts, dsd_state * state) printFrameInfo (opts, state); printf (" TDULC\n"); } - state->cur_mp->repeat = 0; if (opts->mbe_out_dir[0] != 0) { closeMbeOutFile (opts, state); } mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced); - state->tgcount = 0; + state->lasttg = 0; + state->lastsrc = 0; state->lastp25type = 0; + state->err_str[0] = 0; sprintf (state->fsubtype, " TDULC "); state->numtdulc++; if ((opts->resume > 0) && (state->numtdulc > opts->resume)) @@ -304,13 +326,13 @@ processFrame (dsd_opts * opts, dsd_state * state) printFrameInfo (opts, state); printf (" TDU\n"); } - state->cur_mp->repeat = 0; if (opts->mbe_out_dir[0] != 0) { closeMbeOutFile (opts, state); } mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced); - state->tgcount = 0; + state->lasttg = 0; + state->lastsrc = 0; state->lastp25type = 0; state->err_str[0] = 0; sprintf (state->fsubtype, " TDU "); @@ -323,6 +345,12 @@ processFrame (dsd_opts * opts, dsd_state * state) printFrameInfo (opts, state); printf (" TSDU\n"); } + if (opts->resume > 0) + { + resumeScan (opts, state); + } + state->lasttg = 0; + state->lastsrc = 0; state->lastp25type = 3; sprintf (state->fsubtype, " TSDU "); skipDibit (opts, state, 328); @@ -333,10 +361,10 @@ processFrame (dsd_opts * opts, dsd_state * state) { printFrameInfo (opts, state); printf (" PDU\n"); - if (opts->resume > 0) - { - resumeScan (opts, state); - } + } + if (opts->resume > 0) + { + resumeScan (opts, state); } if (opts->mbe_out_dir[0] != 0) { @@ -347,7 +375,6 @@ processFrame (dsd_opts * opts, dsd_state * state) } state->lastp25type = 4; sprintf (state->fsubtype, " PDU "); - } // try to guess based on previous frame if unknown type else if (state->lastp25type == 1) diff --git a/dsd_frame_sync.c b/dsd_frame_sync.c index 26aa100..9f1ea88 100644 --- a/dsd_frame_sync.c +++ b/dsd_frame_sync.c @@ -43,22 +43,24 @@ int getFrameSync (dsd_opts * opts, dsd_state * state) { /* detects frame sync and returns frame type - * 0 = +p25p1 - * 1 = -p25p1 + * 0 = +P25p1 + * 1 = -P25p1 * 2 = +X2-TDMA (non inverted signal data frame) * 3 = +X2-TDMA (inverted signal voice frame) * 4 = -X2-TDMA (non inverted signal voice frame) * 5 = -X2-TDMA (inverted signal data frame) * 6 = +D-STAR * 7 = -D-STAR - * 8 = +NXDN96 - * 9 = -NXDN96 + * 8 = +NXDN (non inverted voice frame) + * 9 = -NXDN (inverted voice frame) * 10 = +DMR (non inverted singlan data frame) * 11 = -DMR (inverted signal voice frame) * 12 = +DMR (non inverted signal voice frame) * 13 = -DMR (inverted signal data frame) * 14 = +ProVoice * 15 = -ProVoice + * 16 = +NXDN (non inverted data frame) + * 17 = -NXDN (inverted data frame) */ int i, j, t, o, dibit, sync, symbol, synctest_pos, lastt; @@ -73,13 +75,19 @@ getFrameSync (dsd_opts * opts, dsd_state * state) int lsum; char spectrum[64]; + for (i = 18; i < 24; i++) + { + lbuf[i] = 0; + lbuf2[i] = 0; + } + // detect frame sync t = 0; synctest[24] = 0; synctest18[18] = 0; synctest32[32] = 0; synctest_pos = 0; - synctest_p = synctest_buf; + synctest_p = synctest_buf + 10; sync = 0; lmin = 0; lmax = 0; @@ -158,18 +166,8 @@ getFrameSync (dsd_opts * opts, dsd_state * state) dibit = 51; } -/* -printf("%c", dibit); -if (t == 768) -{ - printf("\n"); - t=0; -} -*/ - - *synctest_p = dibit; - if (t >= 24) + if (t >= 18) { for (i = 0; i < 24; i++) { @@ -304,7 +302,7 @@ if (t == 768) strncpy (synctest, (synctest_p - 23), 24); if (opts->frame_p25p1 == 1) { - if (strcmp (synctest, FRAME_SYNC) == 0) + if (strcmp (synctest, P25P1_SYNC) == 0) { state->carrier = 1; state->offset = synctest_pos; @@ -313,12 +311,12 @@ if (t == 768) sprintf (state->ftype, " P25 Phase 1 "); if (opts->errorbars == 1) { - printFrameSync (opts, state, " +p25p1 ", synctest_pos + 1, modulation); + printFrameSync (opts, state, " +P25p1 ", synctest_pos + 1, modulation); } state->lastsynctype = 0; return (0); } - if (strcmp (synctest, INV_FRAME_SYNC) == 0) + if (strcmp (synctest, INV_P25P1_SYNC) == 0) { state->carrier = 1; state->offset = synctest_pos; @@ -327,7 +325,7 @@ if (t == 768) sprintf (state->ftype, " P25 Phase 1 "); if (opts->errorbars == 1) { - printFrameSync (opts, state, " -p25p1 ", synctest_pos + 1, modulation); + printFrameSync (opts, state, " -P25p1 ", synctest_pos + 1, modulation); } state->lastsynctype = 1; return (1); @@ -335,7 +333,7 @@ if (t == 768) } if (opts->frame_x2tdma == 1) { - if (strcmp (synctest, X2TDMA_DATA_SYNC) == 0) + if ((strcmp (synctest, X2TDMA_BS_DATA_SYNC) == 0) || (strcmp (synctest, X2TDMA_MS_DATA_SYNC) == 0)) { state->carrier = 1; state->offset = synctest_pos; @@ -368,7 +366,7 @@ if (t == 768) return (3); } } - if (strcmp (synctest, X2TDMA_VOICE_SYNC) == 0) + if ((strcmp (synctest, X2TDMA_BS_VOICE_SYNC) == 0) || (strcmp (synctest, X2TDMA_MS_VOICE_SYNC) == 0)) { state->carrier = 1; state->offset = synctest_pos; @@ -404,7 +402,7 @@ if (t == 768) } if (opts->frame_dmr == 1) { - if (strcmp (synctest, DMR_DATA_SYNC) == 0) + if ((strcmp (synctest, DMR_MS_DATA_SYNC) == 0) || (strcmp (synctest, DMR_BS_DATA_SYNC) == 0)) { state->carrier = 1; state->offset = synctest_pos; @@ -437,7 +435,7 @@ if (t == 768) return (11); } } - if (strcmp (synctest, DMR_VOICE_SYNC) == 0) + if ((strcmp (synctest, DMR_MS_VOICE_SYNC) == 0) || (strcmp (synctest, DMR_BS_VOICE_SYNC) == 0)) { state->carrier = 1; state->offset = synctest_pos; @@ -474,7 +472,7 @@ if (t == 768) if (opts->frame_provoice == 1) { strncpy (synctest32, (synctest_p - 31), 32); - if (strcmp (synctest32, PROVOICE_SYNC) == 0) + if ((strcmp (synctest32, PROVOICE_SYNC) == 0) || (strcmp (synctest32, PROVOICE_EA_SYNC) == 0)) { state->carrier = 1; state->offset = synctest_pos; @@ -488,7 +486,7 @@ if (t == 768) state->lastsynctype = 14; return (14); } - else if (strcmp (synctest32, INV_PROVOICE_SYNC) == 0) + else if ((strcmp (synctest32, INV_PROVOICE_SYNC) == 0) || (strcmp (synctest32, INV_PROVOICE_EA_SYNC) == 0)) { state->carrier = 1; state->offset = synctest_pos; @@ -504,36 +502,137 @@ if (t == 768) } } - if (opts->frame_nxdn == 1) + if ((opts->frame_nxdn96 == 1) || (opts->frame_nxdn48 == 1)) { strncpy (synctest18, (synctest_p - 17), 18); - if (strcmp (synctest18, NXDN96_SYNC) == 0) + if ((strcmp (synctest18, NXDN_BS_VOICE_SYNC) == 0) || (strcmp (synctest18, NXDN_MS_VOICE_SYNC) == 0)) { - state->carrier = 1; - state->offset = synctest_pos; - state->max = ((state->max) + lmax) / 2; - state->min = ((state->min) + lmin) / 2; - sprintf (state->ftype, " NXDN96 "); - if (opts->errorbars == 1) + if ((state->lastsynctype == 8) || (state->lastsynctype == 16)) { - printFrameSync (opts, state, " +NXDN96 ", synctest_pos + 1, modulation); + state->carrier = 1; + state->offset = synctest_pos; + state->max = ((state->max) + lmax) / 2; + state->min = ((state->min) + lmin) / 2; + if (state->samplesPerSymbol == 20) + { + sprintf (state->ftype, " NXDN48 "); + if (opts->errorbars == 1) + { + printFrameSync (opts, state, " +NXDN48 ", synctest_pos + 1, modulation); + } + } + else + { + sprintf (state->ftype, " NXDN96 "); + if (opts->errorbars == 1) + { + printFrameSync (opts, state, " +NXDN96 ", synctest_pos + 1, modulation); + } + } + state->lastsynctype = 8; + return (8); + } + else + { + state->lastsynctype = 8; } - state->lastsynctype = 8; - return (8); } - if (strcmp (synctest18, INV_NXDN96_SYNC) == 0) + else if ((strcmp (synctest18, INV_NXDN_BS_VOICE_SYNC) == 0) || (strcmp (synctest18, INV_NXDN_MS_VOICE_SYNC) == 0)) { - state->carrier = 1; - state->offset = synctest_pos; - state->max = ((state->max) + lmax) / 2; - state->min = ((state->min) + lmin) / 2; - sprintf (state->ftype, " NXDN96 "); - if (opts->errorbars == 1) + if ((state->lastsynctype == 9) || (state->lastsynctype == 17)) { - printFrameSync (opts, state, " -NXDN96 ", synctest_pos + 1, modulation); + state->carrier = 1; + state->offset = synctest_pos; + state->max = ((state->max) + lmax) / 2; + state->min = ((state->min) + lmin) / 2; + if (state->samplesPerSymbol == 20) + { + sprintf (state->ftype, " NXDN48 "); + if (opts->errorbars == 1) + { + printFrameSync (opts, state, " -NXDN48 ", synctest_pos + 1, modulation); + } + } + else + { + sprintf (state->ftype, " NXDN96 "); + if (opts->errorbars == 1) + { + printFrameSync (opts, state, " -NXDN96 ", synctest_pos + 1, modulation); + } + } + state->lastsynctype = 9; + return (9); + } + else + { + state->lastsynctype = 9; + } + } + else if ((strcmp (synctest18, NXDN_BS_DATA_SYNC) == 0) || (strcmp (synctest18, NXDN_MS_DATA_SYNC) == 0)) + { + if ((state->lastsynctype == 8) || (state->lastsynctype == 16)) + { + state->carrier = 1; + state->offset = synctest_pos; + state->max = ((state->max) + lmax) / 2; + state->min = ((state->min) + lmin) / 2; + if (state->samplesPerSymbol == 20) + { + sprintf (state->ftype, " NXDN48 "); + if (opts->errorbars == 1) + { + printFrameSync (opts, state, " +NXDN48 ", synctest_pos + 1, modulation); + } + } + else + { + sprintf (state->ftype, " NXDN96 "); + if (opts->errorbars == 1) + { + printFrameSync (opts, state, " +NXDN96 ", synctest_pos + 1, modulation); + } + } + state->lastsynctype = 16; + return (16); + } + else + { + state->lastsynctype = 16; + } + } + else if ((strcmp (synctest18, INV_NXDN_BS_DATA_SYNC) == 0) || (strcmp (synctest18, INV_NXDN_MS_DATA_SYNC) == 0)) + { + if ((state->lastsynctype == 9) || (state->lastsynctype == 17)) + { + state->carrier = 1; + state->offset = synctest_pos; + state->max = ((state->max) + lmax) / 2; + state->min = ((state->min) + lmin) / 2; + sprintf (state->ftype, " NXDN "); + if (state->samplesPerSymbol == 20) + { + sprintf (state->ftype, " NXDN48 "); + if (opts->errorbars == 1) + { + printFrameSync (opts, state, " -NXDN48 ", synctest_pos + 1, modulation); + } + } + else + { + sprintf (state->ftype, " NXDN96 "); + if (opts->errorbars == 1) + { + printFrameSync (opts, state, " -NXDN96 ", synctest_pos + 1, modulation); + } + } + state->lastsynctype = 17; + return (17); + } + else + { + state->lastsynctype = 17; } - state->lastsynctype = 9; - return (9); } } if (opts->frame_dstar == 1) @@ -579,7 +678,7 @@ if (t == 768) sprintf (state->ftype, "(P25 Phase 1)"); if (opts->errorbars == 1) { - printFrameSync (opts, state, "(+p25p1) ", synctest_pos + 1, modulation); + printFrameSync (opts, state, "(+P25p1) ", synctest_pos + 1, modulation); } state->lastsynctype = -1; return (0); @@ -593,12 +692,12 @@ if (t == 768) sprintf (state->ftype, "(P25 Phase 1)"); if (opts->errorbars == 1) { - printFrameSync (opts, state, "(-p25p1) ", synctest_pos + 1, modulation); + printFrameSync (opts, state, "(-P25p1) ", synctest_pos + 1, modulation); } state->lastsynctype = -1; return (1); } - else if ((state->lastsynctype == 3) && (strcmp (synctest, X2TDMA_VOICE_SYNC) != 0)) + else if ((state->lastsynctype == 3) && ((strcmp (synctest, X2TDMA_BS_VOICE_SYNC) != 0) || (strcmp (synctest, X2TDMA_MS_VOICE_SYNC) != 0))) { state->carrier = 1; state->offset = synctest_pos; @@ -612,7 +711,7 @@ if (t == 768) state->lastsynctype = -1; return (3); } - else if ((state->lastsynctype == 4) && (strcmp (synctest, X2TDMA_DATA_SYNC) != 0)) + else if ((state->lastsynctype == 4) && ((strcmp (synctest, X2TDMA_BS_DATA_SYNC) != 0) || (strcmp (synctest, X2TDMA_MS_DATA_SYNC) != 0))) { state->carrier = 1; state->offset = synctest_pos; @@ -626,7 +725,7 @@ if (t == 768) state->lastsynctype = -1; return (4); } - else if ((state->lastsynctype == 11) && (strcmp (synctest, DMR_VOICE_SYNC) != 0)) + else if ((state->lastsynctype == 11) && ((strcmp (synctest, DMR_BS_VOICE_SYNC) != 0) || (strcmp (synctest, DMR_MS_VOICE_SYNC) != 0))) { state->carrier = 1; state->offset = synctest_pos; @@ -640,7 +739,7 @@ if (t == 768) state->lastsynctype = -1; return (11); } - else if ((state->lastsynctype == 12) && (strcmp (synctest, DMR_DATA_SYNC) != 0)) + else if ((state->lastsynctype == 12) && ((strcmp (synctest, DMR_BS_DATA_SYNC) != 0) || (strcmp (synctest, DMR_MS_DATA_SYNC) != 0))) { state->carrier = 1; state->offset = synctest_pos; @@ -657,6 +756,11 @@ if (t == 768) } } + if (exitflag == 1) + { + cleanupAndExit (opts, state); + } + if (synctest_pos < 10200) { synctest_pos++; @@ -670,16 +774,13 @@ if (t == 768) noCarrier (opts, state); } - if (state->carrier == 1) + if (state->lastsynctype != 1) { if (synctest_pos >= 1800) { - if (opts->errorbars == 1) + if ((opts->errorbars == 1) && (opts->verbose > 1) && (state->carrier == 1)) { - if (opts->verbose > 1) - { - printf ("Sync: no sync\n"); - } + printf ("Sync: no sync\n"); } noCarrier (opts, state); return (-1); diff --git a/dsd_main.c b/dsd_main.c index dbe1c28..27d520a 100644 --- a/dsd_main.c +++ b/dsd_main.c @@ -21,7 +21,7 @@ #include "p25p1_const.h" #include "x2tdma_const.h" #include "dstar_const.h" -#include "nxdn96_const.h" +#include "nxdn_const.h" #include "dmr_const.h" #include "provoice_const.h" @@ -39,7 +39,6 @@ comp (const void *a, const void *b) void noCarrier (dsd_opts * opts, dsd_state * state) { - state->dibit_buf_p = state->dibit_buf + 200; memset (state->dibit_buf, 0, sizeof (int) * 200); if (opts->mbe_out_f != NULL) @@ -55,6 +54,8 @@ noCarrier (dsd_opts * opts, dsd_state * state) state->err_str[0] = 0; sprintf (state->fsubtype, " "); sprintf (state->ftype, " "); + state->errs = 0; + state->errs2 = 0; state->lasttg = 0; state->lastsrc = 0; state->lastp25type = 0; @@ -112,7 +113,8 @@ initOpts (dsd_opts * opts) opts->frame_dstar = 0; opts->frame_x2tdma = 1; opts->frame_p25p1 = 1; - opts->frame_nxdn = 0; + opts->frame_nxdn48 = 0; + opts->frame_nxdn96 = 1; opts->frame_dmr = 1; opts->frame_provoice = 0; opts->mod_c4fm = 1; @@ -147,6 +149,7 @@ initState (dsd_state * state) state->audio_out_idx = 0; state->audio_out_idx2 = 0; state->audio_out_temp_buf_p = state->audio_out_temp_buf; + state->wav_out_bytes = 0; state->center = 0; state->jitter = -1; state->synctype = -1; @@ -181,11 +184,11 @@ initState (dsd_state * state) state->lastp25type = 0; state->offset = 0; state->carrier = 0; - for (j = 0; i < 25; j++) + for (i = 0; i < 25; i++) { - for (i = 0; j < 16; i++) + for (j = 0; j < 16; j++) { - state->tg[i][j] = 0; + state->tg[i][j] = 48; } } state->tgcount = 0; @@ -218,7 +221,6 @@ initState (dsd_state * state) void usage () { - printf ("Digital Speech Decoder 1.3\n"); printf ("\n"); printf ("Usage:\n"); printf (" dsd [options] Live scanner mode\n"); @@ -227,10 +229,10 @@ usage () printf ("\n"); printf ("Display Options:\n"); printf (" -e Show Frame Info and errorbars (default)\n"); - printf (" -pe Show p25 encryption sync bits\n"); - printf (" -pl Show p25 link control bits\n"); - printf (" -ps Show p25 status bits and low speed data\n"); - printf (" -pt Show p25 talkgroup info\n"); + printf (" -pe Show P25 encryption sync bits\n"); + printf (" -pl Show P25 link control bits\n"); + printf (" -ps Show P25 status bits and low speed data\n"); + printf (" -pt Show P25 talkgroup info\n"); printf (" -q Don't show Frame Info/errorbars\n"); printf (" -s Datascope (disables other display options)\n"); printf (" -t Show symbol timing during sync\n"); @@ -248,13 +250,14 @@ usage () printf ("Scanner control options:\n"); printf (" -B Serial port baud rate (default=115200)\n"); printf (" -C Serial port for scanner control (default=/dev/ttyUSB0)\n"); - printf (" -R Resume scan after TDULC frames or any PDU\n"); + printf (" -R Resume scan after TDULC frames or any PDU or TSDU\n"); printf ("\n"); printf ("Decoder options:\n"); printf (" -fa Auto-detect frame type (default)\n"); printf (" -f1 Decode only P25 Phase 1\n"); printf (" -fd Decode only D-STAR* (no audio)\n"); - printf (" -fn Decode only NXDN96* (no audio)\n"); + printf (" -fi Decode only NXDN48* (6.25 kHz) / IDAS*\n"); + printf (" -fn Decode only NXDN96 (12.5 kHz)\n"); printf (" -fp Decode only ProVoice*\n"); printf (" -fr Decode only DMR/MOTOTRBO\n"); printf (" -fx Decode only X2-TDMA\n"); @@ -300,6 +303,25 @@ liveScanner (dsd_opts * opts, dsd_state * state) } } +void +cleanupAndExit (dsd_opts * opts, dsd_state * state) +{ + noCarrier (opts, state); + if (opts->wav_out_f != NULL) + { + closeWavOutFile (opts, state); + } + printf ("Exiting.\n"); + exit (0); +} + +void +sigfun (int sig) +{ + exitflag = 1; + signal (SIGINT, SIG_DFL); +} + int main (int argc, char **argv) { @@ -307,13 +329,20 @@ main (int argc, char **argv) int c; extern char *optarg; extern int optind, opterr, optopt; - dsd_opts opts; dsd_state state; + char versionstr[25]; + mbe_printVersion (versionstr); + + printf ("Digital Speech Decoder 1.4.1\n"); + printf ("mbelib version %s\n", versionstr); initOpts (&opts); initState (&state); + exitflag = 0; + signal (SIGINT, sigfun); + while ((c = getopt (argc, argv, "hep:qstv:z:i:o:d:g:nw:B:C:R:f:m:u:x:A:S:M:r")) != -1) { opterr = 0; @@ -424,7 +453,8 @@ main (int argc, char **argv) opts.frame_dstar = 0; opts.frame_x2tdma = 1; opts.frame_p25p1 = 1; - opts.frame_nxdn = 0; + opts.frame_nxdn48 = 0; + opts.frame_nxdn96 = 1; opts.frame_dmr = 1; opts.frame_provoice = 0; } @@ -433,7 +463,8 @@ main (int argc, char **argv) opts.frame_dstar = 1; opts.frame_x2tdma = 0; opts.frame_p25p1 = 0; - opts.frame_nxdn = 0; + opts.frame_nxdn48 = 0; + opts.frame_nxdn96 = 0; opts.frame_dmr = 0; opts.frame_provoice = 0; printf ("Decoding only D-STAR frames.\n"); @@ -443,7 +474,8 @@ main (int argc, char **argv) opts.frame_dstar = 0; opts.frame_x2tdma = 1; opts.frame_p25p1 = 0; - opts.frame_nxdn = 0; + opts.frame_nxdn48 = 0; + opts.frame_nxdn96 = 0; opts.frame_dmr = 0; opts.frame_provoice = 0; printf ("Decoding only X2-TDMA frames.\n"); @@ -453,7 +485,8 @@ main (int argc, char **argv) opts.frame_dstar = 0; opts.frame_x2tdma = 0; opts.frame_p25p1 = 0; - opts.frame_nxdn = 0; + opts.frame_nxdn48 = 0; + opts.frame_nxdn96 = 0; opts.frame_dmr = 0; opts.frame_provoice = 1; state.samplesPerSymbol = 5; @@ -462,6 +495,7 @@ main (int argc, char **argv) opts.mod_qpsk = 0; opts.mod_gfsk = 1; state.rf_mod = 2; + printf ("Setting symbol rate to 9600 / second\n"); printf ("Enabling only GFSK modulation optimizations.\n"); printf ("Decoding only ProVoice frames.\n"); } @@ -470,19 +504,45 @@ main (int argc, char **argv) opts.frame_dstar = 0; opts.frame_x2tdma = 0; opts.frame_p25p1 = 1; - opts.frame_nxdn = 0; + opts.frame_nxdn48 = 0; + opts.frame_nxdn96 = 0; opts.frame_dmr = 0; opts.frame_provoice = 0; printf ("Decoding only P25 Phase 1 frames.\n"); } + else if (optarg[0] == 'i') + { + opts.frame_dstar = 0; + opts.frame_x2tdma = 0; + opts.frame_p25p1 = 0; + opts.frame_nxdn48 = 1; + opts.frame_nxdn96 = 0; + opts.frame_dmr = 0; + opts.frame_provoice = 0; + state.samplesPerSymbol = 20; + state.symbolCenter = 10; + opts.mod_c4fm = 0; + opts.mod_qpsk = 0; + opts.mod_gfsk = 1; + state.rf_mod = 2; + printf ("Setting symbol rate to 2400 / second\n"); + printf ("Enabling only GFSK modulation optimizations.\n"); + printf ("Decoding only NXDN 4800 baud frames.\n"); + } else if (optarg[0] == 'n') { opts.frame_dstar = 0; opts.frame_x2tdma = 0; opts.frame_p25p1 = 0; - opts.frame_nxdn = 1; + opts.frame_nxdn48 = 0; + opts.frame_nxdn96 = 1; opts.frame_dmr = 0; opts.frame_provoice = 0; + opts.mod_c4fm = 0; + opts.mod_qpsk = 0; + opts.mod_gfsk = 1; + state.rf_mod = 2; + printf ("Enabling only GFSK modulation optimizations.\n"); printf ("Decoding only NXDN 9600 baud frames.\n"); } else if (optarg[0] == 'r') @@ -490,7 +550,8 @@ main (int argc, char **argv) opts.frame_dstar = 0; opts.frame_x2tdma = 0; opts.frame_p25p1 = 0; - opts.frame_nxdn = 0; + opts.frame_nxdn48 = 0; + opts.frame_nxdn96 = 0; opts.frame_dmr = 1; opts.frame_provoice = 0; printf ("Decoding only DMR/MOTOTRBO frames.\n"); @@ -617,7 +678,7 @@ main (int argc, char **argv) else { opts.split = 0; - opts.playoffset = 38; + opts.playoffset = 25; // 38 opts.delay = 0; openAudioInDevice (&opts); opts.audio_out_fd = opts.audio_in_fd; @@ -631,5 +692,6 @@ main (int argc, char **argv) { liveScanner (&opts, &state); } + cleanupAndExit (&opts, &state); return (0); } diff --git a/dsd_mbe.c b/dsd_mbe.c index 67f1b34..43db40e 100644 --- a/dsd_mbe.c +++ b/dsd_mbe.c @@ -27,7 +27,7 @@ playMbeFiles (dsd_opts * opts, dsd_state * state, int argc, char **argv) for (i = state->optind; i < argc; i++) { - sprintf (opts->mbe_in_file, argv[i]); + sprintf (opts->mbe_in_file, "%s", argv[i]); openMbeInFile (opts, state); mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced); printf ("playing %s\n", opts->mbe_in_file); @@ -62,6 +62,10 @@ playMbeFiles (dsd_opts * opts, dsd_state * state, int argc, char **argv) playSynthesizedVoice (opts, state); } } + if (exitflag == 1) + { + cleanupAndExit (opts, state); + } } } } diff --git a/dsd_serial.c b/dsd_serial.c index dfd6a03..cc6a100 100644 --- a/dsd_serial.c +++ b/dsd_serial.c @@ -18,6 +18,7 @@ openSerial (dsd_opts * opts, dsd_state * state) tty.c_cflag = 0; + baud = B115200; switch (opts->serial_baud) { case 1200: @@ -70,19 +71,20 @@ void resumeScan (dsd_opts * opts, dsd_state * state) { - char cmd[7]; + char cmd[16]; + ssize_t result; if (opts->serial_fd > 0) { sprintf (cmd, "\rKEY00\r"); - write (opts->serial_fd, cmd, 7); + result = write (opts->serial_fd, cmd, 7); cmd[0] = 2; cmd[1] = 75; cmd[2] = 15; cmd[3] = 3; cmd[4] = 93; cmd[5] = 0; - write (opts->serial_fd, cmd, 5); + result = write (opts->serial_fd, cmd, 5); state->numtdulc = 0; } } diff --git a/dsd_symbol.c b/dsd_symbol.c index 45cda67..6827378 100644 --- a/dsd_symbol.c +++ b/dsd_symbol.c @@ -23,6 +23,7 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync) short sample; int i, sum, symbol, count; + ssize_t result; sum = 0; count = 0; @@ -31,7 +32,18 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync) // timing control if ((i == 0) && (have_sync == 0)) { - if (state->rf_mod == 1) + if (state->samplesPerSymbol == 20) + { + if ((state->jitter >= 7) && (state->jitter <= 10)) + { + i--; + } + else if ((state->jitter >= 11) && (state->jitter <= 14)) + { + i++; + } + } + else if (state->rf_mod == 1) { if ((state->jitter >= 0) && (state->jitter < state->symbolCenter)) { @@ -67,7 +79,7 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync) state->jitter = -1; } - read (opts->audio_in_fd, &sample, 2); + result = read (opts->audio_in_fd, &sample, 2); if ((sample > state->max) && (have_sync == 1) && (state->rf_mod == 0)) { sample = state->max; @@ -143,9 +155,17 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync) } } } + if (state->samplesPerSymbol == 20) + { + if ((i >= 9) && (i <= 11)) + { + sum += sample; + count++; + } + } if (state->samplesPerSymbol == 5) { - if ((i >= 2) && (i <= 2)) + if (i == 2) { sum += sample; count++; diff --git a/dsd_upsample.c b/dsd_upsample.c index 8d12aa2..3bbc584 100644 --- a/dsd_upsample.c +++ b/dsd_upsample.c @@ -22,150 +22,47 @@ upsample (dsd_state * state, float invalue) { int i, j, sum; - float *outbuf1, a, b, c, d; - float phasestart, phaseend, resamplestart, resampleend, phasestep, resampleamp2; - float resamplemin, resamplemax; + float *outbuf1, c, d; - if (state->audio_out_idx2 > 23) + outbuf1 = state->audio_out_float_buf_p; + outbuf1--; + c = *outbuf1; + d = invalue; + // basic triangle interpolation + outbuf1++; + *outbuf1 = ((invalue * (float) 0.166) + (c * (float) 0.834)); + outbuf1++; + *outbuf1 = ((invalue * (float) 0.332) + (c * (float) 0.668)); + outbuf1++; + *outbuf1 = ((invalue * (float) 0.5) + (c * (float) 0.5)); + outbuf1++; + *outbuf1 = ((invalue * (float) 0.668) + (c * (float) 0.332)); + outbuf1++; + *outbuf1 = ((invalue * (float) 0.834) + (c * (float) 0.166)); + outbuf1++; + *outbuf1 = d; + outbuf1++; + + if (state->audio_out_idx2 > 24) { - outbuf1 = state->audio_out_float_buf_p; - outbuf1--; - c = *outbuf1; - outbuf1 -= 6; - b = *outbuf1; - outbuf1 -= 6; - a = *outbuf1; - d = (invalue); - resamplemin = 32767; - resamplemax = -32768; - if (a < resamplemin) + // smoothing + outbuf1 -= 16; + for (j = 0; j < 4; j++) { - resamplemin = a; - } - if (a > resamplemax) - { - resamplemax = a; - } - if (b < resamplemin) - { - resamplemin = b; - } - if (b > resamplemax) - { - resamplemax = b; - } - if (c < resamplemin) - { - resamplemin = c; - } - if (c > resamplemax) - { - resamplemax = c; - } - if (d < resamplemin) - { - resamplemin = d; - } - if (d > resamplemax) - { - resamplemax = d; - } - resampleamp2 = ((float) resamplemax - (float) resamplemin) / (float) 2; -#ifdef UPSAMPLE_DEBUG - printf ("a:%f b:%f c:%f d:%f resamplemin:%f resamplemax:%f resampleamp2:%f\n", a, b, c, d, resamplemin, resamplemax, resampleamp2); -#endif - if (resampleamp2 == 0) - { - resamplestart = (float) 0; - resampleend = (float) 0; - } - else - { - resamplestart = (((float) b - (float) resamplemin) / resampleamp2) - (float) 1.0; - resampleend = (((float) c - (float) resamplemin) / resampleamp2) - (float) 1.0; - } - - if (resamplestart < -1) - { - resamplestart = (float) -1; - } - else if (resamplestart > (float) 1) - { - resamplestart = (float) 1; - } - if (resampleend < -1) - { - resampleend = (float) -1; - } - else if (resampleend > (float) 1) - { - resampleend = (float) 1; - } - - phasestart = asinf (resamplestart); - phaseend = asinf (resampleend); - phasestep = (phaseend - phasestart) / 6; -#ifdef UPSAMPLE_DEBUG - printf ("resamplestart:%f, resampleend:%f, phasestart:%f, phaseend:%f, phasestep:%f\n", resamplestart, resampleend, phasestart, phaseend, phasestep); -#endif - - // rewrite samples between b and c - outbuf1 = state->audio_out_float_buf_p; - outbuf1 -= 6; - for (i = 1; i < 6; i++) - { - *outbuf1 = (resamplemin + resampleamp2 + (resampleamp2 * sin (phasestart + (phasestep * (float) i)))); -#ifdef UPSAMPLE_DEBUG - printf ("audio_out_idx2:%i outbuf:%f\n", state->audio_out_idx2, *outbuf1); -#endif - outbuf1++; - } -#ifdef UPSAMPLE_DEBUG - printf ("(c):%f\n", *outbuf1); -#endif - // write d - outbuf1 += 6; - *outbuf1 = d; -#ifdef UPSAMPLE_DEBUG - printf ("audio_out_idx2:%i outbuf(d):%f\n", state->audio_out_idx2, *outbuf1); -#endif - outbuf1++; - - // smooth - outbuf1 -= 36; - for (j = 0; j < 12; j++) - { - for (i = 0; i < 12; i++) + for (i = 0; i < 6; i++) { sum = 0; - outbuf1--; + outbuf1 -= 2; sum += *outbuf1; - outbuf1++; + outbuf1 += 2; sum += *outbuf1; - outbuf1++; + outbuf1 += 2; sum += *outbuf1; - outbuf1--; + outbuf1 -= 2; *outbuf1 = (sum / (float) 3); outbuf1++; } - outbuf1 -= 11; + outbuf1 -= 8; } } - else - { - outbuf1 = state->audio_out_float_buf_p; - outbuf1--; - c = *outbuf1; - *outbuf1 = ((invalue * (float) 0.166) + (c * (float) 0.834)); - outbuf1++; - *outbuf1 = ((invalue * (float) 0.332) + (c * (float) 0.668)); - outbuf1++; - *outbuf1 = ((invalue * (float) 0.5) + (c * (float) 0.5)); - outbuf1++; - *outbuf1 = ((invalue * (float) 0.668) + (c * (float) 0.332)); - outbuf1++; - *outbuf1 = ((invalue * (float) 0.834) + (c * (float) 0.166)); - outbuf1++; - *outbuf1 = invalue; - } } diff --git a/nxdn_const.h b/nxdn_const.h new file mode 100644 index 0000000..a447faa --- /dev/null +++ b/nxdn_const.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2010 DSD Author + * GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0) + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MAIN +extern const int nW[36]; +extern const int nX[36]; +extern const int nY[36]; +extern const int nZ[36]; +extern const char nxdnpr[145]; + +#else +/* + * pseudorandom bit sequence + */ +const char nxdnpr[145] = { 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1 }; + +/* + * NXDN AMBE interleave schedule + */ +const int nW[36] = { 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 2, + 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2 +}; + +const int nX[36] = { 23, 10, 22, 9, 21, 8, + 20, 7, 19, 6, 18, 5, + 17, 4, 16, 3, 15, 2, + 14, 1, 13, 0, 12, 10, + 11, 9, 10, 8, 9, 7, + 8, 6, 7, 5, 6, 4 +}; + +const int nY[36] = { 0, 2, 0, 2, 0, 2, + 0, 2, 0, 3, 0, 3, + 1, 3, 1, 3, 1, 3, + 1, 3, 1, 3, 1, 3, + 1, 3, 1, 3, 1, 3, + 1, 3, 1, 3, 1, 3 +}; + +const int nZ[36] = { 5, 3, 4, 2, 3, 1, + 2, 0, 1, 13, 0, 12, + 22, 11, 21, 10, 20, 9, + 19, 8, 18, 7, 17, 6, + 16, 5, 15, 4, 14, 3, + 13, 2, 12, 1, 11, 0 +}; + +#endif diff --git a/nxdn_data.c b/nxdn_data.c new file mode 100644 index 0000000..403fe7a --- /dev/null +++ b/nxdn_data.c @@ -0,0 +1,36 @@ +#include "dsd.h" + +void +processNXDNData (dsd_opts * opts, dsd_state * state) +{ + int i, dibit; + + if (opts->errorbars == 1) + { + printf ("DATA "); + } + + for (i = 0; i < 30; i++) + { + dibit = getDibit (opts, state); +#ifdef NXDN_DUMP + printf ("%c", dibit + 48); +#endif + } +#ifdef NXDN_DUMP + printf (" "); +#endif + + for (i = 0; i < 144; i++) + { + dibit = getDibit (opts, state); +#ifdef NXDN_DUMP + printf ("%c", dibit + 48); +#endif + } + + if (opts->errorbars == 1) + { + printf ("\n"); + } +} diff --git a/nxdn_voice.c b/nxdn_voice.c new file mode 100644 index 0000000..2f001fc --- /dev/null +++ b/nxdn_voice.c @@ -0,0 +1,59 @@ +#include "dsd.h" +#include "nxdn_const.h" + +void +processNXDNVoice (dsd_opts * opts, dsd_state * state) +{ + int i, j, dibit; + char ambe_fr[4][24]; + const int *w, *x, *y, *z; + const char *pr; + + if (opts->errorbars == 1) + { + printf ("VOICE e:"); + } + + for (i = 0; i < 30; i++) + { + dibit = getDibit (opts, state); +#ifdef NXDN_DUMP + printf ("%c", dibit + 48); +#endif + } +#ifdef NXDN_DUMP + printf (" "); +#endif + + pr = nxdnpr; + for (j = 0; j < 4; j++) + { + w = nW; + x = nX; + y = nY; + z = nZ; + for (i = 0; i < 36; i++) + { + dibit = getDibit (opts, state); +#ifdef NXDN_DUMP + printf ("%c", dibit + 48); +#endif + ambe_fr[*w][*x] = *pr ^ (1 & (dibit >> 1)); // bit 1 + pr++; + ambe_fr[*y][*z] = (1 & dibit); // bit 0 + w++; + x++; + y++; + z++; + } + processMbeFrame (opts, state, NULL, ambe_fr, NULL); +#ifdef NXDN_DUMP + printf (" "); +#endif + } + + if (opts->errorbars == 1) + { + printf ("\n"); + } +} diff --git a/p25_lcw.c b/p25_lcw.c index 43014c2..392d11e 100644 --- a/p25_lcw.c +++ b/p25_lcw.c @@ -23,27 +23,13 @@ processP25lcw (dsd_opts * opts, dsd_state * state, char *lcformat, char *mfid, c { // first tg is the active channel - if (state->tgcount < 24) - { - // update tg buffer - j = 0; - for (i = 40; i < 52; i++) - { - state->tg[state->tgcount][j] = lcinfo[i]; - j++; - } - tmpstr[12] = 48; - tmpstr[13] = 48; - tmpstr[14] = 48; - tmpstr[15] = 48; - tmpstr[16] = 0; - state->tgcount = state->tgcount + 1; - } - - // first one again for tg display j = 0; for (i = 40; i < 52; i++) { + if (state->tgcount < 24) + { + state->tg[state->tgcount][j] = lcinfo[i]; + } tmpstr[j] = lcinfo[i]; j++; } @@ -52,9 +38,17 @@ processP25lcw (dsd_opts * opts, dsd_state * state, char *lcformat, char *mfid, c tmpstr[14] = 48; tmpstr[15] = 48; tmpstr[16] = 0; - tmpstr[16] = 0; talkgroup = strtol (tmpstr, NULL, 2); state->lasttg = talkgroup; + if (state->tgcount < 24) + { + state->tgcount = state->tgcount + 1; + } + if (opts->p25tg == 1) + { + printf ("tg: %li ", talkgroup); + } + if (opts->p25tg == 1) { printf ("tg: %li ", talkgroup); @@ -136,6 +130,10 @@ processP25lcw (dsd_opts * opts, dsd_state * state, char *lcformat, char *mfid, c tmpstr[16] = 0; talkgroup = strtol (tmpstr, NULL, 2); state->lasttg = talkgroup; + if (state->tgcount < 24) + { + state->tgcount = state->tgcount + 1; + } if (opts->p25tg == 1) { printf ("tg: %li ", talkgroup); diff --git a/p25p1_hdu.c b/p25p1_hdu.c index 699e07a..abf8c8d 100644 --- a/p25p1_hdu.c +++ b/p25p1_hdu.c @@ -305,6 +305,10 @@ processHDU (dsd_opts * opts, dsd_state * state) tmpstr[16] = 0; talkgroup = strtol (tmpstr, NULL, 2); state->lasttg = talkgroup; + if (state->tgcount < 24) + { + state->tgcount = state->tgcount + 1; + } if (opts->p25tg == 1) { printf ("tg: %li\n", talkgroup); diff --git a/x2tdma_data.c b/x2tdma_data.c index c70f3f3..3829270 100644 --- a/x2tdma_data.c +++ b/x2tdma_data.c @@ -207,7 +207,7 @@ processX2TDMAdata (dsd_opts * opts, dsd_state * state) printf ("%s ", syncbits); #endif - if (strcmp (sync, X2TDMA_DATA_SYNC) == 0) + if ((strcmp (sync, X2TDMA_BS_DATA_SYNC) == 0) || (strcmp (sync, X2TDMA_BS_DATA_SYNC) == 0)) { if (state->currentslot == 0) { @@ -218,17 +218,6 @@ processX2TDMAdata (dsd_opts * opts, dsd_state * state) sprintf (state->slot1light, "[slot1]"); } } - else if (strcmp (sync, X2TDMA_VOICE_SYNC) == 0) - { - if (state->currentslot == 0) - { - sprintf (state->slot0light, "[SLOT0]"); - } - else - { - sprintf (state->slot1light, "[SLOT1]"); - } - } if (opts->errorbars == 1) { diff --git a/x2tdma_voice.c b/x2tdma_voice.c index da3eeeb..4fd6d21 100644 --- a/x2tdma_voice.c +++ b/x2tdma_voice.c @@ -38,6 +38,7 @@ processX2TDMAvoice (dsd_opts * opts, dsd_state * state) int burstd; int mutecurrentslot; int algidhex, kidhex; + int msMode; #ifdef X2TDMA_DUMP int k; @@ -53,6 +54,7 @@ processX2TDMAvoice (dsd_opts * opts, dsd_state * state) aiei = 0; burstd = 0; mutecurrentslot = 0; + msMode = 0; dibit_p = state->dibit_buf_p - 144; for (j = 0; j < 6; j++) @@ -206,7 +208,7 @@ processX2TDMAvoice (dsd_opts * opts, dsd_state * state) sync[24] = 0; syncdata[24] = 0; - if (strcmp (sync, X2TDMA_DATA_SYNC) == 0) + if ((strcmp (sync, X2TDMA_BS_DATA_SYNC) == 0) || (strcmp (sync, X2TDMA_MS_DATA_SYNC) == 0)) { mutecurrentslot = 1; if (state->currentslot == 0) @@ -218,7 +220,7 @@ processX2TDMAvoice (dsd_opts * opts, dsd_state * state) sprintf (state->slot1light, "[slot1]"); } } - else if (strcmp (sync, X2TDMA_VOICE_SYNC) == 0) + else if ((strcmp (sync, X2TDMA_BS_VOICE_SYNC) == 0) || (strcmp (sync, X2TDMA_MS_VOICE_SYNC) == 0)) { mutecurrentslot = 0; if (state->currentslot == 0) @@ -231,6 +233,11 @@ processX2TDMAvoice (dsd_opts * opts, dsd_state * state) } } + if ((strcmp (sync, X2TDMA_MS_VOICE_SYNC) == 0) || (strcmp (sync, X2TDMA_MS_DATA_SYNC) == 0)) + { + msMode = 1; + } + if ((j == 0) && (opts->errorbars == 1)) { printf ("%s %s VOICE e:", state->slot0light, state->slot1light); @@ -564,7 +571,7 @@ processX2TDMAvoice (dsd_opts * opts, dsd_state * state) sync[24] = 0; syncdata[24] = 0; - if (strcmp (sync, X2TDMA_DATA_SYNC) == 0) + if ((strcmp (sync, X2TDMA_BS_DATA_SYNC) == 0) || (msMode == 1)) { if (state->currentslot == 0) { @@ -575,7 +582,7 @@ processX2TDMAvoice (dsd_opts * opts, dsd_state * state) sprintf (state->slot0light, " slot0 "); } } - else if (strcmp (sync, X2TDMA_VOICE_SYNC) == 0) + else if (strcmp (sync, X2TDMA_BS_VOICE_SYNC) == 0) { if (state->currentslot == 0) {