[Scummvm-cvs-logs] CVS: scummvm/sound audiocd.cpp,NONE,1.1 audiocd.h,NONE,1.1 mp3.cpp,NONE,1.1 mp3.h,NONE,1.1 vorbis.cpp,NONE,1.1 vorbis.h,NONE,1.1 module.mk,1.14,1.15

Max Horn fingolfin at users.sourceforge.net
Sat Nov 29 04:10:03 CET 2003


Update of /cvsroot/scummvm/scummvm/sound
In directory sc8-pr-cvs1:/tmp/cvs-serv6926

Modified Files:
	module.mk 
Added Files:
	audiocd.cpp audiocd.h mp3.cpp mp3.h vorbis.cpp vorbis.h 
Log Message:
moved Audio CD (emulation) code from scumm/sound.cpp to sound/, so that it may be reused by other engines in the future

--- NEW FILE: audiocd.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2003 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/sound/audiocd.cpp,v 1.1 2003/11/29 12:09:51 fingolfin Exp $
 *
 */

#include "stdafx.h"

#include "sound/audiocd.h"
#include "sound/mp3.h"
#include "sound/vorbis.h"
#include "base/engine.h"
#include "common/file.h"
#include "common/util.h"


AudioCDManager::AudioCDManager() {
	_current_cache = 0;
}

void AudioCDManager::playCDTrack(int track, int numLoops, int startFrame, int duration) {
	if (numLoops != 0 || startFrame != 0) {
		// Try to load the track from a .mp3/.ogg file, and if found, use
		// that. If not found, attempt to do regular Audio CD playback of
		// the requested track.
		int index = getCachedTrack(track);
		if (index >= 0) {
			g_engine->_mixer->stopHandle(_cd.handle);
			_cd.playing = true;
			_cd.track = track;
			_cd.numLoops = numLoops;
			_cd.start = startFrame;
			_cd.duration = duration;
			_track_info[index]->play(g_engine->_mixer, &_cd.handle, _cd.start, _cd.duration);
		} else {
			g_system->play_cdrom(track, numLoops, startFrame, duration);
		}
	}
}

void AudioCDManager::stopCD() {
	if (_cd.playing) {
		g_engine->_mixer->stopHandle(_cd.handle);
		_cd.playing = false;
	} else {
		g_system->stop_cdrom();
	}
}

int AudioCDManager::pollCD() const {
	return _cd.playing || g_system->poll_cdrom();
}

void AudioCDManager::updateCD() {
	if (_cd.playing) {
		// If the sound handle is 0, then playback stopped.
		if (!_cd.handle) {
			// If playback just stopped, check if the current track is supposed
			// to be repeated, and if that's the case, play it again. Else, stop
			// the CD explicitly.
			if (_cd.numLoops == -1 || --_cd.numLoops > 0) {
//FIXME				_scumm->VAR(_scumm->VAR_MUSIC_TIMER) = 0;
//FIXME				if (!_soundsPaused) {
					int index = getCachedTrack(_cd.track);
					assert(index >= 0);
					_track_info[index]->play(g_engine->_mixer, &_cd.handle, _cd.start, _cd.duration);
//FIXME				}
			} else {
				g_engine->_mixer->stopHandle(_cd.handle);
				_cd.playing = false;
			}
		}
	} else {
		g_system->update_cdrom();
	}
}

int AudioCDManager::getCachedTrack(int track) {
	int i;
#if defined(USE_MAD) || defined(USE_VORBIS)
	char track_name[1024];
	File *file = new File();
#endif
	int current_index;

	// See if we find the track in the cache
	for (i = 0; i < CACHE_TRACKS; i++)
		if (_cached_tracks[i] == track) {
			if (_track_info[i])
				return i;
			else
				return -1;
		}
	current_index = _current_cache++;
	_current_cache %= CACHE_TRACKS;

	// Not found, see if it exists

	// First, delete the previous track info object
	delete _track_info[current_index];
	_track_info[current_index] = NULL;

	_cached_tracks[current_index] = track;

#ifdef USE_MAD
	sprintf(track_name, "track%d.mp3", track);
	file->open(track_name, g_engine->getGameDataPath());

	if (file->isOpen()) {
		_track_info[current_index] = new MP3TrackInfo(file);
		if (_track_info[current_index]->error()) {
			delete _track_info[current_index];
			_track_info[current_index] = NULL;
			return -1;
		}
		return current_index;
	}
#endif

#ifdef USE_VORBIS
	sprintf(track_name, "track%d.ogg", track);
	file->open(track_name, g_engine->getGameDataPath());

	if (file->isOpen()) {
		_track_info[current_index] = new VorbisTrackInfo(file);
		if (_track_info[current_index]->error()) {
			delete _track_info[current_index];
			_track_info[current_index] = NULL;
			return -1;
		}
		return current_index;
	}
#endif

	debug(2, "Track %d not available in compressed format", track);
	return -1;
}

--- NEW FILE: audiocd.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2003 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/sound/audiocd.h,v 1.1 2003/11/29 12:09:51 fingolfin Exp $
 *
 */

#ifndef SOUND_AUDIOCD_H
#define SOUND_AUDIOCD_H

#include "stdafx.h"
#include "common/scummsys.h"
#include "common/singleton.h"
#include "sound/mixer.h"

class DigitalTrackInfo {
public:
	virtual bool error() = 0;
	virtual int play(SoundMixer *mixer, PlayingSoundHandle *handle, int startFrame, int duration) = 0;
	virtual ~DigitalTrackInfo() { }
};


class AudioCDManager : public Common::Singleton<AudioCDManager> {
public:
	void playCDTrack(int track, int numLoops, int startFrame, int duration);
	void stopCD();
	int pollCD() const;
	void updateCD();

private:
	friend class Common::Singleton<AudioCDManager>;
	AudioCDManager();

	int getCachedTrack(int track);

private:
	/* used for emulated CD music */
	enum {
		CACHE_TRACKS = 10
	};
	int _cached_tracks[CACHE_TRACKS];
	DigitalTrackInfo *_track_info[CACHE_TRACKS];
	int _current_cache;

	struct {
		PlayingSoundHandle handle;
		int track;
		int start;
		int duration;
		int numLoops;
		bool playing;
	} _cd;

};

/** Shortcut for accessing the audio CD manager. */
#define AudioCD		AudioCDManager::instance()

#endif

--- NEW FILE: mp3.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2003 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/sound/mp3.cpp,v 1.1 2003/11/29 12:09:51 fingolfin Exp $
 *
 */

#include "stdafx.h"

#include "sound/mp3.h"
#include "common/file.h"
#include "common/util.h"

#ifdef USE_MAD
MP3TrackInfo::MP3TrackInfo(File *file) {
	struct mad_stream stream;
	struct mad_frame frame;
	unsigned char buffer[8192];
	unsigned int buflen = 0;
	int count = 0;

	// Check the format and bitrate
	mad_stream_init(&stream);
	mad_frame_init(&frame);

	while (1) {
		if (buflen < sizeof(buffer)) {
			int bytes;

			bytes = file->read(buffer + buflen, sizeof(buffer) - buflen);
			if (bytes <= 0) {
				if (bytes == -1) {
					warning("Invalid file format");
					goto error;
				}
				break;
			}

			buflen += bytes;
		}

		mad_stream_buffer(&stream, buffer, buflen);

		while (1) {
			if (mad_frame_decode(&frame, &stream) == -1) {
				if (!MAD_RECOVERABLE(stream.error))
					break;

				if (stream.error != MAD_ERROR_BADCRC)
					continue;
			}

			if (count++)
				break;
		}

		if (count || stream.error != MAD_ERROR_BUFLEN)
			break;

		memmove(buffer, stream.next_frame,
		        buflen = &buffer[buflen] - stream.next_frame);
	}

	if (count)
		memcpy(&_mad_header, &frame.header, sizeof(mad_header));
	else {
		warning("Invalid file format");
		goto error;
	}

	mad_frame_finish(&frame);
	mad_stream_finish(&stream);
	// Get file size
	_size = file->size();
	_file = file;
	_error_flag = false;
	return;

error:
	mad_frame_finish(&frame);
	mad_stream_finish(&stream);
	_error_flag = true;
	delete file;
}

int MP3TrackInfo::play(SoundMixer *mixer, PlayingSoundHandle *handle, int startFrame, int duration) {
	unsigned int offset;
	mad_timer_t durationTime;

	// Calc offset. As all bitrates are in kilobit per seconds, the division by 200 is always exact
	offset = (startFrame * (_mad_header.bitrate / (8 * 25))) / 3;
	_file->seek(offset, SEEK_SET);

	// Calc delay
	if (!duration) {
		// FIXME: Using _size here is a problem if offset (or equivalently
		// startFrame) is non-zero.
		mad_timer_set(&durationTime, (_size * 8) / _mad_header.bitrate,
					(_size * 8) % _mad_header.bitrate, _mad_header.bitrate);
	} else {
		mad_timer_set(&durationTime, duration / 75, duration % 75, 75);
	}

	// Play it
	return mixer->playMP3CDTrack(handle, _file, durationTime);
}

MP3TrackInfo::~MP3TrackInfo() {
	if (! _error_flag)
		_file->close();
}

#endif

--- NEW FILE: mp3.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2003 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/sound/mp3.h,v 1.1 2003/11/29 12:09:51 fingolfin Exp $
 *
 */

#ifndef SOUND_MP3_H
#define SOUND_MP3_H

#include "sound/audiocd.h"

class File;

#ifdef USE_MAD
class MP3TrackInfo : public DigitalTrackInfo {
private:
	struct mad_header _mad_header;
	long _size;
	File *_file;
	bool _error_flag;

public:
	MP3TrackInfo(File *file);
	~MP3TrackInfo();
	bool error() { return _error_flag; }
	int play(SoundMixer *mixer, PlayingSoundHandle *handle, int startFrame, int duration);
};
#endif



#endif

--- NEW FILE: vorbis.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2003 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/sound/vorbis.cpp,v 1.1 2003/11/29 12:09:51 fingolfin Exp $
 *
 */

#include "stdafx.h"

#include "sound/vorbis.h"
#include "common/file.h"
#include "common/util.h"

#ifdef USE_VORBIS
// These are wrapper functions to allow using a File object to
// provide data to the OggVorbis_File object.

struct file_info {
	File *file;
	int start, curr_pos;
	size_t len;
};

static size_t read_wrap(void *ptr, size_t size, size_t nmemb, void *datasource) {
	file_info *f = (file_info *) datasource;
	int result;

	nmemb *= size;
	if (f->curr_pos > (int) f->len)
		nmemb = 0;
	else if (nmemb > f->len - f->curr_pos)
		nmemb = f->len - f->curr_pos;
	result = f->file->read(ptr, nmemb);
	if (result == -1) {
		f->curr_pos = f->file->pos() - f->start;
		return (size_t) -1;
	} else {
		f->curr_pos += result;
		return result / size;
	}
}

static int seek_wrap(void *datasource, ogg_int64_t offset, int whence) {
	file_info *f = (file_info *) datasource;

	if (whence == SEEK_SET)
		offset += f->start;
	else if (whence == SEEK_END) {
		offset += f->start + f->len;
		whence = SEEK_SET;
	}

	f->file->seek(offset, whence);
	f->curr_pos = f->file->pos() - f->start;
	return f->curr_pos;
}

static int close_wrap(void *datasource) {
	file_info *f = (file_info *) datasource;

	f->file->close();
	delete f;
	return 0;
}

static long tell_wrap(void *datasource) {
	file_info *f = (file_info *) datasource;

	return f->curr_pos;
}

static ov_callbacks g_File_wrap = {
	read_wrap, seek_wrap, close_wrap, tell_wrap
};
#endif

#ifdef USE_VORBIS

VorbisTrackInfo::VorbisTrackInfo(File *file) {
	file_info *f = new file_info;

	f->file = file;
	f->start = 0;
	f->len = file->size();
	f->curr_pos = file->pos();

	if (ov_open_callbacks((void *) f, &_ov_file, NULL, 0, g_File_wrap) < 0) {
		warning("Invalid file format");
		_error_flag = true;
		delete f;
		delete file;
	} else {
		_error_flag = false;
		_file = file;
	}
}

#ifdef CHUNKSIZE
#define VORBIS_TREMOR
#endif

int VorbisTrackInfo::play(SoundMixer *mixer, PlayingSoundHandle *handle, int startFrame, int duration) {
#ifdef VORBIS_TREMOR
	ov_time_seek(&_ov_file, (ogg_int64_t)(startFrame / 75.0 * 1000));
#else
	ov_time_seek(&_ov_file, startFrame / 75.0);
#endif
	return mixer->playVorbis(handle, &_ov_file,
							duration * ov_info(&_ov_file, -1)->rate / 75, true);
}

VorbisTrackInfo::~VorbisTrackInfo() {
	if (! _error_flag) {
		ov_clear(&_ov_file);
		delete _file;
	}
}

void playSfxSound_Vorbis(SoundMixer *mixer, File *file, uint32 size, PlayingSoundHandle *handle) {
	OggVorbis_File *ov_file = new OggVorbis_File;
	file_info *f = new file_info;

	f->file = file;
	f->start = file->pos();
	f->len = size;
	f->curr_pos = 0;

	if (ov_open_callbacks((void *) f, ov_file, NULL, 0, g_File_wrap) < 0) {
		warning("Invalid file format");
		delete ov_file;
		delete f;
	} else
		mixer->playVorbis(handle, ov_file, 0, false);
}

#endif

--- NEW FILE: vorbis.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2003 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/sound/vorbis.h,v 1.1 2003/11/29 12:09:51 fingolfin Exp $
 *
 */

#ifndef SOUND_VORBIS_H
#define SOUND_VORBIS_H

#include "sound/audiocd.h"

class File;

#ifdef USE_VORBIS

class VorbisTrackInfo : public DigitalTrackInfo {
private:
	File *_file;
	OggVorbis_File _ov_file;
	bool _error_flag;

public:
	VorbisTrackInfo(File *file);
	~VorbisTrackInfo();
	bool error() { return _error_flag; }
	int play(SoundMixer *mixer, PlayingSoundHandle *handle, int startFrame, int duration);
};


void playSfxSound_Vorbis(SoundMixer *mixer, File *file, uint32 size, PlayingSoundHandle *handle);

#endif

#endif

Index: module.mk
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sound/module.mk,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- module.mk	2 Oct 2003 22:52:56 -0000	1.14
+++ module.mk	29 Nov 2003 12:09:51 -0000	1.15
@@ -1,6 +1,7 @@
 MODULE := sound
 
 MODULE_OBJS := \
+	sound/audiocd.o \
 	sound/audiostream.o \
 	sound/fmopl.o \
 	sound/mididrv.o \
@@ -8,9 +9,11 @@
 	sound/midiparser_smf.o \
 	sound/midiparser_xmidi.o \
 	sound/mixer.o \
+	sound/mp3.o \
 	sound/mpu401.o \
 	sound/rate.o \
-	sound/voc.o
+	sound/voc.o \
+	sound/vorbis.o
 #	sound/resample.o \
 
 MODULE_DIRS += \





More information about the Scummvm-git-logs mailing list