1 /* libSoX raw I/O
2  *
3  * Copyright 1991-2007 Lance Norskog And Sundry Contributors
4  * This source code is freely redistributable and may be used for
5  * any purpose.  This copyright notice must be maintained.
6  * Lance Norskog And Sundry Contributors are not responsible for
7  * the consequences of using this software.
8  */
9 
10 #include "sox_i.h"
11 #include "g711.h"
12 
13 typedef sox_uint16_t sox_uint14_t;
14 typedef sox_uint16_t sox_uint13_t;
15 typedef sox_int16_t sox_int14_t;
16 typedef sox_int16_t sox_int13_t;
17 #define SOX_ULAW_BYTE_TO_SAMPLE(d,clips)   SOX_SIGNED_16BIT_TO_SAMPLE(sox_ulaw2linear16(d),clips)
18 #define SOX_ALAW_BYTE_TO_SAMPLE(d,clips)   SOX_SIGNED_16BIT_TO_SAMPLE(sox_alaw2linear16(d),clips)
19 #define SOX_SAMPLE_TO_ULAW_BYTE(d,c) sox_14linear2ulaw(SOX_SAMPLE_TO_UNSIGNED(14,d,c) - 0x2000)
20 #define SOX_SAMPLE_TO_ALAW_BYTE(d,c) sox_13linear2alaw(SOX_SAMPLE_TO_UNSIGNED(13,d,c) - 0x1000)
21 
lsx_rawseek(sox_format_t * ft,uint64_t offset)22 int lsx_rawseek(sox_format_t * ft, uint64_t offset)
23 {
24   return lsx_offset_seek(ft, (off_t)ft->data_start, (off_t)offset);
25 }
26 
27 /* Works nicely for starting read and write; lsx_rawstart{read,write}
28  * are #defined in sox_i.h */
lsx_rawstart(sox_format_t * ft,sox_bool default_rate,sox_bool default_channels,sox_bool default_length,sox_encoding_t encoding,unsigned size)29 int lsx_rawstart(sox_format_t * ft, sox_bool default_rate,
30                  sox_bool default_channels, sox_bool default_length,
31                  sox_encoding_t encoding, unsigned size)
32 {
33   if (default_rate && ft->signal.rate == 0) {
34     lsx_warn("`%s': sample rate not specified; trying 8kHz", ft->filename);
35     ft->signal.rate = 8000;
36   }
37 
38   if (default_channels && ft->signal.channels == 0) {
39     lsx_warn("`%s': # channels not specified; trying mono", ft->filename);
40     ft->signal.channels = 1;
41   }
42 
43   if (encoding != SOX_ENCODING_UNKNOWN) {
44     if (ft->mode == 'r' && ft->encoding.encoding != SOX_ENCODING_UNKNOWN &&
45         ft->encoding.encoding != encoding)
46       lsx_report("`%s': Format options overriding file-type encoding",
47                  ft->filename);
48     else
49       ft->encoding.encoding = encoding;
50   }
51 
52   if (size != 0) {
53     if (ft->mode == 'r' && ft->encoding.bits_per_sample != 0 &&
54         ft->encoding.bits_per_sample != size)
55       lsx_report("`%s': Format options overriding file-type sample-size",
56                  ft->filename);
57     else
58       ft->encoding.bits_per_sample = size;
59   }
60 
61   if (!ft->signal.length && ft->mode == 'r' && default_length &&
62       ft->encoding.bits_per_sample)
63     ft->signal.length =
64         div_bits(lsx_filelength(ft), ft->encoding.bits_per_sample);
65 
66   return SOX_SUCCESS;
67 }
68 
69 #define READ_SAMPLES_FUNC(type, size, sign, ctype, uctype, cast) \
70   static size_t sox_read_ ## sign ## type ## _samples( \
71       sox_format_t * ft, sox_sample_t *buf, size_t len) \
72   { \
73     size_t n, nread; \
74     SOX_SAMPLE_LOCALS; \
75     ctype *data = lsx_malloc(sizeof(ctype) * len); \
76     LSX_USE_VAR(sox_macro_temp_sample), LSX_USE_VAR(sox_macro_temp_double); \
77     nread = lsx_read_ ## type ## _buf(ft, (uctype *)data, len); \
78     for (n = 0; n < nread; n++) \
79       *buf++ = cast(data[n], ft->clips); \
80     free(data); \
81     return nread; \
82   }
83 
84 READ_SAMPLES_FUNC(b, 1, u, uint8_t, uint8_t, SOX_UNSIGNED_8BIT_TO_SAMPLE)
85 READ_SAMPLES_FUNC(b, 1, s, int8_t, uint8_t, SOX_SIGNED_8BIT_TO_SAMPLE)
86 READ_SAMPLES_FUNC(b, 1, ulaw, uint8_t, uint8_t, SOX_ULAW_BYTE_TO_SAMPLE)
87 READ_SAMPLES_FUNC(b, 1, alaw, uint8_t, uint8_t, SOX_ALAW_BYTE_TO_SAMPLE)
88 READ_SAMPLES_FUNC(w, 2, u, uint16_t, uint16_t, SOX_UNSIGNED_16BIT_TO_SAMPLE)
89 READ_SAMPLES_FUNC(w, 2, s, int16_t, uint16_t, SOX_SIGNED_16BIT_TO_SAMPLE)
90 READ_SAMPLES_FUNC(3, 3, u, sox_uint24_t, sox_uint24_t, SOX_UNSIGNED_24BIT_TO_SAMPLE)
91 READ_SAMPLES_FUNC(3, 3, s, sox_int24_t, sox_uint24_t, SOX_SIGNED_24BIT_TO_SAMPLE)
92 READ_SAMPLES_FUNC(dw, 4, u, uint32_t, uint32_t, SOX_UNSIGNED_32BIT_TO_SAMPLE)
93 READ_SAMPLES_FUNC(dw, 4, s, int32_t, uint32_t, SOX_SIGNED_32BIT_TO_SAMPLE)
94 READ_SAMPLES_FUNC(f, sizeof(float), su, float, float, SOX_FLOAT_32BIT_TO_SAMPLE)
95 READ_SAMPLES_FUNC(df, sizeof(double), su, double, double, SOX_FLOAT_64BIT_TO_SAMPLE)
96 
97 #define WRITE_SAMPLES_FUNC(type, size, sign, ctype, uctype, cast) \
98   static size_t sox_write_ ## sign ## type ## _samples( \
99       sox_format_t * ft, sox_sample_t const * buf, size_t len) \
100   { \
101     SOX_SAMPLE_LOCALS; \
102     size_t n, nwritten; \
103     ctype *data = lsx_malloc(sizeof(ctype) * len); \
104     LSX_USE_VAR(sox_macro_temp_sample), LSX_USE_VAR(sox_macro_temp_double); \
105     for (n = 0; n < len; n++) \
106       data[n] = cast(buf[n], ft->clips); \
107     nwritten = lsx_write_ ## type ## _buf(ft, (uctype *)data, len); \
108     free(data); \
109     return nwritten; \
110   }
111 
112 
113 WRITE_SAMPLES_FUNC(b, 1, u, uint8_t, uint8_t, SOX_SAMPLE_TO_UNSIGNED_8BIT)
114 WRITE_SAMPLES_FUNC(b, 1, s, int8_t, uint8_t, SOX_SAMPLE_TO_SIGNED_8BIT)
115 WRITE_SAMPLES_FUNC(b, 1, ulaw, uint8_t, uint8_t, SOX_SAMPLE_TO_ULAW_BYTE)
116 WRITE_SAMPLES_FUNC(b, 1, alaw, uint8_t, uint8_t, SOX_SAMPLE_TO_ALAW_BYTE)
117 WRITE_SAMPLES_FUNC(w, 2, u, uint16_t, uint16_t, SOX_SAMPLE_TO_UNSIGNED_16BIT)
118 WRITE_SAMPLES_FUNC(w, 2, s, int16_t, uint16_t, SOX_SAMPLE_TO_SIGNED_16BIT)
119 WRITE_SAMPLES_FUNC(3, 3, u, sox_uint24_t, sox_uint24_t, SOX_SAMPLE_TO_UNSIGNED_24BIT)
120 WRITE_SAMPLES_FUNC(3, 3, s, sox_int24_t, sox_uint24_t, SOX_SAMPLE_TO_SIGNED_24BIT)
121 WRITE_SAMPLES_FUNC(dw, 4, u, uint32_t, uint32_t, SOX_SAMPLE_TO_UNSIGNED_32BIT)
122 WRITE_SAMPLES_FUNC(dw, 4, s, int32_t, uint32_t, SOX_SAMPLE_TO_SIGNED_32BIT)
123 WRITE_SAMPLES_FUNC(f, sizeof(float), su, float, float, SOX_SAMPLE_TO_FLOAT_32BIT)
124 WRITE_SAMPLES_FUNC(df, sizeof (double), su, double, double, SOX_SAMPLE_TO_FLOAT_64BIT)
125 
126 #define GET_FORMAT(type) \
127 static ft_##type##_fn * type##_fn(sox_format_t * ft) { \
128   switch (ft->encoding.bits_per_sample) { \
129     case 8: \
130       switch (ft->encoding.encoding) { \
131         case SOX_ENCODING_SIGN2: return sox_##type##_sb_samples; \
132         case SOX_ENCODING_UNSIGNED: return sox_##type##_ub_samples; \
133         case SOX_ENCODING_ULAW: return sox_##type##_ulawb_samples; \
134         case SOX_ENCODING_ALAW: return sox_##type##_alawb_samples; \
135         default: break; } \
136       break; \
137     case 16: \
138       switch (ft->encoding.encoding) { \
139         case SOX_ENCODING_SIGN2: return sox_##type##_sw_samples; \
140         case SOX_ENCODING_UNSIGNED: return sox_##type##_uw_samples; \
141         default: break; } \
142       break; \
143     case 24: \
144       switch (ft->encoding.encoding) { \
145         case SOX_ENCODING_SIGN2:    return sox_##type##_s3_samples; \
146         case SOX_ENCODING_UNSIGNED: return sox_##type##_u3_samples; \
147         default: break; } \
148       break; \
149     case 32: \
150       switch (ft->encoding.encoding) { \
151         case SOX_ENCODING_SIGN2: return sox_##type##_sdw_samples; \
152         case SOX_ENCODING_UNSIGNED: return sox_##type##_udw_samples; \
153         case SOX_ENCODING_FLOAT: return sox_##type##_suf_samples; \
154         default: break; } \
155       break; \
156     case 64: \
157       switch (ft->encoding.encoding) { \
158         case SOX_ENCODING_FLOAT: return sox_##type##_sudf_samples; \
159         default: break; } \
160       break; \
161     default: \
162       lsx_fail_errno(ft, SOX_EFMT, "this handler does not support this data size"); \
163       return NULL; } \
164   lsx_fail_errno(ft, SOX_EFMT, "this encoding is not supported for this data size"); \
165   return NULL; }
166 
167 typedef size_t(ft_read_fn)
168   (sox_format_t * ft, sox_sample_t * buf, size_t len);
169 
GET_FORMAT(read)170 GET_FORMAT(read)
171 
172 /* Read a stream of some type into SoX's internal buffer format. */
173 size_t lsx_rawread(sox_format_t * ft, sox_sample_t * buf, size_t nsamp)
174 {
175   ft_read_fn * read_buf = read_fn(ft);
176 
177   if (read_buf && nsamp)
178     return read_buf(ft, buf, nsamp);
179   return 0;
180 }
181 
182 typedef size_t(ft_write_fn)
183   (sox_format_t * ft, sox_sample_t const * buf, size_t len);
184 
GET_FORMAT(write)185 GET_FORMAT(write)
186 
187 /* Writes SoX's internal buffer format to buffer of various data types. */
188 size_t lsx_rawwrite(
189     sox_format_t * ft, sox_sample_t const * buf, size_t nsamp)
190 {
191   ft_write_fn * write_buf = write_fn(ft);
192 
193   if (write_buf && nsamp)
194     return write_buf(ft, buf, nsamp);
195   return 0;
196 }
197