1 /* libSoX file format: CVSD (see cvsd.c)        (c) 2007-8 SoX contributors
2  *
3  * This library is free software; you can redistribute it and/or modify it
4  * under the terms of the GNU Lesser General Public License as published by
5  * the Free Software Foundation; either version 2.1 of the License, or (at
6  * your option) any later version.
7  *
8  * This library is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this library; if not, write to the Free Software Foundation,
15  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
16  */
17 
18 #include "cvsd.h"
19 
LSX_FORMAT_HANDLER(cvsd)20 LSX_FORMAT_HANDLER(cvsd)
21 {
22   static char const * const names[] = {"cvsd", "cvs", NULL};
23   static unsigned const write_encodings[] = {SOX_ENCODING_CVSD, 1, 0, 0};
24   static sox_format_handler_t const handler = {SOX_LIB_VERSION_CODE,
25     "Headerless MIL Std 188 113 Continuously Variable Slope Delta modulation",
26     names, SOX_FILE_MONO,
27     lsx_cvsdstartread, lsx_cvsdread, lsx_cvsdstopread,
28     lsx_cvsdstartwrite, lsx_cvsdwrite, lsx_cvsdstopwrite,
29     lsx_rawseek, write_encodings, NULL, sizeof(cvsd_priv_t)
30   };
31   return &handler;
32 }
33 
34 /* libSoX file format: CVU   (c) 2008 robs@users.sourceforge.net
35  * Unfiltered, therefore, on decode, use with either filter -4k or rate 8k */
36 
37 typedef struct {
38   double         sample, step, step_mult, step_add;
39   unsigned       last_n_bits;
40   unsigned char  byte;
41   off_t          bit_count;
42 } priv_t;
43 
start(sox_format_t * ft)44 static int start(sox_format_t * ft)
45 {
46   priv_t *p = (priv_t *) ft->priv;
47 
48   ft->signal.channels = 1;
49   lsx_rawstart(ft, sox_true, sox_false, sox_true, SOX_ENCODING_CVSD, 1);
50   p->last_n_bits = 5; /* 101 */
51   p->step_mult = exp((-1 / .005 / ft->signal.rate));
52   p->step_add = (1 - p->step_mult) * (.1 * SOX_SAMPLE_MAX);
53   lsx_debug("step_mult=%g step_add=%f", p->step_mult, p->step_add);
54   return SOX_SUCCESS;
55 }
56 
decode(priv_t * p,int bit)57 static void decode(priv_t * p, int bit)
58 {
59   p->last_n_bits = ((p->last_n_bits << 1) | bit) & 7;
60 
61   p->step *= p->step_mult;
62   if (p->last_n_bits == 0 || p->last_n_bits == 7)
63     p->step += p->step_add;
64 
65   if (p->last_n_bits & 1)
66     p->sample = min(p->step_mult * p->sample + p->step, SOX_SAMPLE_MAX);
67   else
68     p->sample = max(p->step_mult * p->sample - p->step, SOX_SAMPLE_MIN);
69 }
70 
cvsdread(sox_format_t * ft,sox_sample_t * buf,size_t len)71 static size_t cvsdread(sox_format_t * ft, sox_sample_t * buf, size_t len)
72 {
73   priv_t *p = (priv_t *) ft->priv;
74   size_t i;
75 
76   for (i = 0; i < len; ++i) {
77     if (!(p->bit_count & 7))
78       if (lsx_read_b_buf(ft, &p->byte, (size_t)1) != 1)
79         break;
80     ++p->bit_count;
81     decode(p, p->byte & 1);
82     p->byte >>= 1;
83     *buf++ = floor(p->sample + .5);
84   }
85   return i;
86 }
87 
cvsdwrite(sox_format_t * ft,sox_sample_t const * buf,size_t len)88 static size_t cvsdwrite(sox_format_t * ft, sox_sample_t const * buf, size_t len)
89 {
90   priv_t *p = (priv_t *) ft->priv;
91   size_t i;
92 
93   for (i = 0; i < len; ++i) {
94     decode(p, *buf++ > p->sample);
95     p->byte >>= 1;
96     p->byte |= p->last_n_bits << 7;
97     if (!(++p->bit_count & 7))
98       if (lsx_writeb(ft, p->byte) != SOX_SUCCESS)
99         break;
100   }
101   return len;
102 }
103 
LSX_FORMAT_HANDLER(cvu)104 LSX_FORMAT_HANDLER(cvu)
105 {
106   static char const * const names[] = {"cvu", NULL};
107   static unsigned const write_encodings[] = {SOX_ENCODING_CVSD, 1, 0, 0};
108   static sox_format_handler_t const handler = {SOX_LIB_VERSION_CODE,
109     "Headerless Continuously Variable Slope Delta modulation (unfiltered)",
110     names, SOX_FILE_MONO, start, cvsdread, NULL, start, cvsdwrite, NULL,
111     lsx_rawseek, write_encodings, NULL, sizeof(priv_t)
112   };
113   return &handler;
114 }
115