1 /*
2 * raw2adpcm converts a raw sound data to adpcm compressed.
3 * This is based on adpcm.cpp found at http://www.openswf.org .
4 * The original code is the code posted on news:forums.macromedia.com by Jonathan Gay.
5 */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include "../src/blocks/input.h"
10 #include "../src/blocks/output.h"
11 #include "../src/libming.h"
12
13 /*
14 * ADPCM tables
15 */
16
17 static const int piIndexTable2[2] =
18 {
19 -1, 2,
20 };
21
22 static const int piIndexTable3[4] =
23 {
24 -1, -1, 2, 4,
25 };
26
27 static const int piIndexTable4[8] =
28 {
29 -1, -1, -1, -1, 2, 4, 6, 8,
30 };
31
32 static const int piIndexTable5[16] =
33 {
34 -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 4, 6, 8, 10, 13, 16,
35 };
36
37 static const int* ppiIndexTables[] =
38 {
39 piIndexTable2,
40 piIndexTable3,
41 piIndexTable4,
42 piIndexTable5
43 };
44
45 static const int piStepSizeTable[89] =
46 {
47 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
48 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
49 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
50 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
51 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
52 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
53 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
54 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
55 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
56 };
57
writeADPCMData(short * samples,int stereo,int sample_count,SWFOutput output)58 void writeADPCMData(short *samples, int stereo, int sample_count, SWFOutput output) {
59 int nBits = 4; /* number of bits per ADPCM sample */
60 int iSignBit = 1 << (nBits-1); /* Sign bit mask */
61 const int* piIndexTable = ppiIndexTables[nBits-2]; /* Select index table to use */
62
63 int iValPred[2] = {0, 0}; /* Predicted output value(s) */
64 int iIndex[2] = {0, 0}; /* Indeces int StepSizeTable */
65 int iStep[2] = {0, 0}; /* Step size */
66
67 int iSampleCount = sample_count; /* Number of samples. */
68 int iChannelCount = 1 + stereo; /* Number of channels (mono, stereo) */
69
70 short* psSample = samples; /* Pointer to start of 16-bit/sample data */
71
72 int i;
73
74 /* Write number of bits per ADPCM sample */
75 SWFOutput_writeBits(output, nBits-2, 2);
76
77 for (i=0; i < iSampleCount; i++) {
78 if ((i & 0xfff) == 0) {
79 int c;
80 for (c=0; c<iChannelCount; c++) {
81 /* First sample in the block, so no delta */
82 short sSample = *psSample++;
83 int iDiff;
84
85 /* Write full 16-bit sample */
86 SWFOutput_writeSBits(output, (int)sSample, 16); /* XXX - should be swapped? */
87 iValPred[c] = sSample;
88
89 /* Calculate initial index & step */
90 if (iSampleCount == 1) /* XXX - stereo OK? */
91 iDiff = abs(*psSample - sSample);
92 else
93 iDiff = abs(*(psSample+1) - sSample);
94 for (iIndex[c]=0; iIndex[c] < 88; iIndex[c]++)
95 if (iDiff <= piStepSizeTable[iIndex[c]])
96 break;
97
98 if (iIndex[c] > 63)
99 iIndex[c] = 63;
100
101 iStep[c] = piStepSizeTable[iIndex[c]];
102
103 /* Write initial index into StepSizeTable */
104 SWFOutput_writeBits(output, (int)iIndex[c], 6);
105 }
106 } else {
107 int c;
108 for (c=0; c<iChannelCount; c++) {
109 short sSample = *psSample++;
110 int iDiff, iSign, iDelta, iVPDiff;
111 int k;
112
113 /* Step 1 - compute difference with previous value */
114 iDiff = sSample - iValPred[c];
115
116 /* Make iDiff absolute value */
117 iSign = (iDiff < 0) ? iSignBit : 0;
118 if (iSign)
119 iDiff = (-iDiff);
120
121 /*
122 * Step 2 - Divide and clamp
123 * Note:
124 * This code *approximately* computes:
125 * iDelta = iDiff*4/iStep;
126 * iVPDiff = (iDelta+0.5)*iStep/4;
127 * but in shift step bits are dropped. The net result of this is
128 * that even if you have fast mul/div hardware you cannot put it to
129 * good use since the fixup would be too expensive.
130 */
131 iDelta = 0;
132 iVPDiff = (iStep[c] >> (nBits-1));
133
134 for (k = nBits-2; k >= 0; k--, iStep[c] >>= 1) {
135 if (iDiff >= iStep[c]) {
136 iDelta |= (1<<k);
137 iVPDiff += iStep[c];
138 if (k > 0)
139 iDiff -= iStep[c];
140 }
141 }
142
143 /* Step 3 - Update previous value */
144 if (iSign)
145 iValPred[c] -= iVPDiff;
146 else
147 iValPred[c] += iVPDiff;
148
149 /* Step 4 - Clamp previous value to 16 bits */
150 if (iValPred[c] > 32767)
151 iValPred[c] = 32767;
152 else if (iValPred[c] < -32768)
153 iValPred[c] = -32768;
154
155 /* Step 5 - Assemble value, update index and step values */
156 iIndex[c] += piIndexTable[iDelta];
157 iDelta |= iSign; /* Or with iSign *after* indexing */
158
159 /* Clamp StepSizeTable index */
160 if (iIndex[c] < 0) iIndex[c] = 0;
161 if (iIndex[c] > 88) iIndex[c] = 88;
162 iStep[c] = piStepSizeTable[iIndex[c]];
163
164 /* Step 6 - Output value */
165 SWFOutput_writeBits(output, iDelta, nBits);
166 }
167 }
168 }
169 }
170
main(int argc,char * argv[])171 int main(int argc, char *argv[])
172 {
173 FILE *fp_in, *fp_out;
174 SWFInput input;
175 SWFOutput output;
176 int bits16;
177 int stereo;
178 int sample_count;
179 short *samples, *i_sample;
180 int i;
181
182 if (argc < 3) {
183 printf(
184 "%s converts a raw sound data to adpcm compressed.\n"
185 "\n"
186 "Usage:\n"
187 "%s in out [16bit] [stereo]\n"
188 "\n"
189 "in : the filename of input file, raw sound data\n"
190 "out : the filename of output file, ADPCM compressed\n"
191 "16bit : bits per sample 0=8bit 1=16bit default=1=16bit\n"
192 "stereo : number of channels 0=mono 1=stereo default=1=stereo\n"
193 , argv[0], argv[0]);
194 exit(0);
195 }
196
197 fp_in = fopen(argv[1], "rb");
198 if (!fp_in) {
199 fprintf(stderr, "file '%s' cannot open.\n", argv[1]);
200 exit(1);
201 }
202 fp_out = fopen(argv[2], "wb");
203 if (!fp_out) {
204 fprintf(stderr, "file '%s' cannnot open.\n", argv[2]);
205 exit(1);
206 }
207 bits16 = 1;
208 if (argc > 3) bits16 = atoi(argv[3]);
209 stereo = 1;
210 if (argc > 4) stereo = atoi(argv[4]);
211
212 /* read RAW sound data */
213 input = newSWFInput_file(fp_in);
214 sample_count = SWFInput_length(input) / (1+bits16) / (1+stereo);
215 samples = malloc(sizeof(short) * sample_count * (1+stereo));
216 i_sample = samples;
217 for (i=0; i<sample_count*(1+stereo); i++) {
218 if (bits16 == 0) {
219 *i_sample = (short)SWFInput_getChar(input);
220 } else {
221 *i_sample = (short)SWFInput_getSInt16(input);
222 }
223 i_sample++;
224 }
225 destroySWFInput(input);
226 fclose(fp_in);
227
228 /* create a SWFOutput */
229 output = newSWFOutput();
230
231 writeADPCMData(samples, stereo, sample_count, output);
232
233 /* write to file */
234 SWFOutput_writeToMethod(output, fileOutputMethod, fp_out);
235
236 fclose(fp_out);
237
238 exit(0);
239 }
240