2009-02-17 15:05:16 +00:00
|
|
|
/* ScummVM - Graphic Adventure Engine
|
|
|
|
*
|
|
|
|
* ScummVM is the legal property of its developers, whose names
|
|
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
|
|
* file distributed with this source distribution.
|
|
|
|
*
|
|
|
|
* 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$
|
|
|
|
*
|
|
|
|
*/
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-24 15:33:40 +00:00
|
|
|
#ifndef SCI_SFX_SFX_ITERATOR_INTERNAL
|
|
|
|
#define SCI_SFX_SFX_ITERATOR_INTERNAL
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-03-01 06:02:17 +00:00
|
|
|
#include "sci/sfx/iterator.h"
|
2009-02-27 02:23:00 +00:00
|
|
|
#include "sci/sfx/sci_midi.h"
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-03-07 06:57:17 +00:00
|
|
|
#include "common/list.h"
|
|
|
|
|
2009-02-21 10:23:36 +00:00
|
|
|
namespace Sci {
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
/* States */
|
|
|
|
|
|
|
|
#define SI_STATE_UNINITIALISED -1
|
|
|
|
#define SI_STATE_DELTA_TIME 0 /* Now at a delta time */
|
|
|
|
#define SI_STATE_COMMAND 1 /* Now at a MIDI operation */
|
|
|
|
#define SI_STATE_PENDING 2 /* Pending for loop */
|
|
|
|
#define SI_STATE_FINISHED 3 /* End of song */
|
|
|
|
#define SI_STATE_PCM 4 /* Should report a PCM next (-> DELTA_TIME) */
|
|
|
|
#define SI_STATE_PCM_MAGIC_DELTA 5 /* Should report a ``magic'' one tick delta time next (goes on to FINISHED) */
|
|
|
|
|
|
|
|
|
|
|
|
/* Iterator types */
|
|
|
|
|
|
|
|
#define SCI_SONG_ITERATOR_TYPE_SCI0 0
|
|
|
|
#define SCI_SONG_ITERATOR_TYPE_SCI1 1
|
|
|
|
|
|
|
|
#define SIPFX __FILE__" : "
|
|
|
|
|
|
|
|
|
2009-03-06 07:25:06 +00:00
|
|
|
struct SongIteratorChannel {
|
2009-02-15 06:10:59 +00:00
|
|
|
int state; /* SI_STATE_* */
|
|
|
|
int offset; /* Offset into the data chunk */
|
|
|
|
int end; /* Last allowed byte in track */
|
|
|
|
int id; /* Some channel ID */
|
|
|
|
int loop_offset;
|
|
|
|
int delay; /* Number of ticks before the
|
|
|
|
** specified channel is next
|
|
|
|
** used, or
|
|
|
|
** CHANNEL_DELAY_MISSING to
|
|
|
|
** indicate that the delay has
|
|
|
|
** not yet been read */
|
|
|
|
|
|
|
|
/* Two additional offsets for recovering: */
|
|
|
|
int initial_offset;
|
|
|
|
int playmask; /* Active playmask (MIDI channels to play in here) */
|
|
|
|
int notes_played; /* #of notes played since the last loop start */
|
|
|
|
int loop_timepos; /* Total delay for this channel's loop marker */
|
|
|
|
int total_timepos; /* Number of ticks since the beginning, ignoring loops */
|
|
|
|
int timepos_increment; /* Number of ticks until the next command (to add) */
|
|
|
|
|
|
|
|
int saw_notes; /* Bitmask of channels we have currently played notes on */
|
|
|
|
byte last_cmd; /* Last operation executed, for running status */
|
2009-03-07 06:56:39 +00:00
|
|
|
|
|
|
|
public:
|
|
|
|
void resetSynthChannels();
|
2009-02-21 22:06:42 +00:00
|
|
|
};
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-03-06 07:25:48 +00:00
|
|
|
class BaseSongIterator : public SongIterator {
|
|
|
|
public:
|
2009-03-01 06:01:48 +00:00
|
|
|
int polyphony[MIDI_CHANNELS]; /* # of simultaneous notes on each */
|
|
|
|
int importance[MIDI_CHANNELS]; /* priority rating for each channel, 0 means unrated. */
|
|
|
|
|
|
|
|
|
|
|
|
int ccc; /* Cumulative cue counter, for those who need it */
|
2009-03-07 06:56:39 +00:00
|
|
|
byte resetflag; /* for 0x4C -- on DoSound StopSound, do we return to start? */
|
2009-03-06 07:25:48 +00:00
|
|
|
int _deviceId; /* ID of the device we generating events for */
|
2009-03-01 06:01:48 +00:00
|
|
|
int active_channels; /* Number of active channels */
|
2009-03-07 06:56:39 +00:00
|
|
|
uint _size; /* Song size */
|
|
|
|
byte *_data;
|
2009-03-01 06:01:48 +00:00
|
|
|
|
|
|
|
int loops; /* Number of loops remaining */
|
|
|
|
int recover_delay;
|
2009-03-06 17:53:11 +00:00
|
|
|
|
|
|
|
public:
|
2009-03-07 06:56:39 +00:00
|
|
|
BaseSongIterator(byte *data, uint size, songit_id_t id);
|
2009-03-09 19:55:18 +00:00
|
|
|
|
|
|
|
// Copy constructor taking care of memory handling
|
|
|
|
BaseSongIterator(const BaseSongIterator&);
|
|
|
|
|
2009-03-06 17:53:11 +00:00
|
|
|
~BaseSongIterator();
|
2009-02-21 22:06:42 +00:00
|
|
|
};
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
/********************************/
|
|
|
|
/*--------- SCI 0 --------------*/
|
|
|
|
/********************************/
|
|
|
|
|
2009-03-06 07:25:25 +00:00
|
|
|
class Sci0SongIterator : public BaseSongIterator {
|
|
|
|
public:
|
2009-03-06 07:25:06 +00:00
|
|
|
SongIteratorChannel channel;
|
2009-03-06 07:25:25 +00:00
|
|
|
|
|
|
|
public:
|
2009-03-07 06:56:39 +00:00
|
|
|
Sci0SongIterator(byte *data, uint size, songit_id_t id);
|
2009-03-06 17:39:46 +00:00
|
|
|
|
2009-03-06 07:25:48 +00:00
|
|
|
int nextCommand(byte *buf, int *result);
|
|
|
|
Audio::AudioStream *getAudioStream();
|
|
|
|
SongIterator *handleMessage(SongIteratorMessage msg);
|
|
|
|
void init();
|
|
|
|
int getTimepos();
|
2009-02-21 22:06:42 +00:00
|
|
|
};
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
|
|
|
|
/********************************/
|
|
|
|
/*--------- SCI 1 --------------*/
|
|
|
|
/********************************/
|
|
|
|
|
|
|
|
|
2009-03-06 07:25:06 +00:00
|
|
|
struct Sci1Sample {
|
2009-03-07 06:56:39 +00:00
|
|
|
/* Time left-- initially, this is 'Sample point 1'.
|
|
|
|
* After initialisation, it is 'sample point 1 minus the sample
|
|
|
|
* point of the previous sample'
|
|
|
|
*/
|
|
|
|
int delta;
|
2009-02-15 06:10:59 +00:00
|
|
|
int size;
|
2009-03-07 06:56:39 +00:00
|
|
|
bool announced; /* Announced for download (SI_PCM) */
|
2009-02-15 06:10:59 +00:00
|
|
|
sfx_pcm_config_t format;
|
2009-03-07 06:56:39 +00:00
|
|
|
byte *_data;
|
2009-02-21 22:06:42 +00:00
|
|
|
};
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-03-06 07:25:25 +00:00
|
|
|
class Sci1SongIterator : public BaseSongIterator {
|
|
|
|
public:
|
2009-03-06 07:25:48 +00:00
|
|
|
SongIteratorChannel _channels[MIDI_CHANNELS];
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
/* Invariant: Whenever channels[i].delay == CHANNEL_DELAY_MISSING,
|
|
|
|
** channel_offset[i] points to a delta time object. */
|
|
|
|
|
2009-03-07 06:56:39 +00:00
|
|
|
bool _initialised; /* Whether the MIDI channel setup has been initialised */
|
2009-03-06 07:25:48 +00:00
|
|
|
int _numChannels; /* Number of channels actually used */
|
2009-03-07 06:57:17 +00:00
|
|
|
Common::List<Sci1Sample> _samples;
|
2009-03-06 07:25:48 +00:00
|
|
|
int _numLoopedChannels; /* Number of channels that are ready to loop */
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-03-06 07:25:48 +00:00
|
|
|
int _delayRemaining; /* Number of ticks that haven't been polled yet */
|
2009-03-07 06:56:39 +00:00
|
|
|
int _hold;
|
2009-03-06 07:25:25 +00:00
|
|
|
|
|
|
|
public:
|
2009-03-07 06:56:39 +00:00
|
|
|
Sci1SongIterator(byte *data, uint size, songit_id_t id);
|
2009-03-06 17:53:11 +00:00
|
|
|
~Sci1SongIterator();
|
2009-03-06 17:39:46 +00:00
|
|
|
|
2009-03-06 07:25:48 +00:00
|
|
|
int nextCommand(byte *buf, int *result);
|
|
|
|
Audio::AudioStream *getAudioStream();
|
|
|
|
SongIterator *handleMessage(SongIteratorMessage msg);
|
|
|
|
void init();
|
|
|
|
int getTimepos();
|
2009-02-21 22:06:42 +00:00
|
|
|
};
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
#define PLAYMASK_NONE 0x0
|
|
|
|
|
|
|
|
/**********************************/
|
|
|
|
/*--------- Fast Forward ---------*/
|
|
|
|
/**********************************/
|
|
|
|
|
2009-03-06 07:25:25 +00:00
|
|
|
class FastForwardSongIterator : public SongIterator {
|
2009-03-07 06:56:39 +00:00
|
|
|
protected:
|
|
|
|
SongIterator *_delegate;
|
|
|
|
int _delta; /**< Remaining time */
|
2009-03-06 07:25:25 +00:00
|
|
|
|
|
|
|
public:
|
2009-03-07 06:56:39 +00:00
|
|
|
FastForwardSongIterator(SongIterator *capsit, int delta);
|
|
|
|
|
2009-03-06 07:25:48 +00:00
|
|
|
int nextCommand(byte *buf, int *result);
|
|
|
|
Audio::AudioStream *getAudioStream();
|
|
|
|
SongIterator *handleMessage(SongIteratorMessage msg);
|
|
|
|
int getTimepos();
|
2009-02-21 22:06:42 +00:00
|
|
|
};
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
|
|
|
|
/**********************************/
|
2009-03-07 06:56:39 +00:00
|
|
|
/*--------- Tee iterator ---------*/
|
2009-02-15 06:10:59 +00:00
|
|
|
/**********************************/
|
|
|
|
|
2009-03-07 06:56:39 +00:00
|
|
|
enum {
|
|
|
|
MAX_BUF_SIZE = 4,
|
|
|
|
|
|
|
|
TEE_LEFT = 0,
|
|
|
|
TEE_RIGHT = 1,
|
|
|
|
TEE_LEFT_ACTIVE = (1<<0),
|
|
|
|
TEE_RIGHT_ACTIVE = (1<<1),
|
|
|
|
TEE_LEFT_READY = (1<<2), /**< left result is ready */
|
|
|
|
TEE_RIGHT_READY = (1<<3), /**< right result is ready */
|
|
|
|
TEE_LEFT_PCM = (1<<4),
|
|
|
|
TEE_RIGHT_PCM = (1<<5),
|
|
|
|
|
|
|
|
TEE_MORPH_NONE = 0, /**< Not waiting to self-morph */
|
|
|
|
TEE_MORPH_READY = 1 /**< Ready to self-morph */
|
|
|
|
};
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-03-06 07:25:25 +00:00
|
|
|
class TeeSongIterator : public SongIterator {
|
|
|
|
public:
|
|
|
|
int _status;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
int morph_deferred; /* One of TEE_MORPH_* above */
|
|
|
|
|
|
|
|
struct {
|
2009-03-06 07:25:06 +00:00
|
|
|
SongIterator *it;
|
2009-02-15 06:10:59 +00:00
|
|
|
byte buf[MAX_BUF_SIZE];
|
|
|
|
int result;
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
byte channel_remap[MIDI_CHANNELS];
|
|
|
|
/* Remapping for channels */
|
|
|
|
|
2009-03-06 07:25:48 +00:00
|
|
|
} _children[2];
|
2009-03-06 07:25:25 +00:00
|
|
|
|
|
|
|
public:
|
2009-03-06 17:39:46 +00:00
|
|
|
~TeeSongIterator();
|
|
|
|
|
2009-03-06 07:25:48 +00:00
|
|
|
int nextCommand(byte *buf, int *result);
|
|
|
|
Audio::AudioStream *getAudioStream();
|
|
|
|
SongIterator *handleMessage(SongIteratorMessage msg);
|
|
|
|
void init();
|
|
|
|
int getTimepos() { return 0; }
|
2009-02-21 22:06:42 +00:00
|
|
|
};
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-21 10:23:36 +00:00
|
|
|
} // End of namespace Sci
|
|
|
|
|
2009-02-24 15:33:40 +00:00
|
|
|
#endif // SCI_SFX_SFX_ITERATOR_INTERNAL
|