| /* libSoX file format: CVSD (see cvsd.c) (c) 2007-8 SoX contributors |
| * |
| * This library is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU Lesser General Public License as published by |
| * the Free Software Foundation; either version 2.1 of the License, or (at |
| * your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, but |
| * WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser |
| * General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public License |
| * along with this library; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include "third_party/sox/src/src/cvsd.h" |
| |
| LSX_FORMAT_HANDLER(cvsd) |
| { |
| static char const * const names[] = {"cvsd", "cvs", NULL}; |
| static unsigned const write_encodings[] = {SOX_ENCODING_CVSD, 1, 0, 0}; |
| static sox_format_handler_t const handler = {SOX_LIB_VERSION_CODE, |
| "Headerless MIL Std 188 113 Continuously Variable Slope Delta modulation", |
| names, SOX_FILE_MONO, |
| lsx_cvsdstartread, lsx_cvsdread, lsx_cvsdstopread, |
| lsx_cvsdstartwrite, lsx_cvsdwrite, lsx_cvsdstopwrite, |
| lsx_rawseek, write_encodings, NULL, sizeof(cvsd_priv_t) |
| }; |
| return &handler; |
| } |
| |
| /* libSoX file format: CVU (c) 2008 robs@users.sourceforge.net |
| * Unfiltered, therefore, on decode, use with either filter -4k or rate 8k */ |
| |
| typedef struct { |
| double sample, step, step_mult, step_add; |
| unsigned last_n_bits; |
| unsigned char byte; |
| off_t bit_count; |
| } priv_t; |
| |
| static int start(sox_format_t * ft) |
| { |
| priv_t *p = (priv_t *) ft->priv; |
| |
| ft->signal.channels = 1; |
| lsx_rawstart(ft, sox_true, sox_false, sox_true, SOX_ENCODING_CVSD, 1); |
| p->last_n_bits = 5; /* 101 */ |
| p->step_mult = exp((-1 / .005 / ft->signal.rate)); |
| p->step_add = (1 - p->step_mult) * (.1 * SOX_SAMPLE_MAX); |
| lsx_debug("step_mult=%g step_add=%f", p->step_mult, p->step_add); |
| return SOX_SUCCESS; |
| } |
| |
| static void decode(priv_t * p, int bit) |
| { |
| p->last_n_bits = ((p->last_n_bits << 1) | bit) & 7; |
| |
| p->step *= p->step_mult; |
| if (p->last_n_bits == 0 || p->last_n_bits == 7) |
| p->step += p->step_add; |
| |
| if (p->last_n_bits & 1) |
| p->sample = min(p->step_mult * p->sample + p->step, SOX_SAMPLE_MAX); |
| else |
| p->sample = max(p->step_mult * p->sample - p->step, SOX_SAMPLE_MIN); |
| } |
| |
| static size_t cvsdread(sox_format_t * ft, sox_sample_t * buf, size_t len) |
| { |
| priv_t *p = (priv_t *) ft->priv; |
| size_t i; |
| |
| for (i = 0; i < len; ++i) { |
| if (!(p->bit_count & 7)) |
| if (lsx_read_b_buf(ft, &p->byte, (size_t)1) != 1) |
| break; |
| ++p->bit_count; |
| decode(p, p->byte & 1); |
| p->byte >>= 1; |
| *buf++ = floor(p->sample + .5); |
| } |
| return i; |
| } |
| |
| static size_t cvsdwrite(sox_format_t * ft, sox_sample_t const * buf, size_t len) |
| { |
| priv_t *p = (priv_t *) ft->priv; |
| size_t i; |
| |
| for (i = 0; i < len; ++i) { |
| decode(p, *buf++ > p->sample); |
| p->byte >>= 1; |
| p->byte |= p->last_n_bits << 7; |
| if (!(++p->bit_count & 7)) |
| if (lsx_writeb(ft, p->byte) != SOX_SUCCESS) |
| break; |
| } |
| return len; |
| } |
| |
| LSX_FORMAT_HANDLER(cvu) |
| { |
| static char const * const names[] = {"cvu", NULL}; |
| static unsigned const write_encodings[] = {SOX_ENCODING_CVSD, 1, 0, 0}; |
| static sox_format_handler_t const handler = {SOX_LIB_VERSION_CODE, |
| "Headerless Continuously Variable Slope Delta modulation (unfiltered)", |
| names, SOX_FILE_MONO, start, cvsdread, NULL, start, cvsdwrite, NULL, |
| lsx_rawseek, write_encodings, NULL, sizeof(priv_t) |
| }; |
| return &handler; |
| } |