コード例 #1
0
ファイル: compand.c プロジェクト: Amalerd/SoxPlayer
static int flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf,
                    size_t *isamp, size_t *osamp)
{
  priv_t * l = (priv_t *) effp->priv;
  int len =  (*isamp > *osamp) ? *osamp : *isamp;
  int filechans = effp->out_signal.channels;
  int idone,odone;

  for (idone = 0,odone = 0; idone < len; ibuf += filechans) {
    int chan;

    /* Maintain the volume fields by simulating a leaky pump circuit */
    for (chan = 0; chan < filechans; ++chan) {
      if (l->expectedChannels == 1 && filechans > 1) {
        /* User is expecting same compander for all channels */
        int i;
        double maxsamp = 0.0;
        for (i = 0; i < filechans; ++i) {
          double rect = fabs((double)ibuf[i]);
          if (rect > maxsamp) maxsamp = rect;
        }
        doVolume(&l->channels[0].volume, maxsamp, l, 0);
        break;
      } else
        doVolume(&l->channels[chan].volume, fabs((double)ibuf[chan]), l, chan);
    }

    /* Volume memory is updated: perform compand */
    for (chan = 0; chan < filechans; ++chan) {
      int ch = l->expectedChannels > 1 ? chan : 0;
      double level_in_lin = l->channels[ch].volume;
      double level_out_lin = lsx_compandt(&l->transfer_fn, level_in_lin);
      double checkbuf;

      if (l->delay_buf_size <= 0) {
        checkbuf = ibuf[chan] * level_out_lin;
        SOX_SAMPLE_CLIP_COUNT(checkbuf, effp->clips);
        obuf[odone++] = checkbuf;
        idone++;
      } else {
        if (l->delay_buf_cnt >= l->delay_buf_size) {
          l->delay_buf_full=1; /* delay buffer is now definitely full */
          checkbuf = l->delay_buf[l->delay_buf_index] * level_out_lin;
          SOX_SAMPLE_CLIP_COUNT(checkbuf, effp->clips);
          obuf[odone] = checkbuf;
          odone++;
          idone++;
        } else {
          l->delay_buf_cnt++;
          idone++; /* no "odone++" because we did not fill obuf[...] */
        }
        l->delay_buf[l->delay_buf_index++] = ibuf[chan];
        l->delay_buf_index %= l->delay_buf_size;
      }
    }
  }

  *isamp = idone; *osamp = odone;
  return (SOX_SUCCESS);
}
コード例 #2
0
ファイル: mcompand.c プロジェクト: DeathOfMe/sox
static int sox_mcompand_flow_1(sox_effect_t * effp, priv_t * c, comp_band_t * l, const sox_sample_t *ibuf, sox_sample_t *obuf, size_t len, size_t filechans)
{
  size_t idone, odone;

  for (idone = 0, odone = 0; idone < len; ibuf += filechans) {
    size_t chan;

    /* Maintain the volume fields by simulating a leaky pump circuit */

    if (l->expectedChannels == 1 && filechans > 1) {
      /* User is expecting same compander for all channels */
      double maxsamp = 0.0;
      for (chan = 0; chan < filechans; ++chan) {
        double rect = fabs((double)ibuf[chan]);
        if (rect > maxsamp)
          maxsamp = rect;
      }
      doVolume(&l->volume[0], maxsamp, l, (size_t) 0);
    } else {
      for (chan = 0; chan < filechans; ++chan)
        doVolume(&l->volume[chan], fabs((double)ibuf[chan]), l, chan);
    }

    /* Volume memory is updated: perform compand */
    for (chan = 0; chan < filechans; ++chan) {
      int ch = l->expectedChannels > 1 ? chan : 0;
      double level_in_lin = l->volume[ch];
      double level_out_lin = lsx_compandt(&l->transfer_fn, level_in_lin);
      double checkbuf;

      if (c->delay_buf_size <= 0) {
        checkbuf = ibuf[chan] * level_out_lin;
        SOX_SAMPLE_CLIP_COUNT(checkbuf, effp->clips);
        obuf[odone++] = checkbuf;
        idone++;
      } else {
        /* FIXME: note that this lookahead algorithm is really lame:
           the response to a peak is released before the peak
           arrives. */

        /* because volume application delays differ band to band, but
           total delay doesn't, the volume is applied in an iteration
           preceding that in which the sample goes to obuf, except in
           the band(s) with the longest vol app delay.

           the offset between delay_buf_ptr and the sample to apply
           vol to, is a constant equal to the difference between this
           band's delay and the longest delay of all the bands. */

        if (l->delay_buf_cnt >= l->delay_size) {
          checkbuf = l->delay_buf[(l->delay_buf_ptr + c->delay_buf_size - l->delay_size)%c->delay_buf_size] * level_out_lin;
          SOX_SAMPLE_CLIP_COUNT(checkbuf, effp->clips);
          l->delay_buf[(l->delay_buf_ptr + c->delay_buf_size - l->delay_size)%c->delay_buf_size] = checkbuf;
        }
        if (l->delay_buf_cnt >= c->delay_buf_size) {
          obuf[odone] = l->delay_buf[l->delay_buf_ptr];
          odone++;
          idone++;
        } else {
          l->delay_buf_cnt++;
          idone++; /* no "odone++" because we did not fill obuf[...] */
        }
        l->delay_buf[l->delay_buf_ptr++] = ibuf[chan];
        l->delay_buf_ptr %= c->delay_buf_size;
      }
    }
  }

  if (idone != odone || idone != len) {
    /* Emergency brake - will lead to memory corruption otherwise since we
       cannot report back to flow() how many samples were consumed/emitted.
       Additionally, flow() doesn't know how to handle diverging
       sub-compander delays. */
    lsx_fail("Using a compander delay within mcompand is currently not supported");
    exit(1);
    /* FIXME */
  }

  return (SOX_SUCCESS);
}
コード例 #3
0
ファイル: mcompand.c プロジェクト: Amalerd/SoxPlayer
static int sox_mcompand_flow_1(sox_effect_t * effp, priv_t * c, comp_band_t * l, const sox_sample_t *ibuf, sox_sample_t *obuf, size_t len, size_t filechans)
{
  size_t done, chan;

  for (done = 0; done < len; ibuf += filechans) {

    /* Maintain the volume fields by simulating a leaky pump circuit */

    if (l->expectedChannels == 1 && filechans > 1) {
      /* User is expecting same compander for all channels */
      double maxsamp = 0.0;
      for (chan = 0; chan < filechans; ++chan) {
        double rect = fabs((double)ibuf[chan]);
        if (rect > maxsamp)
          maxsamp = rect;
      }
      doVolume(&l->volume[0], maxsamp, l, (size_t) 0);
    } else {
      for (chan = 0; chan < filechans; ++chan)
        doVolume(&l->volume[chan], fabs((double)ibuf[chan]), l, chan);
    }

    /* Volume memory is updated: perform compand */
    for (chan = 0; chan < filechans; ++chan) {
      int ch = l->expectedChannels > 1 ? chan : 0;
      double level_in_lin = l->volume[ch];
      double level_out_lin = lsx_compandt(&l->transfer_fn, level_in_lin);
      double checkbuf;

      if (c->delay_buf_size <= 0) {
        checkbuf = ibuf[chan] * level_out_lin;
        SOX_SAMPLE_CLIP_COUNT(checkbuf, effp->clips);
        obuf[done++] = checkbuf;

      } else {
        /* FIXME: note that this lookahead algorithm is really lame:
           the response to a peak is released before the peak
           arrives. */

        /* because volume application delays differ band to band, but
           total delay doesn't, the volume is applied in an iteration
           preceding that in which the sample goes to obuf, except in
           the band(s) with the longest vol app delay.

           the offset between delay_buf_ptr and the sample to apply
           vol to, is a constant equal to the difference between this
           band's delay and the longest delay of all the bands. */

        if (l->delay_buf_cnt >= l->delay_size) {
          checkbuf = l->delay_buf[(l->delay_buf_ptr + c->delay_buf_size - l->delay_size)%c->delay_buf_size] * level_out_lin;
          SOX_SAMPLE_CLIP_COUNT(checkbuf, effp->clips);
          l->delay_buf[(l->delay_buf_ptr + c->delay_buf_size - l->delay_size)%c->delay_buf_size] = checkbuf;
        }
        if (l->delay_buf_cnt >= c->delay_buf_size)
          obuf[done++] = l->delay_buf[l->delay_buf_ptr];
        else
          l->delay_buf_cnt++;
        l->delay_buf[l->delay_buf_ptr++] = ibuf[chan];
        l->delay_buf_ptr %= c->delay_buf_size;
      }
    }
  }

  return (SOX_SUCCESS);
}
コード例 #4
0
/*
 * Processed signed long samples from ibuf to obuf.
 * Return number of samples processed.
 */
int st_compand_flow(eff_t effp, st_sample_t *ibuf, st_sample_t *obuf,
                    st_size_t *isamp, st_size_t *osamp)
{
    compand_t l = (compand_t) effp->priv;
    int len =  (*isamp > *osamp) ? *osamp : *isamp;
    int filechans = effp->outinfo.channels;
    int idone,odone;
    int64_t checkbuf; //if st_sample_t of type int32_t

    for (idone = 0,odone = 0; idone < len; ibuf += filechans) {
        int chan;

        /* Maintain the volume fields by simulating a leaky pump circuit */

        for (chan = 0; chan < filechans; ++chan) {
            if (l->expectedChannels == 1 && filechans > 1) {
                /* User is expecting same compander for all channels */
                int i;
                double maxsamp = 0.0;
                for (i = 0; i < filechans; ++i) {
                    double rect = fabs(ibuf[i]);
                    if (rect > maxsamp) maxsamp = rect;
                }
                doVolume(&l->volume[0], maxsamp, l, 0);
                break;
            } else
                doVolume(&l->volume[chan], fabs(ibuf[chan]), l, chan);
        }

        /* Volume memory is updated: perform compand */

        for (chan = 0; chan < filechans; ++chan) {
            double v = l->expectedChannels > 1 ?
                       l->volume[chan] : l->volume[0];
            double outv;
            int piece;

            for (piece = 1 /* yes, 1 */;
                    piece < l->transferPoints;
                    ++piece)
                if (v >= l->transferIns[piece - 1] &&
                        v < l->transferIns[piece])
                    break;

            outv = l->transferOuts[piece-1] +
                   (l->transferOuts[piece] - l->transferOuts[piece-1]) *
                   (v - l->transferIns[piece-1]) /
                   (l->transferIns[piece] - l->transferIns[piece-1]);

            if (l->delay_buf_size <= 0)
            {
                checkbuf = ibuf[chan]*(outv/v)*l->outgain;
                if(checkbuf > ST_SAMPLE_MAX)
                    obuf[odone] = ST_SAMPLE_MAX;
                else if(checkbuf < ST_SAMPLE_MIN)
                    obuf[odone] = ST_SAMPLE_MIN;
                else
                    obuf[odone] = checkbuf;

                idone++;
                odone++;
            }
            else
            {
                if (l->delay_buf_cnt >= l->delay_buf_size)
                {
                    l->delay_buf_full=1; //delay buffer is now definetly full
                    checkbuf = l->delay_buf[l->delay_buf_ptr]*(outv/v)*l->outgain;
                    if(checkbuf > ST_SAMPLE_MAX)
                        obuf[odone] = ST_SAMPLE_MAX;
                    else if(checkbuf < ST_SAMPLE_MIN)
                        obuf[odone] = ST_SAMPLE_MIN;
                    else
                        obuf[odone] = checkbuf;

                    odone++;
                    idone++;
                }
                else
                {
                    l->delay_buf_cnt++;
                    idone++; //no "odone++" because we did not fill obuf[...]
                }
                l->delay_buf[l->delay_buf_ptr++] = ibuf[chan];
                l->delay_buf_ptr %= l->delay_buf_size;
            }
        }
    }

    *isamp = idone;
    *osamp = odone;
    return (ST_SUCCESS);
}
static int st_mcompand_flow_1(compand_t c, comp_band_t l, st_sample_t *ibuf, st_sample_t *obuf, int len, int filechans)
{
  int done, chan;

  for (done = 0; done < len; ibuf += filechans) {

    /* Maintain the volume fields by simulating a leaky pump circuit */

    if (l->expectedChannels == 1 && filechans > 1) {
      /* User is expecting same compander for all channels */
      double maxsamp = 0.0;
      for (chan = 0; chan < filechans; ++chan) {
        double rect = fabs(ibuf[chan]);
        if (rect > maxsamp)
          maxsamp = rect;
      }
      doVolume(&l->volume[0], maxsamp, l, 0);
    } else {
      for (chan = 0; chan < filechans; ++chan)
        doVolume(&l->volume[chan], fabs(ibuf[chan]), l, chan);
    }

    /* Volume memory is updated: perform compand */

    for (chan = 0; chan < filechans; ++chan) {
      double v = l->expectedChannels > 1 ? 
        l->volume[chan] : l->volume[0];
      double outv;
      int piece;

      for (piece = 1 /* yes, 1 */;
           piece < l->transferPoints;
           ++piece)
        if (v >= l->transferIns[piece - 1] &&
            v < l->transferIns[piece])
          break;
      
      outv = l->transferOuts[piece-1] +
        (l->transferOuts[piece] - l->transferOuts[piece-1]) *
        (v - l->transferIns[piece-1]) /
        (l->transferIns[piece] - l->transferIns[piece-1]);

      if (c->delay_buf_size <= 0)
        obuf[done++] = ibuf[chan]*(outv/v)*l->outgain;
      else {


        /* note that this lookahead algorithm is really lame.  the response to a peak is released before the peak arrives.  fix! */

        /* because volume application delays differ band to band, but
           total delay doesn't, the volume is applied in an iteration
           preceding that in which the sample goes to obuf, except in
           the band(s) with the longest vol app delay.

           the offset between delay_buf_ptr and the sample to apply
           vol to, is a constant equal to the difference between this
           band's delay and the longest delay of all the bands. */

        if (l->delay_buf_cnt >= l->delay_size)
          l->delay_buf[(l->delay_buf_ptr + c->delay_buf_size - l->delay_size)%c->delay_buf_size] *= (outv/v)*l->outgain;
        if (l->delay_buf_cnt >= c->delay_buf_size)
          obuf[done++] = l->delay_buf[l->delay_buf_ptr];
        else
          l->delay_buf_cnt++;
        l->delay_buf[l->delay_buf_ptr++] = ibuf[chan];
        l->delay_buf_ptr %= c->delay_buf_size;
      }
    }
  }

  return (ST_SUCCESS);
}