|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24: /*
25: * audio_mix.c
26: *
27: * Copyright (c) 1991, NeXT Computer, Inc. All rights reserved.
28: *
29: * Audio driver mixing.
30: *
31: * HISTORY
32: * 07/14/92/mtm Original coding.
33: */
34:
35: #import "audioLog.h"
36: #import "audio_mix.h"
37: #import "audio_peak.h"
38: #import "audio_mulaw.h"
39: #import <architecture/byte_order.h>
40: #import <limits.h>
41: #import <bsd/string.h>
42:
43: #define MULAW_MAX 128
44: #define MULAW_MIN 0
45:
46: /*
47: * Macros to clip int to short/byte/mulaw-byte and load into pointer.
48: * Increments destination pointer.
49: * Increments clip count.
50: */
51: #define clip16(i,p,c) if (i > SHRT_MAX) { \
52: *p++ = SHRT_MAX; \
53: c++; \
54: } else if (i < SHRT_MIN) { \
55: *p++ = SHRT_MIN; \
56: c++; \
57: } else \
58: *p++ = (short)i;
59:
60: #define clip8(i,p,c) if (i > SCHAR_MAX) { \
61: *p++ = SCHAR_MAX; \
62: c++; \
63: } else if (i < SCHAR_MIN) { \
64: *p++ = SCHAR_MIN; \
65: c++; \
66: } else \
67: *p++ = (char)i;
68:
69: /* xor the high bit to convert between 2's comp and 1's comp (unary) */
70: #define unary(i) (((i) ^ (char)0x80) | ((i) & (char)0x7f))
71:
72: #define clipUnary8(i,p,c) if (i > SCHAR_MAX) { \
73: *p++ = unary(SCHAR_MAX); \
74: c++; \
75: } else if (i < SCHAR_MIN) { \
76: *p++ = unary(SCHAR_MIN); \
77: c++; \
78: } else \
79: *p++ = unary((char)i);
80:
81: #define clipMulaw8(i,p,c) if (i > SHRT_MAX) { \
82: *p++ = MULAW_MAX; \
83: c++; \
84: } else if (i < SHRT_MIN) { \
85: *p++ = MULAW_MIN; \
86: c++; \
87: } else \
88: *p++ = audio_shortToMulaw((short)i);
89:
90:
91: void audio_swapSamples(short *src, short *dest, u_int count)
92: {
93: #if defined(hppa) || defined(sparc)
94: // I have noticed that src is not aligned to short boundary when two samples with
95: // different sampling rate are played at the same time. Also this happens at the end of
96: // second sample. This results in an alignment trap in hppa leading to system crash.
97: // Therefore I am providing this workaround of forcing the alignment to even bounary,
98: // instead of a complete fix. This is
99: // a late stage for us to make big changes for FCS (6/6/94).
100: // This has to be fixed for 3.3
101: // TBD: Fix the alignment probs
102: unsigned int ptr,ptr1;
103: ptr = (unsigned int)src;
104: ptr1 = (unsigned int)dest;
105:
106: // if (!count) return;
107: if ((ptr & 1)){
108: // printf("The source is not aligned %x\n",src);
109: ptr &= 0xfffffffe; //forcing the alignment
110: src = (short *)ptr;
111: }
112: if ((ptr1 & 1)){
113: // printf("The Dest is not aligned %x \n",dest);
114: ptr1 &= 0xfffffffe; //forcing the alignment
115: dest = (short *)ptr1;
116: }
117: #endif
118: while (count--)
119: *dest++ = NXSwapBigShortToHost(*src++);
120: }
121:
122: void audio_twosComp8ToUnary(char *src, char *dest, u_int count)
123: {
124: while (count--) {
125: /* xor the high bit */
126: *dest++ = unary(*src);
127: src++;
128: }
129: }
130:
131: /*
132: * Scale samples, return number of times clipped.
133: */
134: u_int audio_scaleSamples(char *src, char *dest, u_int count,
135: IOAudioDataFormat format, u_int chanCount,
136: int leftGain, int rightGain)
137: {
138: short *shortSrc, *shortDest;
139: u_int clips = 0;
140: int val = 0;
141: int leftGain8, rightGain8, monoGain = 0;
142: unsigned char *uSrc, *uDest;
143:
144: /*
145: * Gains MUST be signed values when used in the following
146: * calculations. It is not clear (to me) why.
147: */
148:
149: switch (format) {
150: case IOAudioDataFormatLinear16:
151: count /= 2;
152: shortSrc = (short *)src;
153: shortDest = (short *)dest;
154: switch (chanCount) {
155: case 1:
156: monoGain = (leftGain + rightGain) / 2;
157: while (count--) {
158: val = (((int)*shortSrc++)*monoGain)>>15;
159: clip16(val, shortDest, clips);
160: }
161: break;
162: case 2:
163: count /= 2;
164: while (count--) {
165: val = (((int)*shortSrc++)*leftGain)>>15;
166: /*
167: * FIXME: clipping not working.
168: */
169: *shortDest++ = (short)val;
170: //clip16(val, shortDest, clips);
171: val = (((int)*shortSrc++)*rightGain)>>15;
172: *shortDest++ = (short)val;
173: //clip16(val, shortDest, clips);
174: }
175: break;
176: default:
177: break;
178: }
179: break;
180: case IOAudioDataFormatLinear8:
181: /* Gains are passed in 16-bit range */
182: leftGain8 = leftGain >> 8;
183: rightGain8 = rightGain >> 8;
184: switch (chanCount) {
185: case 1:
186: monoGain = (leftGain8 + rightGain8) / 2;
187: while (count--) {
188: val = (((int)*src++)*monoGain)>>7;
189: clip8(val, dest, clips);
190: }
191: break;
192: case 2:
193: count /= 2;
194: while (count--) {
195: val = (((int)*src++)*leftGain8)>>7;
196: clip8(val, dest, clips);
197: val = (((int)*src++)*rightGain8)>>7;
198: clip8(val, dest, clips);
199: }
200: break;
201: default:
202: break;
203: }
204: break;
205: case IOAudioDataFormatMulaw8:
206: /* Gains are passed in 16-bit range */
207: leftGain8 = leftGain >> 8;
208: rightGain8 = rightGain >> 8;
209: uSrc = (unsigned char *)src;
210: uDest = (unsigned char *)dest;
211: switch (chanCount) {
212: case 1:
213: monoGain = (leftGain8 + rightGain8) / 2;
214: while (count--) {
215: val = (((int)audio_muLaw[(unsigned int)*uSrc++])*monoGain)>>7;
216: clipMulaw8(val, uDest, clips);
217: }
218: break;
219: case 2:
220: count /= 2;
221: while (count--) {
222: val = (((int)audio_muLaw[(unsigned int)*uSrc++])*leftGain8)>>7;
223: clipMulaw8(val, uDest, clips);
224: val = (((int)audio_muLaw[(unsigned int)*uSrc++])*
225: rightGain8)>>7;
226: clipMulaw8(val, uDest, clips);
227: }
228: break;
229: default:
230: break;
231: }
232: break;
233: default:
234: IOLog("Audio: unrecognized format %d in scaleSamples\n", format);
235: break;
236: }
237:
238: return clips;
239: }
240:
241: void audio_resample22To44(char *src, char *dest, u_int count,
242: IOAudioDataFormat format, u_int channelCount)
243: {
244: if ( channelCount == 1 )
245: {
246: /* Just double samples! */
247: audio_convertMonoToStereo(src, dest, count, format);
248: }
249: else
250: {
251: short *shortSrc, *shortDest;
252:
253: shortSrc = (short *)src;
254: shortDest = (short *)dest;
255:
256: count /= 2;
257: while (count--)
258: {
259: *(shortDest+2) = *shortSrc;
260: *shortDest++ = *shortSrc++;
261: *(shortDest+2) = *shortSrc;
262: *shortDest++ = *shortSrc++;
263: shortDest += 2;
264: }
265: }
266: }
267:
268: void audio_resample44To22(char *src, char *dest, u_int count,
269: IOAudioDataFormat format, u_int *phase)
270: {
271: short *shortSrc, *shortDest;
272:
273: /*
274: * FIXME: implement phase.
275: */
276:
277: count /= 2; /* src is incremented twice each loop */
278:
279: switch (format) {
280: case IOAudioDataFormatLinear16:
281: count /= 2;
282: shortSrc = (short *)src;
283: shortDest = (short *)dest;
284: while (count--) {
285: *shortDest++ = *shortSrc++;
286: shortSrc++;
287: }
288: break;
289: case IOAudioDataFormatLinear8:
290: case IOAudioDataFormatMulaw8:
291: while (count--) {
292: *dest++ = *src++;
293: src++;
294: }
295: break;
296: default:
297: IOLog("Audio: unrecognized format %d in resample\n", format);
298: break;
299: }
300: }
301:
302: void audio_convertMonoToStereo(char *src, char *dest, u_int count,
303: IOAudioDataFormat format)
304: {
305: short *shortSrc, *shortDest;
306:
307: switch (format) {
308: case IOAudioDataFormatLinear16:
309: count /= 2;
310: shortSrc = (short *)src;
311: shortDest = (short *)dest;
312: while (count--) {
313: *shortDest++ = *shortSrc;
314: *shortDest++ = *shortSrc++;
315: }
316: break;
317: case IOAudioDataFormatLinear8:
318: case IOAudioDataFormatMulaw8:
319: while (count--) {
320: *dest++ = *src;
321: *dest++ = *src++;
322: }
323: break;
324: default:
325: IOLog("Audio: unrecognized format %d in convMono\n", format);
326: break;
327: }
328: }
329:
330: void audio_convertStereoToMono(char *src, char *dest, u_int count,
331: IOAudioDataFormat format, u_int *phase)
332: {
333: short *shortSrc, *shortDest;
334: unsigned char *uSrc, *uDest;
335: int sample;
336:
337: /*
338: * FIXME: implement phase.
339: */
340:
341: count /= 2; /* src is incremented twice each loop */
342:
343: switch (format) {
344: case IOAudioDataFormatLinear16:
345: count /= 2;
346: shortSrc = (short *)src;
347: shortDest = (short *)dest;
348: while (count--) {
349: sample = *shortSrc++;
350: sample += *shortSrc++;
351: sample += sample & 1; /* round up if odd */
352: sample /= 2;
353: *shortDest++ = (short)sample;
354: }
355: break;
356: case IOAudioDataFormatLinear8:
357: while (count--) {
358: sample = *src++;
359: sample += *src++;
360: sample += sample & 1;
361: sample /= 2;
362: *dest++ = (char)sample;
363: }
364: break;
365: case IOAudioDataFormatMulaw8:
366: uSrc = (unsigned char *)src;
367: uDest = (unsigned char *)dest;
368: while (count--) {
369: sample = audio_muLaw[(unsigned int)*uSrc++];
370: sample += audio_muLaw[(unsigned int)*uSrc++];
371: sample += sample & 1;
372: sample /= 2;
373: *uDest++ = audio_shortToMulaw((short)sample);
374: }
375: break;
376: default:
377: IOLog("Audio: unrecognized format %d in convMono\n", format);
378: break;
379: }
380: }
381:
382: void audio_convertLinear8ToLinear16(char *src, short *dest, u_int count)
383: {
384: while (count--)
385: *dest++ = *src++ << 8;
386: }
387:
388: void audio_convertLinear8ToMulaw8(char *src, char *dest, u_int count)
389: {
390: while (count--)
391: *dest = audio_shortToMulaw((short)(*src++) << 8);
392: }
393:
394: void audio_convertLinear16ToLinear8(short *src, char *dest, u_int count,
395: u_int *phase)
396: {
397: while (count--)
398: *dest++ = *src++ >> 8;
399: }
400:
401: void audio_convertLinear16ToMulaw8(short *src, char *dest, u_int count,
402: u_int *phase)
403: {
404: while (count--)
405: *dest = audio_shortToMulaw(*src++);
406: }
407:
408: void audio_convertMulaw8ToLinear16(char *src, short *dest, u_int count)
409: {
410: unsigned char *uSrc = (unsigned char *)src;
411: unsigned char *uDest = (unsigned char *)dest;
412:
413: while (count--)
414: *uDest++ = audio_muLaw[(unsigned int)*uSrc++];
415: }
416:
417: void audio_convertMulaw8ToLinear8(char *src, char *dest, u_int count)
418: {
419: return;
420: }
421:
422: /*
423: * Mix source into destination.
424: * Return number of times mix clipped.
425: */
426: u_int audio_mix(char *src, char *dest, u_int count, IOAudioDataFormat format,
427: boolean_t virgin)
428: {
429: int sum;
430: u_int clips = 0;
431: short *shortSrc, *shortDest;
432: unsigned char *uSrc, *uDest;
433:
434: if (count == 0)
435: return 0;
436:
437: if (virgin) {
438: if (format == IOAudioDataFormatLinear8)
439: audio_twosComp8ToUnary(src, dest, count);
440: else
441: bcopy(src, dest, count);
442: } else switch (format) {
443: case IOAudioDataFormatLinear16:
444: count /= 2;
445: shortSrc = (short *)src;
446: shortDest = (short *)dest;
447: while (count--) {
448: sum = (int)*shortDest + (int)*shortSrc++;
449: clip16(sum, shortDest, clips);
450: }
451: break;
452: case IOAudioDataFormatLinear8:
453: while (count--) {
454: /*
455: * FIXME: only convert to unary if devIsUnary.
456: */
457: sum = (int)unary(*dest) + (int)*src++;
458: clipUnary8(sum, dest, clips);
459: }
460: break;
461: case IOAudioDataFormatMulaw8:
462: uSrc = (unsigned char *)src;
463: uDest = (unsigned char *)dest;
464: while (count--) {
465: sum = (int)audio_muLaw[(unsigned int)*uDest] +
466: (int)audio_muLaw[(unsigned int)*uSrc++];
467: clipMulaw8(sum, uDest, clips);
468: }
469: break;
470: default:
471: IOLog("Audio: unrecognized format %d in mix\n", format);
472: break;
473: }
474:
475: return clips;
476: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.