[Scummvm-cvs-logs] SF.net SVN: scummvm:[42021] tools/trunk

drmccoy at users.sourceforge.net drmccoy at users.sourceforge.net
Thu Jul 2 14:19:53 CEST 2009


Revision: 42021
          http://scummvm.svn.sourceforge.net/scummvm/?rev=42021&view=rev
Author:   drmccoy
Date:     2009-07-02 12:19:53 +0000 (Thu, 02 Jul 2009)

Log Message:
-----------
Adding compress_tinsel (patch #2815426 by m_kiewitz)

Modified Paths:
--------------
    tools/trunk/Makefile

Added Paths:
-----------
    tools/trunk/compress_tinsel.cpp

Modified: tools/trunk/Makefile
===================================================================
--- tools/trunk/Makefile	2009-07-02 12:15:04 UTC (rev 42020)
+++ tools/trunk/Makefile	2009-07-02 12:19:53 UTC (rev 42021)
@@ -68,6 +68,7 @@
 	compress_scumm_sou$(EXEEXT) \
 	compress_sword1$(EXEEXT) \
 	compress_sword2$(EXEEXT) \
+	compress_tinsel$(EXEEXT) \
 	compress_touche$(EXEEXT) \
 	compress_tucker$(EXEEXT) \
 	decine$(EXEEXT) \
@@ -144,6 +145,9 @@
 compress_sword2$(EXEEXT): compress_sword2.o compress.o util.o
 	$(CXX) $(LDFLAGS) -o $@ $+ -lvorbis -logg -lvorbisenc -lFLAC
 
+compress_tinsel$(EXEEXT): compress_tinsel.o compress.o util.o
+	$(CXX) $(LDFLAGS) -o $@ $+ -lvorbis -logg -lvorbisenc -lFLAC
+
 compress_touche$(EXEEXT): compress_touche.o compress.o util.o
 	$(CXX) $(LDFLAGS) -o $@ $+ -lvorbis -logg -lvorbisenc -lFLAC
 

Added: tools/trunk/compress_tinsel.cpp
===================================================================
--- tools/trunk/compress_tinsel.cpp	                        (rev 0)
+++ tools/trunk/compress_tinsel.cpp	2009-07-02 12:19:53 UTC (rev 42021)
@@ -0,0 +1,409 @@
+/* compress_tinsel - .smp compressor
+ * Copyright (C) 2009 The ScummVM Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+// By Jimi (m [underline] kiewitz [AT] users.sourceforge.net)
+
+#include "compress.h"
+#include "util.h"
+
+// data-format of index-file:
+//  [pointer to data file DWORD] [pointer to data file DWORD] [pointer to data file DWORD]
+//  we use index[0] to signal the engine what data format it's supposed to expect. It may be 'MP3 ', 'OGG ' or 'FLAC'
+
+// data-format of sample-file:
+//  [sample-length DWORD] [sample-data]
+//  or
+//  [subsamplecount DWORD] [sample-length DWORD] [sample-data]
+//   where subsamplecount has upmost bit 31 set (that's how one differentiates sample-length and subsamplecount)
+// It seems that data-format 1 is used by DiscWorld 1 and data-format 2 is used by DiscWorld 2. Also DiscWorld 1 uses
+//  raw-data as samples and DiscWorld 2 uses ADPCM 6-bit encoded data as samples. We suppose that we will need to do ADPCM
+//  decoding on all multi-sample data.
+
+// We also copy over the first 5000 bytes of the .smp file, because otherwise we would trash ScummVM detection.
+
+#define TEMP_IDX "compressed.idx"
+#define TEMP_SMP "compressed.smp"
+#define TEMP_RAW "tempfile.raw"
+#define TEMP_ENC "tempfile.enc"
+
+static FILE *input_idx, *input_smp, *output_idx, *output_smp;
+static CompressMode gCompMode = kMP3Mode;
+static char INPUT_IDX[256], INPUT_SMP[256];
+
+/* Converts raw-data sample in input_smp of size SampleSize to requested dataformat and writes to output_smp */
+void convertTinselRawSample (uint32 sampleSize) {
+	uint32 copyLeft = 0;
+	uint32 doneRead = 0;
+	char buffer[2048];
+    FILE *curFileHandle;
+
+	printf("Assuming DW1 sample being 8-bit raw...\n");
+
+	unlink(TEMP_RAW); unlink(TEMP_ENC);
+	curFileHandle = fopen(TEMP_RAW, "wb");
+	copyLeft = sampleSize;
+	while (copyLeft > 0) {
+		doneRead = fread(buffer, 1, copyLeft > sizeof(buffer) ? sizeof(buffer) : copyLeft, input_smp);
+		if (doneRead <= 0)
+			break;
+		copyLeft -= (int)doneRead;
+		fwrite(buffer, 1, doneRead, curFileHandle);
+	}
+	fclose(curFileHandle);
+
+	// Encode this raw data...
+	setRawAudioType(true, false, 8); // LE, mono, 8-bit (??)
+	encodeAudio(TEMP_RAW, true, 22050, TEMP_ENC, gCompMode);
+
+	// Append compressed data to output_smp
+	curFileHandle = fopen(TEMP_ENC, "rb");
+	fseek(curFileHandle, 0, SEEK_END);
+	copyLeft = ftell(curFileHandle);
+    fseek(curFileHandle, 0, SEEK_SET);
+	// Write size of compressed data
+	writeUint32LE(output_smp, copyLeft);
+	// Write actual data
+	while (copyLeft > 0) {
+		doneRead = fread(buffer, 1, copyLeft > sizeof(buffer) ? sizeof(buffer) : copyLeft, curFileHandle);
+		if (doneRead <= 0)
+			break;
+		copyLeft -= (int)doneRead;
+		fwrite(buffer, 1, doneRead, output_smp);
+	}
+	fclose(curFileHandle);
+}
+
+static const double TinselFilterTable[4][2] = {
+	{0, 0 },
+	{0.9375, 0},
+	{1.796875, -0.8125},
+	{1.53125, -0.859375}
+};
+
+template<typename T> inline T CLIP (T v, T amin, T amax)
+		{ if (v < amin) return amin; else if (v > amax) return amax; else return v; }
+
+/* Converts ADPCM-data sample in input_smp of size SampleSize to requested dataformat and writes to output_smp */
+/* Quick hack together from adpcm.cpp */
+void convertTinselADPCMSample (uint32 sampleSize) {
+	byte *inBuffer, *inPos;
+	int16 *outBuffer, *outPos;
+	double predictor = 0;
+	double k0 = 0, k1 = 0;
+	double d0 = 0, d1 = 0;
+	uint32 blockAlign, blockPos;
+	uint16 chunkData;
+	int16 chunkWord;
+	uint8 headerByte, filterVal, chunkPos;
+	const double eVal = 1.032226562;
+	uint32 decodeLeft = 0, decodedCount = 0;
+	uint32 uncompressedSize;
+	double sample;
+
+	uint32 copyLeft = 0;
+	uint32 doneRead = 0;
+	char buffer[2048];
+    FILE *curFileHandle;
+
+	printf("Assuming DW2 sample using ADPCM 6-bit, decoding to 16-bit raw...\n");
+
+	// Allocate buffer for the ADPCM-compressed sample
+	inBuffer = (byte *)malloc(sampleSize);
+	if (!inBuffer) {
+		printf("malloc failed!\n");
+		return;
+	}
+
+	// Allocate buffer for uncompressed sample data (3 bytes will be uncompressed to 8 bytes)
+	uncompressedSize = (sampleSize/3)*4*2+16;
+	outBuffer = (int16 *)malloc(uncompressedSize);
+	if (!outBuffer) {
+		printf("malloc failed!\n");
+		return;
+	}
+
+	fread(inBuffer, 1, sampleSize, input_smp);
+
+	// 1 channel, 22050 rate, block align 24,
+	blockAlign = 24; // Fixed for Tinsel 6-bit
+	blockPos = blockAlign; // To make sure first header is read
+
+	inPos = inBuffer; outPos = outBuffer;
+    decodeLeft = sampleSize;
+	while (decodeLeft > 0) {
+		if (blockPos == blockAlign) {
+			// read Tinsel header
+			headerByte = *inPos; inPos++; decodeLeft--;
+			filterVal = (headerByte & 0xC0) >> 6;
+
+			if ((headerByte & 0x20) != 0) {
+				//Lower 6 bit are negative
+				// Negate
+				headerByte = ~(headerByte | 0xC0) + 1;
+				predictor = 1 << headerByte;
+			} else {
+				// Lower 6 bit are positive
+				// Truncate
+				headerByte &= 0x1F;
+				predictor = ((double) 1.0) / (1 << headerByte);
+			}
+			k0 = TinselFilterTable[filterVal][0];
+			k1 = TinselFilterTable[filterVal][1];
+			blockPos = 0;
+			chunkPos = 0;
+		}
+
+		switch (chunkPos) {
+		case 0:
+			chunkData = *inPos; inPos++; decodeLeft--;
+			chunkWord = (chunkData << 8) & 0xFC00;
+			break;
+		case 1:
+			chunkData = (chunkData << 8) | *inPos; inPos++; decodeLeft--;
+			blockPos++;
+			chunkWord = (chunkData << 6) & 0xFC00;
+			break;
+		case 2:
+			chunkData = (chunkData << 8) | *inPos; inPos++; decodeLeft--;
+			blockPos++;
+			chunkWord = (chunkData << 4) & 0xFC00;
+			break;
+		case 3:
+			chunkData = chunkData << 8;
+			blockPos++;
+			chunkWord = (chunkData << 2) & 0xFC00;
+			break;
+		}
+		sample = chunkWord;
+		sample *= eVal * predictor;
+		sample += (d0 * k0) + (d1 * k1);
+		d1 = d0;
+		d0 = sample;
+        *outPos = (int16) CLIP<double>(sample, -32768.0, 32767.0); outPos++;
+		decodedCount++;
+		chunkPos = (chunkPos + 1) % 4;
+	}
+
+	unlink(TEMP_RAW); unlink(TEMP_ENC);
+	curFileHandle = fopen(TEMP_RAW, "wb");
+	fwrite(outBuffer, 1, decodedCount*2, curFileHandle);
+	fclose(curFileHandle);
+
+	free(inBuffer); free(outBuffer);
+
+	// Encode this raw data...
+	setRawAudioType(true, false, 16); // LE, mono, 16-bit
+	encodeAudio(TEMP_RAW, true, 22050, TEMP_ENC, gCompMode);
+
+	// Append compressed data to output_smp
+	curFileHandle = fopen(TEMP_ENC, "rb");
+	fseek(curFileHandle, 0, SEEK_END);
+	copyLeft = ftell(curFileHandle);
+    fseek(curFileHandle, 0, SEEK_SET);
+	// Write size of compressed data
+	writeUint32LE(output_smp, copyLeft);
+	// Write actual data
+	while (copyLeft > 0) {
+		doneRead = fread(buffer, 1, copyLeft > sizeof(buffer) ? sizeof(buffer) : copyLeft, curFileHandle);
+		if (doneRead <= 0)
+			break;
+		copyLeft -= (int)doneRead;
+		fwrite(buffer, 1, doneRead, output_smp);
+	}
+	fclose(curFileHandle);
+}
+
+void showhelp(char *exename) {
+	printf("\nUsage: %s [params] [file]\n", exename);
+
+	printf("\nParams:\n");
+	printf(" --mp3        encode to MP3 format (default)\n");
+	printf(" --vorbis     encode to Vorbis format\n");
+	printf(" --flac       encode to Flac format\n");
+	printf("(If one of these is specified, it must be the first parameter.)\n");
+
+	printf("\nMP3 mode params:\n");
+	printf(" -b <rate>    <rate> is the target bitrate(ABR)/minimal bitrate(VBR) (default:%d)\n", minBitrDef);
+	printf(" -B <rate>    <rate> is the maximum VBR/ABR bitrate (default:%d)\n", maxBitrDef);
+	printf(" --vbr        LAME uses the VBR mode (default)\n");
+	printf(" --abr        LAME uses the ABR mode\n");
+	printf(" -V <value>   specifies the value (0 - 9) of VBR quality (0=best) (default:%d)\n", vbrqualDef);
+	printf(" -q <value>   specifies the MPEG algorithm quality (0-9; 0=best) (default:%d)\n", algqualDef);
+	printf(" --silent     the output of LAME is hidden (default:disabled)\n");
+
+	printf("\nVorbis mode params:\n");
+	printf(" -b <rate>    <rate> is the nominal bitrate (default:unset)\n");
+	printf(" -m <rate>    <rate> is the minimum bitrate (default:unset)\n");
+	printf(" -M <rate>    <rate> is the maximum bitrate (default:unset)\n");
+	printf(" -q <value>   specifies the value (0 - 10) of VBR quality (10=best) (default:%d)\n", oggqualDef);
+	printf(" --silent     the output of oggenc is hidden (default:disabled)\n");
+
+	printf("\nFlac mode params:\n");
+ 	printf(" --fast       FLAC uses compression level 0\n");
+ 	printf(" --best       FLAC uses compression level 8\n");
+ 	printf(" -<value>     specifies the value (0 - 8) of compression (8=best)(default:%d)\n", flacCompressDef);
+ 	printf(" -b <value>   specifies a blocksize of <value> samples (default:%d)\n", flacBlocksizeDef);
+	printf(" --verify     files are encoded and then decoded to check accuracy\n");
+ 	printf(" --silent     the output of FLAC is hidden (default:disabled)\n");
+
+	printf("\n --help     this help message\n");
+
+	printf("\n\nIf a parameter is not given the default value is used\n");
+	printf("If using VBR mode for MP3 -b and -B must be multiples of 8; the maximum is 160!\n");
+	exit(2);
+}
+
+int main(int argc, char *argv[]) {
+	char inputPath[768];
+	int i;
+	uint32 indexNo = 0;
+	uint32 indexCount = 0;
+	uint32 indexOffset = 0;
+	uint32 loopCount = 0;
+	uint32 sampleSize = 0;
+	uint32 sampleCount = 0;
+
+	if (argc < 2) {
+		showhelp(argv[0]);
+	}
+
+	/* Compression mode */
+	gCompMode = kMP3Mode;
+	i = 1;
+
+	if (strcmp(argv[1], "--mp3") == 0) {
+		gCompMode = kMP3Mode;
+		i++;
+	} else if (strcmp(argv[1], "--vorbis") == 0) {
+		gCompMode = kVorbisMode;
+		i++;
+	} else if (strcmp(argv[1], "--flac") == 0) {
+		gCompMode = kFlacMode;
+		i++;
+	}
+
+	switch (gCompMode) {
+	case kMP3Mode:
+		if (!process_mp3_parms(argc, argv, i))
+			showhelp(argv[0]);
+		break;
+	case kVorbisMode:
+		if (!process_ogg_parms(argc, argv, i))
+			showhelp(argv[0]);
+		break;
+	case kFlacMode:
+		if (!process_flac_parms(argc, argv, i))
+			showhelp(argv[0]);
+		break;
+	}
+
+	getPath(argv[argc - 1], inputPath);
+
+	sprintf(INPUT_IDX, "%s.idx", argv[argc - 1]);
+	sprintf(INPUT_SMP, "%s.smp", argv[argc - 1]);
+
+	input_idx = fopen(INPUT_IDX, "rb");
+	if (!input_idx) {
+		printf("Cannot open file: %s\n", INPUT_IDX);
+		exit(-1);
+	}
+
+	input_smp = fopen(INPUT_SMP, "rb");
+	if (!input_smp) {
+		printf("Cannot open file: %s\n", INPUT_SMP);
+		exit(-1);
+	}
+
+	unlink(TEMP_IDX);
+	output_idx = fopen(TEMP_IDX, "wb");
+	if (!output_idx) {
+		printf("Can't open file " TEMP_IDX " for write!\n" );
+		exit(-1);
+	}
+	unlink(TEMP_SMP);
+	output_smp = fopen(TEMP_SMP, "wb");
+	if (!output_smp) {
+		printf("Can't open file " TEMP_SMP " for write!\n");
+		exit(-1);
+	}
+
+	fseek(input_idx, 0, SEEK_END);
+	indexCount = ftell(input_idx) / sizeof(uint32);
+    fseek(input_idx, 0, SEEK_SET);
+
+	loopCount = indexCount;
+	while (loopCount>0) {
+		indexOffset = readUint32LE(input_idx);
+		if (indexOffset) {
+			if (indexNo==0) {
+				printf("The sourcefiles are already compressed, aborting...\n");
+				return 1;
+			}
+			// Got sample(s), so convert...
+			printf("Converting sample %d of %d\n", indexNo, indexCount);
+
+			// Seek to Sample in input-file and read SampleSize
+			fseek(input_smp, indexOffset, SEEK_SET);
+			sampleSize = readUint32LE(input_smp);
+
+			// Write offset of new data to new index file
+			writeUint32LE(output_idx, ftell(output_smp));
+
+			if (sampleSize & 0x80000000) {
+				// multiple samples in ADPCM format
+				sampleCount = sampleSize & ~0x80000000;
+				// Write sample count to new sample file
+				writeUint32LE(output_smp, sampleSize);
+				while (sampleCount>0) {
+					sampleSize = readUint32LE(input_smp);
+					convertTinselADPCMSample(sampleSize);
+					sampleCount--;
+				}
+			} else {
+				// just one sample in raw format
+				convertTinselRawSample(sampleSize);
+			}
+		} else {
+			if (indexNo==0) {
+				// Write signature as index 0
+				switch (gCompMode) {
+				case kMP3Mode: writeUint32BE(output_idx, MKID_BE('MP3 ')); break;
+				case kVorbisMode: writeUint32BE(output_idx, MKID_BE('OGG ')); break;
+				case kFlacMode: writeUint32BE(output_idx, MKID_BE('FLAC')); break;
+				}
+			} else {
+				writeUint32LE(output_idx, 0);
+			}
+		}
+		loopCount--; indexNo++;
+	}
+	fclose(output_smp);
+	fclose(output_idx);
+	fclose(input_smp);
+	fclose(input_idx);
+
+	/* And some clean-up :-) */
+	unlink(TEMP_RAW);
+	unlink(TEMP_ENC);
+
+	return 0;
+}


Property changes on: tools/trunk/compress_tinsel.cpp
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list