wavedata.c revision 9484:fbd5ddc28e96
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright (C) 4Front Technologies 1996-2008.
23 *
24 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
25 * Use is subject to license terms.
26 */
27/*
28 * Purpose: Test sounds for osstest
29 *
30 * Nodoc:
31 */
32
33#include <string.h>
34
35#include "wavedata.h"
36
37static int
38le_int(const unsigned char *p, int l)
39{
40	int i, val;
41
42	val = 0;
43
44	for (i = l - 1; i >= 0; i--) {
45		val = (val << 8) | p[i];
46	}
47
48	return (val);
49}
50
51int
52uncompress_wave(short *outbuf)
53{
54#define	WAVE_FORMAT_ADPCM		0x0002
55
56	int i, n, dataleft, x, l = sizeof (inbuf);
57	const unsigned char *hdr = inbuf;
58	typedef struct {
59		int coeff1, coeff2;
60	}
61	adpcm_coeff;
62
63	adpcm_coeff coeff[32];
64	static int AdaptionTable[] = { 230, 230, 230, 230, 307, 409, 512, 614,
65	    768, 614, 512, 409, 307, 230, 230, 230
66	};
67
68	unsigned char buf[4096];
69
70	int channels = 1;
71	int p = 12, outp = 0;
72	int nBlockAlign = 2048;
73	int wSamplesPerBlock = 2036, wNumCoeff = 7;
74	int nib;
75	int ppp;
76
77	/* filelen = le_int(&hdr[4], 4); */
78
79	while (p < l - 16 && memcmp(&hdr[p], "data", 4) != 0) {
80		n = le_int(&hdr[p + 4], 4);
81
82		if (memcmp(&hdr[p], "fmt ", 4) == 0) {
83
84			/* fmt = le_int(&hdr[p + 8], 2); */
85			channels = le_int(&hdr[p + 10], 2);
86			/* speed = le_int(&hdr[p + 12], 4); */
87			nBlockAlign = le_int(&hdr[p + 20], 2);
88			/* bytes_per_sample = le_int(&hdr[p + 20], 2); */
89
90			wSamplesPerBlock = le_int(&hdr[p + 26], 2);
91			wNumCoeff = le_int(&hdr[p + 28], 2);
92
93			x = p + 30;
94
95			for (i = 0; i < wNumCoeff; i++) {
96				coeff[i].coeff1 = (short)le_int(&hdr[x], 2);
97				x += 2;
98				coeff[i].coeff2 = (short)le_int(&hdr[x], 2);
99				x += 2;
100			}
101		}
102
103		p += n + 8;
104	}
105
106	if (p < l - 16 && memcmp(&hdr[p], "data", 4) == 0) {
107
108		dataleft = n = le_int(&hdr[p + 4], 4);
109		p += 8;
110
111/*
112 * Playback procedure
113 */
114#define	OUT_SAMPLE(s) {				\
115		if (s > 32767)			\
116			s = 32767;		\
117		else if (s < -32768)		\
118			s = -32768;		\
119		outbuf[outp++] = s;		\
120		n += 2;				\
121		}
122
123#define	GETNIBBLE					\
124		((nib == 0) ?				\
125		(buf[x + nib++] >> 4) & 0x0f : buf[x++ + --nib] & 0x0f)
126
127		outp = 0;
128
129		ppp = p;
130		while (dataleft > nBlockAlign) {
131			int predictor[2], delta[2], samp1[2], samp2[2];
132
133			int x = 0;
134
135			(void) memcpy(buf, &inbuf[ppp], nBlockAlign);
136			ppp += nBlockAlign;
137			dataleft -= nBlockAlign;
138
139			nib = 0;
140			n = 0;
141
142			for (i = 0; i < channels; i++) {
143				predictor[i] = buf[x];
144				x++;
145			}
146
147			for (i = 0; i < channels; i++) {
148				delta[i] = (short)le_int(&buf[x], 2);
149				x += 2;
150			}
151
152			for (i = 0; i < channels; i++) {
153				samp1[i] = (short)le_int(&buf[x], 2);
154				x += 2;
155				OUT_SAMPLE(samp1[i]);
156			}
157
158			for (i = 0; i < channels; i++) {
159				samp2[i] = (short)le_int(&buf[x], 2);
160				x += 2;
161				OUT_SAMPLE(samp2[i]);
162			}
163
164			while (n < (wSamplesPerBlock * 2 * channels))
165				for (i = 0; i < channels; i++) {
166					int pred, new, error_delta, i_delta;
167
168					pred = ((samp1[i] *
169					    coeff[predictor[i]].coeff1)
170					    + (samp2[i] *
171					    coeff[predictor[i]].coeff2)) / 256;
172					i_delta = error_delta = GETNIBBLE;
173
174					/* Convert to signed */
175					if (i_delta & 0x08)
176						i_delta -= 0x10;
177
178					new = pred + (delta[i] * i_delta);
179					OUT_SAMPLE(new);
180
181					delta[i] = delta[i] *
182					    AdaptionTable[error_delta] / 256;
183					if (delta[i] < 16)
184						delta[i] = 16;
185
186					samp2[i] = samp1[i];
187					samp1[i] = new;
188				}
189		}
190
191	}
192
193	return (outp * 2);
194}
195