SCI: Merged SfxPlayer/NewPlayer code into sfx/core.cpp

svn-id: r40965
This commit is contained in:
Max Horn 2009-05-28 22:02:45 +00:00
parent 02ac46565b
commit 99b520dd09
9 changed files with 307 additions and 434 deletions

View File

@ -25,7 +25,9 @@
#include "sci/sci.h"
#include "sci/engine/state.h"
#include "sci/sfx/player.h"
//#include "sci/sfx/player.h"
#include "sci/sfx/iterator.h"
#include "sci/sfx/misc.h"
#include "sci/engine/kernel.h"
#include "sci/engine/vm.h" // for Object

View File

@ -35,7 +35,7 @@
#include "sci/engine/kernel_types.h"
#include "sci/engine/seg_manager.h"
#include "sci/engine/gc.h"
#include "sci/sfx/player.h"
#include "sci/sfx/misc.h" // for sfx_reset_player
namespace Sci {

View File

@ -61,7 +61,6 @@ MODULE_OBJS = \
sfx/core.o \
sfx/iterator.o \
sfx/songlib.o \
sfx/player/new_player.o \
sfx/seq/gm.o \
sfx/seq/instrument-map.o \
sfx/seq/map-mt32-to-gm.o \

View File

@ -27,9 +27,13 @@
#include "sci/tools.h"
#include "sci/sfx/core.h"
#include "sci/sfx/player/new_player.h"
#include "sci/sfx/iterator.h"
#include "sci/sfx/misc.h"
#include "sci/sfx/sci_midi.h"
#include "sci/sfx/softseq/pcjr.h"
#include "sci/sfx/softseq/adlib.h"
#include "common/system.h"
#include "common/timer.h"
@ -38,15 +42,295 @@
namespace Sci {
/*#define DEBUG_SONG_API*/
/*#define DEBUG_CUES*/
#ifdef DEBUG_CUES
int sciprintf(char *msg, ...);
#endif
class SfxPlayer;
SfxPlayer *player = NULL; // FIXME: Avoid static vars
#pragma mark -
class SfxPlayer {
public:
/** Number of voices that can play simultaneously */
int _polyphony;
public:
SfxPlayer() : _polyphony(0) {}
virtual ~SfxPlayer() {}
virtual Common::Error init(ResourceManager *resmgr, int expected_latency) = 0;
/* Initializes the player
** Parameters: (ResourceManager *) resmgr: A resource manager for driver initialization
** (int) expected_latency: Expected delay in between calls to 'maintenance'
** (in microseconds)
** Returns : (int) Common::kNoError on success, Common::kUnknownError on failure
*/
virtual Common::Error add_iterator(SongIterator *it, uint32 start_time) = 0;
/* Adds an iterator to the song player
** Parameters: (songx_iterator_t *) it: The iterator to play
** (uint32) start_time: The time to assume as the
** time the first MIDI command executes at
** Returns : (int) Common::kNoError on success, Common::kUnknownError on failure
** The iterator should not be cloned (to avoid memory leaks) and
** may be modified according to the needs of the player.
** Implementors may use the 'sfx_iterator_combine()' function
** to add iterators onto their already existing iterators
*/
virtual Common::Error stop() = 0;
/* Stops the currently playing song and deletes the associated iterator
** Returns : (int) Common::kNoError on success, Common::kUnknownError on failure
*/
virtual Common::Error iterator_message(const SongIterator::Message &msg) = 0;
/* Transmits a song iterator message to the active song
** Parameters: (SongIterator::Message) msg: The message to transmit
** Returns : (int) Common::kNoError on success, Common::kUnknownError on failure
** OPTIONAL -- may be NULL
** If this method is not present, sending messages will stop
** and re-start playing, so it is preferred that it is present
*/
virtual Common::Error pause() = 0;
/* Pauses song playing
** Returns : (int) Common::kNoError on success, Common::kUnknownError on failure
*/
virtual Common::Error resume() = 0;
/* Resumes song playing after a pause
** Returns : (int) Common::kNoError on success, Common::kUnknownError on failure
*/
virtual Common::Error exit() = 0;
/* Stops the player
** Returns : (int) Common::kNoError on success, Common::kUnknownError on failure
*/
virtual void tell_synth(int buf_nr, byte *buf) = 0;
/* Pass a raw MIDI event to the synth
Parameters: (int) argc: Length of buffer holding the midi event
(byte *) argv: The buffer itself
*/
};
#pragma mark -
class NewPlayer : public SfxPlayer {
protected:
MidiPlayer *_mididrv;
SongIterator *_iterator;
Audio::Timestamp _wakeupTime;
Audio::Timestamp _currentTime;
uint32 _pauseTimeDiff;
bool _paused;
bool _iteratorIsDone;
uint32 _tempo;
Common::Mutex *_mutex;
int _volume;
void play_song(SongIterator *it);
static void player_timer_callback(void *refCon);
public:
NewPlayer();
virtual Common::Error init(ResourceManager *resmgr, int expected_latency);
virtual Common::Error add_iterator(SongIterator *it, uint32 start_time);
virtual Common::Error stop();
virtual Common::Error iterator_message(const SongIterator::Message &msg);
virtual Common::Error pause();
virtual Common::Error resume();
virtual Common::Error exit();
virtual void tell_synth(int buf_nr, byte *buf);
};
NewPlayer::NewPlayer() {
_mididrv = 0;
_iterator = NULL;
_pauseTimeDiff = 0;
_paused = false;
_iteratorIsDone = false;
_tempo = 0;
_mutex = 0;
_volume = 15;
}
void NewPlayer::play_song(SongIterator *it) {
while (_iterator && _wakeupTime.msecsDiff(_currentTime) <= 0) {
int delay;
byte buf[8];
int result;
switch ((delay = songit_next(&(_iterator),
buf, &result,
IT_READER_MASK_ALL
| IT_READER_MAY_FREE
| IT_READER_MAY_CLEAN))) {
case SI_FINISHED:
delete _iterator;
_iterator = NULL;
_iteratorIsDone = true;
return;
case SI_IGNORE:
case SI_LOOP:
case SI_RELATIVE_CUE:
case SI_ABSOLUTE_CUE:
break;
case SI_PCM:
sfx_play_iterator_pcm(_iterator, 0);
break;
case 0:
static_cast<MidiDriver *>(_mididrv)->send(buf[0], buf[1], buf[2]);
break;
default:
_wakeupTime = _wakeupTime.addFrames(delay);
}
}
}
void NewPlayer::tell_synth(int buf_nr, byte *buf) {
byte op1 = (buf_nr < 2 ? 0 : buf[1]);
byte op2 = (buf_nr < 3 ? 0 : buf[2]);
static_cast<MidiDriver *>(_mididrv)->send(buf[0], op1, op2);
}
void NewPlayer::player_timer_callback(void *refCon) {
NewPlayer *thePlayer = (NewPlayer *)refCon;
assert(refCon);
Common::StackLock lock(*thePlayer->_mutex);
if (thePlayer->_iterator && !thePlayer->_iteratorIsDone && !thePlayer->_paused) {
thePlayer->play_song(thePlayer->_iterator);
}
thePlayer->_currentTime = thePlayer->_currentTime.addFrames(1);
}
/* API implementation */
Common::Error NewPlayer::init(ResourceManager *resmgr, int expected_latency) {
MidiDriverType musicDriver = MidiDriver::detectMusicDriver(MDT_PCSPK | MDT_ADLIB);
switch(musicDriver) {
case MD_ADLIB:
_mididrv = new MidiPlayer_Adlib();
break;
case MD_PCJR:
_mididrv = new MidiPlayer_PCJr();
break;
case MD_PCSPK:
_mididrv = new MidiPlayer_PCSpeaker();
break;
default:
break;
}
assert(_mididrv);
_polyphony = _mididrv->getPolyphony();
_tempo = _mididrv->getBaseTempo();
uint32 time = g_system->getMillis();
_currentTime = Audio::Timestamp(time, 1000000 / _tempo);
_wakeupTime = Audio::Timestamp(time, SFX_TICKS_PER_SEC);
_mutex = new Common::Mutex();
_mididrv->setTimerCallback(this, player_timer_callback);
_mididrv->open(resmgr);
_mididrv->setVolume(_volume);
return Common::kNoError;
}
Common::Error NewPlayer::add_iterator(SongIterator *it, uint32 start_time) {
Common::StackLock lock(*_mutex);
SIMSG_SEND(it, SIMSG_SET_PLAYMASK(_mididrv->getPlayMask()));
SIMSG_SEND(it, SIMSG_SET_RHYTHM(_mididrv->hasRhythmChannel()));
if (_iterator == NULL) {
// Resync with clock
_currentTime = Audio::Timestamp(g_system->getMillis(), 1000000 / _tempo);
_wakeupTime = Audio::Timestamp(start_time, SFX_TICKS_PER_SEC);
}
_iterator = sfx_iterator_combine(_iterator, it);
_iteratorIsDone = false;
return Common::kNoError;
}
Common::Error NewPlayer::stop(void) {
debug(3, "Player: Stopping song iterator %p", (void *)_iterator);
Common::StackLock lock(*_mutex);
delete _iterator;
_iterator = NULL;
for (int i = 0; i < MIDI_CHANNELS; i++)
static_cast<MidiDriver *>(_mididrv)->send(0xb0 + i, SCI_MIDI_CHANNEL_NOTES_OFF, 0);
return Common::kNoError;
}
Common::Error NewPlayer::iterator_message(const SongIterator::Message &msg) {
Common::StackLock lock(*_mutex);
if (!_iterator) {
return Common::kUnknownError;
}
songit_handle_message(&_iterator, msg);
return Common::kNoError;
}
Common::Error NewPlayer::pause(void) {
Common::StackLock lock(*_mutex);
_paused = true;
_pauseTimeDiff = _wakeupTime.msecsDiff(_currentTime);
_mididrv->playSwitch(false);
return Common::kNoError;
}
Common::Error NewPlayer::resume(void) {
Common::StackLock lock(*_mutex);
_wakeupTime = Audio::Timestamp(_currentTime.msecs() + _pauseTimeDiff, SFX_TICKS_PER_SEC);
_mididrv->playSwitch(true);
_paused = false;
return Common::kNoError;
}
Common::Error NewPlayer::exit(void) {
_mididrv->close();
delete _mididrv;
delete _mutex;
delete _iterator;
_iterator = NULL;
return Common::kNoError;
}
#pragma mark -
int sfx_pcm_available() {
return g_system->getMixer()->isReady();
}
@ -56,6 +340,11 @@ void sfx_reset_player() {
player->stop();
}
void sfx_player_tell_synth(int buf_nr, byte *buf) {
if (player)
player->tell_synth(buf_nr, buf);
}
int sfx_get_player_polyphony() {
if (player)
return player->_polyphony;

View File

@ -24,8 +24,8 @@
*/
/* Sound engine */
#ifndef SCI_SFX_SFX_ENGINE_H
#define SCI_SFX_SFX_ENGINE_H
#ifndef SCI_SFX_CORE_H
#define SCI_SFX_CORE_H
#include "common/error.h"
#include "sci/sfx/songlib.h"
@ -170,6 +170,7 @@ Common::Error sfx_send_midi(SfxState *self, song_handle_t handle, int channel,
int command, int arg1, int arg2);
} // End of namespace Sci
#endif // SCI_SFX_SFX_ENGINE_H
#endif // SCI_SFX_CORE_H

View File

@ -28,7 +28,7 @@
#include "common/util.h"
#include "sci/sfx/iterator_internal.h"
#include "sci/sfx/player.h"
#include "sci/sfx/misc.h" // for sfx_player_tell_synth
#include "sci/tools.h"
#include "sound/audiostream.h"
@ -126,8 +126,6 @@ void SongIteratorChannel::init(int id_, int offset_, int end_) {
saw_notes = 0;
}
extern SfxPlayer *player; // FIXME
void SongIteratorChannel::resetSynthChannels() {
byte buf[5];
@ -136,14 +134,12 @@ void SongIteratorChannel::resetSynthChannels() {
buf[0] = 0xe0 | i; /* Pitch bend */
buf[1] = 0x80; /* Wheel center */
buf[2] = 0x40;
if (player)
player->tell_synth(3, buf);
sfx_player_tell_synth(3, buf);
buf[0] = 0xb0 | i; // Set control
buf[1] = 0x40; // Hold pedal
buf[2] = 0x00; // Off
if (player)
player->tell_synth(3, buf);
sfx_player_tell_synth(3, buf);
/* TODO: Reset other controls? */
}
}

View File

@ -1,126 +0,0 @@
/* 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$
*
*/
/* song player structure */
#ifndef SCI_SFX_SFX_PLAYER_H
#define SCI_SFX_SFX_PLAYER_H
#include "common/scummsys.h"
#include "sci/resource.h"
#include "sci/sfx/iterator.h"
namespace Sci {
class SfxPlayer {
public:
/** Number of voices that can play simultaneously */
int _polyphony;
public:
SfxPlayer() : _polyphony(0) {}
virtual ~SfxPlayer() {}
virtual Common::Error init(ResourceManager *resmgr, int expected_latency) = 0;
/* Initializes the player
** Parameters: (ResourceManager *) resmgr: A resource manager for driver initialization
** (int) expected_latency: Expected delay in between calls to 'maintenance'
** (in microseconds)
** Returns : (int) Common::kNoError on success, Common::kUnknownError on failure
*/
virtual Common::Error add_iterator(SongIterator *it, uint32 start_time) = 0;
/* Adds an iterator to the song player
** Parameters: (songx_iterator_t *) it: The iterator to play
** (uint32) start_time: The time to assume as the
** time the first MIDI command executes at
** Returns : (int) Common::kNoError on success, Common::kUnknownError on failure
** The iterator should not be cloned (to avoid memory leaks) and
** may be modified according to the needs of the player.
** Implementors may use the 'sfx_iterator_combine()' function
** to add iterators onto their already existing iterators
*/
virtual Common::Error stop() = 0;
/* Stops the currently playing song and deletes the associated iterator
** Returns : (int) Common::kNoError on success, Common::kUnknownError on failure
*/
virtual Common::Error iterator_message(const SongIterator::Message &msg) = 0;
/* Transmits a song iterator message to the active song
** Parameters: (SongIterator::Message) msg: The message to transmit
** Returns : (int) Common::kNoError on success, Common::kUnknownError on failure
** OPTIONAL -- may be NULL
** If this method is not present, sending messages will stop
** and re-start playing, so it is preferred that it is present
*/
virtual Common::Error pause() = 0;
/* Pauses song playing
** Returns : (int) Common::kNoError on success, Common::kUnknownError on failure
*/
virtual Common::Error resume() = 0;
/* Resumes song playing after a pause
** Returns : (int) Common::kNoError on success, Common::kUnknownError on failure
*/
virtual Common::Error exit() = 0;
/* Stops the player
** Returns : (int) Common::kNoError on success, Common::kUnknownError on failure
*/
virtual void tell_synth(int buf_nr, byte *buf) = 0;
/* Pass a raw MIDI event to the synth
Parameters: (int) argc: Length of buffer holding the midi event
(byte *) argv: The buffer itself
*/
};
int sfx_get_player_polyphony();
/* Determines the polyphony of the player in use
** Returns : (int) Number of voices the active player can emit
*/
void sfx_reset_player();
/* Tells the player to stop its internal iterator
** Parameters: None.
** Returns: Nothing.
*/
SongIterator *sfx_iterator_combine(SongIterator *it1, SongIterator *it2);
/* Combines two song iterators into one
** Parameters: (sfx_iterator_t *) it1: One of the two iterators, or NULL
** (sfx_iterator_t *) it2: The other iterator, or NULL
** Returns : (sfx_iterator_t *) A combined iterator
** If a combined iterator is returned, it will be flagged to be allowed to
** dispose of 'it1' and 'it2', where applicable. This means that this
** call should be used by song players, but not by the core sound system
*/
} // End of namespace Sci
#endif // SCI_SFX_SFX_PLAYER_H

View File

@ -1,218 +0,0 @@
/* 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$
*
*/
#include "sci/tools.h"
#include "sci/sfx/player/new_player.h"
#include "sci/sfx/sequencer.h"
#include "sci/sfx/iterator.h"
#include "sci/sfx/core.h"
#include "common/system.h"
#include "sci/sfx/softseq/pcjr.h"
#include "sci/sfx/softseq/adlib.h"
namespace Sci {
NewPlayer::NewPlayer() {
_mididrv = 0;
_iterator = NULL;
_pauseTimeDiff = 0;
_paused = false;
_iteratorIsDone = false;
_tempo = 0;
_mutex = 0;
_volume = 15;
}
void NewPlayer::play_song(SongIterator *it) {
while (_iterator && _wakeupTime.msecsDiff(_currentTime) <= 0) {
int delay;
byte buf[8];
int result;
switch ((delay = songit_next(&(_iterator),
buf, &result,
IT_READER_MASK_ALL
| IT_READER_MAY_FREE
| IT_READER_MAY_CLEAN))) {
case SI_FINISHED:
delete _iterator;
_iterator = NULL;
_iteratorIsDone = true;
return;
case SI_IGNORE:
case SI_LOOP:
case SI_RELATIVE_CUE:
case SI_ABSOLUTE_CUE:
break;
case SI_PCM:
sfx_play_iterator_pcm(_iterator, 0);
break;
case 0:
static_cast<MidiDriver *>(_mididrv)->send(buf[0], buf[1], buf[2]);
break;
default:
_wakeupTime = _wakeupTime.addFrames(delay);
}
}
}
void NewPlayer::tell_synth(int buf_nr, byte *buf) {
byte op1 = (buf_nr < 2 ? 0 : buf[1]);
byte op2 = (buf_nr < 3 ? 0 : buf[2]);
static_cast<MidiDriver *>(_mididrv)->send(buf[0], op1, op2);
}
void NewPlayer::player_timer_callback(void *refCon) {
NewPlayer *player = (NewPlayer *)refCon;
assert(refCon);
Common::StackLock lock(*player->_mutex);
if (player->_iterator && !player->_iteratorIsDone && !player->_paused) {
player->play_song(player->_iterator);
}
player->_currentTime = player->_currentTime.addFrames(1);
}
/* API implementation */
Common::Error NewPlayer::init(ResourceManager *resmgr, int expected_latency) {
MidiDriverType musicDriver = MidiDriver::detectMusicDriver(MDT_PCSPK | MDT_ADLIB);
switch(musicDriver) {
case MD_ADLIB:
_mididrv = new MidiPlayer_Adlib();
break;
case MD_PCJR:
_mididrv = new MidiPlayer_PCJr();
break;
case MD_PCSPK:
_mididrv = new MidiPlayer_PCSpeaker();
break;
default:
break;
}
assert(_mididrv);
_polyphony = _mididrv->getPolyphony();
_tempo = _mididrv->getBaseTempo();
uint32 time = g_system->getMillis();
_currentTime = Audio::Timestamp(time, 1000000 / _tempo);
_wakeupTime = Audio::Timestamp(time, SFX_TICKS_PER_SEC);
_mutex = new Common::Mutex();
_mididrv->setTimerCallback(this, player_timer_callback);
_mididrv->open(resmgr);
_mididrv->setVolume(_volume);
return Common::kNoError;
}
Common::Error NewPlayer::add_iterator(SongIterator *it, uint32 start_time) {
Common::StackLock lock(*_mutex);
SIMSG_SEND(it, SIMSG_SET_PLAYMASK(_mididrv->getPlayMask()));
SIMSG_SEND(it, SIMSG_SET_RHYTHM(_mididrv->hasRhythmChannel()));
if (_iterator == NULL) {
// Resync with clock
_currentTime = Audio::Timestamp(g_system->getMillis(), 1000000 / _tempo);
_wakeupTime = Audio::Timestamp(start_time, SFX_TICKS_PER_SEC);
}
_iterator = sfx_iterator_combine(_iterator, it);
_iteratorIsDone = false;
return Common::kNoError;
}
Common::Error NewPlayer::stop(void) {
debug(3, "Player: Stopping song iterator %p", (void *)_iterator);
Common::StackLock lock(*_mutex);
delete _iterator;
_iterator = NULL;
for (int i = 0; i < MIDI_CHANNELS; i++)
static_cast<MidiDriver *>(_mididrv)->send(0xb0 + i, SCI_MIDI_CHANNEL_NOTES_OFF, 0);
return Common::kNoError;
}
Common::Error NewPlayer::iterator_message(const SongIterator::Message &msg) {
Common::StackLock lock(*_mutex);
if (!_iterator) {
return Common::kUnknownError;
}
songit_handle_message(&_iterator, msg);
return Common::kNoError;
}
Common::Error NewPlayer::pause(void) {
Common::StackLock lock(*_mutex);
_paused = true;
_pauseTimeDiff = _wakeupTime.msecsDiff(_currentTime);
_mididrv->playSwitch(false);
return Common::kNoError;
}
Common::Error NewPlayer::resume(void) {
Common::StackLock lock(*_mutex);
_wakeupTime = Audio::Timestamp(_currentTime.msecs() + _pauseTimeDiff, SFX_TICKS_PER_SEC);
_mididrv->playSwitch(true);
_paused = false;
return Common::kNoError;
}
Common::Error NewPlayer::exit(void) {
_mididrv->close();
delete _mididrv;
delete _mutex;
delete _iterator;
_iterator = NULL;
return Common::kNoError;
}
} // End of namespace Sci

View File

@ -1,70 +0,0 @@
/* 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$
*
*/
#ifndef SCI_SFX_SFX_PLAYER_NEW_H
#define SCI_SFX_SFX_PLAYER_NEW_H
#include "sci/sfx/player.h"
namespace Sci {
class MidiPlayer;
class SongIterator;
class NewPlayer : public SfxPlayer {
protected:
MidiPlayer *_mididrv;
SongIterator *_iterator;
Audio::Timestamp _wakeupTime;
Audio::Timestamp _currentTime;
uint32 _pauseTimeDiff;
bool _paused;
bool _iteratorIsDone;
uint32 _tempo;
Common::Mutex *_mutex;
int _volume;
void play_song(SongIterator *it);
static void player_timer_callback(void *refCon);
public:
NewPlayer();
virtual Common::Error init(ResourceManager *resmgr, int expected_latency);
virtual Common::Error add_iterator(SongIterator *it, uint32 start_time);
virtual Common::Error stop();
virtual Common::Error iterator_message(const SongIterator::Message &msg);
virtual Common::Error pause();
virtual Common::Error resume();
virtual Common::Error exit();
virtual void tell_synth(int buf_nr, byte *buf);
};
} // End of namespace Sci
#endif