summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Pöschel <github@basicmaster.de>2015-04-12 19:44:05 +0200
committerStefan Pöschel <github@basicmaster.de>2015-04-12 19:44:05 +0200
commit9c36b2ab9080112b6a3cab9261f32190403b15c8 (patch)
tree04361873724c19579504f0e020f5084e471569e8
parent861ffe7f7376ff3df2c7a7421b2e84a57c6a2b83 (diff)
downloadODR-AudioEnc-9c36b2ab9080112b6a3cab9261f32190403b15c8.tar.gz
ODR-AudioEnc-9c36b2ab9080112b6a3cab9261f32190403b15c8.tar.bz2
ODR-AudioEnc-9c36b2ab9080112b6a3cab9261f32190403b15c8.zip
DLS refactoring
This should fix DLS at lower PAD sizes, where the DLS data group of a DL segment is distributed over more than one PAD.
-rw-r--r--src/mot-encoder.cpp331
1 files changed, 102 insertions, 229 deletions
diff --git a/src/mot-encoder.cpp b/src/mot-encoder.cpp
index f2115c0..e53001b 100644
--- a/src/mot-encoder.cpp
+++ b/src/mot-encoder.cpp
@@ -222,19 +222,26 @@ void writeMotPAD(int output_fd,
unsigned short int mscdgsize,
unsigned short int padlen);
-void create_dls_datagroup(char* text, int padlen, uint8_t charset);
+void create_dls_pads(const char* text, const int padlen, const uint8_t charset);
void writeDLS(int output_fd, const char* dls_file, int padlen, uint8_t charset);
int get_xpadlengthmask(int padlen);
+size_t get_xpadlength(int mask);
#define ALLOWED_PADLEN "23, 26, 34, 42, 58"
-// The toggle info for the DLS
-static uint8_t dls_toggle = 0;
-char dlstext_prev[MAXDLS + 1];
-// The DLS data groups
-std::deque<std::vector<uint8_t> > dlsdg;
+// DLS related
+#define DLS_SEG_LEN_PREFIX 2
+#define DLS_SEG_LEN_CHAR_MAX 16
+#define DLS_SEG_LEN_CRC 2
+#define DLS_SEG_LEN_MAX (DLS_SEG_LEN_PREFIX + DLS_SEG_LEN_CHAR_MAX + DLS_SEG_LEN_CRC)
+
+typedef std::vector<uint8_t> pad_t;
+static std::deque<pad_t> dls_pads;
+static bool dls_toggle = false;
+static char dlstext_prev[MAXDLS + 1];
+
static int verbose = 0;
@@ -900,275 +907,136 @@ void writeDLS(int output_fd, const char* dls_file, int padlen, uint8_t charset)
}
// (Re)Create data groups (and thereby toggle the toggle bit) only on (first call or) new text
- dlstext_new = dlsdg.empty() || strcmp(dlstext, dlstext_prev);
+ dlstext_new = dls_pads.empty() || strcmp(dlstext, dlstext_prev);
if (verbose) {
fprintf(stderr, "mot-encoder writing %s DLS text \"%s\"\n", dlstext_new ? "new" : "old", dlstext);
}
if (dlstext_new) {
- create_dls_datagroup(dlstext, padlen, charset);
+ create_dls_pads(dlstext, padlen, charset);
strcpy(dlstext_prev, dlstext);
}
- for (i = 0; i < dlsdg.size(); i++) {
- size_t dummy = write(output_fd, &dlsdg[i].front(), dlsdg[i].size());
+ for (i = 0; i < dls_pads.size(); i++) {
+ size_t dummy = write(output_fd, &dls_pads[i].front(), dls_pads[i].size());
}
}
-void create_dls_datagroup(char* text, int padlen, uint8_t charset)
-{
- int numdg = 0; // Number of data groups
- int numseg; // Number of DSL segments
- int lastseglen; // Length of the last segment
- int xpadlengthmask;
- int i, j, k, z, idx_start_crc, idx_stop_crc;
- uint16_t dlscrc;
-
- if (dls_toggle == 0)
- dls_toggle = 1;
- else
- dls_toggle = 0;
- numseg = strlen(text) / 16;
- lastseglen = strlen(text) % 16;
- if (padlen-9 >= 16) {
- if (lastseglen > 0) {
- numseg++; // The last incomplete segment
- }
+int dls_count(const char* text) {
+ size_t text_len = strlen(text);
+ return text_len / DLS_SEG_LEN_CHAR_MAX + (text_len % DLS_SEG_LEN_CHAR_MAX ? 1 : 0);
+}
- // The PAD can contain the full segmnet and overhead (9 bytes)
- numdg = numseg;
- }
- else {
- // Each 16 char segment span over 2 dg
- numdg = numseg * 2;
+size_t dls_get(const char* text, const uint8_t charset, const unsigned int seg_index, uint8_t *seg_data) {
+ int seg_count = dls_count(text);
+ if (seg_index >= seg_count)
+ return 0;
- if (lastseglen > 0) {
- numseg++; // The last incomplete segment
+ bool first_seg = seg_index == 0;
+ bool last_seg = seg_index == seg_count - 1;
- if (lastseglen <= padlen-9) {
- numdg += 1;
- }
- else {
- numdg += 2;
- }
- }
- }
+ const char *seg_text_start = text + seg_index * DLS_SEG_LEN_CHAR_MAX;
+ size_t seg_text_len = strnlen(seg_text_start, DLS_SEG_LEN_CHAR_MAX);
+ size_t seg_len = DLS_SEG_LEN_PREFIX + seg_text_len + DLS_SEG_LEN_CRC;
-#if DEBUG
- fprintf(stderr, "PAD Length: %d\n", padlen);
- fprintf(stderr, "DLS text: %s\n", text);
- fprintf(stderr, "Number of DLS segments: %d\n", numseg);
- fprintf(stderr, "Number of DLS data groups: %d\n", numdg);
-#endif
- xpadlengthmask = get_xpadlengthmask(padlen);
+ // prefix: toggle? + first seg? + last seg? + (seg len - 1)
+ seg_data[0] =
+ (dls_toggle ? (1 << 7) : 0) +
+ (first_seg ? (1 << 6) : 0) +
+ (last_seg ? (1 << 5) : 0) +
+ (seg_text_len - 1);
- dlsdg.resize(0);
- dlsdg.resize(numdg);
+ // prefix: charset / seg index
+ seg_data[1] = (first_seg ? charset : seg_index) << 4;
- i = 0;
- for (z=0; z < numseg; z++) {
- char* curseg;
- int curseglen;
- uint8_t firstseg, lastseg;
+ // character field
+ memcpy(seg_data + DLS_SEG_LEN_PREFIX, seg_text_start, seg_text_len);
- curseg = &text[z * 16];
+ // CRC
+ uint16_t crc = 0xFFFF;
+ for (int i = 0; i < seg_len - DLS_SEG_LEN_CRC; i++)
+ crc = update_crc_ccitt(crc, seg_data[i]);
+ crc = ~crc;
#if DEBUG
- fprintf(stderr, "Segment number %d\n", z+1);
+ fprintf(stderr, "crc=%04x ~crc=%04x\n", ~crc, crc);
#endif
+ seg_data[seg_len - 2] = (crc & 0xFF00) >> 8; // HI CRC
+ seg_data[seg_len - 1] = crc & 0x00FF; // LO CRC
- if (z == 0) { // First segment
- firstseg = 1;
- }
- else {
- firstseg = 0;
- }
-
- if (z == numseg-1) { //Last segment
- if (lastseglen != 0) {
- curseglen = lastseglen;
- }
- else {
- curseglen = 16;
- }
- lastseg = 1;
- }
- else {
- curseglen = 16;
- lastseg = 0;
- }
-
- if (curseglen <= padlen-9) { // Segment is composed of 1 data group
- dlsdg[i].resize(padlen);
-
- // FF-PAD Byte L (CI=1)
- dlsdg[i][padlen-1]=0x02;
-
- // FF-PAD Byte L-1 (Variable size X_PAD)
- dlsdg[i][padlen-2]=0x20;
-
- // CI => data length = 12 (011) - Application Type=2
- // (DLS - start of X-PAD data group)
- dlsdg[i][padlen-3]=(xpadlengthmask<<5) | 0x02;
-
- // End of CI list
- dlsdg[i][padlen-4]=0x00;
-
- // DLS Prefix (T=1,Only one segment,segment length-1)
- dlsdg[i][padlen-5]=((dls_toggle*8+firstseg*4+lastseg*2+0)<<4) |
- (curseglen-1);
-
- if (firstseg==1) {
- // DLS Prefix (Charset standard)
- dlsdg[i][padlen-6] = charset << 4;
- }
- else {
- // DLS SegNum
- dlsdg[i][padlen-6]=z<<4;
- }
-
- // CRC start from prefix
- idx_start_crc = padlen-5;
-
- // DLS text
- for (j = 0; j < curseglen; j++) {
- dlsdg[i][padlen-7-j] = curseg[j];
- }
-
- idx_stop_crc = padlen - 7 - curseglen+1;
-
- dlscrc = 0xffff;
- for (j = idx_start_crc; j >= idx_stop_crc; j--) {
- dlscrc = update_crc_ccitt(dlscrc, dlsdg[i][j]);
- }
-
- dlscrc = ~dlscrc;
#if DEBUG
- fprintf(stderr, "crc=%x ~crc=%x\n", ~dlscrc, dlscrc);
+ fprintf(stderr, "DL segment:");
+ for (int i = 0; i < seg_len; i++)
+ fprintf(stderr, " %02x", dls_seg[i]);
+ fprintf(stderr, "\n");
#endif
+ return seg_len;
+}
- dlsdg[i][padlen-7-curseglen] = (dlscrc & 0xFF00) >> 8; // HI CRC
- dlsdg[i][padlen-7-curseglen-1] = dlscrc & 0x00FF; // LO CRC
- // NULL PADDING
- for (j = padlen-7-curseglen-2; j >= 0; j--) {
- dlsdg[i][j]=0x00;
- }
+void create_dls_pads(const char* text, const int padlen, const uint8_t charset) {
+ uint8_t seg_data[DLS_SEG_LEN_MAX];
+ int xpadlengthmask = get_xpadlengthmask(padlen);
+ dls_pads.clear();
+ dls_toggle = !dls_toggle; // indicate changed text
+
+ // process all DL segments
+ int seg_count = dls_count(text);
+ for (int seg_index = 0; seg_index < seg_count; seg_index++) {
#if DEBUG
- fprintf(stderr, "Data group: ");
- for (j = 0; j < padlen; j++)
- fprintf(stderr, "%x ", dlsdg[i][j]);
- fprintf(stderr, "\n");
+ fprintf(stderr, "Segment number %d\n", seg_index + 1);
#endif
- i++;
-
- }
- else { // Segment is composed of 2 data groups
-
- // FIRST DG (NO CRC)
- dlscrc = 0xffff;
-
- dlsdg[i].resize(padlen);
-
- // FF-PAD Byte L (CI=1)
- dlsdg[i][padlen-1]=0x02;
-
- // FF-PAD Byte L-1 (Variable size X_PAD)
- dlsdg[i][padlen-2]=0x20;
-
- // CI => data length = 12 (011) - Application Type=2
- // (DLS - start of X-PAD data group)
- dlsdg[i][padlen-3]=(xpadlengthmask<<5) | 0x02;
-
- // End of CI list
- dlsdg[i][padlen-4]=0x00;
-
- // DLS Prefix (T=1,Only one segment,segment length-1)
- dlsdg[i][padlen-5]=((dls_toggle*8+firstseg*4+lastseg*2+0)<<4) |
- (curseglen-1);
+ int seg_len = dls_get(text, charset, seg_index, seg_data);
+ // distribute the segment over one or more PADs
+ for (int seg_off = 0; seg_off < seg_len;) {
+ dls_pads.push_back(pad_t(padlen));
+ pad_t &pad = dls_pads.back();
+ int pad_off = padlen - 1;
- if (firstseg == 1) {
- // DLS Prefix (Charset standard)
- dlsdg[i][padlen-6] = charset << 4;
- }
- else {
- // DLS SegNum
- dlsdg[i][padlen-6]=(i-1)<<4;
- }
+ bool ci_needed = seg_off == 0; // CI needed only at first data group
+ int dg_len = ci_needed ? get_xpadlength(xpadlengthmask) : padlen - 2;
+ int dg_used = MIN(dg_len, seg_len - seg_off);
- dlscrc = update_crc_ccitt(dlscrc, dlsdg[i][padlen-5]);
- dlscrc = update_crc_ccitt(dlscrc, dlsdg[i][padlen-6]);
- // DLS text
- for (j=0; j < MIN(curseglen, padlen-7); j++) {
- dlsdg[i][padlen-7-j] = curseg[j];
- dlscrc = update_crc_ccitt(dlscrc, dlsdg[i][padlen-7-j]);
- }
- k = j;
+ // F-PAD Byte L (CI if needed)
+ pad[pad_off--] = ci_needed ? 0x02 : 0x00;
- // end of segment
- if (curseglen == padlen-8) {
- dlscrc = ~dlscrc;
- dlsdg[i][1] = (dlscrc & 0xFF00) >> 8; // HI CRC
- }
- else if (curseglen == padlen-7) {
- dlscrc = ~dlscrc;
- }
- dlsdg[i][0]=0x00;
+ // F-PAD Byte L-1 (variable size X-PAD)
+ pad[pad_off--] = 0x20;
-#if DEBUG
- fprintf(stderr, "crc=%x ~crc=%x\n", ~dlscrc, dlscrc);
+ if (ci_needed) {
+ // CI (app type 2 = DLS, start of X-PAD data group)
+ pad[pad_off--] = (xpadlengthmask << 5) | 0x02;
- fprintf(stderr, "First Data group: ");
- for (j = 0; j < padlen; j++) {
- fprintf(stderr, "%x ", dlsdg[i][j]);
+ // CI end marker
+ pad[pad_off--] = 0x00;
}
- fprintf(stderr,"\n");
-#endif
-
- // SECOND DG (NO CI, NO PREFIX)
- i++;
-
- dlsdg[i].resize(padlen);
- // FF-PAD Byte L (CI=0)
- dlsdg[i][padlen-1] = 0x00;
+ // segment (part)
+ for (int i = 0; i < dg_used; i++)
+ pad[pad_off--] = seg_data[seg_off + i];
- // FF-PAD Byte L-1 (Variable size X_PAD)
- dlsdg[i][padlen-2] = 0x20;
+ // NULL PADDING
+ std::fill_n(pad.begin(), pad_off + 1, 0x00);
- if (curseglen == padlen-8) {
- dlsdg[i][padlen-3] = dlscrc & 0x00FF; // LO CRC
- }
- else if (curseglen==padlen-7) {
- dlsdg[i][padlen-3] = (dlscrc & 0xFF00) >> 8; // HI CRC
- dlsdg[i][padlen-4] = dlscrc & 0x00FF; // LO CRC
- }
- else {
- // DLS text
- for (j = 0; j < curseglen-k; j++) {
- dlsdg[i][padlen-3-j] = curseg[k+j];
- dlscrc = update_crc_ccitt(dlscrc, dlsdg[i][padlen-3-j]);
- }
- dlscrc = ~dlscrc;
- dlsdg[i][padlen-3-curseglen+k] = (dlscrc & 0xFF00) >> 8; // HI CRC
- dlsdg[i][padlen-3-curseglen+k-1] = dlscrc & 0x00FF; // LO CRC
- }
#if DEBUG
- fprintf(stderr, "Second Data group: ");
- for (j = 0; j < padlen; j++) {
- fprintf(stderr, "%x ", dlsdg[i][j]);
- }
-
+ fprintf(stderr, "DLS data group:");
+ for (int i = 0; i < padlen; i++)
+ fprintf(stderr, " %02x", dg[i]);
fprintf(stderr, "\n");
- fprintf(stderr, "**** crc=%x ~crc=%x\n", ~dlscrc, dlscrc);
#endif
- i++;
+ seg_off += dg_used;
}
}
+#if DEBUG
+ fprintf(stderr, "PAD length: %d\n", padlen);
+ fprintf(stderr, "DLS text: %s\n", text);
+ fprintf(stderr, "Number of DL segments: %d\n", seg_count);
+ fprintf(stderr, "Number of DLS data groups: %zu\n", dls_pads.size());
+#endif
}
void writeMotPAD(int output_fd,
@@ -1282,6 +1150,11 @@ int get_xpadlengthmask(int padlen)
return xpadlengthmask;
}
+size_t get_xpadlength(int mask) {
+ size_t length[] = {4, 6, 8, 12, 16, 24, 32, 48};
+ return length[mask];
+}
+
int History::find(const fingerprint_t& fp) const
{
size_t i;