[Scummvm-cvs-logs] SF.net SVN: scummvm: [31101] residual/trunk
aquadran at users.sourceforge.net
aquadran at users.sourceforge.net
Tue Mar 11 00:06:08 CET 2008
Revision: 31101
http://scummvm.svn.sourceforge.net/scummvm/?rev=31101&view=rev
Author: aquadran
Date: 2008-03-10 16:06:07 -0700 (Mon, 10 Mar 2008)
Log Message:
-----------
synced imuse digital with scummvm imuse and related stuff
Modified Paths:
--------------
residual/trunk/common/sys.h
residual/trunk/common/timer.h
residual/trunk/dists/msvc9/residual.vcproj
residual/trunk/engine/backend/driver.h
residual/trunk/engine/backend/sdl/driver_sdl.cpp
residual/trunk/engine/backend/sdl/driver_sdl.h
residual/trunk/engine/font.cpp
residual/trunk/engine/imuse/imuse.cpp
residual/trunk/engine/imuse/imuse.h
residual/trunk/engine/imuse/imuse_mcmp_mgr.cpp
residual/trunk/engine/imuse/imuse_music.cpp
residual/trunk/engine/imuse/imuse_script.cpp
residual/trunk/engine/imuse/imuse_sndmgr.cpp
residual/trunk/engine/imuse/imuse_sndmgr.h
residual/trunk/engine/imuse/imuse_track.cpp
residual/trunk/engine/lua.cpp
residual/trunk/engine/main.cpp
residual/trunk/engine/savegame.cpp
residual/trunk/engine/smush/blocky16.cpp
residual/trunk/engine/smush/smush.cpp
residual/trunk/engine/smush/smush.h
residual/trunk/engine/textobject.cpp
Added Paths:
-----------
residual/trunk/common/frac.h
residual/trunk/common/list.h
residual/trunk/common/mutex.cpp
residual/trunk/common/mutex.h
residual/trunk/common/noncopyable.h
residual/trunk/engine/backend/default-timer.cpp
residual/trunk/engine/backend/default-timer.h
residual/trunk/engine/imuse/imuse_tables.h
residual/trunk/engine/imuse/imuse_track.h
Removed Paths:
-------------
residual/trunk/common/timer.cpp
Added: residual/trunk/common/frac.h
===================================================================
--- residual/trunk/common/frac.h (rev 0)
+++ residual/trunk/common/frac.h 2008-03-10 23:06:07 UTC (rev 31101)
@@ -0,0 +1,52 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ * Copyright (C) 2003-2008 The ScummVM-Residual Team (www.scummvm.org)
+ *
+ * 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$
+ *
+ */
+
+#ifndef COMMON_FRAC_H
+#define COMMON_FRAC_H
+
+#include "common/sys.h"
+
+/**
+ * The precision of the fractional (fixed point) type we define below.
+ * Normally you should never have to modify this value.
+ */
+enum {
+ FRAC_BITS = 16,
+ FRAC_LO_MASK = ((1L << FRAC_BITS) - 1),
+ FRAC_HI_MASK = ((1L << FRAC_BITS) - 1) << FRAC_BITS,
+
+ FRAC_ONE = (1L << FRAC_BITS), // 1.0
+ FRAC_HALF = (1L << (FRAC_BITS-1)) // 0.5
+};
+
+/**
+ * Fixed-point fractions, used by the sound rate converter and other code.
+ */
+typedef int32 frac_t;
+
+inline frac_t doubleToFrac(double value) { return (frac_t)(value * FRAC_ONE); }
+inline double fracToDouble(frac_t value) { return ((double)value) / FRAC_ONE; }
+
+inline frac_t intToFrac(int16 value) { return value << FRAC_BITS; }
+inline int16 fracToInt(frac_t value) { return value >> FRAC_BITS; }
+
+#endif
Property changes on: residual/trunk/common/frac.h
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Rev Author URL Id
Name: svn:eol-style
+ native
Added: residual/trunk/common/list.h
===================================================================
--- residual/trunk/common/list.h (rev 0)
+++ residual/trunk/common/list.h 2008-03-10 23:06:07 UTC (rev 31101)
@@ -0,0 +1,264 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ * Copyright (C) 2003-2008 The ScummVM-Residual Team (www.scummvm.org)
+ *
+ * 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$
+ *
+ */
+
+#ifndef COMMON_LIST_H
+#define COMMON_LIST_H
+
+#include "common/sys.h"
+
+namespace Common {
+
+/**
+ * Simple double linked list, modeled after the list template of the standard
+ * C++ library.
+ */
+template <class t_T>
+class List {
+protected:
+#if defined (_WIN32_WCE) || defined (_MSC_VER)
+//FIXME evc4 and msvc7 doesn't like it as protected member
+public:
+#endif
+ struct NodeBase {
+ NodeBase *_prev;
+ NodeBase *_next;
+ };
+
+ template <class t_T2>
+ struct Node : public NodeBase {
+ t_T2 _data;
+
+ Node(const t_T2 &x) : _data(x) {}
+ };
+
+ template <class t_T2>
+ class Iterator {
+ friend class List<t_T>;
+ NodeBase *_node;
+
+#if !defined (__WINSCW__)
+ explicit Iterator(NodeBase *node) : _node(node) {}
+#else
+ Iterator(NodeBase *node) : _node(node) {}
+#endif
+
+ public:
+ Iterator() : _node(0) {}
+
+ // Prefix inc
+ Iterator<t_T2> &operator++() {
+ if (_node)
+ _node = _node->_next;
+ return *this;
+ }
+ // Postfix inc
+ Iterator<t_T2> operator++(int) {
+ Iterator tmp(_node);
+ ++(*this);
+ return tmp;
+ }
+ // Prefix dec
+ Iterator<t_T2> &operator--() {
+ if (_node)
+ _node = _node->_prev;
+ return *this;
+ }
+ // Postfix dec
+ Iterator<t_T2> operator--(int) {
+ Iterator tmp(_node);
+ --(*this);
+ return tmp;
+ }
+ t_T2& operator*() const {
+ assert(_node);
+#if (__GNUC__ == 2) && (__GNUC_MINOR__ >= 95)
+ return static_cast<List<t_T>::Node<t_T2> *>(_node)->_data;
+#else
+ return static_cast<Node<t_T2>*>(_node)->_data;
+#endif
+ }
+ t_T2* operator->() const {
+ return &(operator*());
+ }
+
+ bool operator==(const Iterator<t_T2>& x) const {
+ return _node == x._node;
+ }
+
+ bool operator!=(const Iterator<t_T2>& x) const {
+ return _node != x._node;
+ }
+ };
+
+ NodeBase *_anchor;
+
+public:
+ typedef Iterator<t_T> iterator;
+ typedef Iterator<const t_T> const_iterator;
+
+ typedef t_T value_type;
+
+public:
+ List() {
+ _anchor = new NodeBase;
+ _anchor->_prev = _anchor;
+ _anchor->_next = _anchor;
+ }
+ List(const List<t_T>& list) {
+ _anchor = new NodeBase;
+ _anchor->_prev = _anchor;
+ _anchor->_next = _anchor;
+
+ insert(begin(), list.begin(), list.end());
+ }
+
+ ~List() {
+ clear();
+ delete _anchor;
+ }
+
+ void push_front(const t_T& element) {
+ insert(begin(), element);
+ }
+
+ void push_back(const t_T& element) {
+ insert(end(), element);
+ }
+
+ void insert(iterator pos, const t_T& element) {
+ NodeBase *newNode = new Node<t_T>(element);
+
+ newNode->_next = pos._node;
+ newNode->_prev = pos._node->_prev;
+ newNode->_prev->_next = newNode;
+ newNode->_next->_prev = newNode;
+ }
+
+ template <typename iterator2>
+ void insert(iterator pos, iterator2 first, iterator2 last) {
+ for (; first != last; ++first)
+ insert(pos, *first);
+ }
+
+ iterator erase(iterator pos) {
+ assert(pos != end());
+
+ NodeBase *next = pos._node->_next;
+ NodeBase *prev = pos._node->_prev;
+ Node<t_T> *node = static_cast<Node<t_T> *>(pos._node);
+ prev->_next = next;
+ next->_prev = prev;
+ delete node;
+ return iterator(next);
+ }
+
+ iterator reverse_erase(iterator pos) {
+ assert(pos != end());
+
+ NodeBase *next = pos._node->_next;
+ NodeBase *prev = pos._node->_prev;
+ Node<t_T> *node = static_cast<Node<t_T> *>(pos._node);
+ prev->_next = next;
+ next->_prev = prev;
+ delete node;
+ return iterator(prev);
+ }
+
+ iterator erase(iterator first, iterator last) {
+ while (first != last)
+ erase(first++);
+
+ return last;
+ }
+
+ void remove(const t_T &val) {
+ iterator i = begin();
+ while (i != end())
+ if (val == i.operator*())
+ i = erase(i);
+ else
+ ++i;
+ }
+
+
+ List<t_T>& operator =(const List<t_T>& list) {
+ if (this != &list) {
+ iterator i;
+ const_iterator j;
+
+ for (i = begin(), j = list.begin(); (i != end()) && (j != list.end()) ; ++i, ++j) {
+ static_cast<Node<t_T> *>(i._node)->_data = static_cast<Node<t_T> *>(j._node)->_data;
+ }
+
+ if (i == end())
+ insert(i, j, list.end());
+ else
+ erase(i, end());
+ }
+
+ return *this;
+ }
+
+ uint size() const {
+ int n = 0;
+ for (const_iterator i = begin(); i != end(); ++i)
+ ++n;
+ return n;
+ }
+
+ void clear() {
+ erase(begin(), end());
+ }
+
+ bool empty() const {
+ return (_anchor == _anchor->_next);
+ }
+
+
+ iterator begin() {
+ return iterator(_anchor->_next);
+ }
+
+ iterator reverse_begin() {
+ return iterator(_anchor->_prev);
+ }
+
+ iterator end() {
+ return iterator(_anchor);
+ }
+
+ const_iterator begin() const {
+ return const_iterator(_anchor->_next);
+ }
+
+ const_iterator reverse_begin() const {
+ return const_iterator(_anchor->_prev);
+ }
+
+ const_iterator end() const {
+ return const_iterator(_anchor);
+ }
+};
+
+} // End of namespace Common
+
+#endif
Property changes on: residual/trunk/common/list.h
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Rev Author URL Id
Name: svn:eol-style
+ native
Added: residual/trunk/common/mutex.cpp
===================================================================
--- residual/trunk/common/mutex.cpp (rev 0)
+++ residual/trunk/common/mutex.cpp 2008-03-10 23:06:07 UTC (rev 31101)
@@ -0,0 +1,72 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ * Copyright (C) 2003-2008 The ScummVM-Residual Team (www.scummvm.org)
+ *
+ * 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$
+ *
+ */
+
+#include "common/mutex.h"
+#include "common/debug.h"
+
+#include "engine/backend/driver.h"
+
+namespace Common {
+
+Mutex::Mutex() {
+ _mutex = g_driver->createMutex();
+}
+
+Mutex::~Mutex() {
+ g_driver->deleteMutex(_mutex);
+}
+
+void Mutex::lock() {
+ g_driver->lockMutex(_mutex);
+}
+
+void Mutex::unlock() {
+ g_driver->unlockMutex(_mutex);
+}
+
+
+#pragma mark -
+
+
+StackLock::StackLock(MutexRef mutex, const char *mutexName)
+ : _mutex(mutex), _mutexName(mutexName) {
+ lock();
+}
+
+StackLock::StackLock(const Mutex &mutex, const char *mutexName)
+ : _mutex(mutex._mutex), _mutexName(mutexName) {
+ lock();
+}
+
+StackLock::~StackLock() {
+ unlock();
+}
+
+void StackLock::lock() {
+ g_driver->lockMutex(_mutex);
+}
+
+void StackLock::unlock() {
+ g_driver->unlockMutex(_mutex);
+}
+
+} // End of namespace Common
Property changes on: residual/trunk/common/mutex.cpp
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Rev Author URL Id
Name: svn:eol-style
+ native
Added: residual/trunk/common/mutex.h
===================================================================
--- residual/trunk/common/mutex.h (rev 0)
+++ residual/trunk/common/mutex.h 2008-03-10 23:06:07 UTC (rev 31101)
@@ -0,0 +1,73 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ * Copyright (C) 2003-2008 The ScummVM-Residual Team (www.scummvm.org)
+ *
+ * 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$
+ *
+ */
+
+#ifndef COMMON_MUTEX_H
+#define COMMON_MUTEX_H
+
+#include "common/sys.h"
+
+namespace Common {
+
+class Mutex;
+
+/**
+ * An pseudo-opaque mutex type.
+ */
+typedef struct OpaqueMutex *MutexRef;
+
+
+/**
+ * Auxillary class to (un)lock a mutex on the stack.
+ */
+class StackLock {
+ MutexRef _mutex;
+ const char *_mutexName;
+
+ void lock();
+ void unlock();
+public:
+ StackLock(MutexRef mutex, const char *mutexName = NULL);
+ StackLock(const Mutex &mutex, const char *mutexName = NULL);
+ ~StackLock();
+};
+
+
+/**
+ * Wrapper class.
+ */
+class Mutex {
+ friend class StackLock;
+
+ MutexRef _mutex;
+
+public:
+ Mutex();
+ ~Mutex();
+
+ void lock();
+ void unlock();
+};
+
+
+} // End of namespace Common
+
+#endif
Property changes on: residual/trunk/common/mutex.h
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Rev Author URL Id
Name: svn:eol-style
+ native
Added: residual/trunk/common/noncopyable.h
===================================================================
--- residual/trunk/common/noncopyable.h (rev 0)
+++ residual/trunk/common/noncopyable.h 2008-03-10 23:06:07 UTC (rev 31101)
@@ -0,0 +1,43 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ * Copyright (C) 2003-2008 The ScummVM-Residual Team (www.scummvm.org)
+ *
+ * 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$
+ *
+ */
+
+#ifndef COMMON_NONCOPYABLE_H
+#define COMMON_NONCOPYABLE_H
+
+namespace Common {
+
+/**
+ * Subclass of NonCopyable can not be copied due to the fact that
+ * we made the copy constructor and assigment operator private.
+ */
+class NonCopyable {
+public:
+ NonCopyable() {}
+private:
+ // Prevent copying instances by accident
+ NonCopyable(const NonCopyable&);
+ NonCopyable& operator= (const NonCopyable&);
+};
+
+} // End of namespace Common
+
+#endif
Property changes on: residual/trunk/common/noncopyable.h
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Rev Author URL Id
Name: svn:eol-style
+ native
Modified: residual/trunk/common/sys.h
===================================================================
--- residual/trunk/common/sys.h 2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/common/sys.h 2008-03-10 23:06:07 UTC (rev 31101)
@@ -24,8 +24,6 @@
#define COMMON_SYS_H
-typedef struct Mutex *MutexRef;
-
#ifndef _MSC_VER
#include <unistd.h>
#endif
Deleted: residual/trunk/common/timer.cpp
===================================================================
--- residual/trunk/common/timer.cpp 2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/common/timer.cpp 2008-03-10 23:06:07 UTC (rev 31101)
@@ -1,135 +0,0 @@
-/* Residual - Virtual machine to run LucasArts' 3D adventure games
- * Copyright (C) 2003-2006 The ScummVM-Residual Team (www.scummvm.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
-
- * This library 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
- * Lesser General Public License for more details.
-
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "common/sys.h"
-#include "common/platform.h"
-#include "common/debug.h"
-#include "common/timer.h"
-
-#include "engine/backend/driver.h"
-
-Timer *g_timer = NULL;
-
-Timer::Timer() :
- _mutex(0),
- _timerHandler(0),
- _lastTime(0) {
-
- _mutex = g_driver->createMutex();
-
- g_timer = this;
-
- for (int i = 0; i < MAX_TIMERS; i++) {
- _timerSlots[i].procedure = NULL;
- _timerSlots[i].interval = 0;
- _timerSlots[i].counter = 0;
- }
-
- _thisTime = g_driver->getMillis();
-
- // Set the timer last, after everything has been initialised
- g_driver->setTimerCallback(timer_handler, 10);
-}
-
-Timer::~Timer() {
- g_driver->setTimerCallback(NULL, 0);
-
- {
- StackLock lock(_mutex);
- for (int i = 0; i < MAX_TIMERS; i++) {
- _timerSlots[i].procedure = NULL;
- _timerSlots[i].interval = 0;
- _timerSlots[i].counter = 0;
- }
- }
-
- g_driver->deleteMutex(_mutex);
-}
-
-int Timer::timer_handler(int t) {
- if (g_timer)
- return g_timer->handler(t);
- return 0;
-}
-
-int Timer::handler(int t) {
- StackLock lock(_mutex);
- uint32 interval, l;
-
- _lastTime = _thisTime;
- _thisTime = g_driver->getMillis();
- interval = 1000 * (_thisTime - _lastTime);
-
- // If the timer has been frozen for a long time, don't
- // call the procedures a silly number of times, just resynchronize
- if(interval > 1000000) {
- interval = 0;
- warning("Timer skipped forward");
- }
-
- for (l = 0; l < MAX_TIMERS; l++) {
- if (_timerSlots[l].procedure && _timerSlots[l].interval > 0) {
- _timerSlots[l].counter -= interval;
- while (_timerSlots[l].counter <= 0) {
- // A small paranoia check which catches the case where
- // a timer removes itself (which it never should do).
- assert(_timerSlots[l].procedure && _timerSlots[l].interval > 0);
- _timerSlots[l].counter += _timerSlots[l].interval;
- _timerSlots[l].procedure(_timerSlots[l].refCon);
- }
- }
- }
-
- return t;
-}
-
-bool Timer::installTimerProc(TimerProc procedure, int32 interval, void *refCon) {
- assert(interval > 0);
- StackLock lock(_mutex);
-
- for (int l = 0; l < MAX_TIMERS; l++) {
- if (!_timerSlots[l].procedure) {
- _timerSlots[l].procedure = procedure;
- _timerSlots[l].interval = interval;
- _timerSlots[l].counter = interval;
- _timerSlots[l].refCon = refCon;
- return true;
- }
- }
-
- if (debugLevel == DEBUG_WARN || debugLevel == DEBUG_ALL)
- warning("Couldn't find free timer slot!");
- return false;
-}
-
-void Timer::removeTimerProc(TimerProc procedure) {
- StackLock lock(_mutex);
-
- for (int l = 0; l < MAX_TIMERS; l++) {
- if (_timerSlots[l].procedure == procedure) {
- _timerSlots[l].procedure = 0;
- _timerSlots[l].interval = 0;
- _timerSlots[l].counter = 0;
- _timerSlots[l].refCon = 0;
- }
- }
-}
Modified: residual/trunk/common/timer.h
===================================================================
--- residual/trunk/common/timer.h 2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/common/timer.h 2008-03-10 23:06:07 UTC (rev 31101)
@@ -1,19 +1,19 @@
/* Residual - Virtual machine to run LucasArts' 3D adventure games
- * Copyright (C) 2003-2006 The ScummVM-Residual Team (www.scummvm.org)
+ * Copyright (C) 2003-2008 The ScummVM-Residual Team (www.scummvm.org)
*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
+ * 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 library is distributed in the hope that it will be useful,
+ * 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
- * Lesser General Public License for more details.
+ * 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 Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ * 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$
@@ -24,31 +24,16 @@
#define COMMON_TIMER_H
#include "common/sys.h"
-#include "common/platform.h"
+#include "common/noncopyable.h"
-#define MAX_TIMERS 3
+namespace Common {
-typedef void (*TimerProc)(void *refCon);
-
-class Timer {
-
-private:
- MutexRef _mutex;
- void *_timerHandler;
- int32 _thisTime;
- int32 _lastTime;
-
- struct TimerSlots {
- TimerProc procedure;
- int32 interval;
- int32 counter;
- void *refCon;
- } _timerSlots[MAX_TIMERS];
-
+class TimerManager : NonCopyable {
public:
- Timer();
- ~Timer();
+ typedef void (*TimerProc)(void *refCon);
+ virtual ~TimerManager() {}
+
/**
* Install a new timer callback. It will from now be called every interval microseconds.
* The timer may be invoked from a separate thread. Hence any timer code should be
@@ -61,19 +46,14 @@
* @param refCon an arbitrary void pointer; will be passed to the timer callback
* @return true if the timer was installed successfully, false otherwise
*/
- bool installTimerProc(TimerProc proc, int32 interval, void *refCon);
+ virtual bool installTimerProc(TimerProc proc, int32 interval, void *refCon) = 0;
/**
* Remove the given timer callback. It will not be invoked anymore.
*/
- void removeTimerProc(TimerProc proc);
-
-protected:
- static int timer_handler(int t);
- int handler(int t);
+ virtual void removeTimerProc(TimerProc proc) = 0;
};
-extern Timer *g_timer;
+} // End of namespace Common
#endif
-
Modified: residual/trunk/dists/msvc9/residual.vcproj
===================================================================
--- residual/trunk/dists/msvc9/residual.vcproj 2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/dists/msvc9/residual.vcproj 2008-03-10 23:06:07 UTC (rev 31101)
@@ -199,6 +199,14 @@
>
</File>
<File
+ RelativePath="..\..\common\frac.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\list.h"
+ >
+ </File>
+ <File
RelativePath="..\..\common\matrix3.cpp"
>
</File>
@@ -215,18 +223,26 @@
>
</File>
<File
- RelativePath="..\..\common\platform.h"
+ RelativePath="..\..\common\mutex.cpp"
>
</File>
<File
- RelativePath="..\..\common\sys.h"
+ RelativePath="..\..\common\mutex.h"
>
</File>
<File
- RelativePath="..\..\common\timer.cpp"
+ RelativePath="..\..\common\noncopyable.h"
>
</File>
<File
+ RelativePath="..\..\common\platform.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\sys.h"
+ >
+ </File>
+ <File
RelativePath="..\..\common\timer.h"
>
</File>
@@ -782,9 +798,17 @@
>
</File>
<File
+ RelativePath="..\..\engine\imuse\imuse_tables.h"
+ >
+ </File>
+ <File
RelativePath="..\..\engine\imuse\imuse_track.cpp"
>
</File>
+ <File
+ RelativePath="..\..\engine\imuse\imuse_track.h"
+ >
+ </File>
</Filter>
<Filter
Name="smush"
@@ -814,6 +838,14 @@
Name="backend"
>
<File
+ RelativePath="..\..\engine\backend\default-timer.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engine\backend\default-timer.h"
+ >
+ </File>
+ <File
RelativePath="..\..\engine\backend\driver.h"
>
</File>
Added: residual/trunk/engine/backend/default-timer.cpp
===================================================================
--- residual/trunk/engine/backend/default-timer.cpp (rev 0)
+++ residual/trunk/engine/backend/default-timer.cpp 2008-03-10 23:06:07 UTC (rev 31101)
@@ -0,0 +1,144 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ * Copyright (C) 2003-2008 The ScummVM-Residual Team (www.scummvm.org)
+ *
+ * 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$
+ *
+ */
+
+#include "common/sys.h"
+
+#include "engine/backend/driver.h"
+#include "engine/backend/default-timer.h"
+
+struct TimerSlot {
+ Common::TimerManager::TimerProc callback;
+ void *refCon;
+ uint32 interval; // in microseconds
+
+ uint32 nextFireTime; // in milliseconds
+ uint32 nextFireTimeMicro; // mircoseconds part of nextFire
+
+ TimerSlot *next;
+};
+
+void insertPrioQueue(TimerSlot *head, TimerSlot *newSlot) {
+ // The head points to a fake anchor TimerSlot; this common
+ // trick allows us to get rid of many special cases.
+
+ const uint32 nextFireTime = newSlot->nextFireTime;
+ TimerSlot *slot = head;
+ newSlot->next = 0;
+
+ // Insert the new slot into the sorted list of already scheduled
+ // timers in such a way that the list stays sorted...
+ while (true) {
+ assert(slot);
+ if (slot->next == 0 || nextFireTime < slot->next->nextFireTime) {
+ newSlot->next = slot->next;
+ slot->next = newSlot;
+ return;
+ }
+ slot = slot->next;
+ }
+}
+
+
+DefaultTimerManager::DefaultTimerManager() :
+ _timerHandler(0),
+ _head(0) {
+
+ _head = new TimerSlot();
+ memset(_head, 0, sizeof(TimerSlot));
+}
+
+DefaultTimerManager::~DefaultTimerManager() {
+ Common::StackLock lock(_mutex);
+
+ TimerSlot *slot = _head;
+ while (slot) {
+ TimerSlot *next = slot->next;
+ delete slot;
+ slot = next;
+ }
+ _head = 0;
+}
+
+void DefaultTimerManager::handler() {
+ Common::StackLock lock(_mutex);
+
+ const uint32 curTime = g_driver->getMillis();
+
+ // Repeat as long as there is a TimerSlot that is scheduled to fire.
+ TimerSlot *slot = _head->next;
+ while (slot && slot->nextFireTime < curTime) {
+ // Remove the slot from the priority queue
+ _head->next = slot->next;
+
+ // Update the fire time and reinsert the TimerSlot into the priority
+ // queue. Has to be done before the timer callback is invoked, in case
+ // the callback wants to remove itself.
+ assert(slot->interval > 0);
+ slot->nextFireTime += (slot->interval / 1000);
+ slot->nextFireTimeMicro += (slot->interval % 1000);
+ if (slot->nextFireTimeMicro > 1000) {
+ slot->nextFireTime += slot->nextFireTimeMicro / 1000;
+ slot->nextFireTimeMicro %= 1000;
+ }
+ insertPrioQueue(_head, slot);
+
+ // Invoke the timer callback
+ assert(slot->callback);
+ slot->callback(slot->refCon);
+
+ // Look at the next scheduled timer
+ slot = _head->next;
+ }
+}
+
+bool DefaultTimerManager::installTimerProc(TimerProc callback, int32 interval, void *refCon) {
+ assert(interval > 0);
+ Common::StackLock lock(_mutex);
+
+ TimerSlot *slot = new TimerSlot;
+ slot->callback = callback;
+ slot->refCon = refCon;
+ slot->interval = interval;
+ slot->nextFireTime = g_driver->getMillis() + interval / 1000;
+ slot->nextFireTimeMicro = interval % 1000;
+ slot->next = 0;
+
+ insertPrioQueue(_head, slot);
+
+ return true;
+}
+
+void DefaultTimerManager::removeTimerProc(TimerProc callback) {
+ Common::StackLock lock(_mutex);
+
+ TimerSlot *slot = _head;
+
+ while (slot->next) {
+ if (slot->next->callback == callback) {
+ TimerSlot *next = slot->next->next;
+ delete slot->next;
+ slot->next = next;
+ } else {
+ slot = slot->next;
+ }
+ }
+}
Property changes on: residual/trunk/engine/backend/default-timer.cpp
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Rev Author URL Id
Name: svn:eol-style
+ native
Added: residual/trunk/engine/backend/default-timer.h
===================================================================
--- residual/trunk/engine/backend/default-timer.h (rev 0)
+++ residual/trunk/engine/backend/default-timer.h 2008-03-10 23:06:07 UTC (rev 31101)
@@ -0,0 +1,48 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ * Copyright (C) 2003-2008 The ScummVM-Residual Team (www.scummvm.org)
+ *
+ * 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$
+ *
+ */
+
+#ifndef BACKENDS_TIMER_DEFAULT_H
+#define BACKENDS_TIMER_DEFAULT_H
+
+#include "common/timer.h"
+#include "common/mutex.h"
+
+struct TimerSlot;
+
+class DefaultTimerManager : public Common::TimerManager {
+private:
+ Common::Mutex _mutex;
+ void *_timerHandler;
+ TimerSlot *_head;
+
+
+public:
+ DefaultTimerManager();
+ ~DefaultTimerManager();
+ bool installTimerProc(TimerProc proc, int32 interval, void *refCon);
+ void removeTimerProc(TimerProc proc);
+
+ // Timer callback, to be invoked at regular time intervals by the backend.
+ void handler();
+};
+
+#endif
Property changes on: residual/trunk/engine/backend/default-timer.h
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Rev Author URL Id
Name: svn:eol-style
+ native
Modified: residual/trunk/engine/backend/driver.h
===================================================================
--- residual/trunk/engine/backend/driver.h 2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/backend/driver.h 2008-03-10 23:06:07 UTC (rev 31101)
@@ -25,6 +25,7 @@
#include "common/platform.h"
#include "common/vector3d.h"
+#include "common/mutex.h"
#include "engine/color.h"
#include "engine/model.h"
@@ -33,10 +34,16 @@
#include "engine/font.h"
#include "engine/primitives.h"
#include "engine/actor.h"
+#include "engine/backend/default-timer.h"
class Material;
class Bitmap;
+class Timer;
+namespace Audio {
+ class Mixer;
+}
+
class Driver {
public:
Driver() { ; }
@@ -116,7 +123,7 @@
/** @name Events and Time */
//@{
- typedef int (*TimerProc)(int interval);
+ typedef unsigned int (*TimerProc)(unsigned int interval, void *param);
/**
* The types of events backends may generate.
@@ -239,25 +246,22 @@
* @param interval the interval (in milliseconds) between invocations
* of the callback
*/
- virtual void setTimerCallback(TimerProc callback, int interval) = 0;
+ virtual void setTimerCallback() = 0;
+ virtual void clearTimerCallback() = 0;
+
//@}
/**
* @name Mutex handling
- * Historically, the OSystem API used to have a method which allowed
- * creating threads. Hence mutex support was needed for thread syncing.
- * To ease portability, though, we decided to remove the threading API.
- * Instead, we now use timers (see setTimerCallback() and Timer).
- * But since those may be implemented using threads (and in fact, that's
- * how our primary backend, the SDL one, does it on many systems), we
- * still have to do mutex syncing in our timer callbacks.
*
* Hence backends which do not use threads to implement the timers simply
* can use dummy implementations for these methods.
*/
//@{
+ typedef Common::MutexRef MutexRef;
+
/**
* Create a new mutex.
* @return the newly created mutex, or 0 if an error occured.
@@ -266,6 +270,12 @@
/**
* Lock the given mutex.
+ *
+ * @note Code assumes that the mutex implementation supports
+ * recursive locking. That is, a thread may lock a mutex twice w/o
+ * deadlocking. In case of a multilock, the mutex has to be unlocked
+ * as many times as it was locked befored it really becomes unlocked.
+ *
* @param mutex the mutex to lock.
*/
virtual void lockMutex(MutexRef mutex) = 0;
@@ -329,16 +339,7 @@
};
extern Driver *g_driver;
+extern DefaultTimerManager *g_timer;
+extern Audio::Mixer *g_mixer;
-class StackLock {
- MutexRef _mutex;
-public:
- StackLock(MutexRef mutex) : _mutex(mutex) {
- g_driver->lockMutex(_mutex);
- }
- ~StackLock() {
- g_driver->unlockMutex(_mutex);
- }
-};
-
#endif
Modified: residual/trunk/engine/backend/sdl/driver_sdl.cpp
===================================================================
--- residual/trunk/engine/backend/sdl/driver_sdl.cpp 2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/backend/sdl/driver_sdl.cpp 2008-03-10 23:06:07 UTC (rev 31101)
@@ -359,11 +359,22 @@
SDL_Delay(msecs);
}
-void DriverSDL::setTimerCallback(TimerProc callback, int timer) {
- SDL_SetTimer(timer, (SDL_TimerCallback) callback);
+static SDL_TimerID _timerID = NULL;
+
+static Uint32 timer_handler(Uint32 interval, void *param) {
+ ((DefaultTimerManager *)param)->handler();
+ return interval;
}
-MutexRef DriverSDL::createMutex() {
+void DriverSDL::setTimerCallback() {
+ _timerID = SDL_AddTimer(10, &timer_handler, g_timer);
+}
+
+void DriverSDL::clearTimerCallback() {
+ SDL_RemoveTimer(_timerID);
+}
+
+Common::MutexRef DriverSDL::createMutex() {
return (MutexRef)SDL_CreateMutex();
}
@@ -382,12 +393,20 @@
bool DriverSDL::setSoundCallback(SoundProc proc, void *param) {
SDL_AudioSpec desired;
+ // Determine the sample buffer size. We want it to store enough data for
+ // about 1/10th of a second. Note that it must be a power of two.
+ // So e.g. at 22050 Hz, we request a sample buffer size of 2048.
+ int samples = 0x8000;
+ while (10 * samples >= _samplesPerSec) {
+ samples >>= 1;
+ }
+
memset(&desired, 0, sizeof(desired));
desired.freq = _samplesPerSec;
desired.format = AUDIO_S16SYS;
desired.channels = 2;
- desired.samples = 2048;
+ desired.samples = (uint16)samples;
desired.callback = proc;
desired.userdata = param;
Modified: residual/trunk/engine/backend/sdl/driver_sdl.h
===================================================================
--- residual/trunk/engine/backend/sdl/driver_sdl.h 2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/backend/sdl/driver_sdl.h 2008-03-10 23:06:07 UTC (rev 31101)
@@ -52,7 +52,8 @@
bool pollEvent(Event &event);
uint32 getMillis();
void delayMillis(uint msecs);
- void setTimerCallback(TimerProc callback, int interval);
+ void setTimerCallback();
+ void clearTimerCallback();
MutexRef createMutex();
void lockMutex(MutexRef mutex);
Modified: residual/trunk/engine/font.cpp
===================================================================
--- residual/trunk/engine/font.cpp 2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/font.cpp 2008-03-10 23:06:07 UTC (rev 31101)
@@ -42,7 +42,7 @@
data += 32;
// Read character indexes - are the key/value reversed?
- _charIndex = (uint16 *)malloc(sizeof(_charIndex) * _numChars);
+ _charIndex = new uint16[_numChars];
if (!_charIndex)
error("Could not load font %s. Out of memory\n", filename);
for (uint i = 0; i < _numChars; ++i) {
@@ -52,7 +52,7 @@
data += _numChars * 2;
// Read character headers
- _charHeaders = (CharHeader *)malloc(sizeof(CharHeader) * _numChars);
+ _charHeaders = new CharHeader[_numChars];
if (!_charHeaders)
error("Could not load font %s. Out of memory\n", filename);
for (uint i = 0; i < _numChars; ++i) {
@@ -65,7 +65,7 @@
data += 16;
}
// Read font data
- _fontData = (byte *)malloc(_dataSize);
+ _fontData = new byte[_dataSize];
if (!_fontData)
error("Could not load font %s. Out of memory\n", filename);
@@ -73,9 +73,9 @@
}
Font::~Font() {
- free(_charIndex);
- free(_charHeaders);
- free(_fontData);
+ delete[] _charIndex;
+ delete[] _charHeaders;
+ delete[] _fontData;
}
uint16 Font::getCharIndex(unsigned char c) {
Modified: residual/trunk/engine/imuse/imuse.cpp
===================================================================
--- residual/trunk/engine/imuse/imuse.cpp 2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/imuse/imuse.cpp 2008-03-10 23:06:07 UTC (rev 31101)
@@ -24,6 +24,7 @@
#include "common/platform.h"
#include "common/debug.h"
#include "common/timer.h"
+#include "common/mutex.h"
#include "engine/engine.h"
#include "engine/savegame.h"
@@ -42,26 +43,20 @@
extern ImuseTable grimDemoStateMusicTable[];
extern ImuseTable grimDemoSeqMusicTable[];
-Imuse::Track::Track()
- : used(false), stream(NULL) {
-}
-
void Imuse::timerHandler(void *refCon) {
Imuse *imuse = (Imuse *)refCon;
imuse->callback();
}
Imuse::Imuse(int fps) {
- _mutex = g_driver->createMutex();
_pause = false;
_sound = new ImuseSndMgr();
- _volVoice = 0;
- _volSfx = 0;
- _volMusic = 0;
+ assert(_sound);
_callbackFps = fps;
resetState();
for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
_track[l] = new Track;
+ assert(_track[l]);
_track[l]->trackId = l;
_track[l]->used = false;
strcpy(_track[l]->soundName, "");
@@ -73,13 +68,12 @@
}
Imuse::~Imuse() {
- stopAllSounds();
g_timer->removeTimerProc(timerHandler);
+ stopAllSounds();
for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
delete _track[l];
}
delete _sound;
- g_driver->deleteMutex(_mutex);
}
void Imuse::resetState() {
@@ -89,19 +83,18 @@
}
void Imuse::restoreState(SaveGame *savedState) {
- StackLock lock(_mutex);
+ Common::StackLock lock(_mutex);
printf("Imuse::restoreState() started.\n");
savedState->beginSection('IMUS');
- savedState->read(&_volVoice, sizeof(int32));
- savedState->read(&_volSfx, sizeof(int32));
- savedState->read(&_volMusic, sizeof(int32));
savedState->read(&_curMusicState, sizeof(int32));
savedState->read(&_curMusicSeq, sizeof(int32));
savedState->read(_attributes, sizeof(int32) * 185);
for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
Track *track = _track[l];
+ memset(track, 0, sizeof(Track));
+ track->trackId = l;
savedState->read(&track->pan, sizeof(int32));
savedState->read(&track->panFadeDest, sizeof(int32));
savedState->read(&track->panFadeDelay, sizeof(int32));
@@ -113,50 +106,51 @@
savedState->read(track->soundName, 32);
savedState->read(&track->used, sizeof(bool));
savedState->read(&track->toBeRemoved, sizeof(bool));
- savedState->read(&track->readyToRemove, sizeof(bool));
- savedState->read(&track->started, sizeof(bool));
savedState->read(&track->priority, sizeof(int32));
savedState->read(&track->regionOffset, sizeof(int32));
savedState->read(&track->dataOffset, sizeof(int32));
savedState->read(&track->curRegion, sizeof(int32));
savedState->read(&track->curHookId, sizeof(int32));
savedState->read(&track->volGroupId, sizeof(int32));
- savedState->read(&track->iteration, sizeof(int32));
+ savedState->read(&track->feedSize, sizeof(int32));
savedState->read(&track->mixerFlags, sizeof(int32));
- savedState->read(&track->mixerVol, sizeof(int32));
- savedState->read(&track->mixerPan, sizeof(int32));
if (!track->used)
continue;
- track->readyToRemove = false;
- if (track->toBeRemoved) {
- track->stream = NULL;
+ if (track->toBeRemoved || track->curRegion == -1) {
track->used = false;
continue;
}
- track->soundHandle = _sound->openSound(track->soundName, track->volGroupId);
- assert(track->soundHandle);
+ track->soundDesc = _sound->openSound(track->soundName, track->volGroupId);
+ if (!track->soundDesc) {
+ warning("Imuse::restoreState: Can't open sound so will not be resumed");
+ track->used = false;
+ continue;
+ }
- int32 streamBufferSize = track->iteration;
- int freq = _sound->getFreq(track->soundHandle);
+ int channels = _sound->getChannels(track->soundDesc);
+ int freq = _sound->getFreq(track->soundDesc);
+ track->mixerFlags = kFlag16Bits;
+ if (channels == 2)
+ track->mixerFlags |= kFlagStereo | kFlagReverseStereo;
- track->stream = makeAppendableAudioStream(freq, track->mixerFlags, streamBufferSize);
- g_mixer->playInputStream(&track->handle, track->stream, false, -1, track->mixerVol, track->mixerPan, false);
+ track->stream = Audio::makeAppendableAudioStream(freq, makeMixerFlags(track->mixerFlags));
+ g_mixer->playInputStream(track->getType(), &track->handle, track->stream, -1, track->getVol(), track->getPan());
+ g_mixer->pauseHandle(track->handle, true);
}
savedState->endSection();
+ g_mixer->pauseAll(false);
+
printf("Imuse::restoreState() finished.\n");
}
void Imuse::saveState(SaveGame *savedState) {
- StackLock lock(_mutex);
+ Common::StackLock lock(_mutex);
printf("Imuse::saveState() started.\n");
savedState->beginSection('IMUS');
- savedState->write(&_volVoice, sizeof(int32));
- savedState->write(&_volSfx, sizeof(int32));
- savedState->write(&_volMusic, sizeof(int32));
savedState->write(&_curMusicState, sizeof(int32));
savedState->write(&_curMusicSeq, sizeof(int32));
savedState->write(_attributes, sizeof(int32) * 185);
@@ -174,31 +168,43 @@
savedState->write(track->soundName, 32);
savedState->write(&track->used, sizeof(bool));
savedState->write(&track->toBeRemoved, sizeof(bool));
- savedState->write(&track->readyToRemove, sizeof(bool));
- savedState->write(&track->started, sizeof(bool));
savedState->write(&track->priority, sizeof(int32));
savedState->write(&track->regionOffset, sizeof(int32));
savedState->write(&track->dataOffset, sizeof(int32));
savedState->write(&track->curRegion, sizeof(int32));
savedState->write(&track->curHookId, sizeof(int32));
savedState->write(&track->volGroupId, sizeof(int32));
- savedState->write(&track->iteration, sizeof(int32));
+ savedState->write(&track->feedSize, sizeof(int32));
savedState->write(&track->mixerFlags, sizeof(int32));
- savedState->write(&track->mixerVol, sizeof(int32));
- savedState->write(&track->mixerPan, sizeof(int32));
}
savedState->endSection();
printf("Imuse::saveState() finished.\n");
}
+int32 Imuse::makeMixerFlags(int32 flags) {
+ int32 mixerFlags = 0;
+ if (flags & kFlag16Bits)
+ mixerFlags |= Audio::Mixer::FLAG_16BITS;
+ if (flags & kFlagLittleEndian)
+ mixerFlags |= Audio::Mixer::FLAG_LITTLE_ENDIAN;
+ if (flags & kFlagStereo)
+ mixerFlags |= Audio::Mixer::FLAG_STEREO;
+ if (flags & kFlagReverseStereo)
+ mixerFlags |= Audio::Mixer::FLAG_REVERSE_STEREO;
+ return mixerFlags;
+}
+
void Imuse::callback() {
- StackLock lock(_mutex);
+ Common::StackLock lock(_mutex);
for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
Track *track = _track[l];
- if (track->used && !track->readyToRemove) {
- if (track->toBeRemoved) {
- track->readyToRemove = true;
+ if (track->used) {
+ // Ignore tracks which are about to finish. Also, if it did finish in the meantime,
+ // mark it as unused.
+ if (!track->stream) {
+ if (!g_mixer->isSoundHandleActive(track->handle))
+ memset(track, 0, sizeof(Track));
continue;
}
@@ -209,17 +215,21 @@
if (track->volFadeStep < 0) {
if (track->vol > track->volFadeDest) {
track->vol += track->volFadeStep;
+ //warning("fade: %d", track->vol);
if (track->vol < track->volFadeDest) {
track->vol = track->volFadeDest;
track->volFadeUsed = false;
}
if (track->vol == 0) {
- track->toBeRemoved = true;
+ // Fade out complete -> remove this track
+ flushTrack(track);
+ continue;
}
}
} else if (track->volFadeStep > 0) {
if (track->vol < track->volFadeDest) {
track->vol += track->volFadeStep;
+ //warning("fade: %d", track->vol);
if (track->vol > track->volFadeDest) {
track->vol = track->volFadeDest;
track->volFadeUsed = false;
@@ -248,74 +258,60 @@
}
}
- int pan = track->pan / 1000;
- pan = (pan != 64) ? 2 * pan - 127 : 0;
- int vol = track->vol / 1000;
+ assert(track->stream);
+ byte *data = NULL;
+ int32 result = 0;
- if (track->volGroupId == 1)
- vol = (vol * _volVoice) / 128;
- if (track->volGroupId == 2)
- vol = (vol * _volSfx) / 128;
- if (track->volGroupId == 3)
- vol = (vol * _volMusic) / 128;
+ if (track->curRegion == -1) {
+ switchToNextRegion(track);
+ if (!track->stream) // Seems we reached the end of the stream
+ continue;
+ }
- track->mixerVol = vol;
- track->mixerPan = pan;
+ int channels = _sound->getChannels(track->soundDesc);
+ int32 mixer_size = track->feedSize / _callbackFps;
- if (track->stream) {
- byte *data = NULL;
- int32 result = 0;
+ if (track->stream->endOfData()) {
+ mixer_size *= 2;
+ }
- if (track->curRegion == -1) {
- switchToNextRegion(track);
- if (track->toBeRemoved)
- continue;
- }
+ if (channels == 1)
+ mixer_size &= ~1;
+ if (channels == 2)
+ mixer_size &= ~3;
- int channels = _sound->getChannels(track->soundHandle);
+ if (mixer_size == 0)
+ continue;
- int32 mixer_size = track->iteration / _callbackFps;
-
- if (track->stream->endOfData()) {
- mixer_size *= 2;
+ do {
+ result = _sound->getDataFromRegion(track->soundDesc, track->curRegion, &data, track->regionOffset, mixer_size);
+ if (channels == 1) {
+ result &= ~1;
}
+ if (channels == 2) {
+ result &= ~3;
+ }
- if (channels == 1)
- mixer_size &= ~1;
- if (channels == 2)
- mixer_size &= ~3;
+ if (result > mixer_size)
+ result = mixer_size;
- if (mixer_size == 0)
- continue;
+ if (g_mixer->isReady()) {
+ track->stream->queueBuffer(data, result);
+ track->regionOffset += result;
+ } else
+ delete[] data;
- do {
- result = _sound->getDataFromRegion(track->soundHandle, track->curRegion, &data, track->regionOffset, mixer_size);
- if (channels == 1) {
- result &= ~1;
- }
- if (channels == 2) {
- result &= ~3;
- }
-
- if (result > mixer_size)
- result = mixer_size;
-
- if (g_mixer->isReady()) {
- g_mixer->setChannelVolume(track->handle, vol);
- g_mixer->setChannelBalance(track->handle, pan);
- track->stream->append(data, result);
- track->regionOffset += result;
- free(data);
- }
-
- if (_sound->isEndOfRegion(track->soundHandle, track->curRegion)) {
- switchToNextRegion(track);
- if (track->toBeRemoved)
- break;
- }
- mixer_size -= result;
- assert(mixer_size >= 0);
- } while (mixer_size != 0);
+ if (_sound->isEndOfRegion(track->soundDesc, track->curRegion)) {
+ switchToNextRegion(track);
+ if (!track->stream)
+ break;
+ }
+ mixer_size -= result;
+ assert(mixer_size >= 0);
+ } while (mixer_size);
+ if (g_mixer->isReady()) {
+ g_mixer->setChannelVolume(track->handle, track->getVol());
+ g_mixer->setChannelBalance(track->handle, track->getPan());
}
}
}
@@ -325,51 +321,51 @@
assert(track);
if (track->trackId >= MAX_IMUSE_TRACKS) {
- track->toBeRemoved = true;
+ if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
+ printf("Imuse::switchToNextRegion(): fadeTrack end: soundName:%s\n", track->soundName);
+ flushTrack(track);
return;
}
- int numRegions = _sound->getNumRegions(track->soundHandle);
+ int numRegions = _sound->getNumRegions(track->soundDesc);
if (++track->curRegion == numRegions) {
- track->toBeRemoved = true;
+ if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
+ printf("Imuse::switchToNextRegion(): end of tracks: soundName:%s\n", track->soundName);
+ flushTrack(track);
return;
}
- ImuseSndMgr::SoundStruct *soundHandle = track->soundHandle;
- int jumpId = _sound->getJumpIdByRegionAndHookId(soundHandle, track->curRegion, track->curHookId);
+ ImuseSndMgr::SoundDesc *soundDesc = track->soundDesc;
+ int jumpId = _sound->getJumpIdByRegionAndHookId(soundDesc, track->curRegion, track->curHookId);
if (jumpId == -1)
- jumpId = _sound->getJumpIdByRegionAndHookId(soundHandle, track->curRegion, 0);
+ jumpId = _sound->getJumpIdByRegionAndHookId(soundDesc, track->curRegion, 0);
if (jumpId != -1) {
- int region = _sound->getRegionIdByJumpId(soundHandle, jumpId);
+ if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
+ printf("Imuse::switchToNextRegion(): JUMP: soundName:%s\n", track->soundName);
+ int region = _sound->getRegionIdByJumpId(soundDesc, jumpId);
assert(region != -1);
- int sampleHookId = _sound->getJumpHookId(soundHandle, jumpId);
+ int sampleHookId = _sound->getJumpHookId(soundDesc, jumpId);
assert(sampleHookId != -1);
- int fadeDelay = (60 * _sound->getJumpFade(soundHandle, jumpId)) / 1000;
- if (sampleHookId != 0) {
- if (track->curHookId == sampleHookId) {
- if (fadeDelay != 0) {
- Track *fadeTrack = cloneToFadeOutTrack(track, fadeDelay);
- fadeTrack->dataOffset = _sound->getRegionOffset(fadeTrack->soundHandle, fadeTrack->curRegion);
- fadeTrack->regionOffset = 0;
- fadeTrack->curHookId = 0;
- }
- track->curRegion = region;
- track->curHookId = 0;
- }
- } else {
- if (fadeDelay != 0) {
- Track *fadeTrack = cloneToFadeOutTrack(track, fadeDelay);
- fadeTrack->dataOffset = _sound->getRegionOffset(fadeTrack->soundHandle, fadeTrack->curRegion);
+ int fadeDelay = (60 * _sound->getJumpFade(soundDesc, jumpId)) / 1000;
+ if (fadeDelay) {
+ Track *fadeTrack = cloneToFadeOutTrack(track, fadeDelay);
+ if (fadeTrack) {
+ fadeTrack->dataOffset = _sound->getRegionOffset(fadeTrack->soundDesc, fadeTrack->curRegion);
fadeTrack->regionOffset = 0;
+ fadeTrack->curHookId = 0;
}
- track->curRegion = region;
- if (track->curHookId == 0x80) {
- track->curHookId = 0;
- }
}
+ track->curRegion = region;
+ if (track->curHookId == sampleHookId)
+ track->curHookId = 0;
+ else
+ if (track->curHookId == 0x80)
+ track->curHookId = 0;
}
- track->dataOffset = _sound->getRegionOffset(soundHandle, track->curRegion);
+ if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
+ printf("Imuse::switchToNextRegion(): REGION %d: soundName:%s\n", track->curRegion, track->soundName);
+ track->dataOffset = _sound->getRegionOffset(soundDesc, track->curRegion);
track->regionOffset = 0;
}
Modified: residual/trunk/engine/imuse/imuse.h
===================================================================
--- residual/trunk/engine/imuse/imuse.h 2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/imuse/imuse.h 2008-03-10 23:06:07 UTC (rev 31101)
@@ -34,21 +34,12 @@
#include "engine/imuse/imuse_sndmgr.h"
#include "engine/imuse/imuse_mcmp_mgr.h"
+#include "engine/imuse/imuse_track.h"
+#include "engine/imuse/imuse_tables.h"
#define MAX_IMUSE_TRACKS 16
#define MAX_IMUSE_FADETRACKS 16
-struct ImuseTable {
- byte opcode;
- int16 soundId;
- byte atribPos;
- byte hookId;
- int16 fadeOut60TicksDelay;
- byte volume;
- byte pan;
- char filename[32];
-};
-
class SaveGame;
class Imuse {
@@ -56,52 +47,11 @@
int _callbackFps;
- struct Track {
- int trackId;
-
- int32 pan;
- int32 panFadeDest;
- int32 panFadeStep;
- int32 panFadeDelay;
- bool panFadeUsed;
- int32 vol;
- int32 volFadeDest;
- int32 volFadeStep;
- int32 volFadeDelay;
- bool volFadeUsed;
-
- char soundName[32];
- bool used;
- bool toBeRemoved;
- bool readyToRemove;
- bool started;
- int32 priority;
- int32 regionOffset;
- int32 dataOffset;
- int32 curRegion;
- int32 curHookId;
- int32 volGroupId;
- int32 iteration;
- int32 mixerFlags;
- int32 mixerVol;
- int32 mixerPan;
-
- ImuseSndMgr::SoundStruct *soundHandle;
- PlayingSoundHandle handle;
- AppendableAudioStream *stream;
-
- Track();
- };
-
Track *_track[MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS];
- MutexRef _mutex;
+ Common::Mutex _mutex;
ImuseSndMgr *_sound;
- int32 _volVoice;
- int32 _volSfx;
- int32 _volMusic;
-
bool _pause;
int32 _attributes[185];
@@ -111,6 +61,7 @@
const ImuseTable *_stateMusicTable;
const ImuseTable *_seqMusicTable;
+ int32 makeMixerFlags(int32 flags);
static void timerHandler(void *refConf);
void callback();
void switchToNextRegion(Track *track);
@@ -118,30 +69,27 @@
void selectVolumeGroup(const char *soundName, int volGroupId);
void fadeOutMusic(int fadeDelay);
+ void fadeOutMusicAndStartNew(int fadeDelay, const char *filename, int hookId, int vol, int pan);
Track *cloneToFadeOutTrack(Track *track, int fadeDelay);
void playMusic(const ImuseTable *table, int atribPos, bool sequence);
+ void flushTrack(Track *track);
+
public:
Imuse(int fps);
~Imuse();
- bool startSound(const char *soundName, int volGroupId, int hookId, int volume, int pan, int priority);
+ bool startSound(const char *soundName, int volGroupId, int hookId, int volume, int pan, int priority, Track *otherTrack);
void startVoice(const char *soundName, int volume = 127, int pan = 64);
void startMusic(const char *soundName, int hookId, int volume, int pan);
+ void startMusicWithOtherPos(const char *soundName, int hookId, int volume, int pan, Track *otherTrack);
void startSfx(const char *soundName, int priority = 127);
void restoreState(SaveGame *savedState);
void saveState(SaveGame *savedState);
void resetState();
- void setGroupVoiceVolume(int volume) { _volVoice = volume; }
- void setGroupSfxVolume(int volume) { _volSfx = volume; }
- void setGroupMusicVolume(int volume) { _volMusic = volume; }
- int getGroupVoiceVolume() { return _volVoice; }
- int getGroupSfxVolume() { return _volSfx; }
- int getGroupMusicVolume() { return _volMusic; }
-
Track *findTrack(const char *soundName);
void setPriority(const char *soundName, int priority);
void setVolume(const char *soundName, int volume);
@@ -160,6 +108,8 @@
void flushTracks();
bool isVoicePlaying();
char *getCurMusicSoundName();
+ int getCurMusicPan();
+ int getCurMusicVol();
bool getSoundStatus(const char *soundName);
int32 getPosIn60HzTicks(const char *soundName);
};
Modified: residual/trunk/engine/imuse/imuse_mcmp_mgr.cpp
===================================================================
--- residual/trunk/engine/imuse/imuse_mcmp_mgr.cpp 2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/imuse/imuse_mcmp_mgr.cpp 2008-03-10 23:06:07 UTC (rev 31101)
@@ -45,10 +45,8 @@
McmpMgr::~McmpMgr() {
if (_file)
fclose(_file);
- if (_compTable)
- free(_compTable);
- if (_compInput)
- free(_compInput);
+ delete[] _compTable;
+ delete[] _compInput;
}
bool McmpMgr::openSound(const char *filename, byte **resPtr, int &offsetData) {
@@ -72,7 +70,7 @@
int offset = ftell(_file) + (_numCompItems * 9) + 2;
_numCompItems--;
- _compTable = (CompTable *)malloc(sizeof(CompTable) * _numCompItems);
+ _compTable = new CompTable[_numCompItems];
fseek(_file, 5, SEEK_CUR);
fread(&_compTable[0].decompSize, 1, 4, _file);
int headerSize = _compTable[0].decompSize = READ_BE_UINT32(&_compTable[0].decompSize);
@@ -98,7 +96,7 @@
_compTable[i].offset += sizeCodecs;
}
fseek(_file, sizeCodecs, SEEK_CUR);
- _compInput = (byte *)malloc(maxSize);
+ _compInput = new byte[maxSize];
fread(_compInput, 1, headerSize, _file);
*resPtr = _compInput;
offsetData = headerSize;
@@ -123,7 +121,7 @@
last_block = _numCompItems - 1;
int32 blocks_final_size = 0x2000 * (1 + last_block - first_block);
- *comp_final = (byte *)malloc(blocks_final_size);
+ *comp_final = new byte[blocks_final_size];
final_size = 0;
for (i = first_block; i <= last_block; i++) {
Modified: residual/trunk/engine/imuse/imuse_music.cpp
===================================================================
--- residual/trunk/engine/imuse/imuse_music.cpp 2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/imuse/imuse_music.cpp 2008-03-10 23:06:07 UTC (rev 31101)
@@ -40,10 +40,13 @@
}
assert(num != -1);
+ if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
+ printf("Imuse::setMusicState(): SoundId %d, filename: %s\n", _stateMusicTable[l].soundId, _stateMusicTable[l].filename);
+
if (_curMusicState == num)
return;
- if (_curMusicSeq == 0) {
+ if (!_curMusicSeq) {
playMusic(&_stateMusicTable[num], num, false);
}
@@ -68,10 +71,13 @@
assert(num != -1);
+ if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
+ printf("Imuse::setMusicSequence(): SoundId %d, filename: %s\n", _seqMusicTable[l].soundId, _seqMusicTable[l].filename);
+
if (_curMusicSeq == num)
return _seqMusicTable[_curMusicSeq].soundId;
- if (num != 0) {
+ if (num) {
playMusic(&_seqMusicTable[num], 0, true);
} else {
playMusic(&_stateMusicTable[_curMusicState], _curMusicState, true);
@@ -85,12 +91,12 @@
void Imuse::playMusic(const ImuseTable *table, int atribPos, bool sequence) {
int hookId = 0;
- if (atribPos != 0) {
- if (table->atribPos != 0)
+ if (atribPos) {
+ if (table->atribPos)
atribPos = table->atribPos;
hookId = _attributes[atribPos];
- if (table->hookId != 0) {
- if ((hookId == 0) && (table->hookId > 1)) {
+ if (table->hookId) {
+ if (hookId && table->hookId > 1) {
_attributes[atribPos] = 2;
} else {
_attributes[atribPos] = hookId + 1;
@@ -104,27 +110,51 @@
if (table->opcode == 0) {
fadeOutMusic(120);
- } else if ((table->opcode == 2) || (table->opcode == 3)) {
+ return;
+ }
+
+ if (table->opcode == 2 || table->opcode == 3) {
if (table->filename[0] == 0) {
fadeOutMusic(60);
- } else {
- char *soundName = getCurMusicSoundName();
- int pan;
+ return;
+ }
+ char *soundName = getCurMusicSoundName();
+ int pan;
- if (table->pan == 0)
- pan = 64;
- else
- pan = table->pan;
- if (soundName != NULL && (table->opcode == 3) && (!sequence)
- && (strcmp(soundName, table->filename) == 0) && (table->atribPos != 0)
- && table->atribPos == _stateMusicTable[_curMusicState].atribPos) {
- setFadeVolume(soundName, table->volume, table->fadeOut60TicksDelay);
- setFadePan(soundName, pan, table->fadeOut60TicksDelay);
- setHookId(soundName, hookId);
- } else {
- fadeOutMusic(table->fadeOut60TicksDelay);
- startMusic(table->filename, hookId, table->volume, pan);
- }
+ if (table->pan == 0)
+ pan = 64;
+ else
+ pan = table->pan;
+ if (!soundName) {
+ startMusic(table->filename, hookId, 0, pan);
+ setFadeVolume(table->filename, table->volume, table->fadeOut60TicksDelay);
+ return;
}
+ int old_pan = getCurMusicPan();
+ int old_vol = getCurMusicVol();
+ if (old_pan == -1)
+ old_pan = 64;
+ if (old_vol == -1)
+ old_vol = 127;
+
+ if (table->opcode == 2) {
+ fadeOutMusic(table->fadeOut60TicksDelay);
+ startMusic(table->filename, hookId, table->volume, pan);
+ return;
+ }
+ if (strcmp(soundName, table->filename) == 0) {
+ setFadeVolume(soundName, table->volume, table->fadeOut60TicksDelay);
+ setFadePan(soundName, pan, table->fadeOut60TicksDelay);
+ return;
+ }
+
+ if (!sequence && table->atribPos && table->atribPos == _stateMusicTable[_curMusicState].atribPos) {
+ fadeOutMusicAndStartNew(table->fadeOut60TicksDelay, table->filename, hookId, old_vol, old_pan);
+ setFadeVolume(table->filename, table->volume, table->fadeOut60TicksDelay);
+ setFadePan(table->filename, pan, table->fadeOut60TicksDelay);
+ } else {
+ fadeOutMusic(table->fadeOut60TicksDelay);
+ startMusic(table->filename, hookId, table->volume, pan);
+ }
}
}
Modified: residual/trunk/engine/imuse/imuse_script.cpp
===================================================================
--- residual/trunk/engine/imuse/imuse_script.cpp 2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/imuse/imuse_script.cpp 2008-03-10 23:06:07 UTC (rev 31101)
@@ -24,6 +24,7 @@
#include "common/platform.h"
#include "common/debug.h"
#include "common/timer.h"
+#include "common/mutex.h"
#include "engine/backend/driver.h"
@@ -33,34 +34,41 @@
#include "engine/imuse/imuse.h"
#include "engine/imuse/imuse_sndmgr.h"
+void Imuse::flushTrack(Track *track) {
+ track->toBeRemoved = true;
+
+ if (track->stream) {
+ // Finalize the appendable stream, then remove our reference to it.
+ // Note that there might still be some data left in the buffers of the
+ // appendable stream. We play it nice and wait till all of it
+ // played. The audio mixer will take care of it afterwards (and dispose it).
+ track->stream->finish();
+ track->stream = 0;
+ if (track->soundDesc) {
+ _sound->closeSound(track->soundDesc);
+ track->soundDesc = 0;
+ }
+ }
+
+ if (!g_mixer->isSoundHandleActive(track->handle)) {
+ memset(track, 0, sizeof(Track));
+ }
+}
+
void Imuse::flushTracks() {
- // flushTracks should not lock the stack since all the functions
- // that call it already do (stopAllSounds, startSound)
+ Common::StackLock lock(_mutex);
for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
Track *track = _track[l];
- if (track->used && track->readyToRemove) {
- if (track->stream) {
- if (!track->stream->endOfStream()) {
- track->stream->finish();
- }
- if (track->stream->endOfStream()) {
- g_mixer->stopHandle(track->handle);
- delete track->stream;
- track->stream = NULL;
- _sound->closeSound(track->soundHandle);
- track->soundHandle = NULL;
- track->used = false;
- strcpy(track->soundName, "");
- }
- }
+ if (track->used && track->toBeRemoved && !g_mixer->isSoundHandleActive(track->handle)) {
+ memset(track, 0, sizeof(Track));
}
}
}
void Imuse::refreshScripts() {
+ Common::StackLock lock(_mutex);
bool found = false;
-
- StackLock lock(_mutex);
+
for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
Track *track = _track[l];
if (track->used && !track->toBeRemoved && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
@@ -68,52 +76,58 @@
}
}
- if (!found && (_curMusicSeq != 0)) {
- setMusicSequence(2000);
+ if (!found && _curMusicState) {
+ setMusicSequence(0);
}
}
void Imuse::startVoice(const char *soundName, int volume, int pan) {
- startSound(soundName, IMUSE_VOLGRP_VOICE, 0, volume, pan, 127);
+ if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
+ printf("Imuse::startVoice(): SoundName %s, vol:%d, pan:%d\n", soundName, volume, pan);
+ startSound(soundName, IMUSE_VOLGRP_VOICE, 0, volume, pan, 127, NULL);
}
void Imuse::startMusic(const char *soundName, int hookId, int volume, int pan) {
- startSound(soundName, IMUSE_VOLGRP_MUSIC, hookId, volume, pan, 126);
+ if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
+ printf("Imuse::startMusic(): SoundName %s, hookId:%d, vol:%d, pan:%d\n", soundName, hookId, volume, pan);
+ startSound(soundName, IMUSE_VOLGRP_MUSIC, hookId, volume, pan, 126, NULL);
}
+void Imuse::startMusicWithOtherPos(const char *soundName, int hookId, int volume, int pan, Track *otherTrack) {
+ if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
+ printf("Imuse::startMusicWithOtherPos(): SoundName %s, hookId:%d, vol:%d, pan:%d\n", soundName, volume, pan);
+ startSound(soundName, IMUSE_VOLGRP_MUSIC, hookId, volume, pan, 126, otherTrack);
+}
+
void Imuse::startSfx(const char *soundName, int priority) {
- startSound(soundName, IMUSE_VOLGRP_SFX, 0, 127, 0, priority);
+ if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
+ printf("Imuse::startSfx(): SoundName %s, priority:%d\n", soundName, priority);
+ startSound(soundName, IMUSE_VOLGRP_SFX, 0, 127, 0, priority, NULL);
}
int32 Imuse::getPosIn60HzTicks(const char *soundName) {
+ Common::StackLock lock(_mutex);
Track *getTrack = NULL;
getTrack = findTrack(soundName);
// Warn the user if the track was not found
if (getTrack == NULL) {
if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_WARN || debugLevel == DEBUG_ALL)
- warning("Music track '%s' could not be found to get ticks!", soundName);
+ warning("Sound '%s' could not be found to get ticks!", soundName);
return false;
}
- if (getTrack->handle.isActive()) {
- int32 pos = (5 * (getTrack->dataOffset + getTrack->regionOffset)) / (getTrack->iteration / 12);
- return pos;
- }
- return -1;
+ int32 pos = (5 * (getTrack->dataOffset + getTrack->regionOffset)) / (getTrack->feedSize / 200);
+ return pos;
}
bool Imuse::isVoicePlaying() {
- StackLock lock(_mutex);
+ Common::StackLock lock(_mutex);
for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
Track *track = _track[l];
- // Make sure the track is in use before checking the group ID,
- // otherwise volGroupId can be uninitialized or reference an
- // old track.
if (track->used && track->volGroupId == IMUSE_VOLGRP_VOICE) {
- if (track->handle.isActive()) {
+ if (g_mixer->isSoundHandleActive(track->handle))
return true;
- }
}
}
@@ -121,51 +135,55 @@
}
bool Imuse::getSoundStatus(const char *soundName) {
- Track *statusTrack = NULL;
+ Common::StackLock lock(_mutex);
+ Track *track = NULL;
// If there's no name then don't try to get the status!
if (strlen(soundName) == 0)
return false;
- statusTrack = findTrack(soundName);
+ track = findTrack(soundName);
// Warn the user if the track was not found
- if (statusTrack == NULL) {
+ if (track == NULL || !g_mixer->isSoundHandleActive(track->handle)) {
// This debug warning should be "light" since this function gets called
// on occassion to see if a sound has stopped yet
if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_NORMAL || debugLevel == DEBUG_ALL)
- printf("Music track '%s' could not be found to get status, assume inactive.\n", soundName);
+ printf("Sound '%s' could not be found to get status, assume inactive.\n", soundName);
return false;
}
- return statusTrack->handle.isActive();
+ return true;
}
void Imuse::stopSound(const char *soundName) {
+ Common::StackLock lock(_mutex);
+ if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
+ printf("Imuse::stopSound(): SoundName %s\n", soundName);
Track *removeTrack = NULL;
removeTrack = findTrack(soundName);
// Warn the user if the track was not found
if (removeTrack == NULL) {
if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_WARN || debugLevel == DEBUG_ALL)
- warning("Music track '%s' could not be found to stop!", soundName);
+ warning("Sound track '%s' could not be found to stop!", soundName);
return;
}
- removeTrack->toBeRemoved = true;
+ flushTrack(removeTrack);
}
void Imuse::stopAllSounds() {
- for (;;) {
- bool foundNotRemoved = false;
- for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
- Track *track = _track[l];
- if (track->used) {
- track->toBeRemoved = true;
- foundNotRemoved = true;
+ Common::StackLock lock(_mutex);
+ if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
+ printf("Imuse::stopAllSounds()\n");
+
+ for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
+ Track *track = _track[l];
+ if (track->used) {
+ g_mixer->stopHandle(track->handle);
+ if (track->soundDesc) {
+ _sound->closeSound(track->soundDesc);
}
+ memset(track, 0, sizeof(Track));
}
- if (!foundNotRemoved)
- break;
- flushTracks();
- g_driver->delayMillis(50);
}
}
Modified: residual/trunk/engine/imuse/imuse_sndmgr.cpp
===================================================================
--- residual/trunk/engine/imuse/imuse_sndmgr.cpp 2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/imuse/imuse_sndmgr.cpp 2008-03-10 23:06:07 UTC (rev 31101)
@@ -35,7 +35,7 @@
ImuseSndMgr::ImuseSndMgr() {
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
- memset(&_sounds[l], 0, sizeof(SoundStruct));
+ memset(&_sounds[l], 0, sizeof(SoundDesc));
}
}
@@ -72,10 +72,10 @@
} while (tag != MKID_BE('DATA'));
}
-void ImuseSndMgr::parseSoundHeader(byte *ptr, SoundStruct *sound, int &headerSize) {
+void ImuseSndMgr::parseSoundHeader(byte *ptr, SoundDesc *sound, int &headerSize) {
if (READ_UINT32(ptr) == MKID('RIFF')) {
- sound->region = (Region *)malloc(sizeof(Region));
- sound->jump = (Jump *)malloc(0);
+ sound->region = new Region[1];
+ sound->jump = new Jump[0];
sound->numJumps = 0;
sound->numRegions = 1;
sound->region[0].offset = 0;
@@ -96,8 +96,8 @@
sound->numRegions = 0;
sound->numJumps = 0;
countElements(ptr, sound->numRegions, sound->numJumps);
- sound->region = (Region *)malloc(sizeof(Region) * sound->numRegions);
- sound->jump = (Jump *)malloc(sizeof(Jump) * sound->numJumps);
+ sound->region = new Region [sound->numRegions];
+ sound->jump = new Jump [sound->numJumps];
do {
tag = READ_BE_UINT32(ptr); ptr += 4;
@@ -147,7 +147,7 @@
}
}
-ImuseSndMgr::SoundStruct *ImuseSndMgr::allocSlot() {
+ImuseSndMgr::SoundDesc *ImuseSndMgr::allocSlot() {
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
if (!_sounds[l].inUse) {
_sounds[l].inUse = true;
@@ -158,12 +158,12 @@
return NULL;
}
-ImuseSndMgr::SoundStruct *ImuseSndMgr::openSound(const char *soundName, int volGroupId) {
+ImuseSndMgr::SoundDesc *ImuseSndMgr::openSound(const char *soundName, int volGroupId) {
const char *extension = soundName + std::strlen(soundName) - 3;
byte *ptr = NULL;
int headerSize = 0;
- SoundStruct *sound = allocSlot();
+ SoundDesc *sound = allocSlot();
if (!sound) {
error("ImuseSndMgr::openSound() Can't alloc free sound slot");
}
@@ -197,94 +197,94 @@
return sound;
}
-void ImuseSndMgr::closeSound(SoundStruct *soundHandle) {
- assert(checkForProperHandle(soundHandle));
+void ImuseSndMgr::closeSound(SoundDesc *sound) {
+ assert(checkForProperHandle(sound));
- if (soundHandle->mcmpMgr) {
- delete soundHandle->mcmpMgr;
- soundHandle->mcmpMgr = NULL;
+ if (sound->mcmpMgr) {
+ delete sound->mcmpMgr;
+ sound->mcmpMgr = NULL;
}
- if (soundHandle->blockRes) {
- delete soundHandle->blockRes;
- soundHandle->blockRes = NULL;
+ if (sound->blockRes) {
+ delete sound->blockRes;
+ sound->blockRes = NULL;
}
- if (soundHandle->region) {
- free(soundHandle->region);
- soundHandle->region = NULL;
+ if (sound->region) {
+ delete[] sound->region;
+ sound->region = NULL;
}
- if (soundHandle->jump) {
- free(soundHandle->jump);
- soundHandle->jump = NULL;
+ if (sound->jump) {
+ delete[] sound->jump;
+ sound->jump = NULL;
}
- memset(soundHandle, 0, sizeof(SoundStruct));
+ memset(sound, 0, sizeof(SoundDesc));
}
-ImuseSndMgr::SoundStruct *ImuseSndMgr::cloneSound(SoundStruct *soundHandle) {
- assert(checkForProperHandle(soundHandle));
+ImuseSndMgr::SoundDesc *ImuseSndMgr::cloneSound(SoundDesc *sound) {
+ assert(checkForProperHandle(sound));
- return openSound(soundHandle->name, soundHandle->volGroupId);
+ return openSound(sound->name, sound->volGroupId);
}
-bool ImuseSndMgr::checkForProperHandle(SoundStruct *soundHandle) {
- if (!soundHandle)
+bool ImuseSndMgr::checkForProperHandle(SoundDesc *sound) {
+ if (!sound)
return false;
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
- if (soundHandle == &_sounds[l])
+ if (sound == &_sounds[l])
return true;
}
return false;
}
-int ImuseSndMgr::getFreq(SoundStruct *soundHandle) {
- assert(checkForProperHandle(soundHandle));
- return soundHandle->freq;
+int ImuseSndMgr::getFreq(SoundDesc *sound) {
+ assert(checkForProperHandle(sound));
+ return sound->freq;
}
-int ImuseSndMgr::getBits(SoundStruct *soundHandle) {
- assert(checkForProperHandle(soundHandle));
- return soundHandle->bits;
+int ImuseSndMgr::getBits(SoundDesc *sound) {
+ assert(checkForProperHandle(sound));
+ return sound->bits;
}
-int ImuseSndMgr::getChannels(SoundStruct *soundHandle) {
- assert(checkForProperHandle(soundHandle));
- return soundHandle->channels;
+int ImuseSndMgr::getChannels(SoundDesc *sound) {
+ assert(checkForProperHandle(sound));
+ return sound->channels;
}
-bool ImuseSndMgr::isEndOfRegion(SoundStruct *soundHandle, int region) {
- assert(checkForProperHandle(soundHandle));
- assert(region >= 0 && region < soundHandle->numRegions);
- return soundHandle->endFlag;
+bool ImuseSndMgr::isEndOfRegion(SoundDesc *sound, int region) {
+ assert(checkForProperHandle(sound));
+ assert(region >= 0 && region < sound->numRegions);
+ return sound->endFlag;
}
-int ImuseSndMgr::getNumRegions(SoundStruct *soundHandle) {
- assert(checkForProperHandle(soundHandle));
- return soundHandle->numRegions;
+int ImuseSndMgr::getNumRegions(SoundDesc *sound) {
+ assert(checkForProperHandle(sound));
+ return sound->numRegions;
}
-int ImuseSndMgr::getNumJumps(SoundStruct *soundHandle) {
- assert(checkForProperHandle(soundHandle));
- return soundHandle->numJumps;
+int ImuseSndMgr::getNumJumps(SoundDesc *sound) {
+ assert(checkForProperHandle(sound));
+ return sound->numJumps;
}
-int ImuseSndMgr::getRegionOffset(SoundStruct *soundHandle, int region) {
- assert(checkForProperHandle(soundHandle));
- assert(region >= 0 && region < soundHandle->numRegions);
- return soundHandle->region[region].offset;
+int ImuseSndMgr::getRegionOffset(SoundDesc *sound, int region) {
+ assert(checkForProperHandle(sound));
+ assert(region >= 0 && region < sound->numRegions);
+ return sound->region[region].offset;
}
-int ImuseSndMgr::getJumpIdByRegionAndHookId(SoundStruct *soundHandle, int region, int hookId) {
- assert(checkForProperHandle(soundHandle));
- assert(region >= 0 && region < soundHandle->numRegions);
- int32 offset = soundHandle->region[region].offset;
- for (int l = 0; l < soundHandle->numJumps; l++) {
- if (offset == soundHandle->jump[l].offset) {
- if (soundHandle->jump[l].hookId == hookId)
+int ImuseSndMgr::getJumpIdByRegionAndHookId(SoundDesc *sound, int region, int hookId) {
+ assert(checkForProperHandle(sound));
+ assert(region >= 0 && region < sound->numRegions);
+ int32 offset = sound->region[region].offset;
+ for (int l = 0; l < sound->numJumps; l++) {
+ if (offset == sound->jump[l].offset) {
+ if (sound->jump[l].hookId == hookId)
return l;
}
}
@@ -292,12 +292,12 @@
return -1;
}
-int ImuseSndMgr::getRegionIdByJumpId(SoundStruct *soundHandle, int jumpId) {
- assert(checkForProperHandle(soundHandle));
- assert(jumpId >= 0 && jumpId < soundHandle->numJumps);
- int32 dest = soundHandle->jump[jumpId].dest;
- for (int l = 0; l < soundHandle->numRegions; l++) {
- if (dest == soundHandle->region[l].offset) {
+int ImuseSndMgr::getRegionIdByJumpId(SoundDesc *sound, int jumpId) {
+ assert(checkForProperHandle(sound));
+ assert(jumpId >= 0 && jumpId < sound->numJumps);
+ int32 dest = sound->jump[jumpId].dest;
+ for (int l = 0; l < sound->numRegions; l++) {
+ if (dest == sound->region[l].offset) {
return l;
}
}
@@ -305,38 +305,38 @@
return -1;
}
-int ImuseSndMgr::getJumpHookId(SoundStruct *soundHandle, int number) {
- assert(checkForProperHandle(soundHandle));
- assert(number >= 0 && number < soundHandle->numJumps);
- return soundHandle->jump[number].hookId;
+int ImuseSndMgr::getJumpHookId(SoundDesc *sound, int number) {
+ assert(checkForProperHandle(sound));
+ assert(number >= 0 && number < sound->numJumps);
+ return sound->jump[number].hookId;
}
-int ImuseSndMgr::getJumpFade(SoundStruct *soundHandle, int number) {
- assert(checkForProperHandle(soundHandle));
- assert(number >= 0 && number < soundHandle->numJumps);
- return soundHandle->jump[number].fadeDelay;
+int ImuseSndMgr::getJumpFade(SoundDesc *sound, int number) {
+ assert(checkForProperHandle(sound));
+ assert(number >= 0 && number < sound->numJumps);
+ return sound->jump[number].fadeDelay;
}
-int32 ImuseSndMgr::getDataFromRegion(SoundStruct *soundHandle, int region, byte **buf, int32 offset, int32 size) {
- assert(checkForProperHandle(soundHandle));
+int32 ImuseSndMgr::getDataFromRegion(SoundDesc *sound, int region, byte **buf, int32 offset, int32 size) {
+ assert(checkForProperHandle(sound));
assert(buf && offset >= 0 && size >= 0);
- assert(region >= 0 && region < soundHandle->numRegions);
+ assert(region >= 0 && region < sound->numRegions);
- int32 region_offset = soundHandle->region[region].offset;
- int32 region_length = soundHandle->region[region].length;
+ int32 region_offset = sound->region[region].offset;
+ int32 region_length = sound->region[region].length;
if (offset + size > region_length) {
size = region_length - offset;
- soundHandle->endFlag = true;
+ sound->endFlag = true;
} else {
- soundHandle->endFlag = false;
+ sound->endFlag = false;
}
- if (soundHandle->mcmpData) {
- size = soundHandle->mcmpMgr->decompressSample(region_offset + offset, size, buf);
+ if (sound->mcmpData) {
+ size = sound->mcmpMgr->decompressSample(region_offset + offset, size, buf);
} else {
- *buf = (byte *)malloc(size);
- memcpy(*buf, soundHandle->resPtr + region_offset + offset, size);
+ *buf = new byte[size];
+ memcpy(*buf, sound->resPtr + region_offset + offset, size);
}
return size;
Modified: residual/trunk/engine/imuse/imuse_sndmgr.h
===================================================================
--- residual/trunk/engine/imuse/imuse_sndmgr.h 2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/imuse/imuse_sndmgr.h 2008-03-10 23:06:07 UTC (rev 31101)
@@ -64,7 +64,7 @@
public:
- struct SoundStruct {
+ struct SoundDesc {
uint16 freq; // frequency
byte channels; // stereo or mono
byte bits; // 8, 12, 16
@@ -77,6 +77,7 @@
char name[32];
McmpMgr *mcmpMgr;
Block *blockRes;
+ int type;
int volGroupId;
byte *resPtr;
bool mcmpData;
@@ -84,11 +85,11 @@
private:
- SoundStruct _sounds[MAX_IMUSE_SOUNDS];
+ SoundDesc _sounds[MAX_IMUSE_SOUNDS];
- bool checkForProperHandle(SoundStruct *soundHandle);
- SoundStruct *allocSlot();
- void parseSoundHeader(byte *ptr, SoundStruct *sound, int &headerSize);
+ bool checkForProperHandle(SoundDesc *soundDesc);
+ SoundDesc *allocSlot();
+ void parseSoundHeader(byte *ptr, SoundDesc *sound, int &headerSize);
void countElements(byte *ptr, int &numRegions, int &numJumps);
public:
@@ -96,23 +97,23 @@
ImuseSndMgr();
~ImuseSndMgr();
- SoundStruct *openSound(const char *soundName, int volGroupId);
- void closeSound(SoundStruct *soundHandle);
- SoundStruct *cloneSound(SoundStruct *soundHandle);
+ SoundDesc *openSound(const char *soundName, int volGroupId);
+ void closeSound(SoundDesc *sound);
+ SoundDesc *cloneSound(SoundDesc *sound);
- int getFreq(SoundStruct *soundHandle);
- int getBits(SoundStruct *soundHandle);
- int getChannels(SoundStruct *soundHandle);
- bool isEndOfRegion(SoundStruct *soundHandle, int region);
- int getNumRegions(SoundStruct *soundHandle);
- int getNumJumps(SoundStruct *soundHandle);
- int getRegionOffset(SoundStruct *soundHandle, int region);
- int getJumpIdByRegionAndHookId(SoundStruct *soundHandle, int region, int hookId);
- int getRegionIdByJumpId(SoundStruct *soundHandle, int jumpId);
- int getJumpHookId(SoundStruct *soundHandle, int number);
- int getJumpFade(SoundStruct *soundHandle, int number);
+ int getFreq(SoundDesc *sound);
+ int getBits(SoundDesc *sound);
+ int getChannels(SoundDesc *sound);
+ bool isEndOfRegion(SoundDesc *sound, int region);
+ int getNumRegions(SoundDesc *sound);
+ int getNumJumps(SoundDesc *sound);
+ int getRegionOffset(SoundDesc *sound, int region);
+ int getJumpIdByRegionAndHookId(SoundDesc *sound, int region, int hookId);
+ int getRegionIdByJumpId(SoundDesc *sound, int jumpId);
+ int getJumpHookId(SoundDesc *sound, int number);
+ int getJumpFade(SoundDesc *sound, int number);
- int32 getDataFromRegion(SoundStruct *soundHandle, int region, byte **buf, int32 offset, int32 size);
+ int32 getDataFromRegion(SoundDesc *sound, int region, byte **buf, int32 offset, int32 size);
};
#endif
Added: residual/trunk/engine/imuse/imuse_tables.h
===================================================================
--- residual/trunk/engine/imuse/imuse_tables.h (rev 0)
+++ residual/trunk/engine/imuse/imuse_tables.h 2008-03-10 23:06:07 UTC (rev 31101)
@@ -0,0 +1,49 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ * Copyright (C) 2003-2006 The ScummVM-Residual Team (www.scummvm.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library 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
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef IMUSE_TABLES_H
+#define IMUSE_TABLES_H
+
+#include "common/sys.h"
+#include "common/platform.h"
+#include "common/debug.h"
+
+#include "engine/lua.h"
+
+#include "mixer/mixer.h"
+#include "mixer/audiostream.h"
+
+#include "engine/imuse/imuse_sndmgr.h"
+#include "engine/imuse/imuse_mcmp_mgr.h"
+
+struct ImuseTable {
+ byte opcode;
+ int16 soundId;
+ byte atribPos;
+ byte hookId;
+ int16 fadeOut60TicksDelay;
+ byte volume;
+ byte pan;
+ char filename[32];
+};
+
+#endif
Property changes on: residual/trunk/engine/imuse/imuse_tables.h
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Rev Author URL Id
Name: svn:eol-style
+ native
Modified: residual/trunk/engine/imuse/imuse_track.cpp
===================================================================
--- residual/trunk/engine/imuse/imuse_track.cpp 2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/imuse/imuse_track.cpp 2008-03-10 23:06:07 UTC (rev 31101)
@@ -23,6 +23,7 @@
#include "common/sys.h"
#include "common/platform.h"
#include "common/debug.h"
+#include "common/mutex.h"
#include "engine/backend/driver.h"
@@ -31,6 +32,7 @@
#include "engine/imuse/imuse.h"
#include "engine/imuse/imuse_sndmgr.h"
+#include "engine/imuse/imuse_track.h"
int Imuse::allocSlot(int priority) {
int l, lowest_priority = 127;
@@ -39,35 +41,46 @@
// allocSlot called by startSound so no locking is necessary
for (l = 0; l < MAX_IMUSE_TRACKS; l++) {
if (!_track[l]->used) {
- return l; // Found an unused track
+ trackId = l;
+ break;
}
}
- warning("Imuse::startSound(): All slots are full");
- for (l = 0; l < MAX_IMUSE_TRACKS; l++) {
- Track *track = _track[l];
- if (track->used && !track->toBeRemoved && lowest_priority > track->priority) {
- lowest_priority = track->priority;
- trackId = l;
+ if (trackId == -1) {
+ warning("Imuse::startSound(): All slots are full");
+ for (l = 0; l < MAX_IMUSE_TRACKS; l++) {
+ Track *track = _track[l];
+ if (track->used && !track->toBeRemoved &&
+ (lowest_priority > track->priority)) {
+ lowest_priority = track->priority;
+ trackId = l;
+ }
}
+ if (lowest_priority <= priority) {
+ assert(trackId != -1);
+ Track *track = _track[trackId];
+
+ // Stop the track immediately
+ g_mixer->stopHandle(track->handle);
+ if (track->soundDesc) {
+ _sound->closeSound(track->soundDesc);
+ }
+
+ // Mark it as unused
+ memset(track, 0, sizeof(Track));
+ } else {
+ return -1;
+ }
}
- if (lowest_priority <= priority) {
- assert(trackId != -1);
- _track[trackId]->toBeRemoved = true;
- warning("Imuse::startSound(): Removed sound %s from track %d", _track[trackId]->soundName, trackId);
- } else {
- warning("Imuse::startSound(): Priority sound too low");
- return -1;
- }
return trackId;
}
-bool Imuse::startSound(const char *soundName, int volGroupId, int hookId, int volume, int pan, int priority) {
+bool Imuse::startSound(const char *soundName, int volGroupId, int hookId, int volume, int pan, int priority, Track *otherTrack) {
+ Common::StackLock lock(_mutex);
Track *track = NULL;
- int i, l = -1;
-
- StackLock lock(_mutex);
+ int i;
+
// If the track is already playing then there is absolutely no
// reason to start it again, the existing track should be modified
// instead of starting a new copy of the track
@@ -79,111 +92,73 @@
return true;
}
}
+
// Priority Level 127 appears to mean "load but don't play", so
// within our paradigm this is a much lower priority than everything
// else we're doing
if (priority == 127)
priority = -1;
- l = allocSlot(priority);
+
+ int l = allocSlot(priority);
if (l == -1) {
- warning("Imuse::startSound(): Can't start sound - no free slots");
+ warning("Imuse::startSound() Can't start sound - no free slots");
return false;
}
+
track = _track[l];
- i = 5;
- // At this time it is inappropriate to assume that this will always
- // succeed, so set a limit of 5 tries on running flushTracks
- while (track->used && i > 0) {
- // The designated track is not yet available. So, we call flushTracks()
- // to get it processed (and thus made ready for us). Since the actual
- // processing is done by another thread, we also call parseEvents to
- // give it some time (and to avoid busy waiting/looping).
- flushTracks();
- i--;
- }
- if (i == 0) {
- if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_WARN || debugLevel == DEBUG_ALL)
- warning("Imuse::startSound(): flushTracks was unable to free up a track for %s!", soundName);
- return false;
- }
+ // Reset the track
+ memset(track, 0, sizeof(Track));
track->pan = pan * 1000;
- track->panFadeDest = 0;
- track->panFadeStep = 0;
- track->panFadeDelay = 0;
- track->panFadeUsed = false;
track->vol = volume * 1000;
- track->volFadeDest = 0;
- track->volFadeStep = 0;
- track->volFadeDelay = 0;
- track->volFadeUsed = false;
- track->started = false;
track->volGroupId = volGroupId;
track->curHookId = hookId;
track->priority = priority;
track->curRegion = -1;
- track->dataOffset = 0;
- track->regionOffset = 0;
- track->mixerFlags = 0;
- track->mixerPan = 0;
- track->mixerVol = volume;
- track->toBeRemoved = false;
- track->readyToRemove = false;
int bits = 0, freq = 0, channels = 0;
strcpy(track->soundName, soundName);
- track->soundHandle = _sound->openSound(soundName, volGroupId);
+ track->soundDesc = _sound->openSound(soundName, volGroupId);
- if (track->soundHandle == NULL)
+ if (!track->soundDesc)
return false;
- bits = _sound->getBits(track->soundHandle);
- channels = _sound->getChannels(track->soundHandle);
- freq = _sound->getFreq(track->soundHandle);
+ bits = _sound->getBits(track->soundDesc);
+ channels = _sound->getChannels(track->soundDesc);
+ freq = _sound->getFreq(track->soundDesc);
assert(bits == 8 || bits == 12 || bits == 16);
assert(channels == 1 || channels == 2);
assert(0 < freq && freq <= 65535);
- track->iteration = freq * channels * 2;
- track->mixerFlags = SoundMixer::FLAG_16BITS;
+ track->feedSize = freq * channels * 2;
+ track->mixerFlags = kFlag16Bits;
if (channels == 2)
- track->mixerFlags |= SoundMixer::FLAG_STEREO | SoundMixer::FLAG_REVERSE_STEREO;
+ track->mixerFlags |= kFlagStereo | kFlagReverseStereo;
- pan = track->pan / 1000;
- pan = (pan != 64) ? 2 * pan - 127 : 0;
- volume = track->vol / 1000;
+ if (otherTrack && otherTrack->used && !otherTrack->toBeRemoved) {
+ track->curRegion = otherTrack->curRegion;
+ track->dataOffset = otherTrack->dataOffset;
+ track->regionOffset = otherTrack->regionOffset;
+ }
- if (track->volGroupId == 1)
- volume = (volume * _volVoice) / 128;
- if (track->volGroupId == 2)
- volume = (volume * _volSfx) / 128;
- if (track->volGroupId == 3)
- volume = (volume * _volMusic) / 128;
-
- track->mixerPan = pan;
- track->mixerVol = volume;
-
- // setup 1 second stream wrapped buffer
- int32 streamBufferSize = track->iteration;
- track->stream = makeAppendableAudioStream(freq, track->mixerFlags, streamBufferSize);
- g_mixer->playInputStream(&track->handle, track->stream, false, -1, track->mixerVol, track->mixerPan, false);
- track->started = true;
+ track->stream = Audio::makeAppendableAudioStream(freq, makeMixerFlags(track->mixerFlags));
+ g_mixer->playInputStream(track->getType(), &track->handle, track->stream, -1, track->getVol(), track->getPan());
track->used = true;
return true;
}
-Imuse::Track *Imuse::findTrack(const char *soundName) {
- StackLock lock(_mutex);
+Track *Imuse::findTrack(const char *soundName) {
for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
Track *track = _track[l];
// Since the audio (at least for Eva's keystrokes) can be referenced
// two ways: keyboard.IMU and keyboard.imu, make a case insensitive
// search for the track to make sure we can find it
- if (strlen(track->soundName) != 0 && strcasecmp(track->soundName, soundName) == 0) {
+ if (track->used && !track->toBeRemoved
+ && strlen(track->soundName) != 0 && strcasecmp(track->soundName, soundName) == 0) {
return track;
}
}
@@ -191,6 +166,7 @@
}
void Imuse::setPriority(const char *soundName, int priority) {
+ Common::StackLock lock(_mutex);
Track *changeTrack = NULL;
assert ((priority >= 0) && (priority <= 127));
@@ -204,6 +180,7 @@
}
void Imuse::setVolume(const char *soundName, int volume) {
+ Common::StackLock lock(_mutex);
Track *changeTrack;
changeTrack = findTrack(soundName);
@@ -215,17 +192,19 @@
}
void Imuse::setPan(const char *soundName, int pan) {
+ Common::StackLock lock(_mutex);
Track *changeTrack;
changeTrack = findTrack(soundName);
if (changeTrack == NULL) {
- warning("Unable to find track '%s' to change volume!", soundName);
+ warning("Unable to find track '%s' to change pan!", soundName);
return;
}
- changeTrack->pan = pan;
+ changeTrack->pan = pan * 1000;
}
int Imuse::getVolume(const char *soundName) {
+ Common::StackLock lock(_mutex);
Track *getTrack;
getTrack = findTrack(soundName);
@@ -237,6 +216,7 @@
}
void Imuse::setHookId(const char *soundName, int hookId) {
+ Common::StackLock lock(_mutex);
Track *changeTrack;
changeTrack = findTrack(soundName);
@@ -248,12 +228,12 @@
}
int Imuse::getCountPlayedTracks(const char *soundName) {
+ Common::StackLock lock(_mutex);
int count = 0;
- StackLock lock(_mutex);
for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
Track *track = _track[l];
- if (track->used && !track->toBeRemoved && (strcmp(track->soundName, soundName) == 0)) {
+ if (track->used && !track->toBeRemoved && (strcasecmp(track->soundName, soundName) == 0)) {
count++;
}
}
@@ -262,6 +242,7 @@
}
void Imuse::selectVolumeGroup(const char *soundName, int volGroupId) {
+ Common::StackLock lock(_mutex);
Track *changeTrack;
assert((volGroupId >= 1) && (volGroupId <= 4));
@@ -277,6 +258,7 @@
}
void Imuse::setFadeVolume(const char *soundName, int destVolume, int duration) {
+ Common::StackLock lock(_mutex);
Track *changeTrack;
changeTrack = findTrack(soundName);
@@ -291,6 +273,7 @@
}
void Imuse::setFadePan(const char *soundName, int destPan, int duration) {
+ Common::StackLock lock(_mutex);
Track *changeTrack;
changeTrack = findTrack(soundName);
@@ -305,7 +288,7 @@
}
char *Imuse::getCurMusicSoundName() {
- StackLock lock(_mutex);
+ Common::StackLock lock(_mutex);
for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
Track *track = _track[l];
if (track->used && !track->toBeRemoved && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
@@ -315,65 +298,90 @@
return NULL;
}
+int Imuse::getCurMusicPan() {
+ Common::StackLock lock(_mutex);
+ for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
+ Track *track = _track[l];
+ if (track->used && !track->toBeRemoved && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
+ return track->pan / 1000;
+ }
+ }
+ return NULL;
+}
+
+int Imuse::getCurMusicVol() {
+ Common::StackLock lock(_mutex);
+ for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
+ Track *track = _track[l];
+ if (track->used && !track->toBeRemoved && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
+ return track->vol / 1000;
+ }
+ }
+ return NULL;
+}
+
void Imuse::fadeOutMusic(int duration) {
- StackLock lock(_mutex);
+ Common::StackLock lock(_mutex);
for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
Track *track = _track[l];
if (track->used && !track->toBeRemoved && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
cloneToFadeOutTrack(track, duration);
- track->toBeRemoved = true;
+ flushTrack(track);
+ return;
}
}
}
-Imuse::Track *Imuse::cloneToFadeOutTrack(Track *track, int fadeDelay) {
- assert(track);
- Track *fadeTrack = 0;
+void Imuse::fadeOutMusicAndStartNew(int fadeDelay, const char *filename, int hookId, int vol, int pan) {
+ Common::StackLock lock(_mutex);
- {
- StackLock lock(_mutex);
- for (int l = MAX_IMUSE_TRACKS; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
- if (!_track[l]->used) {
- fadeTrack = _track[l];
- break;
- }
+ for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
+ Track *track = _track[l];
+ if (track->used && !track->toBeRemoved && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
+ startMusicWithOtherPos(filename, 0, vol, pan, track);
+ cloneToFadeOutTrack(track, fadeDelay);
+ flushTrack(track);
+ break;
}
- if (fadeTrack == 0)
- error("Imuse::cloneTofadeTrackId() Can't find free fade track");
+ }
+}
- fadeTrack->pan = track->pan;
- fadeTrack->vol = track->vol;
- fadeTrack->volGroupId = track->volGroupId;
- fadeTrack->priority = track->priority;
- fadeTrack->dataOffset = track->dataOffset;
- fadeTrack->regionOffset = track->regionOffset;
- fadeTrack->curRegion = track->curRegion;
- fadeTrack->curHookId = track->curHookId;
- fadeTrack->iteration = track->iteration;
- fadeTrack->mixerFlags = track->mixerFlags;
- fadeTrack->mixerVol = track->mixerVol;
- fadeTrack->mixerPan = track->mixerPan;
- fadeTrack->toBeRemoved = track->toBeRemoved;
- fadeTrack->readyToRemove = track->readyToRemove;
- fadeTrack->started = track->started;
- strcpy(fadeTrack->soundName, track->soundName);
- fadeTrack->soundHandle = _sound->cloneSound(track->soundHandle);
- assert(fadeTrack->soundHandle);
- fadeTrack->volFadeDelay = fadeDelay;
- fadeTrack->volFadeDest = 0;
- fadeTrack->volFadeStep = (fadeTrack->volFadeDest - fadeTrack->vol) * 60 * (1000 / _callbackFps) / (1000 * fadeDelay);
- fadeTrack->volFadeUsed = true;
- fadeTrack->panFadeDelay = 0;
- fadeTrack->panFadeDest = 0;
- fadeTrack->panFadeStep = 0;
- fadeTrack->panFadeUsed = false;
+Track *Imuse::cloneToFadeOutTrack(Track *track, int fadeDelay) {
+ assert(track);
+ Track *fadeTrack;
+
+ if (track->toBeRemoved) {
+ error("cloneToFadeOutTrack: Tried to clone a track to be removed, please bug report");
+ return NULL;
}
- // setup 1 second stream wrapped buffer
- int32 streamBufferSize = fadeTrack->iteration;
- fadeTrack->stream = makeAppendableAudioStream(_sound->getFreq(fadeTrack->soundHandle), fadeTrack->mixerFlags, streamBufferSize);
- g_mixer->playInputStream(&fadeTrack->handle, fadeTrack->stream, false, -1, fadeTrack->vol / 1000, fadeTrack->pan, false);
- fadeTrack->started = true;
+ assert(track->trackId < MAX_IMUSE_TRACKS);
+ fadeTrack = _track[track->trackId + MAX_IMUSE_TRACKS];
+
+ if (fadeTrack->used) {
+ flushTrack(fadeTrack);
+ g_mixer->stopHandle(fadeTrack->handle);
+ }
+
+ // Clone the settings of the given track
+ memcpy(fadeTrack, track, sizeof(Track));
+ fadeTrack->trackId = track->trackId + MAX_IMUSE_TRACKS;
+
+ // Clone the sound.
+ // leaving bug number for now #1635361
+ ImuseSndMgr::SoundDesc *soundDesc = _sound->cloneSound(track->soundDesc);
+ assert(soundDesc);
+ track->soundDesc = soundDesc;
+
+ // Set the volume fading parameters to indicate a fade out
+ fadeTrack->volFadeDelay = fadeDelay;
+ fadeTrack->volFadeDest = 0;
+ fadeTrack->volFadeStep = (fadeTrack->volFadeDest - fadeTrack->vol) * 60 * (1000 / _callbackFps) / (1000 * fadeDelay);
+ fadeTrack->volFadeUsed = true;
+
+ // Create an appendable output buffer
+ fadeTrack->stream = Audio::makeAppendableAudioStream(_sound->getFreq(fadeTrack->soundDesc), makeMixerFlags(fadeTrack->mixerFlags));
+ g_mixer->playInputStream(track->getType(), &fadeTrack->handle, fadeTrack->stream, -1, fadeTrack->getVol(), fadeTrack->getPan());
fadeTrack->used = true;
return fadeTrack;
Added: residual/trunk/engine/imuse/imuse_track.h
===================================================================
--- residual/trunk/engine/imuse/imuse_track.h (rev 0)
+++ residual/trunk/engine/imuse/imuse_track.h 2008-03-10 23:06:07 UTC (rev 31101)
@@ -0,0 +1,98 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ * Copyright (C) 2003-2006 The ScummVM-Residual Team (www.scummvm.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library 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
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef IMUSE_TRACK_H
+#define IMUSE_TRACK_H
+
+#include "common/sys.h"
+#include "common/platform.h"
+#include "common/debug.h"
+
+#include "engine/lua.h"
+
+#include "mixer/mixer.h"
+#include "mixer/audiostream.h"
+
+#include "engine/imuse/imuse_sndmgr.h"
+#include "engine/imuse/imuse_mcmp_mgr.h"
+
+enum {
+ kFlagUnsigned = 1 << 0,
+ kFlag16Bits = 1 << 1,
+ kFlagLittleEndian = 1 << 2,
+ kFlagStereo = 1 << 3,
+ kFlagReverseStereo = 1 << 4
+};
+
+struct Track {
+ int trackId;
+
+ int32 pan;
+ int32 panFadeDest;
+ int32 panFadeStep;
+ int32 panFadeDelay;
+ bool panFadeUsed;
+ int32 vol;
+ int32 volFadeDest;
+ int32 volFadeStep;
+ int32 volFadeDelay;
+ bool volFadeUsed;
+
+ char soundName[32];
+ bool used;
+ bool toBeRemoved;
+ int32 priority;
+ int32 regionOffset;
+ int32 dataOffset;
+ int32 curRegion;
+ int32 curHookId;
+ int32 volGroupId;
+ int32 feedSize;
+ int32 mixerFlags;
+
+ ImuseSndMgr::SoundDesc *soundDesc;
+ Audio::SoundHandle handle;
+ Audio::AppendableAudioStream *stream;
+
+ Track() : used(false), stream(NULL) {
+ soundName[0] = 0;
+ }
+
+ int getPan() const { return (pan != 6400) ? 2 * (pan / 1000) - 127 : 0; }
+ int getVol() const { return vol / 1000; }
+ Audio::Mixer::SoundType getType() const {
+ Audio::Mixer::SoundType type = Audio::Mixer::kPlainSoundType;
+ if (volGroupId == IMUSE_VOLGRP_VOICE)
+ type = Audio::Mixer::kSpeechSoundType;
+ else if (volGroupId == IMUSE_VOLGRP_SFX)
+ type = Audio::Mixer::kSFXSoundType;
+ else if (volGroupId == IMUSE_VOLGRP_MUSIC)
+ type = Audio::Mixer::kMusicSoundType;
+ else if (volGroupId == IMUSE_VOLGRP_BGND)
+ type = Audio::Mixer::kPlainSoundType;
+ else if (volGroupId == IMUSE_VOLGRP_ACTION)
+ type = Audio::Mixer::kPlainSoundType;
+ return type;
+ }
+};
+
+#endif
Property changes on: residual/trunk/engine/imuse/imuse_track.h
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Rev Author URL Id
Name: svn:eol-style
+ native
Modified: residual/trunk/engine/lua.cpp
===================================================================
--- residual/trunk/engine/lua.cpp 2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/lua.cpp 2008-03-10 23:06:07 UTC (rev 31101)
@@ -42,6 +42,8 @@
#include "engine/imuse/imuse.h"
+#include "mixer/mixer.h"
+
#include <cstdio>
#include <cmath>
#include <zlib.h>
@@ -1880,7 +1882,7 @@
group = check_int(3);
// Start the sound with the appropriate settings
- if (g_imuse->startSound(soundName, group, 0, 127, 0, priority)) {
+ if (g_imuse->startSound(soundName, group, 0, 127, 0, priority, NULL)) {
lua_pushstring(soundName);
} else {
// Allow soft failing when loading sounds, hard failing when not
@@ -1929,32 +1931,32 @@
static void ImSetMusicVol() {
DEBUG_FUNCTION();
- g_imuse->setGroupMusicVolume(check_int(1));
+ g_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, check_int(1));
}
static void ImGetMusicVol() {
DEBUG_FUNCTION();
- lua_pushnumber(g_imuse->getGroupMusicVolume());
+ lua_pushnumber(g_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType));
}
static void ImSetVoiceVol() {
DEBUG_FUNCTION();
- g_imuse->setGroupVoiceVolume(check_int(1));
+ g_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, check_int(1));
}
static void ImGetVoiceVol() {
DEBUG_FUNCTION();
- lua_pushnumber(g_imuse->getGroupVoiceVolume());
+ lua_pushnumber(g_mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType));
}
static void ImSetSfxVol() {
DEBUG_FUNCTION();
- g_imuse->setGroupSfxVolume(check_int(1));
+ g_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, check_int(1));
}
static void ImGetSfxVol() {
DEBUG_FUNCTION();
- lua_pushnumber(g_imuse->getGroupSfxVolume());
+ lua_pushnumber(g_mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType));
}
static void ImSetParam() {
@@ -2961,7 +2963,7 @@
filename = luaL_check_string(1);
SaveGame *savedState = new SaveGame(filename, false);
dataSize = savedState->beginSection('SIMG');
- data = (char *)malloc(dataSize);
+ data = new char[dataSize];
savedState->read(data, dataSize);
screenshot = new Bitmap(data, width, height, "screenshot");
if (screenshot) {
Modified: residual/trunk/engine/main.cpp
===================================================================
--- residual/trunk/engine/main.cpp 2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/main.cpp 2008-03-10 23:06:07 UTC (rev 31101)
@@ -58,6 +58,8 @@
static bool g_lua_initialized = false;
Driver *g_driver = NULL;
+DefaultTimerManager *g_timer = NULL;
+Audio::Mixer *g_mixer = NULL;
static bool parseBoolStr(const char *val) {
if (val == NULL || val[0] == 0)
@@ -168,12 +170,18 @@
g_driver = new DriverTinyGL(640, 480, 16, fullscreen);
else
@@ Diff output truncated at 100000 characters. @@
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