1/**********
2This library is free software; you can redistribute it and/or modify it under
3the terms of the GNU Lesser General Public License as published by the
4Free Software Foundation; either version 3 of the License, or (at your
5option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
6
7This library is distributed in the hope that it will be useful, but WITHOUT
8ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
10more details.
11
12You should have received a copy of the GNU Lesser General Public License
13along with this library; if not, write to the Free Software Foundation, Inc.,
1451 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15**********/
16// "liveMedia"
17// Copyright (c) 1996-2020 Live Networks, Inc. All rights reserved.
18// Filters for converting between raw PCM audio and uLaw
19// Implementation
20
21#include "uLawAudioFilter.hh"
22
23////////// 16-bit PCM (in various byte orders) -> 8-bit u-Law //////////
24
25uLawFromPCMAudioSource* uLawFromPCMAudioSource
26::createNew(UsageEnvironment& env, FramedSource* inputSource, int byteOrdering) {
27 // "byteOrdering" must be 0, 1, or 2:
28 if (byteOrdering < 0 || byteOrdering > 2) {
29 env.setResultMsg("uLawFromPCMAudioSource::createNew(): bad \"byteOrdering\" parameter");
30 return NULL;
31 }
32 return new uLawFromPCMAudioSource(env, inputSource, byteOrdering);
33}
34
35uLawFromPCMAudioSource
36::uLawFromPCMAudioSource(UsageEnvironment& env, FramedSource* inputSource,
37 int byteOrdering)
38 : FramedFilter(env, inputSource),
39 fByteOrdering(byteOrdering), fInputBuffer(NULL), fInputBufferSize(0) {
40}
41
42uLawFromPCMAudioSource::~uLawFromPCMAudioSource() {
43 delete[] fInputBuffer;
44}
45
46void uLawFromPCMAudioSource::doGetNextFrame() {
47 // Figure out how many bytes of input data to ask for, and increase
48 // our input buffer if necessary:
49 unsigned bytesToRead = fMaxSize*2; // because we're converting 16 bits->8
50 if (bytesToRead > fInputBufferSize) {
51 delete[] fInputBuffer; fInputBuffer = new unsigned char[bytesToRead];
52 fInputBufferSize = bytesToRead;
53 }
54
55 // Arrange to read samples into the input buffer:
56 fInputSource->getNextFrame(fInputBuffer, bytesToRead,
57 afterGettingFrame, this,
58 FramedSource::handleClosure, this);
59}
60
61void uLawFromPCMAudioSource
62::afterGettingFrame(void* clientData, unsigned frameSize,
63 unsigned numTruncatedBytes,
64 struct timeval presentationTime,
65 unsigned durationInMicroseconds) {
66 uLawFromPCMAudioSource* source = (uLawFromPCMAudioSource*)clientData;
67 source->afterGettingFrame1(frameSize, numTruncatedBytes,
68 presentationTime, durationInMicroseconds);
69}
70
71#define BIAS 0x84 // the add-in bias for 16 bit samples
72#define CLIP 32635
73
74static unsigned char uLawFrom16BitLinear(u_int16_t sample) {
75 static int const exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
76 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
77 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
78 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
79 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
80 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
81 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
82 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
83 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
84 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
85 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
86 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
87 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
88 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
89 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
90 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
91 unsigned char sign = (sample >> 8) & 0x80;
92 if (sign != 0) sample = -sample; // get the magnitude
93
94 if (sample > CLIP) sample = CLIP; // clip the magnitude
95 sample += BIAS;
96
97 unsigned char exponent = exp_lut[(sample>>7) & 0xFF];
98 unsigned char mantissa = (sample >> (exponent+3)) & 0x0F;
99 unsigned char result = ~(sign | (exponent << 4) | mantissa);
100 if (result == 0 ) result = 0x02; // CCITT trap
101
102 return result;
103}
104
105void uLawFromPCMAudioSource
106::afterGettingFrame1(unsigned frameSize, unsigned numTruncatedBytes,
107 struct timeval presentationTime,
108 unsigned durationInMicroseconds) {
109 // Translate raw 16-bit PCM samples (in the input buffer)
110 // into uLaw samples (in the output buffer).
111 unsigned numSamples = frameSize/2;
112 switch (fByteOrdering) {
113 case 0: { // host order
114 u_int16_t* inputSample = (u_int16_t*)fInputBuffer;
115 for (unsigned i = 0; i < numSamples; ++i) {
116 fTo[i] = uLawFrom16BitLinear(inputSample[i]);
117 }
118 break;
119 }
120 case 1: { // little-endian order
121 for (unsigned i = 0; i < numSamples; ++i) {
122 u_int16_t const newValue = (fInputBuffer[2*i+1]<<8)|fInputBuffer[2*i];
123 fTo[i] = uLawFrom16BitLinear(newValue);
124 }
125 break;
126 }
127 case 2: { // network (i.e., big-endian) order
128 for (unsigned i = 0; i < numSamples; ++i) {
129 u_int16_t const newValue = (fInputBuffer[2*i]<<8)|fInputBuffer[2*i+i];
130 fTo[i] = uLawFrom16BitLinear(newValue);
131 }
132 break;
133 }
134 }
135
136 // Complete delivery to the client:
137 fFrameSize = numSamples;
138 fNumTruncatedBytes = numTruncatedBytes;
139 fPresentationTime = presentationTime;
140 fDurationInMicroseconds = durationInMicroseconds;
141 afterGetting(this);
142}
143
144
145////////// u-Law -> 16-bit PCM (in host order) //////////
146
147PCMFromuLawAudioSource* PCMFromuLawAudioSource
148::createNew(UsageEnvironment& env, FramedSource* inputSource) {
149 return new PCMFromuLawAudioSource(env, inputSource);
150}
151
152PCMFromuLawAudioSource
153::PCMFromuLawAudioSource(UsageEnvironment& env,
154 FramedSource* inputSource)
155 : FramedFilter(env, inputSource),
156 fInputBuffer(NULL), fInputBufferSize(0) {
157}
158
159PCMFromuLawAudioSource::~PCMFromuLawAudioSource() {
160 delete[] fInputBuffer;
161}
162
163void PCMFromuLawAudioSource::doGetNextFrame() {
164 // Figure out how many bytes of input data to ask for, and increase
165 // our input buffer if necessary:
166 unsigned bytesToRead = fMaxSize/2; // because we're converting 8 bits->16
167 if (bytesToRead > fInputBufferSize) {
168 delete[] fInputBuffer; fInputBuffer = new unsigned char[bytesToRead];
169 fInputBufferSize = bytesToRead;
170 }
171
172 // Arrange to read samples into the input buffer:
173 fInputSource->getNextFrame(fInputBuffer, bytesToRead,
174 afterGettingFrame, this,
175 FramedSource::handleClosure, this);
176}
177
178void PCMFromuLawAudioSource
179::afterGettingFrame(void* clientData, unsigned frameSize,
180 unsigned numTruncatedBytes,
181 struct timeval presentationTime,
182 unsigned durationInMicroseconds) {
183 PCMFromuLawAudioSource* source = (PCMFromuLawAudioSource*)clientData;
184 source->afterGettingFrame1(frameSize, numTruncatedBytes,
185 presentationTime, durationInMicroseconds);
186}
187
188static u_int16_t linear16FromuLaw(unsigned char uLawByte) {
189 static int const exp_lut[8] = {0,132,396,924,1980,4092,8316,16764};
190 uLawByte = ~uLawByte;
191
192 Boolean sign = (uLawByte & 0x80) != 0;
193 unsigned char exponent = (uLawByte>>4) & 0x07;
194 unsigned char mantissa = uLawByte & 0x0F;
195
196 u_int16_t result = exp_lut[exponent] + (mantissa << (exponent+3));
197 if (sign) result = -result;
198 return result;
199}
200
201void PCMFromuLawAudioSource
202::afterGettingFrame1(unsigned frameSize, unsigned numTruncatedBytes,
203 struct timeval presentationTime,
204 unsigned durationInMicroseconds) {
205 // Translate uLaw samples (in the input buffer)
206 // into 16-bit PCM samples (in the output buffer), in host order.
207 unsigned numSamples = frameSize;
208 u_int16_t* outputSample = (u_int16_t*)fTo;
209 for (unsigned i = 0; i < numSamples; ++i) {
210 outputSample[i] = linear16FromuLaw(fInputBuffer[i]);
211 }
212
213 // Complete delivery to the client:
214 fFrameSize = numSamples*2;
215 fNumTruncatedBytes = numTruncatedBytes;
216 fPresentationTime = presentationTime;
217 fDurationInMicroseconds = durationInMicroseconds;
218 afterGetting(this);
219}
220
221
222////////// 16-bit values (in host order) -> 16-bit network order //////////
223
224NetworkFromHostOrder16* NetworkFromHostOrder16
225::createNew(UsageEnvironment& env, FramedSource* inputSource) {
226 return new NetworkFromHostOrder16(env, inputSource);
227}
228
229NetworkFromHostOrder16
230::NetworkFromHostOrder16(UsageEnvironment& env,
231 FramedSource* inputSource)
232 : FramedFilter(env, inputSource) {
233}
234
235NetworkFromHostOrder16::~NetworkFromHostOrder16() {
236}
237
238void NetworkFromHostOrder16::doGetNextFrame() {
239 // Arrange to read data directly into the client's buffer:
240 fInputSource->getNextFrame(fTo, fMaxSize,
241 afterGettingFrame, this,
242 FramedSource::handleClosure, this);
243}
244
245void NetworkFromHostOrder16
246::afterGettingFrame(void* clientData, unsigned frameSize,
247 unsigned numTruncatedBytes,
248 struct timeval presentationTime,
249 unsigned durationInMicroseconds) {
250 NetworkFromHostOrder16* source = (NetworkFromHostOrder16*)clientData;
251 source->afterGettingFrame1(frameSize, numTruncatedBytes,
252 presentationTime, durationInMicroseconds);
253}
254
255void NetworkFromHostOrder16
256::afterGettingFrame1(unsigned frameSize, unsigned numTruncatedBytes,
257 struct timeval presentationTime,
258 unsigned durationInMicroseconds) {
259 // Translate the 16-bit values that we have just read from host
260 // to network order (in-place)
261 unsigned numValues = frameSize/2;
262 u_int16_t* value = (u_int16_t*)fTo;
263 for (unsigned i = 0; i < numValues; ++i) {
264 value[i] = htons(value[i]);
265 }
266
267 // Complete delivery to the client:
268 fFrameSize = numValues*2;
269 fNumTruncatedBytes = numTruncatedBytes;
270 fPresentationTime = presentationTime;
271 fDurationInMicroseconds = durationInMicroseconds;
272 afterGetting(this);
273}
274
275
276////////// 16-bit values (in network order) -> 16-bit host order //////////
277
278HostFromNetworkOrder16* HostFromNetworkOrder16
279::createNew(UsageEnvironment& env, FramedSource* inputSource) {
280 return new HostFromNetworkOrder16(env, inputSource);
281}
282
283HostFromNetworkOrder16
284::HostFromNetworkOrder16(UsageEnvironment& env,
285 FramedSource* inputSource)
286 : FramedFilter(env, inputSource) {
287}
288
289HostFromNetworkOrder16::~HostFromNetworkOrder16() {
290}
291
292void HostFromNetworkOrder16::doGetNextFrame() {
293 // Arrange to read data directly into the client's buffer:
294 fInputSource->getNextFrame(fTo, fMaxSize,
295 afterGettingFrame, this,
296 FramedSource::handleClosure, this);
297}
298
299void HostFromNetworkOrder16
300::afterGettingFrame(void* clientData, unsigned frameSize,
301 unsigned numTruncatedBytes,
302 struct timeval presentationTime,
303 unsigned durationInMicroseconds) {
304 HostFromNetworkOrder16* source = (HostFromNetworkOrder16*)clientData;
305 source->afterGettingFrame1(frameSize, numTruncatedBytes,
306 presentationTime, durationInMicroseconds);
307}
308
309void HostFromNetworkOrder16
310::afterGettingFrame1(unsigned frameSize, unsigned numTruncatedBytes,
311 struct timeval presentationTime,
312 unsigned durationInMicroseconds) {
313 // Translate the 16-bit values that we have just read from network
314 // to host order (in-place):
315 unsigned numValues = frameSize/2;
316 u_int16_t* value = (u_int16_t*)fTo;
317 for (unsigned i = 0; i < numValues; ++i) {
318 value[i] = ntohs(value[i]);
319 }
320
321 // Complete delivery to the client:
322 fFrameSize = numValues*2;
323 fNumTruncatedBytes = numTruncatedBytes;
324 fPresentationTime = presentationTime;
325 fDurationInMicroseconds = durationInMicroseconds;
326 afterGetting(this);
327}
328
329
330////////// 16-bit values: little-endian <-> big-endian //////////
331
332EndianSwap16*
333EndianSwap16::createNew(UsageEnvironment& env, FramedSource* inputSource) {
334 return new EndianSwap16(env, inputSource);
335}
336
337EndianSwap16::EndianSwap16(UsageEnvironment& env,
338 FramedSource* inputSource)
339 : FramedFilter(env, inputSource) {
340}
341
342EndianSwap16::~EndianSwap16() {
343}
344
345void EndianSwap16::doGetNextFrame() {
346 // Arrange to read data directly into the client's buffer:
347 fInputSource->getNextFrame(fTo, fMaxSize,
348 afterGettingFrame, this,
349 FramedSource::handleClosure, this);
350}
351
352void EndianSwap16::afterGettingFrame(void* clientData, unsigned frameSize,
353 unsigned numTruncatedBytes,
354 struct timeval presentationTime,
355 unsigned durationInMicroseconds) {
356 EndianSwap16* source = (EndianSwap16*)clientData;
357 source->afterGettingFrame1(frameSize, numTruncatedBytes,
358 presentationTime, durationInMicroseconds);
359}
360
361void EndianSwap16::afterGettingFrame1(unsigned frameSize, unsigned numTruncatedBytes,
362 struct timeval presentationTime,
363 unsigned durationInMicroseconds) {
364 // Swap the byte order of the 16-bit values that we have just read (in place):
365 unsigned numValues = frameSize/2;
366 u_int16_t* value = (u_int16_t*)fTo;
367 for (unsigned i = 0; i < numValues; ++i) {
368 u_int16_t const orig = value[i];
369 value[i] = ((orig&0xFF)<<8) | ((orig&0xFF00)>>8);
370 }
371
372 // Complete delivery to the client:
373 fFrameSize = numValues*2;
374 fNumTruncatedBytes = numTruncatedBytes + (frameSize - fFrameSize);
375 fPresentationTime = presentationTime;
376 fDurationInMicroseconds = durationInMicroseconds;
377 afterGetting(this);
378}
379
380
381////////// 24-bit values: little-endian <-> big-endian //////////
382
383EndianSwap24*
384EndianSwap24::createNew(UsageEnvironment& env, FramedSource* inputSource) {
385 return new EndianSwap24(env, inputSource);
386}
387
388EndianSwap24::EndianSwap24(UsageEnvironment& env,
389 FramedSource* inputSource)
390 : FramedFilter(env, inputSource) {
391}
392
393EndianSwap24::~EndianSwap24() {
394}
395
396void EndianSwap24::doGetNextFrame() {
397 // Arrange to read data directly into the client's buffer:
398 fInputSource->getNextFrame(fTo, fMaxSize,
399 afterGettingFrame, this,
400 FramedSource::handleClosure, this);
401}
402
403void EndianSwap24::afterGettingFrame(void* clientData, unsigned frameSize,
404 unsigned numTruncatedBytes,
405 struct timeval presentationTime,
406 unsigned durationInMicroseconds) {
407 EndianSwap24* source = (EndianSwap24*)clientData;
408 source->afterGettingFrame1(frameSize, numTruncatedBytes,
409 presentationTime, durationInMicroseconds);
410}
411
412void EndianSwap24::afterGettingFrame1(unsigned frameSize, unsigned numTruncatedBytes,
413 struct timeval presentationTime,
414 unsigned durationInMicroseconds) {
415 // Swap the byte order of the 24-bit values that we have just read (in place):
416 unsigned const numValues = frameSize/3;
417 u_int8_t* p = fTo;
418 for (unsigned i = 0; i < numValues; ++i) {
419 u_int8_t tmp = p[0];
420 p[0] = p[2];
421 p[2] = tmp;
422 p += 3;
423 }
424
425 // Complete delivery to the client:
426 fFrameSize = numValues*3;
427 fNumTruncatedBytes = numTruncatedBytes + (frameSize - fFrameSize);
428 fPresentationTime = presentationTime;
429 fDurationInMicroseconds = durationInMicroseconds;
430 afterGetting(this);
431}
432