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); }
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); }
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); }
/* * 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); }