1 /*
2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
4 
5 This file is part of GtkRadiant.
6 
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11 
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21 
22 // To do
23 
24 // Sound error handling (when sound too short)
25 // rle b4 huffing
26 // adpcm encoding of sound
27 
28 #if	0
29 #include "qdata.h"
30 #include "flex.h"
31 #include "fc.h"
32 #include "adpcm.h"
33 
34 #define	MIN_REPT	15
35 #define	MAX_REPT	0
36 #define	HUF_TOKENS	(256 + MAX_REPT)
37 
38 #define BLOCKSIZE	8
39 
40 #define M_PI		3.14159265358979323846	// matches value in gcc v2 math.h
41 #define SQRT2		1.414213562
42 
43 typedef struct hnode_s
44 {
45 	int			count;
46 	qboolean	used;
47 	int			children[2];
48 } hnode_t;
49 
50 typedef struct
51 {
52 	int			rate;
53 	int			width;
54 	int			channels;
55 	int			loopstart;
56 	int			samples;
57 	int			dataofs;		// chunk starts this many bytes from file start
58 } wavinfo_t;
59 
60 // These weren`t picked out my ass....
61 // They were defined at http://www.rahul.net/jfm/dct.html
62 // However, I think he plucked them out of his ass.....
63 
64 float Quantise[BLOCKSIZE * BLOCKSIZE];
65 
66 float LUT_Quantise[BLOCKSIZE * BLOCKSIZE] =
67 {
68 	16.0F/16.0F, 11.0F/16.0F, 10.0F/16.0F, 16.0F/16.0F, 24.0F/16.0F, 40.0F/16.0F, 51.0F/16.0F, 61.0F/16.0F,
69 	12.0F/16.0F, 13.0F/16.0F, 14.0F/16.0F, 19.0F/16.0F, 26.0F/16.0F, 58.0F/16.0F, 60.0F/16.0F, 55.0F/16.0F,
70 	14.0F/16.0F, 13.0F/16.0F, 16.0F/16.0F, 24.0F/16.0F, 40.0F/16.0F, 57.0F/16.0F, 69.0F/16.0F, 56.0F/16.0F,
71 	14.0F/16.0F, 17.0F/16.0F, 22.0F/16.0F, 29.0F/16.0F, 51.0F/16.0F, 87.0F/16.0F, 80.0F/16.0F, 62.0F/16.0F,
72 	18.0F/16.0F, 22.0F/16.0F, 37.0F/16.0F, 56.0F/16.0F, 68.0F/16.0F,109.0F/16.0F,103.0F/16.0F, 77.0F/16.0F,
73 	24.0F/16.0F, 35.0F/16.0F, 55.0F/16.0F, 64.0F/16.0F, 81.0F/16.0F,104.0F/16.0F,113.0F/16.0F, 92.0F/16.0F,
74 	49.0F/16.0F, 64.0F/16.0F, 78.0F/16.0F, 87.0F/16.0F,103.0F/16.0F,121.0F/16.0F,120.0F/16.0F,101.0F/16.0F,
75 	72.0F/16.0F, 92.0F/16.0F, 95.0F/16.0F, 98.0F/16.0F,112.0F/16.0F,100.0F/16.0F,103.0F/16.0F, 99.0F/16.0F
76 };
77 
78 int LUT_ZZ[BLOCKSIZE * BLOCKSIZE] =
79 {
80 	 0,
81 	 1,  8,
82 	16,  9,  2,
83 	 3, 10, 17, 24,
84 	32, 25, 18, 11,  4,
85 	 5, 12, 19, 26, 33, 40,
86 	48, 41, 34, 27, 20, 13, 6,
87 	 7, 14, 21, 28, 35, 42, 49, 56,
88 	57, 50, 43, 36, 29, 22, 15,
89 	23, 30, 37, 44, 51, 58,
90 	59, 52, 45, 38, 31,
91 	39, 46, 53, 60,
92 	61, 54, 47,
93 	55, 62,
94 	63
95 };
96 
97 char			base[32];
98 
99 byte			*soundtrack;
100 
101 byte			scaled[256][HUF_TOKENS];
102 unsigned int	charbits1[256][HUF_TOKENS];
103 int				charbitscount1[256][HUF_TOKENS];
104 hnode_t			hnodes1[256][HUF_TOKENS * 2];
105 int				numhnodes1[256];
106 int				order0counts[256];
107 int				numhnodes;
108 hnode_t			hnodes[512];
109 unsigned		charbits[256];
110 int				charbitscount[256];
111 
112 CineHead_t		cinehead;
113 
114 byte			*data_p;
115 byte			*iff_end;
116 byte			*last_chunk;
117 byte			*iff_data;
118 int				iff_chunk_len;
119 
120 float			dctbase[BLOCKSIZE][BLOCKSIZE];
121 float			red[BLOCKSIZE * BLOCKSIZE];
122 float			green[BLOCKSIZE * BLOCKSIZE];
123 float			blue[BLOCKSIZE * BLOCKSIZE];
124 float			temp[BLOCKSIZE * BLOCKSIZE];
125 
126 wavinfo_t		wavinfo;
127 adpcm_t			adpcm;
128 
129 /*
130 ===============================================================================
131 
132 WAV loading
133 
134 ===============================================================================
135 */
136 
137 /* Intel ADPCM step variation table */
138 static int indexTable[16] =
139 {
140 	-1, -1, -1, -1, 2, 4, 6, 8,
141 	-1, -1, -1, -1, 2, 4, 6, 8,
142 };
143 
144 static int stepsizeTable[89] =
145 {
146 	7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
147 	19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
148 	50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
149 	130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
150 	337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
151 	876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
152 	2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
153 	5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
154 	15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
155 };
156 
157 #if	0
158 static void adpcm_decoder(char *indata, short *outdata, int len, adpcm_state_t *state)
159 {
160 	signed char *inp;		/* Input buffer pointer */
161 	short *outp;		/* output buffer pointer */
162 	int sign;			/* Current adpcm sign bit */
163 	int delta;			/* Current adpcm output value */
164 	int step;			/* Stepsize */
165 	int valpred;		/* Predicted value */
166 	int vpdiff; 		/* Current change to valpred */
167 	int index;			/* Current step change index */
168 	int inputbuffer;		/* place to keep next 4-bit value */
169 	int bufferstep; 	/* toggle between inputbuffer/input */
170 
171 	outp = outdata;
172 	inp = (signed char *)indata;
173 
174 	valpred = state->valprev;
175 	index = state->index;
176 	step = stepsizeTable[index];
177 
178 	bufferstep = 0;
179 
180 	for(; len > 0; len--)
181 	{
182 		/* Step 1 - get the delta value */
183 		if (bufferstep)
184 			delta = inputbuffer & 0xf;
185 		else
186 		{
187 			inputbuffer = *inp++;
188 			delta = (inputbuffer >> 4) & 0xf;
189 		}
190 		bufferstep = !bufferstep;
191 
192 		/* Step 2 - Find new index value (for later) */
193 		index += indexTable[delta];
194 		if(index < 0)
195 			index = 0;
196 		if(index > 88)
197 			index = 88;
198 
199 		/* Step 3 - Separate sign and magnitude */
200 		sign = delta & 8;
201 		delta = delta & 7;
202 
203 		/* Step 4 - Compute difference and new predicted value */
204 		/*
205 		** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
206 		** in adpcm_coder.
207 		*/
208 		vpdiff = step >> 3;
209 		if(delta & 4)
210 			vpdiff += step;
211 		if(delta & 2)
212 			vpdiff += step>>1;
213 		if(delta & 1)
214 			vpdiff += step>>2;
215 
216 		if (sign)
217 		  valpred -= vpdiff;
218 		else
219 		  valpred += vpdiff;
220 
221 		/* Step 5 - clamp output value */
222 		if (valpred > 32767)
223 		  valpred = 32767;
224 		else if (valpred < -32768)
225 		  valpred = -32768;
226 
227 		/* Step 6 - Update step value */
228 		step = stepsizeTable[index];
229 
230 		/* Step 7 - Output value */
231 		*outp++ = valpred;
232 	}
233 
234 	state->valprev = valpred;
235 	state->index = index;
236 }
237 #endif
238 
239 void adpcm_coder(short *inp, adpcm_t *adpcm)
240 {
241 	int				val;			/* Current input sample value */
242 	int				sign;			/* Current adpcm sign bit */
243 	int				delta;			/* Current adpcm output value */
244 	int				diff;			/* Difference between val and valprev */
245 	int				step;			/* Stepsize */
246 	int				valpred;		/* Predicted output value */
247 	int				vpdiff; 		/* Current change to valpred */
248 	int				index;			/* Current step change index */
249 	int				outputbuffer;  	/* place to keep previous 4-bit value */
250 	int				bufferstep; 	/* toggle between outputbuffer/output */
251 	adpcm_state_t	*state;
252 	char			*outp;
253 	int				len;
254 
255 	state = &adpcm->state;
256 	len = state->count;
257 	outp = adpcm->adpcm;
258 
259 	valpred = state->in_valprev;
260 	index = state->in_index;
261 	step = stepsizeTable[index];
262 
263 	bufferstep = 1;
264 	while(len--)
265 	{
266 		val = *inp++;
267 
268 		/* Step 1 - compute difference with previous value */
269 		diff = val - valpred;
270 		sign = (diff < 0) ? 8 : 0;
271 		if (sign)
272 			diff = -diff;
273 
274 		/* Step 2 - Divide and clamp */
275 		/* Note:
276 		** This code *approximately* computes:
277 		**	  delta = diff*4/step;
278 		**	  vpdiff = (delta+0.5)*step/4;
279 		** but in shift step bits are dropped. The net result of this is
280 		** that even if you have fast mul/div hardware you cannot put it to
281 		** good use since the fixup would be too expensive.
282 		*/
283 		delta = 0;
284 		vpdiff = (step >> 3);
285 
286 		if (diff >= step)
287 		{
288 			delta = 4;
289 			diff -= step;
290 			vpdiff += step;
291 		}
292 		step >>= 1;
293 		if (diff >= step)
294 		{
295 			delta |= 2;
296 			diff -= step;
297 			vpdiff += step;
298 		}
299 		step >>= 1;
300 		if (diff >= step)
301 		{
302 			delta |= 1;
303 			vpdiff += step;
304 		}
305 
306 		/* Step 3 - Update previous value */
307 		if (sign)
308 		  valpred -= vpdiff;
309 		else
310 		  valpred += vpdiff;
311 
312 		/* Step 4 - Clamp previous value to 16 bits */
313 		if (valpred > 32767)
314 		  valpred = 32767;
315 		else if (valpred < -32768)
316 		  valpred = -32768;
317 
318 		/* Step 5 - Assemble value, update index and step values */
319 		delta |= sign;
320 
321 		index += indexTable[delta];
322 		if (index < 0)
323 			index = 0;
324 		if (index > 88)
325 			index = 88;
326 		step = stepsizeTable[index];
327 
328 		/* Step 6 - Output value */
329 		if (bufferstep)
330 			outputbuffer = (delta << 4) & 0xf0;
331 		else
332 			*outp++ = (delta & 0x0f) | outputbuffer;
333 
334 		bufferstep = !bufferstep;
335 	}
336 
337 	/* Output last step, if needed */
338 	if(!bufferstep)
339 	  *outp++ = outputbuffer;
340 
341 	state->out_valprev = valpred;
342 	state->out_index = index;
343 }
344 
345 void FindNextChunk(char *name)
346 {
347 	while(1)
348 	{
349 		data_p = last_chunk;
350 
351 		if(data_p >= iff_end)
352 		{								// didn't find the chunk
353 			data_p = NULL;
354 			return;
355 		}
356 
357 		data_p += 4;
358 		iff_chunk_len = *(long *)data_p;
359 		data_p += 4;
360 		if(iff_chunk_len < 0)
361 		{
362 			data_p = NULL;
363 			return;
364 		}
365 
366 		data_p -= 8;
367 		last_chunk = data_p + 8 + ((iff_chunk_len + 1) & ~1);
368 		if (!strncmp(data_p, name, 4))
369 			return;
370 	}
371 }
372 
373 void FindChunk(char *name)
374 {
375 	last_chunk = iff_data;
376 	FindNextChunk (name);
377 }
378 
379 void DumpChunks(void)
380 {
381 	char	str[5];
382 
383 	str[4] = 0;
384 	data_p = iff_data;
385 	do
386 	{
387 		memcpy (str, data_p, 4);
388 		data_p += 4;
389 		iff_chunk_len = *(long *)data_p;
390 		data_p += 4;
391 		printf ("0x%x : %s (%d)\n", (int)(data_p - 4), str, iff_chunk_len);
392 		data_p += (iff_chunk_len + 1) & ~1;
393 	}
394 	while(data_p < iff_end);
395 }
396 
397 /*
398 ============
399 GetWavinfo
400 ============
401 */
402 wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength)
403 {
404 	wavinfo_t	info;
405 	int			i;
406 	int			format;
407 	int			samples;
408 
409 	memset(&info, 0, sizeof(info));
410 
411 	if (!wav)
412 		return(info);
413 
414 	iff_data = wav;
415 	iff_end = wav + wavlength;
416 
417 // find "RIFF" chunk
418 	FindChunk("RIFF");
419 	if (!(data_p && !strncmp(data_p + 8, "WAVE", 4)))
420 	{
421 		printf("Missing RIFF/WAVE chunks\n");
422 		return(info);
423 	}
424 
425 // get "fmt " chunk
426 	iff_data = data_p + 12;
427 
428 	FindChunk("fmt ");
429 	if(!data_p)
430 	{
431 		printf("Missing fmt chunk\n");
432 		return(info);
433 	}
434 	data_p += 8;
435 	format = *(short *)data_p;
436 	data_p += 2;
437 	if (format != 1)
438 	{
439 		printf("Microsoft PCM format only\n");
440 		return(info);
441 	}
442 
443 	info.channels = *(short *)data_p;
444 	data_p += 2;
445 	info.rate = *(long *)data_p;
446 	data_p += 4;
447 	data_p += 6;
448 	info.width = *(short *)data_p / 8;
449 	data_p += 2;
450 
451 // get cue chunk
452 	FindChunk("cue ");
453 	if(data_p)
454 	{
455 		data_p += 32;
456 		info.loopstart = *(long *)data_p;
457 		data_p += 4;
458 
459 // if the next chunk is a LIST chunk, look for a cue length marker
460 		FindNextChunk ("LIST");
461 		if(data_p)
462 		{
463 // this is not a proper parse, but it works with cooledit...
464 			if (!strncmp (data_p + 28, "mark", 4))
465 			{
466 				data_p += 24;
467 				i = *(long *)data_p;					// samples in loop
468 				data_p += 4;
469 				info.samples = info.loopstart + i;
470 			}
471 		}
472 	}
473 	else
474 		info.loopstart = -1;
475 
476 // find data chunk
477 	FindChunk("data");
478 	if (!data_p)
479 	{
480 		printf("Missing data chunk\n");
481 		return(info);
482 	}
483 
484 	data_p += 4;
485 	samples = *(long *)data_p;
486 	data_p += 4;
487 
488 	if (info.samples)
489 	{
490 		if(samples < info.samples)
491 			Error ("Sound %s has a bad loop length", name);
492 	}
493 	else
494 		info.samples = samples;
495 
496 	info.dataofs = data_p - wav;
497 	return(info);
498 }
499 
500 // ==============
501 // LoadSoundtrack
502 // ==============
503 
504 void LoadSoundtrack()
505 {
506 	char	name[1024];
507 	FILE	*f;
508 	int		len;
509 
510 	soundtrack = NULL;
511 	sprintf (name, "%svideo/%s/%s.wav", gamedir, base, base);
512 	printf ("\nLoading sound    : %s\n", name);
513 	f = fopen (name, "rb");
514 	if (!f)
515 	{
516 		printf ("\nNo soundtrack for %s\n", base);
517 		return;
518 	}
519 	len = Q_filelength(f);
520 	soundtrack = SafeMalloc(len, "LoadSoundtrack");
521 	fread(soundtrack, 1, len, f);
522 	fclose(f);
523 
524 	wavinfo = GetWavinfo(name, soundtrack, len);
525 	adpcm.state.out_valprev = 0;
526 	adpcm.state.out_index = 0;
527 }
528 
529 // ==================
530 // WriteSound
531 // ==================
532 
533 int WriteSound(FILE *output, int frame, int numframes)
534 {
535 	int		start, end;
536 	int		count;
537 	int		empty = 0;
538 	int		width;
539 	char	*work;
540 
541 	width = wavinfo.width * wavinfo.channels;
542 	start = ((frame * wavinfo.rate / 14) + 31) & 0xffffffe0;				// start sample
543 	end = (((frame + numframes) * wavinfo.rate / 14) + 31) & 0xffffffe0;	// end sample
544 	count = end - start;
545 
546 	work = soundtrack + wavinfo.dataofs + (start * width);
547 	adpcm.state.count = count * wavinfo.channels;			// Number of samples
548 	adpcm.state.in_valprev = adpcm.state.out_valprev;
549 	adpcm.state.in_index = adpcm.state.out_index;
550 	adpcm_coder((short *)work, &adpcm);
551 	WriteHeader(output, FC_SOUND_22KMADPCM, FC_ADPCM_VERSION, (adpcm.state.count / 2) + sizeof(adpcm_state_t), (char *)&adpcm);
552 	return(count / 2);
553 }
554 // ==============================
555 // Basic run length encoder
556 // ==============================
557 
558 char *RLEZZ(char *in, char *out)
559 {
560 	int		srun;
561 	char	count;
562 	int		idx = 0;
563 
564 	while(idx < 64)
565 	{
566 		srun = idx;								// Start of run
567 
568 		while(idx < 63)
569 		{
570 			if(in[LUT_ZZ[idx]] != in[LUT_ZZ[idx + 1]])
571 				break;
572 			idx++;
573 		}
574 		count = (char)(idx - srun);				// count of repeated bytes
575 
576 		if(!count)
577 		{
578 			while(idx < 63)
579 			{
580 				if(in[LUT_ZZ[idx]] == in[LUT_ZZ[idx + 1]])
581 					break;
582 				idx++;
583 			}
584 			if(idx == 63)
585 				idx++;
586 
587 			count = (char)(idx - srun);			// count of unique bytes
588 			*out++ = count;
589 			while(count--)
590 				*out++ = in[LUT_ZZ[srun++]];
591 		}
592 		else
593 		{
594 			*out++ = -(count + 1);
595 			*out++ = in[LUT_ZZ[idx]];
596 			idx++;
597 		}
598 	}
599 	return(out);
600 }
601 
602 // ==============================
603 // Discrete Cosine Transformation
604 // ==============================
605 
606 void init_base(float quant)
607 {
608 	int			y, x;
609 
610 	for(y = 0; y < BLOCKSIZE; y++)
611 		for(x = 0; x < BLOCKSIZE; x++)
612 		{
613 			if(y == 0)
614 				dctbase[y][x] = 1;
615 			else
616 				dctbase[y][x] = SQRT2 * cos(((x * 2 + 1) * y * M_PI) / (BLOCKSIZE * 2));
617 		}
618 
619 	for(y = 0; y < BLOCKSIZE * BLOCKSIZE; y++)
620 		Quantise[y] = LUT_Quantise[y] / quant;
621 }
622 
623 void SplitComponents(byte *src, int width, int height)
624 {
625 	int		i, j;
626 	float	*tr = red;
627 	float	*tg = green;
628 	float	*tb = blue;
629 
630 	for(i = 0; i < BLOCKSIZE; i++, src += (width - BLOCKSIZE) * 4)
631 		for(j = 0; j < BLOCKSIZE; j++)
632 		{
633 			*tr++ = ((float)*src++) - 128.0F;
634 			*tg++ = ((float)*src++) - 128.0F;
635 			*tb++ = ((float)*src++) - 128.0F;
636 			src++;
637 		}
638 }
639 
640 void transferH(float *src, float *dst)
641 {
642 	int		y, dx, dy;
643 	float	sum;
644 	float	*work;
645 
646 	for(y = 0; y < BLOCKSIZE; y++, src += BLOCKSIZE)
647 	{
648 		for(dy = 0; dy < BLOCKSIZE; dy++)
649 		{
650 			sum = 0;
651 			work = src;
652 			for(dx = 0; dx < BLOCKSIZE; dx++, work++)
653 				sum += dctbase[dy][dx] * *work;
654 
655 			*dst++ = sum / BLOCKSIZE;
656 		}
657 	}
658 }
659 
660 void transferV(float *src, float *dst)
661 {
662 	int		x, dy, fy;
663 	float	sum;
664 	float	*work;
665 
666 	for(x = 0; x < BLOCKSIZE; x++, src++, dst++)
667 	{
668 		for(fy = 0; fy < BLOCKSIZE; fy++)
669 		{
670 			sum = 0;
671 			work = src;
672 			for(dy = 0; dy < BLOCKSIZE; dy++, work += BLOCKSIZE)
673 				sum += dctbase[fy][dy] * *work;
674 
675 			dst[fy * BLOCKSIZE] = sum / BLOCKSIZE;
676 		}
677 	}
678 }
679 
680 char *Combine(byte *dst, float *p, float *q)
681 {
682 	int		i, j;
683 	byte	rlesrc[BLOCKSIZE * BLOCKSIZE];
684  	int		c;
685 	byte	*work;
686 
687 	work = rlesrc;
688 	for(j = 0; j < BLOCKSIZE; j++)
689 		for(i = 0; i < BLOCKSIZE; i++)
690 		{
691 			c = (int)((*p++ / *q++) + 128.5F);
692 			c -= 128;
693 
694 			if(c < -128)
695 				c = -128;
696 			if(c > 127)
697 				c = 127;
698 
699 			*work++ = (char)c;
700 		}
701 
702 	dst = RLEZZ(rlesrc, dst);
703 	return(dst);
704 }
705 
706 char *CombineComponents(char *dst, int width, int height)
707 {
708 	dst = Combine(dst, red, Quantise);
709 	dst = Combine(dst, green, Quantise);
710 	dst = Combine(dst, blue, Quantise);
711 	return(dst);
712 }
713 
714 void DCT(cblock_t *out, cblock_t in, int width, int height)
715 {
716 	int		x, y;
717 	char	*cursrc;
718 	char	*curdst;
719 
720 	curdst = out->data;
721 	for(y = 0; y < height; y += BLOCKSIZE)
722 		for(x = 0; x < width; x += BLOCKSIZE)
723 		{
724 			cursrc = in.data + ((y * width) + x) * 4;
725 			SplitComponents(cursrc, width, height);
726 			transferH(red, temp);
727 			transferV(temp, red);
728 			transferH(green, temp);
729 			transferV(temp, green);
730 			transferH(blue, temp);
731 			transferV(temp, blue);
732 			curdst = CombineComponents(curdst, width, height);
733 		}
734 	out->count = curdst - out->data;
735 }
736 
737 // ==================
738 // BuildChars1
739 // ==================
740 
741 void BuildChars1(int prev, int nodenum, unsigned bits, int bitcount)
742 {
743 	hnode_t		*node;
744 
745 	if(nodenum < HUF_TOKENS)
746 	{
747 		if (bitcount > 32)
748 			Error("bitcount > 32");
749 		charbits1[prev][nodenum] = bits;
750 		charbitscount1[prev][nodenum] = bitcount;
751 		return;
752 	}
753 
754 	node = &hnodes1[prev][nodenum];
755 	bits <<= 1;
756 	BuildChars1(prev, node->children[0], bits, bitcount+1);
757 	bits |= 1;
758 	BuildChars1(prev, node->children[1], bits, bitcount+1);
759 }
760 
761 // ==================
762 // SmallestNode1
763 // ==================
764 
765 int	SmallestNode1(hnode_t *hnodes, int numhnodes)
766 {
767 	int		i;
768 	int		best, bestnode;
769 
770 	best = 99999999;
771 	bestnode = -1;
772 	for(i = 0; i < numhnodes; i++)
773 	{
774 		if(hnodes[i].used)
775 			continue;
776 		if(!hnodes[i].count)
777 			continue;
778 		if(hnodes[i].count < best)
779 		{
780 			best = hnodes[i].count;
781 			bestnode = i;
782 		}
783 	}
784 
785 	if (bestnode == -1)
786 		return(-1);
787 
788 	hnodes[bestnode].used = true;
789 	return(bestnode);
790 }
791 
792 // ==================
793 // BuildTree1
794 // ==================
795 
796 void BuildTree1(int prev)
797 {
798 	hnode_t		*node, *nodebase;
799 	int			numhnodes;
800 
801 	// build the nodes
802 	numhnodes = HUF_TOKENS;
803 	nodebase = hnodes1[prev];
804 	while(1)
805 	{
806 		node = &nodebase[numhnodes];
807 
808 		// pick two lowest counts
809 		node->children[0] = SmallestNode1 (nodebase, numhnodes);
810 		if (node->children[0] == -1)
811 			break;	// no more
812 
813 		node->children[1] = SmallestNode1 (nodebase, numhnodes);
814 		if (node->children[1] == -1)
815 			break;
816 
817 		node->count = nodebase[node->children[0]].count +
818 			nodebase[node->children[1]].count;
819 		numhnodes++;
820 	}
821 	numhnodes1[prev] = numhnodes-1;
822 	BuildChars1 (prev, numhnodes-1, 0, 0);
823 }
824 
825 // ==================
826 // Huffman1_Count
827 // ==================
828 
829 void Huffman1_Count(cblock_t in)
830 {
831 	int		i;
832 	int		prev;
833 	int		v;
834 	int		rept;
835 
836 	prev = 0;
837 	for(i = 0; i < in.count; i++)
838 	{
839 		v = in.data[i];
840 		order0counts[v]++;
841 		hnodes1[prev][v].count++;
842 		prev = v;
843 
844 		for(rept = 1; (i + rept < in.count) && (rept < MAX_REPT); rept++)
845 			if(in.data[i+rept] != v)
846 				break;
847 		if(rept > MIN_REPT)
848 		{
849 			hnodes1[prev][255 + rept].count++;
850 			i += rept - 1;
851 		}
852 	}
853 }
854 
855 // ==================
856 // Huffman1_Build
857 // ==================
858 
859 void Huffman1_Build()
860 {
861 	int		i, j, v;
862 	int		max;
863 	int		total;
864 
865 	for(i = 0; i < 256; i++)
866 	{
867 // normalize and save the counts
868 		max = 0;
869 		for (j = 0; j < HUF_TOKENS; j++)
870 		{
871 			if (hnodes1[i][j].count > max)
872 				max = hnodes1[i][j].count;
873 		}
874 		if (max == 0)
875 			max = 1;
876 		total = 0;
877 // easy to overflow 32 bits here!
878 		for(j = 0; j < HUF_TOKENS; j++)
879 		{
880 			v = (hnodes1[i][j].count * (double) 255 + max - 1) / max;
881 			if (v > 255)
882 				Error ("v > 255");
883 			scaled[i][j] = hnodes1[i][j].count = v;
884 			if (v)
885 				total++;
886 		}
887 		if (total == 1)
888 		{	// must have two tokens
889 			if (!scaled[i][0])
890 				scaled[i][0] = hnodes1[i][0].count = 1;
891 			else
892 				scaled[i][1] = hnodes1[i][1].count = 1;
893 		}
894 		BuildTree1 (i);
895 	}
896 }
897 
898 // ==================
899 // Huffman1
900 // Order 1 compression with pre-built table
901 // ==================
902 
903 cblock_t Huffman1(cblock_t in)
904 {
905 	int			i;
906 	int			outbits, c;
907 	unsigned	bits;
908 	byte		*out_p;
909 	cblock_t	out;
910 	int			prev;
911 	int			v;
912 	int			rept;
913 
914 	out_p = out.data = SafeMalloc((in.count * 2) + 1024 + 4, "Huffman");
915 	memset(out_p, 0, (in.count * 2) + 1024 + 4);
916 
917 	// leave space for compressed count
918 	out_p += 4;
919 	// write count
920 	*(long *)out_p = in.count;
921 	out_p += 4;
922 
923 	// write bits
924 	outbits = 0;
925 	prev = 0;
926 	for(i = 0; i < in.count; i++)
927 	{
928 		v = in.data[i];
929 
930 		c = charbitscount1[prev][v];
931 		bits = charbits1[prev][v];
932 		if (!c)
933 			Error ("!bits");
934 		while (c)
935 		{
936 			c--;
937 			if (bits & (1 << c))
938 				out_p[outbits>>3] |= 1 << (outbits & 7);
939 			outbits++;
940 		}
941 
942 		prev = v;
943 		// check for repeat encodes
944 		for(rept = 1; (i + rept < in.count) && (rept < MAX_REPT); rept++)
945 			if(in.data[i + rept] != v)
946 				break;
947 		if (rept > MIN_REPT)
948 		{
949 			c = charbitscount1[prev][255 + rept];
950 			bits = charbits1[prev][255 + rept];
951 			if (!c)
952 				Error ("!bits");
953 			while (c)
954 			{
955 				c--;
956 				if(bits & (1 << c))
957 					out_p[outbits >> 3] |= 1 << (outbits & 7);
958 				outbits++;
959 			}
960 			i += rept - 1;
961 		}
962 	}
963 	out_p += (outbits + 7) >> 3;
964 	out.count = out_p - out.data;
965 
966 	out_p = out.data;
967 	*(long *)out_p = out.count;
968 	return(out);
969 }
970 // ===================
971 // LoadFrame
972 // ===================
973 
974 void LoadFrame(cblock_t *out, char *base, int frame)
975 {
976 	cblock_t	in;
977 	int			width, height;
978 	char		name[1024];
979 	FILE		*f;
980 
981 	in.data = NULL;
982 	in.count = -1;
983 	sprintf (name, "%svideo/%s/%s%04i.tga", gamedir, base, base, frame);
984 
985 	f = fopen(name, "rb");
986 	if (!f)
987 	{
988 		out->data = NULL;
989 		return;
990 	}
991 	fclose (f);
992 
993 	LoadTGA(name, &in.data, &width, &height);
994 	if((width != cinehead.Width) || (height != cinehead.Height))
995 	{
996 		free(in.data);
997 		printf("Invalid picture size\n");
998 		out->data = NULL;
999 		return;
1000 	}
1001 	out->data = SafeMalloc(width * height * 3, "LoadFrame");		// rle could possibly expand file so this not 100% safe (however DCT should force a lot of compression)
1002 	DCT(out, in, width, height);
1003 	free(in.data);
1004 }
1005 
1006 // ==================================
1007 // Cmd_Video
1008 //
1009 // video <directory> <framedigits>
1010 // ==================================
1011 
1012 void Cmd_Video()
1013 {
1014 	char		savename[256];
1015 	char		name[256];
1016 	FILE		*output;
1017 	int			frame;
1018 	int			width, height;
1019 	cblock_t	in, huffman;
1020 	int			size;
1021 	float		dctconst;
1022 	int			maxsize, ssize;
1023 	int			min_rle_size, warnings;
1024 	int			ave_image, ave_sound;
1025 
1026 	GetScriptToken(false);
1027 	strcpy(base, token);
1028 	if (g_release)
1029 		return;
1030 
1031 	GetScriptToken(false);
1032 	dctconst = atof(token);
1033 	GetScriptToken(false);
1034 	maxsize = atoi(token);
1035 
1036 	sprintf (savename, "%svideo/%s.cin", gamedir, base);
1037 
1038 	// clear stuff
1039 	memset(charbits1, 0, sizeof(charbits1));
1040 	memset(charbitscount1, 0, sizeof(charbitscount1));
1041 	memset(hnodes1, 0, sizeof(hnodes1));
1042 	memset(numhnodes1, 0, sizeof(numhnodes1));
1043 	memset(order0counts, 0, sizeof(order0counts));
1044 
1045 	// load the entire sound wav file if present
1046 	LoadSoundtrack();
1047 
1048 	cinehead.SndRate = wavinfo.rate;
1049 	cinehead.SndWidth = wavinfo.width;
1050 	cinehead.SndChannels = wavinfo.channels;
1051 
1052 	sprintf(name, "%svideo/%s/%s0000.tga", gamedir, base, base);
1053 	printf("Loading sequence : %s\n", name);
1054 	printf("DCT constant     : %f\n", dctconst);
1055 
1056 	LoadTGA (name, NULL, &width, &height);
1057 
1058 	output = fopen (savename, "wb");
1059 	if (!output)
1060 		Error ("Can't open %s", savename);
1061 
1062 	if((width % BLOCKSIZE) || (height % BLOCKSIZE))
1063 		Error("Width and height must be a multiple of %d", BLOCKSIZE);
1064 
1065 	cinehead.Width = width;
1066 	cinehead.Height = height;
1067 	init_base(dctconst);
1068 
1069 	// build the dictionary
1070 	printf("Counting         : ");
1071 	min_rle_size = 0;
1072 	for (frame = 0;  ; frame++)
1073 	{
1074 		printf(".");
1075 		LoadFrame(&in, base, frame);
1076 		if(!in.data)
1077 			break;
1078 		Huffman1_Count(in);
1079 		if(in.count > min_rle_size)
1080 			min_rle_size = in.count;
1081 		free(in.data);
1082 	}
1083 	printf ("\n");
1084 	cinehead.NumFrames = frame;
1085 	printf("Num Frames       : %d\n", frame);
1086 	cinehead.MaxRleSize = (min_rle_size + 0x1f) & 0xfffffe0;
1087 	cinehead.MaxSndSize = ((4 * wavinfo.rate * wavinfo.channels / 14) + 0x1f) & 0xffffffe0;
1088 
1089 	WriteHeader(output, FC_HEADER_NAME, FC_HEADER_VERSION, sizeof(CineHead_t), &cinehead);
1090 
1091 	// build nodes and write counts
1092 	Huffman1_Build();
1093 	WriteHeader(output, FC_HUFFBITS_NAME, FC_HUFFBITS_VERSION, sizeof(scaled), scaled);
1094 	WriteHeader(output, FC_QUANT_NAME, FC_QUANT_VERSION, sizeof(Quantise), Quantise);
1095 
1096 	ave_image = 0;
1097 	ave_sound = 0;
1098 	warnings = 0;
1099 	// compress it with the dictionary
1100 	if(soundtrack)
1101 	{
1102 		ssize = WriteSound(output, frame, 4);
1103 		ave_sound += ssize;
1104 	}
1105 
1106 	for (frame = 0; frame < cinehead.NumFrames; frame++)
1107 	{
1108 		// save some sound samples
1109 		printf ("Packing          : ", frame);
1110 		LoadFrame(&in, base, frame);
1111 
1112 		// save the image
1113 		huffman = Huffman1(in);
1114 		printf ("%d bytes rle, %d bytes huffman", in.count, huffman.count);
1115 		size = (huffman.count + 3) & 0xfffffffc;					// round up to longwords
1116 		if(size > maxsize)
1117 		{
1118 			printf(" ** WARNING **");
1119 			warnings++;
1120 		}
1121 		printf("\n");
1122 		ave_image += huffman.count;
1123 
1124 		WriteHeader(output, FC_IMAGE_NAME, FC_IMAGE_VERSION, size, huffman.data);
1125 		if(soundtrack)
1126 		{
1127 			ssize = WriteSound(output, frame + 4, 1);
1128 			ave_sound += ssize;
1129 		}
1130 
1131 		free (in.data);
1132 		free (huffman.data);
1133 	}
1134 	printf("\nTotal size: %d (headers + %d image + %d sound)\n", ftell(output), ave_image, ave_sound);
1135 	printf("Data rate : %d bytes per sec (image and sound)\n", (ave_image + ave_sound) / cinehead.NumFrames);
1136 	printf("Cin created ok with %d warnings.\n", warnings);
1137 	fclose (output);
1138 
1139 	if (soundtrack)
1140 		free (soundtrack);
1141 }
1142 #endif
1143 
Cmd_Video()1144 void Cmd_Video()
1145 {
1146 }
1147 
1148 // end
1149 
1150