[Scummvm-cvs-logs] SF.net SVN: scummvm: [28592] scummvm/trunk/engines/agi/sound.cpp

buddha_ at users.sourceforge.net buddha_ at users.sourceforge.net
Mon Aug 13 16:06:30 CEST 2007


Revision: 28592
          http://scummvm.svn.sourceforge.net/scummvm/?rev=28592&view=rev
Author:   buddha_
Date:     2007-08-13 07:06:30 -0700 (Mon, 13 Aug 2007)

Log Message:
-----------
Added more functions to help with determining the Apple IIGS samples' real lengths.

Modified Paths:
--------------
    scummvm/trunk/engines/agi/sound.cpp

Modified: scummvm/trunk/engines/agi/sound.cpp
===================================================================
--- scummvm/trunk/engines/agi/sound.cpp	2007-08-13 14:04:50 UTC (rev 28591)
+++ scummvm/trunk/engines/agi/sound.cpp	2007-08-13 14:06:30 UTC (rev 28592)
@@ -123,7 +123,7 @@
 	return !stream.ioFailed();
 }
 
-bool readIIgsWaveInfo(IIgsWaveInfo &waveInfo, Common::SeekableReadStream &stream) {
+bool readIIgsWaveInfo(IIgsWaveInfo &waveInfo, Common::SeekableReadStream &stream, bool ignoreAddr = false) {
 	waveInfo.top      = stream.readByte();
 	waveInfo.addr     = stream.readByte() * 256;
 	waveInfo.size     = (1 << (stream.readByte() & 7)) * 256;
@@ -135,6 +135,11 @@
 	waveInfo.halt     = (mode & 1) != 0; // Bit 0 (Converted to boolean)
 
 	waveInfo.relPitch = stream.readUint16BE();
+
+	// Zero the wave address if we want to ignore the wave address info
+	if (ignoreAddr)
+		waveInfo.addr = 0;
+
 	return !stream.ioFailed();
 }
 
@@ -142,9 +147,10 @@
  * Read an Apple IIGS instrument header from the given stream.
  * @param header The header to which to write the data.
  * @param stream The source stream from which to read the data.
+ * @param ignoreAddr Should we ignore wave infos' wave address variable's value?
  * @return True if successful, false otherwise.
  */
-bool readIIgsInstrumentHeader(IIgsInstrumentHeader &header, Common::SeekableReadStream &stream) {
+bool readIIgsInstrumentHeader(IIgsInstrumentHeader &header, Common::SeekableReadStream &stream, bool ignoreAddr = false) {
 	readIIgsEnvelope(header.env, stream);
 	header.relseg    = stream.readByte();
 	header.priority  = stream.readByte();
@@ -155,9 +161,9 @@
 	header.wac       = stream.readByte();
 	header.wbc       = stream.readByte();
 	for (int waveA = 0; waveA < header.wac; waveA++) // Read A wave lists
-		readIIgsWaveInfo(header.wal[waveA], stream);
+		readIIgsWaveInfo(header.wal[waveA], stream, ignoreAddr);
 	for (int waveB = 0; waveB < header.wbc; waveB++) // Read B wave lists
-		readIIgsWaveInfo(header.wbl[waveB], stream);
+		readIIgsWaveInfo(header.wbl[waveB], stream, ignoreAddr);
 	return !stream.ioFailed();
 }
 
@@ -175,28 +181,54 @@
 	header.unknownByte_Ofs5 = stream.readByte();
 	header.instrumentSize   = stream.readUint16LE();
 	header.sampleSize       = stream.readUint16LE();
-	return readIIgsInstrumentHeader(header.instrument, stream);
+	// Read the instrument headers *ignoring* their wave address info
+	return readIIgsInstrumentHeader(header.instrument, stream, true);
 }
 
 /**
  * Calculates an Apple IIGS sample's true size.
  * Needed because a zero byte in the sample data ends the sample prematurely.
  */
-uint calcTrueSampleSize(byte *sample, uint size) {
-	if (sample == NULL) { // Check for an erroneous input value
-		warning("Agi::calcTrueSampleSize: A NULL-pointer parameter");
-		return size; // Might as well return 0
-	} else { // Input values are ok
-		// Search for a zero byte in the sample data,
-		// as that would end the sample prematurely.
-		for (uint i = 0; i < size; i++)
-			if (sample[i] == 0)
-				return i;
-		// If no zero was found in the sample, then return its whole size.
-		return size;
-	}
+uint calcTrueSampleSize(Common::SeekableReadStream &sample, uint size) {
+	// Search for a zero byte in the sample data,
+	// as that would end the sample prematurely.
+	for (uint i = 0; i < size; i++)
+		if (sample.readByte() == 0)
+			return i;
+	// If no zero was found in the sample, then return its whole size.
+	return size;
 }
 
+bool finalizeWaveInfo(IIgsWaveInfo &waveInfo, Common::SeekableReadStream &uint8Wave) {
+	uint32 startPos = uint8Wave.pos(); // Save stream's starting position
+	uint8Wave.seek(waveInfo.addr, SEEK_CUR); // Seek to wave's address
+	// Calculate the true sample size (A zero ends the sample prematurely)
+	waveInfo.size = calcTrueSampleSize(uint8Wave, waveInfo.size);
+	uint8Wave.seek(startPos); // Seek back to the stream's starting position
+	return true;
+}
+
+bool finalizeInstrument(IIgsInstrumentHeader &header, Common::SeekableReadStream &uint8Wave) {
+	for (int waveA = 0; waveA < header.wac; waveA++) // Finalize A-waves
+		if (!finalizeWaveInfo(header.wal[waveA], uint8Wave))
+			return false;
+	for (int waveB = 0; waveB < header.wbc; waveB++) // Finalize B-waves
+		if (!finalizeWaveInfo(header.wbl[waveB], uint8Wave))
+			return false;
+	return true;
+}
+
+bool finalizeInstruments(Common::SeekableReadStream &uint8Wave) {
+	for (uint i = 0; i < g_numInstruments; i++)
+		if (!finalizeInstrument(g_instruments[i], uint8Wave))
+			return false;
+	return true;
+}
+
+bool finalizeSample(IIgsSampleHeader &header, Common::SeekableReadStream &uint8Wave) {
+	return finalizeInstrument(header.instrument, uint8Wave);
+}
+
 /**
  * Load an Apple IIGS AGI sample resource from the given stream and
  * create an AudioStream out of it.
@@ -234,18 +266,15 @@
 		byte *sampleData = (byte *) malloc(header.sampleSize);
 		uint32 readBytes = stream.read(sampleData, header.sampleSize);
 		if (readBytes == header.sampleSize) { // Check that we got all the data we requested
-			// Calculate true sample size (A zero byte ends the sample prematurely)
-			uint trueSampleSize = calcTrueSampleSize(sampleData, header.sampleSize);
-			if (trueSampleSize != header.sampleSize) {
-				debugC(3, kDebugLevelSound, "Apple IIGS sample (%d): Size changed from %d to %d (Zero byte encountered)",
-					resnum, header.sampleSize, trueSampleSize);
-			}
-			header.sampleSize = (uint16) trueSampleSize; // Set the true sample size
+			// Create a stream out of the read sample data (Needed by the finalizeSample-function)
+			Common::MemoryReadStream sampleStream(sampleData, readBytes);
+			finalizeSample(header, sampleStream);
 			// Make an audio stream from the mono, 8 bit, unsigned input data
 			byte flags = Audio::Mixer::FLAG_AUTOFREE | Audio::Mixer::FLAG_UNSIGNED;
 			int rate = (int) (1076 * pow(SEMITONE, header.pitch));
 			result = Audio::makeLinearInputStream(sampleData, header.sampleSize, rate, flags, 0, 0);
-		}
+		} else // Couldn't read enough data, so let's delete the sample data buffer
+			delete sampleData;
 	}
 
 	// If couldn't make a sample out of the input stream for any reason then
@@ -873,7 +902,20 @@
 	return loadedOk;
 }
 
-bool loadWaveFile(const Common::String &wavePath, const IIgsExeInfo &exeInfo) {
+/**
+ * Convert sample from 8-bit unsigned to 16-bit signed format.
+ * @param source  Source stream containing the 8-bit unsigned sample data.
+ * @param dest  Destination buffer for the 16-bit signed sample data.
+ * @param length  Length of the sample data to be converted.
+ */
+bool convertWave(Common::SeekableReadStream &source, int16 *dest, uint length) {
+	// Convert the wave from 8-bit unsigned to 16-bit signed format
+	for (uint i = 0; i < length; i++)
+		dest[i] = (int16) ((source.readByte() - 128) * 256);
+	return !source.ioFailed();
+}
+
+Common::MemoryReadStream *loadWaveFile(const Common::String &wavePath, const IIgsExeInfo &exeInfo) {
 	bool loadedOk = false; // Was loading successful?
 	Common::File file;
 
@@ -892,18 +934,12 @@
 				"Please report the information on the previous line to the ScummVM team.\n" \
 				"Using the wave file as it is - music may sound weird", md5str, exeInfo.exePrefix);
 		}
-
-		// Convert wave file from 8 bit unsigned to 16 bit signed format
-		uint8Wave->seek(0);
-		for (int i = 0; i < SIERRASTANDARD_SIZE; i++)
-			g_wave[i] = (int16) ((uint8Wave->readByte() - 128) * 256);
-
-		loadedOk = true; // Loading was successful
-	} else // Couldn't read the wave file or it had incorrect size
+		return uint8Wave;
+	} else { // Couldn't read the wave file or it had incorrect size
 		warning("Error loading Apple IIGS wave file (%s), not loading instruments", wavePath.c_str());
-
-	delete uint8Wave; // Free the memory buffer allocated for reading the wave file
-	return loadedOk;
+		delete uint8Wave; // Free the memory buffer allocated for reading the wave file
+		return NULL;
+	}
 }
 
 /**
@@ -973,8 +1009,16 @@
 		return false;
 	}
 
-	// Load the instrument headers and the wave file
-	return loadInstrumentHeaders(exeFsnode->path(), *exeInfo) && loadWaveFile(waveFsnode->path(), *exeInfo);
+	// First load the wave file and then load the instrument headers.
+	// Finally fix the instruments' lengths using the wave file data
+	// (A zero in the wave file data can end the sample prematurely)
+	// and convert the wave file from 8-bit unsigned to 16-bit signed format.
+	Common::MemoryReadStream *uint8Wave = loadWaveFile(waveFsnode->path(), *exeInfo);
+	bool result = uint8Wave != NULL && loadInstrumentHeaders(exeFsnode->path(), *exeInfo) &&
+		finalizeInstruments(*uint8Wave) && convertWave(*uint8Wave, g_wave, uint8Wave->size());
+
+	delete uint8Wave; // Free the 8-bit unsigned wave file buffer
+	return result;
 }
 
 #endif /* USE_IIGS_SOUND */


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