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

eriktorbjorn at users.sourceforge.net eriktorbjorn at users.sourceforge.net
Mon Apr 9 11:58:41 CEST 2007


Revision: 26423
          http://scummvm.svn.sourceforge.net/scummvm/?rev=26423&view=rev
Author:   eriktorbjorn
Date:     2007-04-09 02:58:41 -0700 (Mon, 09 Apr 2007)

Log Message:
-----------
Implemented enough of AIFF to play the music from the Broken Sword 1 demo. At
least as far as I tried it which, admittedly, wasn't very far.

Modified Paths:
--------------
    scummvm/trunk/engines/sword1/music.cpp
    scummvm/trunk/sound/module.mk

Added Paths:
-----------
    scummvm/trunk/sound/aiff.cpp
    scummvm/trunk/sound/aiff.h

Modified: scummvm/trunk/engines/sword1/music.cpp
===================================================================
--- scummvm/trunk/engines/sword1/music.cpp	2007-04-09 07:50:52 UTC (rev 26422)
+++ scummvm/trunk/engines/sword1/music.cpp	2007-04-09 09:58:41 UTC (rev 26423)
@@ -27,6 +27,7 @@
 #include "common/system.h"
 
 #include "sword1/music.h"
+#include "sound/aiff.h"
 #include "sound/mixer.h"
 #include "sound/mp3.h"
 #include "sound/vorbis.h"
@@ -127,6 +128,97 @@
 	return retVal;
 }
 
+class AiffAudioStream : public Audio::AudioStream {
+public:
+	AiffAudioStream(Common::SeekableReadStream *source, bool loop);
+	virtual ~AiffAudioStream();
+	virtual int readBuffer(int16 *buffer, const int numSamples);
+	virtual bool isStereo() const { return _isStereo; }
+	virtual bool endOfData() const { return (_samplesLeft == 0); }
+	virtual int getRate() const { return _rate; }
+private:
+	Common::SeekableReadStream	*_sourceStream;
+	uint8	*_sampleBuf;
+	uint32	 _rate;
+	bool	 _isStereo;
+	uint32	 _samplesLeft;
+	uint16	 _bitsPerSample;
+	bool	 _loop;
+	
+	void rewind();
+};
+
+AiffAudioStream::AiffAudioStream(Common::SeekableReadStream *source, bool loop) {
+	// TODO: honor the loop flag
+
+	_sourceStream = source;
+	_sampleBuf = (uint8*)malloc(SMP_BUFSIZE);
+
+	_samplesLeft = 0;
+	_isStereo = false;
+	_bitsPerSample = 16;
+	_rate = 22050;
+	_loop = loop;
+	
+	rewind();
+	
+	if (_samplesLeft == 0)
+		_loop = false;
+}
+
+AiffAudioStream::~AiffAudioStream() {
+	free(_sampleBuf);
+}
+
+void AiffAudioStream::rewind() {
+	int rate, size;
+	byte flags;
+	
+	_sourceStream->seek(0);
+
+	if (Audio::loadAIFFFromStream(*_sourceStream, size, rate, flags)) {
+		_isStereo = (flags & Audio::Mixer::FLAG_STEREO) != 0;
+		_rate = rate;
+		assert((uint)size <= (_sourceStream->size() - _sourceStream->pos()));
+		_bitsPerSample = ((flags & Audio::Mixer::FLAG_16BITS) != 0) ? 16 : 8;
+		_samplesLeft = (size * 8) / _bitsPerSample;
+		if ((_bitsPerSample != 16) && (_bitsPerSample != 8))
+			error("AiffAudioStream: unknown wave type");
+	}
+}
+
+int AiffAudioStream::readBuffer(int16 *buffer, const int numSamples) {
+	int retVal = 0;
+
+	while (retVal < numSamples && _samplesLeft > 0) {
+		int samples = MIN((int)_samplesLeft, numSamples - retVal);
+		retVal += samples;
+		_samplesLeft -= samples;
+		while (samples > 0) {
+			int readBytes = MIN(samples * (_bitsPerSample >> 3), SMP_BUFSIZE);
+			_sourceStream->read(_sampleBuf, readBytes);
+			if (_bitsPerSample == 16) {
+				readBytes >>= 1;
+				samples -= readBytes;
+				int16 *src = (int16*)_sampleBuf;
+				while (readBytes--)
+					*buffer++ = (int16)READ_BE_UINT16(src++);
+			} else {
+				samples -= readBytes;
+				int8 *src = (int8*)_sampleBuf;
+				while (readBytes--)
+					*buffer++ = (int16)*src++ << 8;
+			}
+		}
+
+		if (!_samplesLeft && _loop) {
+			rewind();
+		}
+	}
+	
+	return retVal;
+}
+
 // This means fading takes 3 seconds.
 #define FADE_LENGTH 3
 
@@ -156,6 +248,12 @@
 		if (_file.open(fileName))
 			_audioSource = new WaveAudioStream(&_file, loop);
 	}
+
+	if (!_audioSource) {
+		sprintf(fileName, "%s.aif", fileBase);
+		if (_file.open(fileName))
+			_audioSource = new AiffAudioStream(&_file, loop);
+	}
 	
 	if (!_audioSource)
 		return false;

Added: scummvm/trunk/sound/aiff.cpp
===================================================================
--- scummvm/trunk/sound/aiff.cpp	                        (rev 0)
+++ scummvm/trunk/sound/aiff.cpp	2007-04-09 09:58:41 UTC (rev 26423)
@@ -0,0 +1,178 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2007 The ScummVM project
+ *
+ * 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: wave.cpp 25926 2007-03-02 15:26:22Z fingolfin $
+ *
+ */
+
+/*
+ * The code in this file is based on information found at
+ * http://www.borg.com/~jglatt/tech/aiff.htm
+ *
+ * We currently only implement uncompressed AIFF. If we ever need AIFF-C, SoX
+ * (http://sox.sourceforge.net) may be a good place to start from.
+ */
+
+#include "common/stdafx.h"
+#include "common/endian.h"
+#include "common/util.h"
+#include "common/stream.h"
+
+#include "sound/aiff.h"
+#include "sound/audiostream.h"
+#include "sound/mixer.h"
+
+namespace Audio {
+
+uint32 readExtended(Common::SeekableReadStream &stream) {
+	// The sample rate is stored as an "80 bit IEEE Standard 754 floating
+	// point number (Standard Apple Numeric Environment [SANE] data type
+	// Extended).
+
+	byte buf[10];
+	uint32 mantissa;
+	uint32 last;
+	byte exp;
+
+	stream.read(buf, 10);
+	mantissa = READ_BE_UINT32(buf + 2);
+	exp = 30 - buf[1];
+
+	while (exp--) {
+		last = mantissa;
+		mantissa >>= 1;
+	}
+
+	if (last & 0x00000001)
+		mantissa++;
+
+	return mantissa;
+}
+
+bool loadAIFFFromStream(Common::SeekableReadStream &stream, int &size, int &rate, byte &flags) {
+	byte buf[4];
+
+	stream.read(buf, 4);
+	if (memcmp(buf, "FORM", 4) != 0) {
+		warning("loadAIFFFromStream: No 'FORM' header");
+		return false;
+	}
+
+	stream.readUint32BE();
+
+	// This could be AIFC, but we don't handle that case.
+
+	stream.read(buf, 4);
+	if (memcmp(buf, "AIFF", 4) != 0) {
+		warning("loadAIFFFromStream: No 'AIFF' header");
+		return false;
+	}
+
+	// From here on, we only care about the COMM and SSND chunks, which are
+	// the only required chunks.
+
+	bool foundCOMM = false;
+	bool foundSSND = false;
+
+	uint16 numChannels, bitsPerSample;
+	uint32 numSampleFrames, offset, blockSize, soundOffset;
+
+	while ((!foundCOMM || !foundSSND) && !stream.ioFailed()) {
+		uint32 length, pos;
+
+		stream.read(buf, 4);
+		length = stream.readUint32BE();
+		pos = stream.pos();
+
+		if (memcmp(buf, "COMM", 4) == 0) {
+			foundCOMM = true;
+			numChannels = stream.readUint16BE();
+			numSampleFrames = stream.readUint32BE();
+			bitsPerSample = stream.readUint16BE();
+			rate = readExtended(stream);
+			size = numSampleFrames * numChannels * (bitsPerSample / 8);
+		} else if (memcmp(buf, "SSND", 4) == 0) {
+			foundSSND = true;
+			offset = stream.readUint32BE();
+			blockSize = stream.readUint32BE();
+			soundOffset = stream.pos();
+		}
+
+		stream.seek(pos + length);
+	}
+
+	if (!foundCOMM) {
+		warning("loadAIFFFromStream: Cound not find 'COMM' chunk");
+		return false;
+	}
+
+	if (!foundSSND) {
+		warning("loadAIFFFromStream: Cound not find 'SSND' chunk");
+		return false;
+	}
+
+	// We only implement a subset of the AIFF standard.
+
+	if (numChannels < 1 || numChannels > 2) {
+		warning("loadAIFFFromStream: Only 1 or 2 channels are supported, not %d", numChannels);
+		return false;
+	}
+
+	if (bitsPerSample != 8 && bitsPerSample != 16) {
+		warning("loadAIFFFromStream: Only 8 or 16 bits per sample are supported, not %d", bitsPerSample);
+		return false;
+	}
+
+	if (offset != 0 || blockSize != 0) {
+		warning("loadAIFFFromStream: Block-aligned data is not supported");
+		return false;
+	}
+
+	// Samples are always signed, and big endian.
+
+	flags = 0;
+	if (bitsPerSample == 16)
+		flags |= Audio::Mixer::FLAG_16BITS;
+	if (numChannels == 2)
+		flags |= Audio::Mixer::FLAG_STEREO;
+
+	stream.seek(soundOffset);
+
+	// Stream now points at the sample data
+
+	return true;
+}
+
+AudioStream *makeAIFFStream(Common::SeekableReadStream &stream) {
+	int size, rate;
+	byte *data, flags;
+
+	if (!loadAIFFFromStream(stream, size, rate, flags))
+		return 0;
+
+	data = (byte *)malloc(size);
+	assert(data);
+	stream.read(data, size);
+
+	// Since we allocated our own buffer for the data, we must set the autofree flag.
+	flags |= Audio::Mixer::FLAG_AUTOFREE;
+
+	return makeLinearInputStream(data, size, rate, flags, 0, 0);
+}
+
+} // End of namespace Audio


Property changes on: scummvm/trunk/sound/aiff.cpp
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + "Date Rev Author URL Id"
Name: svn:eol-style
   + native

Added: scummvm/trunk/sound/aiff.h
===================================================================
--- scummvm/trunk/sound/aiff.h	                        (rev 0)
+++ scummvm/trunk/sound/aiff.h	2007-04-09 09:58:41 UTC (rev 26423)
@@ -0,0 +1,54 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2007 The ScummVM project
+ *
+ * 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: wave.h 22231 2006-04-29 22:33:31Z fingolfin $
+ *
+ */
+
+#ifndef SOUND_AIFF_H
+#define SOUND_AIFF_H
+
+#include "common/stdafx.h"
+#include "common/scummsys.h"
+
+namespace Common { class SeekableReadStream; }
+
+namespace Audio {
+
+class AudioStream;
+
+/**
+ * Try to load an AIFF from the given seekable stream. Returns true if
+ * successful. In that case, the stream's seek position will be set to the
+ * start of the audio data, and size, rate and flags contain information
+ * necessary for playback. Currently this function only supports uncompressed
+ * raw PCM data as well as IMA ADPCM.
+ */
+extern bool loadAIFFFromStream(Common::SeekableReadStream &stream, int &size, int &rate, byte &flags);
+
+/**
+ * Try to load an AIFF from the given seekable stream and create an AudioStream
+ * from that data.
+ *
+ * This function uses loadAIFFFromStream() internally.
+ */
+AudioStream *makeAIFFStream(Common::SeekableReadStream &stream);
+
+} // End of namespace Audio
+
+#endif


Property changes on: scummvm/trunk/sound/aiff.h
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + "Date Rev Author URL Id"
Name: svn:eol-style
   + native

Modified: scummvm/trunk/sound/module.mk
===================================================================
--- scummvm/trunk/sound/module.mk	2007-04-09 07:50:52 UTC (rev 26422)
+++ scummvm/trunk/sound/module.mk	2007-04-09 09:58:41 UTC (rev 26423)
@@ -2,6 +2,7 @@
 
 MODULE_OBJS := \
 	adpcm.o \
+	aiff.o \
 	audiocd.o \
 	audiostream.o \
 	flac.o \


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