aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore18
-rw-r--r--b100-2048.ini25
-rw-r--r--b200-2048-zmq.ini20
-rw-r--r--b200-2048.ini6
-rw-r--r--b200-30.72.ini25
-rw-r--r--b200-resample.ini6
-rw-r--r--b200-sync-zmq.ini75
-rw-r--r--b200-sync.ini6
-rw-r--r--edi-test.mux163
-rwxr-xr-xedi/edidebug.py3
-rwxr-xr-xedi/edisend.py193
-rwxr-xr-xencode-alsa32.sh17
-rwxr-xr-xencode-alsasrc-gst-dabplus.sh39
-rwxr-xr-xencode-alsasrc-sox-mpeg.sh22
-rwxr-xr-xencode-fb.sh3
-rwxr-xr-xencode-fbplus.sh36
-rwxr-xr-xencode-jack.sh154
-rwxr-xr-xencode-stdin.sh3
-rwxr-xr-xencode-url-gst-dabplus.sh44
-rwxr-xr-xhistogram.py28
-rw-r--r--minimal.ini11
-rw-r--r--modulatoroffset2
-rwxr-xr-xmpeg_analyse.py117
-rw-r--r--rdsparse/decoder_impl.cc21
-rw-r--r--test.ini31
-rw-r--r--zmq-simul.mux94
26 files changed, 768 insertions, 394 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..fce88b8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,18 @@
+zmqtest
+eti
+*.sub
+*.pub
+*.raw
+*.wav
+*.mp2
+*.dab
+*.dabp
+*.dabplus
+keys
+filter
+rdsparse/CMakeCache.txt
+rdsparse/CMakeFiles/
+rdsparse/Makefile
+rdsparse/cmake_install.cmake
+rdsparse/cmake_uninstall.cmake
+rdsparse/rdsparse
diff --git a/b100-2048.ini b/b100-2048.ini
index 7d4b94c..f990a2d 100644
--- a/b100-2048.ini
+++ b/b100-2048.ini
@@ -10,11 +10,12 @@ filelog=1
filename=/dev/stderr
[input]
-transport=file
-source=/dev/stdin
-;transport=zeromq
-;source=tcp://mpb.li:9100
-loop=0
+;transport=file
+;source=/dev/stdin
+;loop=0
+transport=zeromq
+source=tcp://core.mpb.li:9100
+max_frames_queued=400
[modulator]
; Gain mode: 0=FIX, 1=MAX, 2=VAR
@@ -33,8 +34,8 @@ digital_gain=1.0
rate=2048000
[firfilter]
-enabled=0
-filtertapsfile=filter/simplefiltertaps.txt
+enabled=1
+filtertapsfile=filter/filtertaps.txt
[output]
; choose output: possible values: uhd, file
@@ -48,7 +49,7 @@ filename=/dev/null
device=
master_clock_rate=20480000
type=b100
-txgain=4
+txgain=12
;frequency=234208000
channel=13C
@@ -64,10 +65,6 @@ behaviour_refclk_lock_lost=crash
; Used for SFN with the UHD output
[delaymanagement]
-synchronous=0
+synchronous=1
-; choose between fixed and dynamic offset definition
-management=dynamic
-
-fixedoffset=0.002
-dynamicoffsetfile=modulatoroffset
+offset=2.0
diff --git a/b200-2048-zmq.ini b/b200-2048-zmq.ini
index 905454f..f79f0c3 100644
--- a/b200-2048-zmq.ini
+++ b/b200-2048-zmq.ini
@@ -1,4 +1,5 @@
-; Sample configuration file for CRC-DABMOD
+; Sample configuration file for ODR-DabMod
+; using a zeromq input
[remotecontrol]
telnet=1
@@ -6,7 +7,7 @@ telnetport=2121
[log]
syslog=0
-filelog=1
+filelog=0
filename=/dev/stderr
[input]
@@ -15,6 +16,7 @@ filename=/dev/stderr
transport=zeromq
source=tcp://localhost:9100
loop=0
+max_frames_queued=400
[modulator]
; Gain mode: 0=FIX, 1=MAX, 2=VAR
@@ -22,12 +24,12 @@ gainmode=2
; Transmission mode
; If not defined, take the mode from ETI
-;mode=2
+mode=1
; Set to 0 to disable CicEqualiser
dac_clk_rate=0
-digital_gain=1.0
+digital_gain=0.8
; Output sample rate
rate=2048000
@@ -49,7 +51,7 @@ filename=/dev/null
device=
master_clock_rate=32768000
type=b200
-txgain=45
+txgain=50
;frequency=234208000
channel=13C
@@ -63,12 +65,10 @@ pps_source=none
; possible values: ignore, crash
behaviour_refclk_lock_lost=crash
+max_gps_holdover_time=300
+
; Used for SFN with the UHD output
[delaymanagement]
synchronous=0
-; choose between fixed and dynamic offset definition
-management=dynamic
-
-fixedoffset=0.002
-dynamicoffsetfile=modulatoroffset
+offset=2.0
diff --git a/b200-2048.ini b/b200-2048.ini
index 7742a1d..92fe43e 100644
--- a/b200-2048.ini
+++ b/b200-2048.ini
@@ -67,8 +67,4 @@ behaviour_refclk_lock_lost=crash
[delaymanagement]
synchronous=0
-; choose between fixed and dynamic offset definition
-management=dynamic
-
-fixedoffset=0.002
-dynamicoffsetfile=modulatoroffset
+offset=0.002
diff --git a/b200-30.72.ini b/b200-30.72.ini
index a66fbfe..be0e204 100644
--- a/b200-30.72.ini
+++ b/b200-30.72.ini
@@ -12,13 +12,13 @@ filename=/dev/stderr
[input]
;transport=file
-;source=/dev/stdin
-loop=0
+;source=/home/bram/dab/mmbtools-aux/eti/AnnouncementTest-FraunhoferIIS-2013-11-25.eti
+;loop=1
transport=zeromq
;source=tcp://localhost:9100
source=tcp://core.mpb.li:9100
-max_frames_queued=400
+max_frames_queued=800
[modulator]
; Gain mode: 0=FIX, 1=MAX, 2=VAR
@@ -26,12 +26,12 @@ gainmode=2
; Transmission mode
; If not defined, take the mode from ETI
-;mode=2
+mode=1
; Set to 0 to disable CicEqualiser
dac_clk_rate=0
-digital_gain=1.0
+digital_gain=0.8
; Output sample rate
rate=2048000
@@ -53,12 +53,12 @@ filename=/dev/null
device=
master_clock_rate=32768000
type=b200
-txgain=50
+txgain=40
;frequency=234208000
channel=13C
; possible values : internal, external, MIMO
-refclk_source=gpsdo
+refclk_source=gpsdo-ettus
; possible values : none, external, MIMO
pps_source=gpsdo
@@ -67,12 +67,15 @@ pps_source=gpsdo
; possible values: ignore, crash
behaviour_refclk_lock_lost=crash
+max_gps_holdover_time=600
+
; Used for SFN with the UHD output
[delaymanagement]
synchronous=1
-; choose between fixed and dynamic offset definition
-management=dynamic
+offset=2.0
-fixedoffset=0.002
-dynamicoffsetfile=modulatoroffset
+[tii]
+enable = 0
+comb = 16
+pattern = 5
diff --git a/b200-resample.ini b/b200-resample.ini
index ad72801..c537f1c 100644
--- a/b200-resample.ini
+++ b/b200-resample.ini
@@ -67,8 +67,4 @@ behaviour_refclk_lock_lost=crash
[delaymanagement]
synchronous=0
-; choose between fixed and dynamic offset definition
-management=dynamic
-
-fixedoffset=0.002
-dynamicoffsetfile=modulatoroffset
+offset=2.0
diff --git a/b200-sync-zmq.ini b/b200-sync-zmq.ini
new file mode 100644
index 0000000..60f6611
--- /dev/null
+++ b/b200-sync-zmq.ini
@@ -0,0 +1,75 @@
+; Sample configuration file for ODR-DabMod
+
+[remotecontrol]
+telnet=1
+telnetport=2121
+
+[log]
+syslog=0
+filelog=0
+filename=/dev/stderr
+
+[input]
+;transport=file
+;source=/dev/stdin
+transport=zeromq
+source=tcp://core.mpb.li:9100
+loop=0
+
+[modulator]
+; Gain mode: 0=FIX, 1=MAX, 2=VAR
+gainmode=2
+
+; Transmission mode
+; If not defined, take the mode from ETI
+mode=1
+
+; Set to 0 to disable CicEqualiser
+dac_clk_rate=0
+
+digital_gain=0.8
+
+; Output sample rate
+rate=2048000
+
+[firfilter]
+enabled=1
+filtertapsfile=filter/simplefiltertaps.txt
+
+[output]
+; choose output: possible values: uhd, file
+output=uhd
+
+[fileoutput]
+filename=/dev/null
+
+[uhdoutput]
+;device=master_clock_rate=32768000,type=b100
+;txgain=2
+device=
+master_clock_rate=32768000
+type=b200
+txgain=45
+;frequency=234208000
+channel=13C
+
+; possible values : internal, external, MIMO
+refclk_source=internal
+
+; possible values : none, external, MIMO
+pps_source=none
+
+; behaviour when external clock reference lock lost
+; possible values: ignore, crash
+behaviour_refclk_lock_lost=crash
+
+; Used for SFN with the UHD output
+[delaymanagement]
+synchronous=1
+
+offset=2.0
+
+[tii]
+enable = 1
+comb = 16
+pattern = 6
diff --git a/b200-sync.ini b/b200-sync.ini
index 6a996d5..b232f36 100644
--- a/b200-sync.ini
+++ b/b200-sync.ini
@@ -67,8 +67,4 @@ behaviour_refclk_lock_lost=crash
[delaymanagement]
synchronous=1
-; choose between fixed and dynamic offset definition
-management=dynamic
-
-fixedoffset=0.002
-dynamicoffsetfile=modulatoroffset
+offset=2.0
diff --git a/edi-test.mux b/edi-test.mux
new file mode 100644
index 0000000..6d835b7
--- /dev/null
+++ b/edi-test.mux
@@ -0,0 +1,163 @@
+general {
+ ; the DAB Transmission mode (values 1-4 accepted)
+ dabmode 1
+
+ ; the number of ETI frames to generate (set to 0 to get an unlimited number)
+ nbframes 0
+
+ ; The statsserver for extracting statistics
+ statsserverport 12720
+
+ syslog false
+ writescca false
+ tist false
+
+ new_fig_carousel true
+}
+
+remotecontrol {
+ ; enable the remote control server
+ telnetport 12721
+}
+
+; Some ensemble parameters
+ensemble {
+ id 20479
+ ; Extended Country Code (decimal)
+ ecc 225
+
+ local-time-offset 2
+ international-table 1
+ label "TuxMux"
+ shortlabel "Tux"
+}
+
+services {
+ funk {
+ label "funk"
+ shortlabel "funk"
+ pty 0
+ language 0
+ id 10
+ }
+
+ funk2 {
+ label "funk2"
+ shortlabel "funk2"
+ pty 0
+ language 0
+ id 11
+ }
+ funk3 {
+ label "funk3"
+ shortlabel "funk3"
+ pty 1
+ language 0
+ id 12
+ }
+
+}
+
+subchannels {
+ funk {
+ type audio
+ inputfile "funk.mp2"
+ nonblock false
+ bitrate 128
+ id 10
+ protection 5
+ }
+
+ funk2 {
+ type dabplus
+ inputfile "funk2.dabp"
+ nonblock false
+ bitrate 96
+ id 11
+ protection 3
+ }
+
+ funk3 {
+ type audio
+ inputfile "funk.mp2"
+ nonblock false
+ bitrate 128
+ id 12
+ protection 3
+ }
+}
+
+; For now, each component links one service to one subchannel
+components {
+ ; the component unique identifiers are not used anywhere, but
+ ; are useful to disambiguate different components.
+ funky {
+ label funk
+ shortlabel fu
+ service funk
+ subchannel funk
+ }
+
+ funky2 {
+ label funk2
+ shortlabel funk2
+ service funk2
+ subchannel funk2
+ }
+
+ funky3 {
+ label funk3
+ shortlabel funk3
+ service funk3
+ subchannel funk3
+ }
+}
+
+; A list of outputs, in the format
+; unique_id "uri"
+outputs {
+ ;foobar "fifo:///home/bram/dab/mmbtools-aux/eti/funk2.10000.eti?type=raw"
+ simul "simul://"
+ null "fifo:///dev/null"
+
+ ; ZeroMQ output example
+ ; zmq "zmq+tcp://*:8080"
+
+ edi {
+
+ fec 2
+ ;chunk_len 140
+
+ destinations {
+ unicast {
+ destination "10.31.0.120"
+ ;destination "239.20.64.1"
+ ;source "192.168.2.10"
+ sourceport 15321
+ }
+ un_autre {
+ destination "239.20.64.1"
+ source "10.31.0.121"
+ sourceport 15322
+ ttl 2
+ }
+ }
+
+ port 12002
+
+ ; EDI uses the UDP protocol
+
+ ; Enable the PFT subsystem. If false, AFPackets are sent.
+ enable_pft true
+
+ ; Save the packets sent over ethernet to the file ./edi.debug
+ dump false
+
+ ; show more debugging info
+ verbose false
+
+ ; optional: what kind of alignment to do in the tagpacket
+ ;tagpacket_alignment 16
+ }
+
+}
diff --git a/edi/edidebug.py b/edi/edidebug.py
index 64d605d..c41d9a6 100755
--- a/edi/edidebug.py
+++ b/edi/edidebug.py
@@ -482,7 +482,8 @@ def tagitems(tagpacket):
name, length = struct.unpack(tag_item_head_struct, tagpacket[i:i+8])
# length is in bits, because it's more annoying this way
- assert(length % 8 == 0)
+ if length % 8 != 0:
+ print("ASSERTION ERROR: length of tagpacket is not multiple of 8: {}".format(length))
length /= 8
tag_value = tagpacket[i+8:i+8+length]
diff --git a/edi/edisend.py b/edi/edisend.py
new file mode 100755
index 0000000..2bd6bc1
--- /dev/null
+++ b/edi/edisend.py
@@ -0,0 +1,193 @@
+#!/usr/bin/env python2
+#
+# Read an EDI dump file and transmit over UDP
+#
+# The MIT License (MIT)
+#
+# Copyright (c) 2015 Matthias P. Braendli
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+import sys
+import struct
+
+from crc import crc16
+from reedsolo import RSCodec
+
+import socket
+import time
+
+UDP_IP = "239.20.64.1"
+UDP_PORT = 12002
+
+class BufferedFile:
+ def __init__(self, fname):
+ self.buf = []
+
+ if fname == "-":
+ self.fd = sys.stdin
+ else:
+ self.fd = open(fname, "rb")
+
+ def read(self, n):
+ if not self.buf:
+ return self.fd.read(n)
+ else:
+ if len(self.buf) < n:
+ self.buf.extend(self.fd.read(n - len(self.buf)))
+
+ if len(self.buf) == n:
+ ret = b"".join(self.buf)
+ self.buf = []
+ else:
+ ret = b"".join(self.buf[:n])
+ del self.buf[:n]
+
+ return ret
+
+ def peek(self, n):
+ dat = self.fd.read(n)
+ self.buf.extend(dat)
+ return dat
+
+
+pft_head_struct = "!2sH3B3BH"
+pft_rs_head_struct = "!2B"
+pft_addr_head_struct = "!2H"
+af_head_struct = "!2sLHBc"
+class EDI:
+ def __init__(self):
+ self.last_send_time = time.time()
+ self.sock = socket.socket(socket.AF_INET, # Internet
+ socket.SOCK_DGRAM) # UDP
+
+ def send_udp(self, message):
+ self.sock.sendto(message, (UDP_IP, UDP_PORT))
+
+
+ def decode(self, stream):
+ sync = stream.peek(2)
+
+ if len(sync) < 2:
+ return False
+
+ if sync == "PF":
+ return self.decode_pft(stream)
+ elif sync == "AF":
+ return self.decode_af(stream, is_stream=True)
+
+
+
+ def decode_pft(self, stream):
+ headerdata = stream.read(12)
+ header = struct.unpack(pft_head_struct, headerdata)
+
+ psync, pseq, findex1, findex2, findex3, fcount1, fcount2, fcount3, fec_ad_plen = header
+
+ findex = (findex1 << 16) | (findex2 << 8) | findex3
+ fcount = (fcount1 << 16) | (fcount2 << 8) | fcount3
+
+ fec = (fec_ad_plen & 0x8000) != 0x00
+ addr = (fec_ad_plen & 0x4000) != 0x00
+ plen = fec_ad_plen & 0x3FFF
+
+ rs_k = 0
+ rs_z = 0
+ if fec:
+ rs_head = stream.read(2)
+ rs_k, rs_z = struct.unpack(pft_rs_head_struct, rs_head)
+ headerdata += rs_head
+
+ addr_source = 0
+ addr_dest = 0
+ if addr:
+ addr_head = stream.read(4)
+ addr_source, addr_dest = struct.unpack(pft_addr_head_struct, addr_head)
+ headerdata += addr_head
+
+ # read CRC
+ crc_data = stream.read(2)
+ crc = struct.unpack("!H", crc_data)[0]
+
+ crc_calc = crc16(headerdata)
+ crc_calc ^= 0xFFFF
+
+ crc_ok = crc_calc == crc
+
+ time_now = time.time()
+ if findex == 0:
+ if self.last_send_time + 24e-3 > time_now:
+ delay = self.last_send_time + 24e-3 - time_now
+ print("Sleeping for {} ms".format(1000 * delay))
+ time.sleep(delay)
+ self.last_send_time = time_now
+
+
+ if crc_ok:
+ payload = stream.read(plen)
+ self.send_udp(headerdata + crc_data + payload)
+
+ return crc_ok
+
+
+ def decode_af(self, in_data, is_stream=False):
+ if is_stream:
+ headerdata = in_data.read(10)
+ else:
+ headerdata = in_data[:10]
+
+ sync, plen, seq, ar, pt = struct.unpack(af_head_struct, headerdata)
+
+ if sync != "AF":
+ return False
+
+ crc_flag = (ar & 0x80) != 0x00
+ revision = ar & 0x7F
+
+ if is_stream:
+ payload = in_data.read(plen)
+ crc_data = in_data.read(2)
+ crc = struct.unpack("!H", crc_data)[0]
+ else:
+ payload = in_data[10:10+plen]
+ crc_data = in_data[10+plen:10+plen+2]
+ crc = struct.unpack("!H", crc_data)[0]
+
+ crc_calc = crc16(headerdata)
+ crc_calc = crc16(payload, crc_calc)
+ crc_calc ^= 0xFFFF
+
+ crc_ok = crc_calc == crc
+
+ if crc_ok:
+ self.send_udp(headerdata + payload + crc_data)
+
+ return crc_ok
+
+if len(sys.argv) > 1:
+ filename = sys.argv[1]
+
+ edi_fd = BufferedFile(filename)
+else:
+ edi_fd = BufferedFile("-")
+
+edi = EDI()
+while edi.decode(edi_fd):
+ pass
+
diff --git a/encode-alsa32.sh b/encode-alsa32.sh
deleted file mode 100755
index 750ecc5..0000000
--- a/encode-alsa32.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Read audio from ALSA input using sox, and encode with fdk-aac-dabplus-zmq
-#
-BITRATE=$1
-DST=$2
-ALSASRC="default"
-
-if [ "$DST" == "" ]
-then
- echo "Usage:"
- echo " $0 <bitrate> <zmq destination>"
- exit 1
-fi
-
-dabplus-enc -d $ALSASRC -c 2 -r 32000 -b $BITRATE -o $DST -p 48
-
diff --git a/encode-alsasrc-gst-dabplus.sh b/encode-alsasrc-gst-dabplus.sh
deleted file mode 100755
index 7ec5d9e..0000000
--- a/encode-alsasrc-gst-dabplus.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/bash
-#
-# Read audio from ALSA input using gstreamer, and encode with fdk-aac-dabplus-zmq
-#
-BITRATE=$1
-DST=$2
-QUEUEDELAY=400000 #400ms
-
-GSTREAMER_VERSION="0"
-
-if [ "$DST" == "" ]
-then
- echo "Usage:"
- echo " $0 <bitrate> <zmq destination>"
- exit 1
-fi
-
-
-if [ "$GSTREAMER_VERSION" == "1" ]
-then
- gst-launch-1.0 -q \
- alsasrc "device=default" ! \
- audio/x-raw, 'rate=48000,format=S16LE,channels=2' ! \
- queue "max-size-time=$QUEUEDELAY" ! \
- filesink location="/dev/stdout" | \
- dabplus-enc \
- -i /dev/stdin -b $BITRATE -f raw -a -o "${DST}"
-
-elif [ "$GSTREAMER_VERSION" == "0" ]
-then
- gst-launch -q \
- alsasrc "device=default" ! \
- audio/x-raw-int, 'rate=48000,format=S16LE,channels=2' ! \
- queue "max-size-time=$QUEUEDELAY" ! \
- filesink location="/dev/stdout" | \
- dabplus-enc \
- -i /dev/stdin -b $BITRATE -f raw -a -o "${DST}"
-fi
-
diff --git a/encode-alsasrc-sox-mpeg.sh b/encode-alsasrc-sox-mpeg.sh
deleted file mode 100755
index 3de71b5..0000000
--- a/encode-alsasrc-sox-mpeg.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/bash
-#
-# Read audio from ALSA input using sox, and encode with toolame,
-# send to ZMQ
-#
-# This needs toolame-dab from
-# https://github.com/Opendigitalradio/toolame-dab
-#
-BITRATE=$1
-DST=$2
-ALSASRC="default"
-
-if [ "$DST" == "" ]
-then
- echo "Usage:"
- echo " $0 <bitrate> <zmq destination>"
- exit 1
-fi
-
-sox -t alsa $ALSASRC -b 16 -t raw - rate 48k channels 2 | \
- toolame -s 48 -D 4 -b $BITRATE /dev/stdin $DST
-
diff --git a/encode-fb.sh b/encode-fb.sh
deleted file mode 100755
index f97f3a3..0000000
--- a/encode-fb.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-echo "Encoding FB to 1.ff"
-mpg123 -r 48000 -s http://fbpc5.epfl.ch:8001 |toolame -s 48 -D 4 -b 128 /dev/stdin ./1.ff
diff --git a/encode-fbplus.sh b/encode-fbplus.sh
deleted file mode 100755
index 1e1bfc8..0000000
--- a/encode-fbplus.sh
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/bin/bash
-#
-# Encode Frequence Banane to ZMQ
-#
-# Remarks: it's probably better to use the
-# snd-aloop scenario now.
-
-WITH_GSTREAMER=0
-URL=http://fbpc5.epfl.ch:8000/fb_192
-BITRATE=$1
-DST=$2
-
-if [ "$DST" == "" ]
-then
- echo "Usage:"
- echo " $0 <bitrate> <zmq destination>"
- exit 1
-fi
-
-if [ "$WITH_GSTREAMER" == "1" ]
-then
- gst-launch-0.10 -q \
- uridecodebin uri=$URL ! \
- queue ! \
- audioresample quality=8 ! \
- audioconvert ! \
- audio/x-raw-int, 'rate=48000,format=S16LE,channels=2' ! \
- filesink location="/dev/stdout" | \
- dabplus-enc \
- -i /dev/stdin -b $BITRATE -f raw -a -o $DST
-else
- mpg123 -s $URL |\
- sox -t raw -r 44100 -e signed -b 16 -c 2 - -t raw - rate 32k |\
- dabplus-enc \
- -i /dev/stdin -r 32000 -b $BITRATE -f raw -a -o $DST
-fi
diff --git a/encode-jack.sh b/encode-jack.sh
deleted file mode 100755
index ab7e9aa..0000000
--- a/encode-jack.sh
+++ /dev/null
@@ -1,154 +0,0 @@
-#!/bin/bash
-#
-# mplayer - jack - jack-stdout - dabplus-enc
-# encoder script.
-#
-# Used to encode webstreams for DAB+, requires
-# jackd -d dummy -r 32000
-# to be running
-
-printerr() {
- echo -e "\033[01;31m$1\033[0m"
-}
-
-printmsg() {
- echo -e "\033[01;32m$1\033[0m"
-}
-
-set -u
-
-# check number of arguments
-if [[ "$#" < 3 ]] ; then
- echo "Usage $0 url jack-id destination [volume]"
- echo "The volume setting is optional"
- exit 1
-fi
-
-if [[ "$#" > 2 ]] ; then
- URL=$1
- ID=$2
- DST=$3
-fi
-
-if [[ "$#" == 4 ]] ; then
- VOL=$4
-else
- VOL=""
-fi
-
-BITRATE=80
-RATE=32000
-
-encoderalive=0
-mplayerpid=0
-encoderpid=0
-
-# The trap for Ctrl-C
-sigint_trap() {
- printerr "Got Ctrl-C, killing mplayer and encoder"
-
- if [[ "$mplayerpid" != "0" ]] ; then
- kill -TERM $mplayerpid
- sleep 2
- kill -KILL $mplayerpid
- fi
-
- if [[ "$encoderpid" != "0" ]] ; then
- kill -TERM $encoderpid
- sleep 2
- kill -KILL $encoderpid
- fi
-
- printmsg "Goodbye"
- exit
-}
-
-trap sigint_trap SIGINT
-
-while true
-do
- mplayer_ok=0
-
- if [[ "$mplayerpid" == "0" ]] ; then
- if [[ "$VOL" == "" ]] ; then
- mplayer -quiet -af resample=$RATE:0:2 -ao jack:name=$ID $URL &
- mplayerpid=$!
- else
- mplayer -quiet -af resample=$RATE:0:2 -af volume=$VOL -ao jack:name=$ID $URL &
- mplayerpid=$!
- fi
-
- printmsg "Started mplayer with pid $mplayerpid"
-
- # give some time to mplayer to set up and
- # wait until port becomes visible
- timeout=10
-
- while [[ "$mplayer_ok" == "0" ]]
- do
- printmsg "Waiting for mplayer to connect to jack ($timeout)"
- sleep 1
- mplayer_ok=$(jack_lsp $ID:out_0 | wc -l)
-
- timeout=$(( $timeout - 1))
-
- if [[ "$timeout" == "0" ]] ; then
- printerr "mplayer doesn't connect to jack !"
- kill $mplayerpid
- break
- fi
- done
- else
- printmsg "No need to start mplayer: $mplayerpid"
- fi
-
- if [[ "$mplayer_ok" == "1" ]] ; then
- jack-stdout $ID:out_0 $ID:out_1 | \
- dabplus-enc -i /dev/stdin -l \
- -b $BITRATE -r $RATE -f raw -a -o $DST &
- encoderpid=$!
- fi
-
- printmsg "Started encoder with pid $encoderpid"
-
- sleep 5
-
- checkloop=1
- while [[ "$checkloop" == "1" ]]
- do
- sleep 2
-
- kill -s 0 $mplayerpid
- if [[ "$?" != "0" ]] ; then
- # mplayer died
- # we must kill jack-stdout, because we cannot reconnect it
- # to a new mplayer, since we do not know the jack-stdout name.
- # And it has no cmdline option to set one, Rrrrongntudtjuuu!
- if [[ "$encoderpid" != "0" ]] ; then
- kill -TERM $encoderpid
- fi
- checkloop=0
-
- # mark as dead
- mplayerpid=0
-
- printerr "Mplayer died"
- fi
-
- if [[ "$encoderpid" != "0" ]] ; then
- kill -s 0 $encoderpid
- if [[ "$?" != "0" ]] ; then
- # the encoder died,
- # no need to kill the mplayer, we can reconnect to it
-
- checkloop=0
-
- printerr "Encoder died"
- fi
- fi
- done
-
- sleep 5
-
-done
-
diff --git a/encode-stdin.sh b/encode-stdin.sh
deleted file mode 100755
index c97a5ce..0000000
--- a/encode-stdin.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-
-toolame -s 48 -D 4 -b 128 /dev/stdin /dev/stdout > 1.ff
diff --git a/encode-url-gst-dabplus.sh b/encode-url-gst-dabplus.sh
deleted file mode 100755
index b05d7bb..0000000
--- a/encode-url-gst-dabplus.sh
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/bin/bash
-#
-# Read a URL using gstreamer, and encode with fdk-aac-dabplus-enc
-#
-URL=$1
-BITRATE=$2
-DST=$3
-QUEUEDELAY=400000 #400ms
-
-GSTREAMER_VERSION="1"
-
-if [ "$DST" == "" ]
-then
- echo "Usage:"
- echo " $0 <url> <bitrate> <zmq destination>"
- exit 1
-fi
-
-
-if [ "$GSTREAMER_VERSION" == "1" ]
-then
- gst-launch-1.0 -q \
- uridecodebin uri=$URL ! \
- queue "max-size-time=$QUEUEDELAY" ! \
- audioresample quality=8 ! \
- audioconvert ! \
- audio/x-raw, 'rate=48000,format=S16LE,channels=2' ! \
- filesink location="/dev/stdout" | \
- dabplus-enc \
- -i /dev/stdin -b $BITRATE -f raw -a -o "${DST}"
-
-elif [ "$GSTREAMER_VERSION" == "0" ]
-then
- gst-launch -q \
- uridecodebin uri=$URL ! \
- queue "max-size-time=$QUEUEDELAY" ! \
- audioresample quality=8 ! \
- audioconvert ! \
- audio/x-raw-int, 'rate=48000,format=S16LE,channels=2' ! \
- filesink location="/dev/stdout" | \
- dabplus-enc \
- -i /dev/stdin -b $BITRATE -f raw -a -o "${DST}"
-fi
-
diff --git a/histogram.py b/histogram.py
new file mode 100755
index 0000000..c17a255
--- /dev/null
+++ b/histogram.py
@@ -0,0 +1,28 @@
+#!/usr/bin/python2
+#
+# Print sample histograms from dabmod I/Q file
+
+import sys
+
+import pylab as P
+import numpy
+
+
+fd = open('test.iq', 'rb')
+
+read_data = numpy.fromfile(file=fd, dtype=numpy.float32, count=-1)
+
+print("MAX absolute value: {}".format(numpy.max(numpy.abs(read_data))))
+
+if 0:
+ P.plot(read_data)
+
+if 1:
+ P.figure()
+
+ # the histogram of the data with histtype='step'
+ n, bins, patches = P.hist(read_data, 50, normed=1, histtype='stepfilled')
+ P.setp(patches, 'facecolor', 'g', 'alpha', 0.75)
+
+P.show()
+
diff --git a/minimal.ini b/minimal.ini
new file mode 100644
index 0000000..8f98890
--- /dev/null
+++ b/minimal.ini
@@ -0,0 +1,11 @@
+[input]
+transport=zeromq
+source=tcp://core.mpb.li:9100
+max_frames_queued=400
+
+[output]
+output=file
+
+[fileoutput]
+filename=/dev/null
+
diff --git a/modulatoroffset b/modulatoroffset
index 2348025..5186d07 100644
--- a/modulatoroffset
+++ b/modulatoroffset
@@ -1 +1 @@
-1.200151
+4.0
diff --git a/mpeg_analyse.py b/mpeg_analyse.py
new file mode 100755
index 0000000..495e808
--- /dev/null
+++ b/mpeg_analyse.py
@@ -0,0 +1,117 @@
+#!/usr/bin/env python2
+#
+# Analyse an mp2 file for debugging
+#
+# The MIT License (MIT)
+#
+# Copyright (c) 2016 Matthias P. Braendli
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+from pprint import pprint
+import sys
+import struct
+
+# Header:
+# AAAAAAAA AAABBCCD EEEEFFGH IIJJKLMM
+# see http://mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm
+
+audio_version_ids = ["MPEG version 2.5", "reserved", "MPEG Version 2 (ISO/IEC 13818-3)", "MPEG Version 1 (ISO/IEC 11172-3)"]
+layer_descriptions = ["reserved", "Layer III", "Layer II", "Layer I"]
+
+# bitrate index:
+# bits V1,L1 V1,L2 V1,L3 V2,L1 V2, L2 & L3
+# 0000 free free free free free
+# 0001 32 32 32 32 8
+# 0010 64 48 40 48 16
+# 0011 96 56 48 56 24
+# 0100 128 64 56 64 32
+# 0101 160 80 64 80 40
+# 0110 192 96 80 96 48
+# 0111 224 112 96 112 56
+# 1000 256 128 112 128 64
+# 1001 288 160 128 144 80
+# 1010 320 192 160 160 96
+# 1011 352 224 192 176 112
+# 1100 384 256 224 192 128
+# 1101 416 320 256 224 144
+# 1110 448 384 320 256 160
+# 1111 bad bad bad bad bad
+
+def analyse(fd):
+ headerdata = struct.unpack("!BBBB", fd.read(4))
+
+ sync = (headerdata[0] << 3) | (headerdata[1] >> 5)
+ print("Sync: {:x}".format(sync))
+
+ audio_version_id = (headerdata[1] >> 3) & 0x3
+ print("audio_version_id {}".format(audio_version_ids[audio_version_id]))
+
+ layer_description = (headerdata[1] >> 1) & 0x3
+ print("layer_description {}".format(layer_descriptions[layer_description]))
+
+ protection_bit = headerdata[1] & 0x1
+ if protection_bit:
+ print("Without protection")
+ else:
+ print("With protection")
+
+ bitrate_index = headerdata[2] >> 4
+ print("bitrate_index {}".format(bitrate_index))
+
+ sampling_rate = (headerdata[2] >> 2) & 0x3
+ print("sampling_rate {}".format(sampling_rate))
+
+ padding_bit = (headerdata[2] >> 1) & 0x1
+ if padding_bit:
+ print("With padding")
+ else:
+ print("Without padding")
+
+ private_bit = headerdata[2] & 0x1
+ if private_bit:
+ print("Private bit set")
+ else:
+ print("Private bit unset")
+
+ channel_mode = headerdata[3] >> 6
+ print("channel_mode {}".format(channel_mode))
+
+ mode_extension = (headerdata[3] >> 4) & 0x3
+ print("mode_extension {}".format(mode_extension))
+
+ copyright = (headerdata[3] >> 3) & 0x1
+ if copyright:
+ print("With copyright")
+ else:
+ print("Without copyright")
+
+ original = (headerdata[3] >> 2) & 0x1
+ if original:
+ print("With original")
+ else:
+ print("Without original")
+
+ emphasis = headerdata[3] & 0x3
+ print("emphasis {}".format(emphasis))
+
+
+
+fd = open(sys.argv[1], "rb")
+analyse(fd)
diff --git a/rdsparse/decoder_impl.cc b/rdsparse/decoder_impl.cc
index 2bfa5a4..625a520 100644
--- a/rdsparse/decoder_impl.cc
+++ b/rdsparse/decoder_impl.cc
@@ -101,14 +101,24 @@ int decoder_impl::work (int noutput_items,
lastseen_offset=j;
lastseen_offset_counter=bit_counter;
presync=true;
+ lout << "@@@@@ presync" << std::endl;
}
else {
bit_distance=bit_counter-lastseen_offset_counter;
- if (offset_pos[lastseen_offset]>=offset_pos[j])
+ if (offset_pos[lastseen_offset]>=offset_pos[j]) {
block_distance=offset_pos[j]+4-offset_pos[lastseen_offset];
- else
+ }
+ else {
block_distance=offset_pos[j]-offset_pos[lastseen_offset];
- if ((block_distance*26)!=bit_distance) presync=false;
+ }
+
+ if ((block_distance*26)!=bit_distance) {
+ presync=false;
+ lout << "@@@@@ presync lost " << j << " " <<
+ block_distance*26 << " " <<
+ bit_distance << " " <<
+ std::endl;
+ }
else {
lout << "@@@@@ Sync State Detected" << std::endl;
enter_sync(j);
@@ -148,6 +158,11 @@ int decoder_impl::work (int noutput_items,
else {
wrong_blocks_counter++;
good_block=false;
+ lout << "@@@@@ CRC " <<
+ std::hex << std::setfill('0') << std::setw(4) <<
+ block_received_crc << " " <<
+ std::hex << std::setfill('0') << std::setw(4) <<
+ block_calculated_crc << std::dec << std::endl;
}
}
/* done checking CRC */
diff --git a/test.ini b/test.ini
index d6673b0..9e16aa0 100644
--- a/test.ini
+++ b/test.ini
@@ -1,7 +1,7 @@
; Sample configuration file for CRC-DABMOD
[remotecontrol]
-telnet=1
+telnet=0
telnetport=2121
[log]
@@ -11,12 +11,13 @@ filename=/dev/stderr
[input]
transport=file
-;source=/home/bram/dab/mmbtools-aux/eti/csp.eti
-source=/dev/stdin
+source=/home/bram/dab/mmbtools-aux/eti/funk2.100.eti
+;source=/dev/stdin
+loop=0
;transport=zeromq
-;source=tcp://localhost:8080
-loop=0
+;source=tcp://localhost:9100
+;max_frames_queued=400
[modulator]
; Gain mode: 0=FIX, 1=MAX, 2=VAR
@@ -24,7 +25,7 @@ gainmode=2
; Transmission mode
; If not defined, take the mode from ETI
-mode=1
+;mode=0
; Set to 0 to disable CicEqualiser
dac_clk_rate=0
@@ -32,25 +33,30 @@ dac_clk_rate=0
digital_gain=1.0
; Output sample rate
-rate=8000000
+rate=2048000
[firfilter]
-enabled=1
+enabled=0
filtertapsfile=filter/simplefiltertaps.txt
[output]
; choose output: possible values: uhd, file
output=file
+[zmqoutput]
+listen=tcp://*:9200
+socket_type=rep
+
[fileoutput]
-filename=/dev/stdout
+filename=ofdm.iq
+;filename=/dev/null
[uhdoutput]
;frequency=234208000
channel=13C
; For the B200
-master_clock_rate=32000000
+master_clock_rate=32768000
type=b200
txgain=35
@@ -73,7 +79,4 @@ behaviour_refclk_lock_lost=crash
synchronous=0
; choose between fixed and dynamic offset definition
-management=dynamic
-
-fixedoffset=0.002
-dynamicoffsetfile=modulatoroffset
+offset=0.002
diff --git a/zmq-simul.mux b/zmq-simul.mux
index 5689f31..6a599dc 100644
--- a/zmq-simul.mux
+++ b/zmq-simul.mux
@@ -8,9 +8,11 @@ general {
; The statsserver for extracting statistics
statsserverport 12720
- syslog false
+ syslog true
writescca false
tist true
+
+ new_fig_carousel true
}
remotecontrol {
@@ -29,6 +31,26 @@ ensemble {
international-table 1
label "TuxMux"
shortlabel "Tux"
+
+ ; Announcement settings for FIG0/19
+ announcements {
+ alarm {
+ cluster 0xFF
+ flags {
+ Alarm true
+ }
+
+ subchannel sub-fb
+ }
+ test_announcement {
+ cluster 1
+ flags {
+ Traffic true
+ }
+
+ subchannel sub-fb
+ }
+ }
}
services {
@@ -39,11 +61,23 @@ services {
language 0
id 0x4060
; also supports id
+
+ announcements {
+ Traffic true
+ Alarm true
+ clusters "1,255"
+ }
}
srv-label {
label "label"
id 0x4040
; also supports id
+
+ announcements {
+ Traffic true
+ Alarm true
+ clusters "1,255"
+ }
}
}
@@ -54,10 +88,11 @@ subchannels {
sub-fb {
type dabplus
; use ZeroMQ:
- inputfile "tcp://*:9001"
+ ;inputfile "tcp://*:9001"
+ inputfile "./stream-0.msc"
zmq-buffer 40
zmq-prebuffering 20
- bitrate 80
+ bitrate 128
id 24
protection 3
@@ -68,13 +103,21 @@ subchannels {
}
sub-label {
type audio
- inputfile "tcp://*:9002"
+ inputfile "/home/bram/dab/mmbtools-aux/fip-j-ok.mp2"
+ ;inputfile "tcp://*:9002"
zmq-buffer 40
zmq-prebuffering 20
bitrate 128
id 4
protection 3
}
+; sub-data {
+; type data
+; inputfile "udp://:9003"
+; bitrate 16
+; id 5
+; protection 3
+; }
}
; For now, each component links one service to one subchannel
@@ -91,7 +134,6 @@ components {
}
comp-label {
- label "label"
service srv-label
subchannel sub-label
}
@@ -100,10 +142,48 @@ components {
; A list of outputs, in the format
; unique-id "uri"
outputs {
- stdout "fifo:///dev/stdout?type=raw"
- zmq "zmq+tcp://*:9100"
+ ;stdout "fifo:///dev/stdout?type=raw"
+ ;thefile "file://./zmq-simul.eti?type=raw"
+ ;zmq "zmq+tcp://*:9100"
; This throttles muxing down to nominal rate
throttle "simul://"
+
+ ;net_udp "udp://shack.local:31000"
+ net_tcp "tcp://0.0.0.0:31000"
+
+ edi {
+ fec 0
+ chunk_len 200
+
+ destinations {
+ multicast {
+ destination "239.20.64.1"
+ ;source "192.168.2.10"
+ source "192.168.0.100"
+ sourceport 52321
+ ttl 1
+ }
+ ;unicast {
+ ;destination "192.168.2.2"
+ ;}
+ }
+
+ port 52002
+
+ ; EDI uses the UDP protocol
+
+ ; Enable the PFT subsystem. If false, AFPackets are sent.
+ enable_pft true
+
+ ; Save the packets sent over ethernet to the file ./edi.debug
+ dump false
+
+ ; show more debugging info
+ verbose false
+
+ ; optional: what kind of alignment to do in the tagpacket
+ tagpacket_alignment 16
+ }
}