aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sci/module.mk3
-rw-r--r--engines/sci/sfx/core.cpp39
-rw-r--r--engines/sci/sfx/iterator.cpp2
-rw-r--r--engines/sci/sfx/mixer.cpp (renamed from engines/sci/sfx/mixer/soft.cpp)116
-rw-r--r--engines/sci/sfx/mixer.h4
-rw-r--r--engines/sci/sfx/pcm_device.cpp79
-rw-r--r--engines/sci/sfx/sfx_pcm.h54
7 files changed, 85 insertions, 212 deletions
diff --git a/engines/sci/module.mk b/engines/sci/module.mk
index cebd4b87f7..a175f13595 100644
--- a/engines/sci/module.mk
+++ b/engines/sci/module.mk
@@ -67,12 +67,11 @@ MODULE_OBJS = \
sfx/adlib.o \
sfx/core.o \
sfx/iterator.o \
- sfx/pcm_device.o \
+ sfx/mixer.o \
sfx/pcm-iterator.o \
sfx/songlib.o \
sfx/time.o \
sfx/device/devices.o \
- sfx/mixer/soft.o \
sfx/player/players.o \
sfx/player/polled.o \
sfx/player/realtime.o \
diff --git a/engines/sci/sfx/core.cpp b/engines/sci/sfx/core.cpp
index a08c0824b5..4f532b0e61 100644
--- a/engines/sci/sfx/core.cpp
+++ b/engines/sci/sfx/core.cpp
@@ -44,11 +44,10 @@ int sciprintf(char *msg, ...);
static sfx_player_t *player = NULL;
sfx_pcm_mixer_t *mixer = NULL;
-static sfx_pcm_device_t *pcm_device = NULL;
-extern sfx_pcm_device_t sfx_pcm_driver_scummvm;
+
int sfx_pcm_available() {
- return (pcm_device != NULL);
+ return (mixer != NULL);
}
void sfx_reset_player() {
@@ -375,14 +374,12 @@ void sfx_init(sfx_state_t *self, ResourceManager *resmgr, int flags) {
if (flags & SFX_STATE_FLAG_NOSOUND) {
mixer = NULL;
- pcm_device = NULL;
player = NULL;
sciprintf("[SFX] Sound disabled.\n");
return;
}
mixer = getMixer();
- pcm_device = &sfx_pcm_driver_scummvm;
player = sfx_find_player(NULL);
@@ -390,25 +387,13 @@ void sfx_init(sfx_state_t *self, ResourceManager *resmgr, int flags) {
fprintf(stderr, "[sfx-core] Initialising: flags=%x\n", flags);
#endif
- /*----------------*/
- /* Initialise PCM */
- /*----------------*/
+ /*------------------*/
+ /* Initialise mixer */
+ /*------------------*/
- if (!pcm_device) {
- sciprintf("[SFX] No PCM device found, disabling PCM support\n");
+ if (mixer->init(mixer)) {
+ sciprintf("[SFX] Failed to initialise PCM mixer; disabling PCM support\n");
mixer = NULL;
- } else {
- if (pcm_device->init(pcm_device)) {
- sciprintf("[SFX] Failed to open PCM device, disabling PCM support\n");
- mixer = NULL;
- pcm_device = NULL;
- } else {
- if (mixer->init(mixer, pcm_device)) {
- sciprintf("[SFX] Failed to initialise PCM mixer; disabling PCM support\n");
- mixer = NULL;
- pcm_device = NULL;
- }
- }
}
/*-------------------*/
@@ -433,14 +418,13 @@ void sfx_init(sfx_state_t *self, ResourceManager *resmgr, int flags) {
/*------------------*/
// We initialise the timer last, so there is no possibility of the
- // timer callback being triggered while the pcm_device or player are
+ // timer callback being triggered while the mixer or player are
// still being initialized.
- if (pcm_device || (player && player->maintenance)) {
+ if (mixer || (player && player->maintenance)) {
if (!g_system->getTimerManager()->installTimerProc(&_sfx_timer_callback, DELAY, NULL)) {
warning("[SFX] " __FILE__": Timer failed to initialize");
warning("[SFX] Disabled sound support");
- pcm_device = NULL;
player = NULL;
mixer = NULL;
return;
@@ -462,11 +446,6 @@ void sfx_exit(sfx_state_t *self) {
song_lib_free(self->songlib);
- // FIXME: We need a pcm_device->exit() function to release the
- // mixer channel allocated for pcm_device in ScummVM's mixer.
- pcm_device = NULL;
-
-
/* WARNING: The mixer may hold feeds from the
** player, so we must stop the mixer BEFORE
** stopping the player. */
diff --git a/engines/sci/sfx/iterator.cpp b/engines/sci/sfx/iterator.cpp
index d738d1222e..501ebb0ad9 100644
--- a/engines/sci/sfx/iterator.cpp
+++ b/engines/sci/sfx/iterator.cpp
@@ -676,7 +676,7 @@ static void _sci0_cleanup(sci0_song_iterator_t *self) {
#define SCI01_INVALID_DEVICE 0xff
-/* First index determines whether DSP output is supported */
+/* Second index determines whether PCM output is supported */
static int sci0_to_sci1_device_map[][2] = {
{0x06, 0x0c}, /* MT-32 */
{0xff, 0xff}, /* YM FB-01 */
diff --git a/engines/sci/sfx/mixer/soft.cpp b/engines/sci/sfx/mixer.cpp
index 53e4d94399..a845627222 100644
--- a/engines/sci/sfx/mixer/soft.cpp
+++ b/engines/sci/sfx/mixer.cpp
@@ -30,6 +30,9 @@
#include "sci/sfx/mixer.h"
#include "sci/sci_memory.h"
+#include "sound/audiostream.h"
+#include "sound/mixer.h"
+
namespace Sci {
/* Max. number of milliseconds in difference allowed between independent audio streams */
@@ -72,20 +75,41 @@ struct mixer_private {
/* Pause data */
int paused;
+
+ sfx_pcm_config_t conf;
+ int _framesize;
+ Audio::AppendableAudioStream *_audioStream;
+ Audio::SoundHandle _soundHandle;
};
#define P ((struct mixer_private *)(self->private_bits))
+enum {
+ BUF_SIZE = 2048 << 1
+};
-static int mix_init(sfx_pcm_mixer_t *self, sfx_pcm_device_t *device) {
- self->dev = device;
+static int mix_init(sfx_pcm_mixer_t *self) {
self->private_bits = new mixer_private();
P->outbuf = P->writebuf = NULL;
P->lastbuf_len = 0;
- P->compbuf_l = (int32*)sci_malloc(sizeof(int32) * device->buf_size);
- P->compbuf_r = (int32*)sci_malloc(sizeof(int32) * device->buf_size);
+ P->compbuf_l = (int32*)sci_malloc(sizeof(int32) * BUF_SIZE);
+ P->compbuf_r = (int32*)sci_malloc(sizeof(int32) * BUF_SIZE);
P->played_this_second = 0;
P->paused = 0;
+
+ P->conf.rate = g_system->getMixer()->getOutputRate();
+ P->conf.stereo = SFX_PCM_STEREO_LR;
+ P->conf.format = SFX_PCM_FORMAT_S16_NATIVE;
+ P->_framesize = SFX_PCM_FRAME_SIZE(P->conf);
+
+
+ int flags = Audio::Mixer::FLAG_16BITS | Audio::Mixer::FLAG_STEREO;
+#ifdef SCUMM_LITTLE_ENDIAN
+ flags |= Audio::Mixer::FLAG_LITTLE_ENDIAN;
+#endif
+
+ P->_audioStream = Audio::makeAppendableAudioStream(P->conf.rate, flags);
+ g_system->getMixer()->playInputStream(Audio::Mixer::kSFXSoundType, &P->_soundHandle, P->_audioStream);
return SFX_OK;
}
@@ -135,19 +159,19 @@ static void mix_subscribe(sfx_pcm_mixer_t *self, sfx_pcm_feed_t *feed) {
feed->frame_size = SFX_PCM_FRAME_SIZE(feed->conf);
- /* fs->buf_size = (self->dev->buf_size
+ /* fs->buf_size = (BUF_SIZE
* (feed->conf.rate
- + self->dev->conf.rate - 1))
- / self->dev->conf.rate;
+ + P->conf.rate - 1))
+ / P->conf.rate;
*/
/* For the sake of people without 64 bit CPUs: */
fs->buf_size = 2 + /* Additional safety */
- (self->dev->buf_size *
- (1 + (feed->conf.rate / self->dev->conf.rate)));
+ (BUF_SIZE *
+ (1 + (feed->conf.rate / P->conf.rate)));
fprintf(stderr, " ---> %d/%d/%d/%d = %d\n",
- self->dev->buf_size,
+ BUF_SIZE,
feed->conf.rate,
- self->dev->conf.rate,
+ P->conf.rate,
feed->frame_size,
fs->buf_size);
@@ -159,7 +183,7 @@ static void mix_subscribe(sfx_pcm_mixer_t *self, sfx_pcm_feed_t *feed) {
fs->buf[i] = 0xa5;
}
fs->scount = urat(0, 1);
- fs->spd = urat(feed->conf.rate, self->dev->conf.rate);
+ fs->spd = urat(feed->conf.rate, P->conf.rate);
fs->scount.den = fs->spd.den;
fs->ch_old.left = 0;
fs->ch_old.right = 0;
@@ -226,6 +250,9 @@ static void _mix_unsubscribe(sfx_pcm_mixer_t *self, sfx_pcm_feed_t *feed) {
}
static void mix_exit(sfx_pcm_mixer_t *self) {
+ g_system->getMixer()->stopHandle(P->_soundHandle);
+ P->_audioStream = 0;
+
ACQUIRE_LOCK();
while (self->feeds_nr)
_mix_unsubscribe(self, self->feeds[0].feed);
@@ -254,7 +281,7 @@ static void mix_exit(sfx_pcm_mixer_t *self) {
static inline void mix_compute_output(sfx_pcm_mixer_t *self, int outplen) {
int frame_i;
- sfx_pcm_config_t conf = self->dev->conf;
+ const sfx_pcm_config_t conf = P->conf;
int use_16 = conf.format & SFX_PCM_FORMAT_16;
int bias = conf.format & ~SFX_PCM_FORMAT_LMASK;
byte *lchan, *rchan = NULL;
@@ -266,7 +293,7 @@ static inline void mix_compute_output(sfx_pcm_mixer_t *self, int outplen) {
if (!P->writebuf)
- P->writebuf = (byte*)sci_malloc(self->dev->buf_size * frame_size + 4);
+ P->writebuf = (byte*)sci_malloc(BUF_SIZE * frame_size + 4);
if (conf.stereo) {
if (conf.stereo == SFX_PCM_STEREO_RL) {
@@ -374,28 +401,28 @@ static inline int mix_compute_buf_len(sfx_pcm_mixer_t *self, int *skip_frames) {
P->played_this_second = 0;
*skip_frames = 0;
- return self->dev->buf_size;
+ return BUF_SIZE;
}
/* fprintf(stderr, "[%d:%d]S%d ", secs, usecs, P->skew);*/
msecs -= P->skew;
- frame_pos = (msecs % 1000) * self->dev->conf.rate / 1000;
+ frame_pos = (msecs % 1000) * P->conf.rate / 1000;
played_frames = frame_pos - P->played_this_second
- + ((msecs / 1000 - P->lsec) * self->dev->conf.rate);
+ + ((msecs / 1000 - P->lsec) * P->conf.rate);
/*
fprintf(stderr, "%d:%d - %d:%d => %d\n", secs, frame_pos,
P->lsec, P->played_this_second, played_frames);
*/
- if (played_frames > self->dev->buf_size)
- played_frames = self->dev->buf_size;
+ if (played_frames > BUF_SIZE)
+ played_frames = BUF_SIZE;
/*
fprintf(stderr, "Between %d:? offset=%d and %d:%d offset=%d: Played %d at %d\n", P->lsec, P->played_this_second,
- secs, usecs, frame_pos, played_frames, self->dev->conf.rate);
+ secs, usecs, frame_pos, played_frames, P->conf.rate);
*/
@@ -404,16 +431,16 @@ static inline int mix_compute_buf_len(sfx_pcm_mixer_t *self, int *skip_frames) {
free_frames = played_frames;
- if (free_frames > self->dev->buf_size) {
+ if (free_frames > BUF_SIZE) {
if (!diagnosed_too_slow) {
sciprintf("[sfx-mixer] Your timer is too slow for your PCM output device (%d/%d), free=%d.\n"
"[sfx-mixer] You might want to try changing the device, timer, or mixer, if possible.\n",
- played_frames, self->dev->buf_size, free_frames);
+ played_frames, BUF_SIZE, free_frames);
}
diagnosed_too_slow = 1;
- *skip_frames = free_frames - self->dev->buf_size;
- free_frames = self->dev->buf_size;
+ *skip_frames = free_frames - BUF_SIZE;
+ free_frames = BUF_SIZE;
} else
*skip_frames = 0;
@@ -423,14 +450,14 @@ static inline int mix_compute_buf_len(sfx_pcm_mixer_t *self, int *skip_frames) {
/* /\* Disabled, broken *\/ */
/* if (0 && P->delta_observations > MIN_DELTA_OBSERVATIONS) { /\* Start improving after a while *\/ */
- /* int diff = self->dev->conf.rate - P->max_delta; */
+ /* int diff = P->conf.rate - P->max_delta; */
/* /\* log-approximate P->max_delta over time *\/ */
/* recommended_frames = P->max_delta + */
/* ((diff * MIN_DELTA_OBSERVATIONS) / P->delta_observations); */
/* /\* WTF? *\/ */
/* } else */
- /* recommended_frames = self->dev->buf_size; /\* Initially, keep the buffer full *\/ */
+ /* recommended_frames = BUF_SIZE; /\* Initially, keep the buffer full *\/ */
#if (DEBUG >= 1)
sciprintf("[soft-mixer] played since last time: %d, free: %d\n",
@@ -443,15 +470,15 @@ static inline int mix_compute_buf_len(sfx_pcm_mixer_t *self, int *skip_frames) {
result_frames = 0;
P->played_this_second += result_frames;
- while (P->played_this_second >= self->dev->conf.rate) {
+ while (P->played_this_second >= P->conf.rate) {
/* Won't normally happen more than once */
- P->played_this_second -= self->dev->conf.rate;
+ P->played_this_second -= P->conf.rate;
P->lsec++;
}
- if (result_frames > self->dev->buf_size) {
+ if (result_frames > BUF_SIZE) {
fprintf(stderr, "[soft-mixer] Internal assertion failed: frames-to-write %d > %d\n",
- result_frames, self->dev->buf_size);
+ result_frames, BUF_SIZE);
}
return result_frames;
}
@@ -781,27 +808,31 @@ static int mix_process_linear(sfx_pcm_mixer_t *self) {
min_timestamp.msecs = 0;
sfx_timestamp_t timestamp;
- if (self->dev->get_output_timestamp)
- start_timestamp = self->dev->get_output_timestamp(self->dev);
- else
- start_timestamp = sfx_new_timestamp(g_system->getMillis(), self->dev->conf.rate);
+// if (self->dev->get_output_timestamp)
+// start_timestamp = self->dev->get_output_timestamp(self->dev);
+// else
+ start_timestamp = sfx_new_timestamp(g_system->getMillis(), P->conf.rate);
if ((P->outbuf) && (P->lastbuf_len)) {
sfx_timestamp_t ts;
int rv;
if (P->have_outbuf_timestamp) {
- ts = sfx_timestamp_renormalise(P->outbuf_timestamp, self->dev->conf.rate);
+ ts = sfx_timestamp_renormalise(P->outbuf_timestamp, P->conf.rate);
}
- rv = self->dev->output(self->dev, P->outbuf,
- P->lastbuf_len,
- (P->have_outbuf_timestamp) ? &ts : NULL);
-
- if (rv == SFX_ERROR) {
+ const int totalBufSize = P->lastbuf_len * P->_framesize;
+ byte *buf = new byte[totalBufSize];
+ if (!buf) {
RELEASE_LOCK();
return rv; /* error */
}
+ memcpy(buf, P->outbuf, totalBufSize);
+ P->_audioStream->queueBuffer(buf, totalBufSize);
+ // TODO: We currently ignore the timestamp:
+ // (P->have_outbuf_timestamp) ? &ts : NULL
+ // Re-add support for that? Maybe by enhancing the ScummVM mixer (i.e.,
+ // expanding the getTotalPlayTime() audiostream API to "proper" timestamps?)
}
#if (DEBUG >= 1)
@@ -814,8 +845,8 @@ static int mix_process_linear(sfx_pcm_mixer_t *self) {
** or a fraction of the buf length to discard. */
do {
if (frames_skip) {
- if (frames_skip > self->dev->buf_size)
- fake_buflen = self->dev->buf_size;
+ if (frames_skip > BUF_SIZE)
+ fake_buflen = BUF_SIZE;
else
fake_buflen = frames_skip;
@@ -917,7 +948,6 @@ sfx_pcm_mixer_t sfx_pcm_mixer_soft_linear = {
0,
0,
NULL,
- NULL,
NULL
};
diff --git a/engines/sci/sfx/mixer.h b/engines/sci/sfx/mixer.h
index 5f24482904..534085ad66 100644
--- a/engines/sci/sfx/mixer.h
+++ b/engines/sci/sfx/mixer.h
@@ -70,10 +70,9 @@ struct sfx_pcm_mixer_t {
const char *name;
const char *version;
- int (*init)(sfx_pcm_mixer_t *self, sfx_pcm_device_t *device);
+ int (*init)(sfx_pcm_mixer_t *self);
/* Initialises the mixer
** Parameters: (sfx_pcm_mixer_t *) self: Self reference
- ** (sfx_pcm_device_t *) device: An _already initialised_ PCM output driver
** Returns : (int) SFX_OK on success, SFX_ERROR otherwise
*/
@@ -109,7 +108,6 @@ struct sfx_pcm_mixer_t {
int feeds_nr;
int feeds_allocd;
sfx_pcm_feed_state_t *feeds;
- sfx_pcm_device_t *dev;
void *private_bits;
};
diff --git a/engines/sci/sfx/pcm_device.cpp b/engines/sci/sfx/pcm_device.cpp
deleted file mode 100644
index 5934b76b21..0000000000
--- a/engines/sci/sfx/pcm_device.cpp
+++ /dev/null
@@ -1,79 +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/sfx/sfx_time.h"
-#include "sci/sfx/sfx_pcm.h"
-#include "engines/engine.h"
-#include "sound/audiostream.h"
-#include "sound/mixer.h"
-
-namespace Sci {
-
-static int pcmout_scummvm_framesize;
-static Audio::AppendableAudioStream * pcmout_scummvm_audiostream;
-static Audio::SoundHandle pcmout_scummvm_sound_handle;
-
-
-static int pcmout_scummvm_init(sfx_pcm_device_t *self) {
- int pcmout_scummvm_audiostream_flags = Audio::Mixer::FLAG_16BITS | Audio::Mixer::FLAG_STEREO;
-
-#ifdef SCUMM_LITTLE_ENDIAN
- pcmout_scummvm_audiostream_flags |= Audio::Mixer::FLAG_LITTLE_ENDIAN;
-#endif
-
- self->buf_size = 2048 << 1;
- self->conf.rate = g_engine->_mixer->getOutputRate();
- self->conf.stereo = SFX_PCM_STEREO_LR;
- self->conf.format = SFX_PCM_FORMAT_S16_NATIVE;
- pcmout_scummvm_framesize = SFX_PCM_FRAME_SIZE(self->conf);
-
- pcmout_scummvm_audiostream = Audio::makeAppendableAudioStream(self->conf.rate, pcmout_scummvm_audiostream_flags);
- ::g_engine->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &pcmout_scummvm_sound_handle, pcmout_scummvm_audiostream);
-
- return SFX_OK;
-}
-
-static int pcmout_scummvm_output(sfx_pcm_device_t *self, byte *buf, int count,
- sfx_timestamp_t *timestamp) {
-
- byte *__buf = new byte[count * pcmout_scummvm_framesize];
-
- memcpy(__buf, buf, count * pcmout_scummvm_framesize);
-
- pcmout_scummvm_audiostream->queueBuffer(__buf, count * pcmout_scummvm_framesize);
-
- return SFX_OK;
-}
-
-
-sfx_pcm_device_t sfx_pcm_driver_scummvm = {
- &pcmout_scummvm_init,
- &pcmout_scummvm_output,
- NULL,
- {0, 0, 0},
- 0
-};
-
-} // End of namespace Sci
diff --git a/engines/sci/sfx/sfx_pcm.h b/engines/sci/sfx/sfx_pcm.h
index 89ccee04d9..0459afd2ee 100644
--- a/engines/sci/sfx/sfx_pcm.h
+++ b/engines/sci/sfx/sfx_pcm.h
@@ -69,60 +69,6 @@ struct sfx_pcm_config_t {
unsigned int format; /* Sample format (SFX_PCM_FORMAT_*) */
};
-struct sfx_pcm_device_t {
- /* SFX devices are PCM players, i.e. output drivers for digitalised audio (sequences of audio samples).
- ** Implementors are (in general) allowed to export specifics of these devices and let the mixer handle
- ** endianness/signedness/bit size/mono-vs-stereo conversions.
- */
-
- int (*init)(sfx_pcm_device_t *self);
- /* Initializes the device
- ** Parameters: (sfx_pcm_device_t *) self: Self reference
- ** Returns : (int) SFX_OK on success, SFX_ERROR if the device could not be
- ** opened
- ** This should attempt to open the highest quality output allowed by any options
- ** specified beforehand.
- */
-
- int (*output)(sfx_pcm_device_t *self, byte *buf,
- int count, sfx_timestamp_t *timestamp);
- /* Writes output to the device
- ** Parameters: (sfx_pcm_device_t *) self: Self reference
- ** (byte *) buf: The buffer to write
- ** (int) count: Number of /frames/ that should be written
- ** (sfx_timestamp_t *) timestamp: Optional point in time
- ** for which the PCM data is scheduled
- ** Returns : (int) SFX_OK on success, SFX_ERROR on error
- ** The size of the buffer allocated as 'buf' equals buf_size.
- ** 'buf' is guaranteed not to be modified in between calls to 'output()'.
- ** 'timestamp' is guaranteed to be used only in sequential order, but not
- ** guaranteed to be used in all cases. It is guaranteed to be compaible with
- ** the sample rate used by the device itself (i.e., the sfx_time.h functionality
- ** is applicable)
- */
-
- sfx_timestamp_t
- (*get_output_timestamp)(sfx_pcm_device_t *self);
- /* Determines the timestamp for 'output'
- ** Parameters: (sfx_pcm_device_t *) self: Self reference
- ** Returns : (sfx_timestamp_t) A timestamp (with the device's conf.rate)
- ** describing the point in time at which
- ** the next frame passed to 'output'
- ** will be played
- ** This function is OPTIONAL and may be NULL, but it is recommended
- ** that pcm device implementers attempt to really implement it.
- */
-
- /* The following must be set after initialisation */
- sfx_pcm_config_t conf;
- int buf_size; /* Output buffer size, i.e. the number of frames (!)
- ** that can be queued by this driver before calling
- ** output() will block or fail, drained according
- ** to conf.rate */
-
-};
-
-
#define PCM_FEED_TIMESTAMP 0 /* New timestamp available */
#define PCM_FEED_IDLE 1 /* No sound ATM, but new timestamp may be available later */
#define PCM_FEED_EMPTY 2 /* Feed is finished, can be destroyed */