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