Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement the 32-bit version of RadwareSigcompress #8

Open
gipert opened this issue Jun 20, 2023 · 0 comments
Open

Implement the 32-bit version of RadwareSigcompress #8

gipert opened this issue Jun 20, 2023 · 0 comments
Assignees
Labels
compression Waveform Compression

Comments

@gipert
Copy link
Member

gipert commented Jun 20, 2023

We should rename RadwareSigcompress to RadwareSigcompress16 (or similar) and implement the 32-bit version, to compress presummed waveforms.

Here's the 32-bit version of the original C code from @radforddc (with more comments, to be added to our data format specs docs):

int compress_signal_32(int *sig_in, unsigned int *sig_out, int sig_len_in) {

  /* 32-bit version of compress_signal() for waveforms that are int32 values
     Assume ADC is actually a maximum of 20 bits, i.e. signed values between 
     0x7FFFF = 524287  and  0xfff8000 = -524288

     returned value = iso = number of ints stored in output stream *sig_out
     *sig_in = input waveform (uncompressed) of length sig_len_in samples
     *sig_out = output waveform (compressed) of length iso
  */

  int   i, j, max1, max2, min1, min2, ds, nb1, nb2;
  int   iso, nw, bp, dd1, dd2;
  unsigned int db[2];
  unsigned long *dd = (unsigned long *) db;
  static unsigned short mask[21] = {0, 1,3,7,15, 31,63,127,255,
                                    511,1023,2047,4095, 8191,16383,32767,65535,
                                    0x1ffff, 0x3ffff, 0x7ffff, 0xfffff};

  //static int len[17] = {4096, 2048,512,256,128, 128,128,128,128,
  //                      128,128,128,128, 48,48,48,48};
  /* ------------ do compression of signal ------------ */
  j = iso = bp = 0;

  sig_out[iso++] = sig_len_in;     // signal length
  while (j < sig_len_in) {         // j = starting index of section of signal to be compressed
    // find optimal method and length for compression of next section of signal 
    max1 = min1 = sig_in[j];
    max2 = -0x100000;
    min2 =  0xfffff;    // initialize to min and max expected values
    nb1 = nb2 = 2;      // number of bits needed for encoding each sample
    nw = 1;             // number of samples to encode in this segment
    for (i=j+1; i < sig_len_in && i < j+48; i++) { // FIXME; # 48 could be tuned better?
      if (max1 < sig_in[i]) max1 = sig_in[i];  // max and min of first 48 absolute values
      if (min1 > sig_in[i]) min1 = sig_in[i];
      ds = sig_in[i] - sig_in[i-1];
      if (max2 < ds) max2 = ds;                // max and min of first 48 difference values
      if (min2 > ds) min2 = ds;
      nw++;
    }
    if (max1-min1 <= max2-min2) { // use absolute ADC values
      nb2 = 99;
      while (max1 - min1 > mask[nb1]) nb1++;  // updated number of bits needed for encoding each sample
      //for (; i < sig_len_in && i < j+len[nb1]; i++) {
      for (; i < sig_len_in && i < j+128; i++) { // FIXME; # 128 could be tuned better?
        if (max1 < sig_in[i]) max1 = sig_in[i];
        dd1 = max1 - min1;
        if (min1 > sig_in[i]) dd1 = max1 - sig_in[i];   // updated range of values to encode
        if (dd1 > mask[nb1]) break;                     // uh-oh, would need to add another bit for encoding
        if (min1 > sig_in[i]) min1 = sig_in[i];
        nw++;                                           // updated number of samples to encode in this segment
      }
    } else {                      // use differences/derivative of ADC values
      nb1 = 99;
      while (max2 - min2 > mask[nb2]) nb2++;  // updated number of bits needed for encoding each sample
      //for (; i < sig_len_in && i < j+len[nb1]; i++) {
      for (; i < sig_len_in && i < j+128; i++) { // FIXME; # 128 could be tuned better?
        ds = sig_in[i] - sig_in[i-1];
        if (max2 < ds) max2 = ds;
        dd2 = max2 - min2;
        if (min2 > ds) dd2 = max2 - ds;   // updated range of values to encode
        if (dd2 > mask[nb2]) break;       // uh-oh, would need to add another bit for encoding
        if (min2 > ds) min2 = ds;
        nw++;                             // updated number of samples to encode in this segment
      }
    }

    if (bp > 0) iso++;    // increment iso if we have a partial short already used in the oputput stream
    /*  -----  do actual compression  -----  */
    sig_out[iso++] = nw;  // compressed signal data, first byte = # samples
    bp = 0;               // bit pointer into output stream
    if (nb1 <= nb2) {
      /*  -----  encode absolute values  -----  */
      sig_out[iso++] = nb1;                    // # bits used for encoding
      sig_out[iso++] = (unsigned short) min1;  // min value used for encoding
      for (i = iso; i <= iso + nw*nb1/16; i++) sig_out[i] = 0;  // initialze output stream to 0
      for (i = j; i < j + nw; i++) {
        dd[0] = sig_in[i] - min1;              // value to encode
        dd[0] = dd[0] << (32 - bp - nb1);      // pack nb1 bits
        sig_out[iso] |= db[1];
        bp += nb1;
        while (bp > 31) {
          sig_out[++iso] = db[0];
          bp -= 32;
        }
      }

    } else {
      /*  -----  encode derivative / difference values  -----  */
      sig_out[iso++] = nb2 + 32;  // # bits used for encoding, plus flag indicating derivatives
      sig_out[iso++] = (unsigned short) sig_in[j];  // starting signal value
      sig_out[iso++] = (unsigned short) min2;       // min value used for encoding
      for (i = iso; i <= iso + nw*nb2/16; i++) sig_out[i] = 0;  // initialze output stream to 0
      for (i = j+1; i < j + nw; i++) {
        dd[0] = sig_in[i] - sig_in[i-1] - min2;     // value to encode
        dd[0]= dd[0] << (32 - bp - nb2);            // pack nb2 bits
        sig_out[iso] |= db[1];
        bp += nb2;
        while (bp > 31) {
          sig_out[++iso] = db[0];
          bp -= 32;
        }
      }
    }
    j += nw;
  }

  if (bp > 0) iso++;    // increment iso if we have a partial short left over in the oputput stream
  if (iso%2)  iso++;    // make sure iso is even for 4-byte padding
  return iso;           // return number of shorts in compressed signal data

}
@gipert gipert added the compression Waveform Compression label Jun 20, 2023
@gipert gipert self-assigned this Oct 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compression Waveform Compression
Projects
None yet
Development

No branches or pull requests

1 participant