diff options
author | Jordi Vilalta Prat | 2009-02-16 16:23:48 +0000 |
---|---|---|
committer | Jordi Vilalta Prat | 2009-02-16 16:23:48 +0000 |
commit | c8a3a05a5d83758582e0b89c4646476c535f84b0 (patch) | |
tree | 82742edd88e11afe079087d8c05394e3b20d38a9 /engines/sci/sfx/pcm_device | |
parent | ee1cae3ebcad65ac30c2ce84853b3c07ce4568f7 (diff) | |
download | scummvm-rg350-c8a3a05a5d83758582e0b89c4646476c535f84b0.tar.gz scummvm-rg350-c8a3a05a5d83758582e0b89c4646476c535f84b0.tar.bz2 scummvm-rg350-c8a3a05a5d83758582e0b89c4646476c535f84b0.zip |
SCI: Changed pcm_device and timer "driver" functionality to use directly the ScummVM modules
svn-id: r38373
Diffstat (limited to 'engines/sci/sfx/pcm_device')
-rw-r--r-- | engines/sci/sfx/pcm_device/alsa.cpp | 375 | ||||
-rw-r--r-- | engines/sci/sfx/pcm_device/audbuf_test.cpp | 186 | ||||
-rw-r--r-- | engines/sci/sfx/pcm_device/audiobuf.cpp | 339 | ||||
-rw-r--r-- | engines/sci/sfx/pcm_device/audiobuf.h | 140 | ||||
-rw-r--r-- | engines/sci/sfx/pcm_device/pcm_devices.cpp | 48 | ||||
-rw-r--r-- | engines/sci/sfx/pcm_device/scummvm.cpp | 60 | ||||
-rw-r--r-- | engines/sci/sfx/pcm_device/sdl.cpp | 261 |
7 files changed, 0 insertions, 1409 deletions
diff --git a/engines/sci/sfx/pcm_device/alsa.cpp b/engines/sci/sfx/pcm_device/alsa.cpp deleted file mode 100644 index 4698d66478..0000000000 --- a/engines/sci/sfx/pcm_device/alsa.cpp +++ /dev/null @@ -1,375 +0,0 @@ -/*************************************************************************** - alsa.c Copyright (C) 2004 Walter van Niftrik - - - This program may be modified and copied freely according to the terms of - the GNU general public license (GPL), as long as the above copyright - notice and the licensing information contained herein are preserved. - - Please refer to www.gnu.org for licensing details. - - This work is provided AS IS, without warranty of any kind, expressed or - implied, including but not limited to the warranties of merchantibility, - noninfringement, and fitness for a specific purpose. The author will not - be held liable for any damage caused by this work or derivatives of it. - - By using this source code, you agree to the licensing terms as stated - above. - - - Please contact the maintainer for bug reports or inquiries. - - Current Maintainer: - - Walter van Niftrik <w.f.b.w.v.niftrik@stud.tue.nl> - -***************************************************************************/ - -/* Based on ALSA's pcm.c example. */ - -#include <sfx_pcm.h> -#include "audiobuf.h" - -#ifdef HAVE_ALSA -#ifdef HAVE_PTHREAD - -#define ALSA_PCM_NEW_HW_PARAMS_API -#define ALSA_PCM_NEW_SW_PARAMS_API - -#include <alsa/asoundlib.h> -#include <pthread.h> - -static const char *device = "default"; /* FIXME */ -static snd_pcm_format_t format = SND_PCM_FORMAT_S16; -static unsigned int rate = 44100; /* FIXME */ -static unsigned int channels = 2; /* FIXME */ -static unsigned int buffer_time = 100000; /* FIXME */ -static unsigned int period_time = 1000000 / 60; /* 60Hz */ /* FIXME */ - -static snd_pcm_sframes_t buffer_size; -static snd_pcm_sframes_t period_size; - -static int frame_size; -static long last_callback_secs, last_callback_usecs; - -static sfx_audio_buf_t audio_buffer; -static void (*alsa_sfx_timer_callback)(void *data); -static void *alsa_sfx_timer_data; - -static snd_pcm_t *handle; - -static pthread_t thread; -static volatile byte run_thread; - -static pthread_mutex_t mutex; - -static int -xrun_recovery(snd_pcm_t *handle, int err) { - if (err == -EPIPE) { /* under-run */ - err = snd_pcm_prepare(handle); - if (err < 0) - fprintf(stderr, "Can't recovery from underrun, prepare failed: %s\n", snd_strerror(err)); - return 0; - } else if (err == -ESTRPIPE) { - while ((err = snd_pcm_resume(handle)) == -EAGAIN) - sleep(1); /* wait until the suspend flag is released */ - if (err < 0) { - err = snd_pcm_prepare(handle); - if (err < 0) - fprintf(stderr, "Can't recovery from suspend, prepare failed: %s\n", snd_strerror(err)); - } - return 0; - } - return err; -} - -static void * -alsa_thread(void *arg) { - gint16 *ptr; - int err, cptr; - guint8 *buf; - sfx_pcm_device_t *self = (sfx_pcm_device_t *) arg; - - buf = (guint8 *) malloc(period_size * frame_size); - - while (run_thread) { - ptr = (gint16 *) buf; - cptr = period_size; - - sci_gettime(&last_callback_secs, &last_callback_usecs); - - self->timer->block(); - - if (alsa_sfx_timer_callback) - alsa_sfx_timer_callback(alsa_sfx_timer_data); - - self->timer->unblock(); - - sfx_audbuf_read(&audio_buffer, buf, period_size); - - while (cptr > 0) { - err = snd_pcm_writei(handle, ptr, cptr); - if (err == -EAGAIN) - continue; - if (err < 0) { - if (xrun_recovery(handle, err) < 0) { - fprintf(stderr, "[SND:ALSA] Write error: %s\n", snd_strerror(err)); - run_thread = 0; - } - break; /* skip one period */ - } - ptr += err * channels; - cptr -= err; - } - } - - free(buf); - return NULL; -} - -static sfx_timestamp_t -pcmout_alsa_output_timestamp(sfx_pcm_device_t *self) { - /* Number of frames enqueued in the output device: */ - int delta = (buffer_size - period_size) / frame_size - /* Number of frames enqueued in the internal audio buffer: */ - + audio_buffer.frames_nr; - - return sfx_timestamp_add(sfx_new_timestamp(last_callback_secs, - last_callback_usecs, - rate), - delta); -} - -static int -pcmout_alsa_init(sfx_pcm_device_t *self) { - unsigned int rrate; - int err, dir; - snd_pcm_hw_params_t *hwparams; - snd_pcm_sw_params_t *swparams; - pthread_attr_t attr; - - snd_pcm_hw_params_alloca(&hwparams); - snd_pcm_sw_params_alloca(&swparams); - - err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0); - if (err < 0) { - sciprintf("[SND:ALSA] Playback open error: %s\n", snd_strerror(err)); - return SFX_ERROR; - } - err = snd_pcm_hw_params_any(handle, hwparams); - if (err < 0) { - sciprintf("[SND:ALSA] Broken configuration for playback: no configurations available: %s\n", snd_strerror(err)); - return SFX_ERROR; - } - err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); - if (err < 0) { - sciprintf("[SND:ALSA] Access type not available for playback: %s\n", snd_strerror(err)); - return SFX_ERROR; - } - err = snd_pcm_hw_params_set_format(handle, hwparams, format); - if (err < 0) { - sciprintf("[SND:ALSA] Sample format not available for playback: %s\n", snd_strerror(err)); - return SFX_ERROR; - } - err = snd_pcm_hw_params_set_channels(handle, hwparams, channels); - if (err < 0) { - sciprintf("[SND:ALSA] Channels count (%i) not available for playback: %s\n", channels, snd_strerror(err)); - return SFX_ERROR; - } - rrate = rate; - err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &rrate, 0); - if (err < 0) { - sciprintf("[SND:ALSA] Rate %iHz not available for playback: %s\n", rate, snd_strerror(err)); - return SFX_ERROR; - } - if (rrate != rate) { - sciprintf("[SND:ALSA] Rate doesn't match (requested %iHz, get %iHz)\n", rate, err); - return SFX_ERROR; - } - err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, &dir); - if (err < 0) { - sciprintf("[SND:ALSA] Unable to set buffer time %i for playback: %s\n", buffer_time, snd_strerror(err)); - return SFX_ERROR; - } - err = snd_pcm_hw_params_get_buffer_size(hwparams, (snd_pcm_uframes_t*) & buffer_size); - if (err < 0) { - sciprintf("[SND:ALSA] Unable to get buffer size for playback: %s\n", snd_strerror(err)); - return SFX_ERROR; - } - err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, &dir); - if (err < 0) { - sciprintf("[SND:ALSA] Unable to set period time %i for playback: %s\n", period_time, snd_strerror(err)); - return SFX_ERROR; - } - err = snd_pcm_hw_params_get_period_size(hwparams, (snd_pcm_uframes_t*) & period_size, &dir); - if (err < 0) { - sciprintf("[SND:ALSA] Unable to get period size for playback: %s\n", snd_strerror(err)); - return SFX_ERROR; - } - if (period_size >= buffer_size) { - sciprintf("[SND:ALSA] Period size %i matches or exceeds buffer size %i\n", period_size, buffer_size); - return SFX_ERROR; - } - err = snd_pcm_hw_params(handle, hwparams); - if (err < 0) { - sciprintf("[SND:ALSA] Unable to set hw params for playback: %s\n", snd_strerror(err)); - return SFX_ERROR; - } - err = snd_pcm_sw_params_current(handle, swparams); - if (err < 0) { - sciprintf("[SND:ALSA] Unable to determine current swparams for playback: %s\n", snd_strerror(err)); - return SFX_ERROR; - } - err = snd_pcm_sw_params_set_start_threshold(handle, swparams, buffer_size); - if (err < 0) { - sciprintf("[SND:ALSA] Unable to set start threshold mode for playback: %s\n", snd_strerror(err)); - return SFX_ERROR; - } - err = snd_pcm_sw_params_set_avail_min(handle, swparams, period_size); - if (err < 0) { - sciprintf("[SND:ALSA] Unable to set avail min for playback: %s\n", snd_strerror(err)); - return SFX_ERROR; - } - err = snd_pcm_sw_params_set_xfer_align(handle, swparams, 1); - if (err < 0) { - sciprintf("[SND:ALSA] Unable to set transfer align for playback: %s\n", snd_strerror(err)); - return SFX_ERROR; - } - err = snd_pcm_sw_params(handle, swparams); - if (err < 0) { - sciprintf("[SND:ALSA] Unable to set sw params for playback: %s\n", snd_strerror(err)); - return SFX_ERROR; - } - - self->buf_size = buffer_size; - self->conf.rate = rate; - self->conf.stereo = channels > 1; - self->conf.format = SFX_PCM_FORMAT_S16_NATIVE; - - frame_size = SFX_PCM_FRAME_SIZE(self->conf); - - sfx_audbuf_init(&audio_buffer, self->conf); - - if (pthread_mutex_init(&mutex, NULL) != 0) { - sciprintf("[SND:ALSA] Failed to create mutex\n"); - return SFX_ERROR; - } - - run_thread = 1; - if (pthread_create(&thread, NULL, alsa_thread, self) != 0) { - sciprintf("[SND:ALSA] Failed to create thread\n"); - return SFX_ERROR; - } - - return SFX_OK; -} - -static int -pcmout_alsa_output(sfx_pcm_device_t *self, byte *buf, - int count, sfx_timestamp_t *ts) { - if (ts) - sfx_audbuf_write_timestamp(&audio_buffer, *ts); - - sfx_audbuf_write(&audio_buffer, buf, count); - return SFX_OK; -} - -static int -pcmout_alsa_set_option(sfx_pcm_device_t *self, char *name, char *value) { - return SFX_ERROR; -} - -static void -pcmout_alsa_exit(sfx_pcm_device_t *self) { - int err; - - run_thread = 0; - sciprintf("[SND:ALSA] Waiting for PCM thread to exit... "); - if (!pthread_join(thread, NULL)) - sciprintf("OK\n"); - else - sciprintf("Failed\n"); - - pthread_mutex_destroy(&mutex); - - if ((err = snd_pcm_drop(handle)) < 0) { - sciprintf("[SND:ALSA] Can't stop PCM device: %s\n", snd_strerror(err)); - } - if ((err = snd_pcm_close(handle)) < 0) { - sciprintf("[SND:ALSA] Can't close PCM device: %s\n", snd_strerror(err)); - } - - sfx_audbuf_free(&audio_buffer); -} - -static int -timer_alsa_set_option(char *name, char *value) { - return SFX_ERROR; -} - - -static int -timer_alsa_init(void (*callback)(void *data), void *data) { - alsa_sfx_timer_callback = callback; - alsa_sfx_timer_data = data; - - return SFX_OK; -} - -static int -timer_alsa_stop(void) { - alsa_sfx_timer_callback = NULL; - - return SFX_OK; -} - -static int -timer_alsa_block(void) { - if (pthread_mutex_lock(&mutex) != 0) { - fprintf(stderr, "[SND:ALSA] Failed to lock mutex\n"); - return SFX_ERROR; - } - - return SFX_OK; -} - -static int -timer_alsa_unblock(void) { - if (pthread_mutex_unlock(&mutex) != 0) { - fprintf(stderr, "[SND:ALSA] Failed to unlock mutex\n"); - return SFX_ERROR; - } - - return SFX_OK; -} - -#define ALSA_PCM_VERSION "0.2" - -sfx_timer_t pcmout_alsa_timer = { - "alsa-pcm-timer", - ALSA_PCM_VERSION, - 0, - 0, - timer_alsa_set_option, - timer_alsa_init, - timer_alsa_stop, - timer_alsa_block, - timer_alsa_unblock -}; - -sfx_pcm_device_t sfx_pcm_driver_alsa = { - "alsa", - ALSA_PCM_VERSION, - pcmout_alsa_init, - pcmout_alsa_exit, - pcmout_alsa_set_option, - pcmout_alsa_output, - pcmout_alsa_output_timestamp, - {0, 0, 0}, - 0, - &pcmout_alsa_timer, - NULL -}; - -#endif /* HAVE_PTHREAD */ -#endif /* HAVE_ALSA */ diff --git a/engines/sci/sfx/pcm_device/audbuf_test.cpp b/engines/sci/sfx/pcm_device/audbuf_test.cpp deleted file mode 100644 index 08e8b2ad5e..0000000000 --- a/engines/sci/sfx/pcm_device/audbuf_test.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/*************************************************************************** - audbuf_test.c Copyright (C) 2002 Christoph Reichenbach - - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public Licence as - published by the Free Software Foundaton; either version 2 of the - Licence, or (at your option) any later version. - - It is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - merchantibility or fitness for a particular purpose. See the - GNU General Public Licence for more details. - - You should have received a copy of the GNU General Public Licence - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - - Please contact the maintainer for any program-related bug reports or - inquiries. - - Current Maintainer: - - Christoph Reichenbach (CR) <jameson@linuxgames.com> - -***************************************************************************/ - -#include "audiobuf.h" -#if 0 -sfx_audio_buf_t buf; - -#define MIN_FRAMESIZE 1 -#define MAX_FRAMESIZE 8 - - -void -tester_write(unsigned char *data, int datalen, int framesize, int gran) { - int i; - - for (i = 0; i < datalen; i += gran) { - int size = (i + gran < datalen) ? gran : datalen - i; - - sfx_audbuf_write(&buf, data + (i * framesize), framesize, size); - } -} - - -void -tester_read(unsigned char *data, int datalen, int framesize, int gran) { - unsigned char *readdata = malloc(datalen * framesize); - int i; - - for (i = 0; i < datalen; i += gran) { - int size = (i + gran < datalen) ? gran : datalen - i; - int j; - - sfx_audbuf_read(&buf, readdata + (i * framesize), framesize, size); - for (j = 0; j < gran * framesize; j++) { - int offset = i * framesize + j; - - if (data[i] != readdata[i]) { - fprintf(stderr, "[ERROR] Mismatch at offset %08x (sample #%d): Expected %02x, got %02x\n", - offset, i, readdata[i], data[i]); - } - } - } - - free(readdata); -} - - -void -test1(unsigned char *data, int len) -/* Test the 'regular' case */ -{ - int framesize; - int stepsize; - - fprintf(stderr, "[Test-1] Commenced; len=%d.\n", len); - - for (framesize = MAX_FRAMESIZE; framesize >= MIN_FRAMESIZE; framesize >>= 1) { - fprintf(stderr, "[Test-1] Writing frame size %d\n", framesize); - for (stepsize = 1; stepsize <= len; stepsize++) - tester_write(data, len / framesize, framesize, stepsize); - } - - for (framesize = MAX_FRAMESIZE; framesize >= MIN_FRAMESIZE; framesize >>= 1) { - fprintf(stderr, "[Test-1] Reading frame size %d\n", framesize); - for (stepsize = len; stepsize >= 1; stepsize--) - tester_read(data, len / framesize, framesize, stepsize); - } - - fprintf(stderr, "[Test-1] Completed.\n"); -} - -#define TEST2_COUNT 10 -#define TEST2_LEN 3 - -void -test2(unsigned char *data, int framesize) -/* Test whether buffer underrun repeats are handled correctly */ -{ - int i; - unsigned char *src; - - fprintf(stderr, "[Test-2] Commenced; framesize=%d.\n", framesize); - - sfx_audbuf_write(&buf, data, framesize, 1); - src = malloc(framesize * TEST2_LEN); - - for (i = 0; i < TEST2_COUNT + 1; i++) { - int inst; - sfx_audbuf_read(&buf, src, framesize, TEST2_LEN); - - for (inst = 0; inst < TEST2_LEN; inst++) { - int offset = inst * framesize; - int j; - - for (j = 0; j < framesize; j++) - if (src[j + offset] != data[j]) { - fprintf(stderr, "[ERROR] At copy sample %d, frame %d, offset %d: Expected %02x, got %02x\n", - i, inst, j, data[j], src[j+offset]); - } - } - memset(src, 0xbf, framesize * TEST2_LEN); - } - - free(src); - fprintf(stderr, "[Test-1] Completed.\n"); -} - - -#define CHUNKS_NR 4 - -#define CHUNK_LEN_0 8 -#define CHUNK_LEN_1 20 -#define CHUNK_LEN_2 16 -#define CHUNK_LEN_3 40 - -unsigned char test_data_0[CHUNK_LEN_0] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; -unsigned char test_data_1[CHUNK_LEN_1] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, - 0xff, 0x00, 0xff, 0x00 - }; -unsigned char test_data_2[CHUNK_LEN_2] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; -unsigned char test_data_3[CHUNK_LEN_3] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, - 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, - 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88 - }; - -struct { - int len; - unsigned char *data; -} test_chunks[CHUNKS_NR] = { - { CHUNK_LEN_0, test_data_0 }, - { CHUNK_LEN_1, test_data_1 }, - { CHUNK_LEN_2, test_data_2 }, - { CHUNK_LEN_3, test_data_3 } -}; - -int -main(int argc, char **argv) { - int i; - - sfx_audbuf_init(&buf); - for (i = 0; i < CHUNKS_NR; i++) { - int k; - - /* for (k = MAX_FRAMESIZE; k >= MIN_FRAMESIZE; k >>= 1) - test2(test_chunks[i].data, k);*/ - - test1(test_chunks[i].data, test_chunks[i].len); - } - sfx_audbuf_exit(&buf); - - return 0; -} -#else -int main() {} -#endif diff --git a/engines/sci/sfx/pcm_device/audiobuf.cpp b/engines/sci/sfx/pcm_device/audiobuf.cpp deleted file mode 100644 index 15c5bb765b..0000000000 --- a/engines/sci/sfx/pcm_device/audiobuf.cpp +++ /dev/null @@ -1,339 +0,0 @@ -/*************************************************************************** - audiobuf.c Copyright (C) 2003 Christoph Reichenbach - - - This program may be modified and copied freely according to the terms of - the GNU general public license (GPL), as long as the above copyright - notice and the licensing information contained herein are preserved. - - Please refer to www.gnu.org for licensing details. - - This work is provided AS IS, without warranty of any kind, expressed or - implied, including but not limited to the warranties of merchantibility, - noninfringement, and fitness for a specific purpose. The author will not - be held liable for any damage caused by this work or derivatives of it. - - By using this source code, you agree to the licensing terms as stated - above. - - - Please contact the maintainer for bug reports or inquiries. - - Current Maintainer: - - Christoph Reichenbach (CR) <jameson@linuxgames.com> - -***************************************************************************/ - -#include "audiobuf.h" - -#define NO_BUFFER_UNDERRUN 0 -#define SAW_BUFFER_UNDERRUN 1 -#define REPORTED_BUFFER_UNDERRUN 2 - -static int -buffer_underrun_status = NO_BUFFER_UNDERRUN; - - -static sfx_audio_buf_chunk_t * -sfx_audbuf_alloc_chunk(void) { - sfx_audio_buf_chunk_t *ch = (sfx_audio_buf_chunk_t*)sci_malloc(sizeof(sfx_audio_buf_chunk_t)); - ch->used = 0; - ch->next = NULL; - ch->prev = NULL; - - return ch; -} - -void -sfx_audbuf_init(sfx_audio_buf_t *buf, sfx_pcm_config_t pcm_conf) { - int framesize = SFX_PCM_FRAME_SIZE(pcm_conf); - byte silence[16]; - int silencew = pcm_conf.format & ~SFX_PCM_FORMAT_LMASK; - - /* Determine the correct 'silence' for the channel and install it */ - /* Conservatively assume stereo */ - if (pcm_conf.format & SFX_PCM_FORMAT_16) { - if (pcm_conf.format & SFX_PCM_FORMAT_LE) { - silence[0] = silencew & 0xff; - silence[1] = (silencew >> 8) & 0xff; - } else { - silence[0] = (silencew >> 8) & 0xff; - silence[1] = silencew & 0xff; - } - memcpy(silence + 2, silence, 2); - } else { - silence[0] = silencew; - silence[1] = silencew; - } - - buf->last = buf->first = sfx_audbuf_alloc_chunk(); - buf->unused = NULL; - memcpy(buf->last_frame, silence, framesize); /* Initialise, in case we - ** underrun before the - ** first write */ - buf->read_offset = 0; - buf->framesize = framesize; - buf->read_timestamp.secs = -1; /* Mark as inactive */ - buf->frames_nr = 0; -} - -static void -sfx_audbuf_free_chain(sfx_audio_buf_chunk_t *b) { - while (b) { - sfx_audio_buf_chunk_t *n = b->next; - sci_free(b); - b = n; - } -} - -void -sfx_audbuf_free(sfx_audio_buf_t *buf) { - sfx_audbuf_free_chain(buf->first); - sfx_audbuf_free_chain(buf->unused); - buf->first = buf->last = buf->unused = NULL; - buf->read_offset = (int) 0xdeadbeef; -} - -void -sfx_audbuf_write(sfx_audio_buf_t *buf, unsigned char *src, int frames) { - /* In here, we compute PER BYTE */ - int data_left = buf->framesize * frames; - - if (!buf->last) { - fprintf(stderr, "FATAL: Violation of audiobuf.h usage protocol: Must use 'init' before 'write'\n"); - exit(1); - } - - if (buffer_underrun_status == SAW_BUFFER_UNDERRUN) { - /* Print here to avoid threadsafeness issues */ - sciprintf("[audiobuf] Buffer underrun\n"); - buffer_underrun_status = REPORTED_BUFFER_UNDERRUN; - } - - buf->frames_nr += frames; - - while (data_left) { - int cpsize; - int buf_free; - buf_free = SFX_AUDIO_BUF_SIZE - buf->last->used; - - - if (buf_free >= data_left) - cpsize = data_left; - else - cpsize = buf_free; - - /* Copy and advance pointers */ - memcpy(buf->last->data + buf->last->used, src, cpsize); - data_left -= cpsize; - buf->last->used += cpsize; - src += cpsize; - - if (buf->last->used == SFX_AUDIO_BUF_SIZE) { - if (!buf->last->next) { - sfx_audio_buf_chunk_t *old = buf->last; - if (buf->unused) { /* Re-use old chunks */ - sfx_audio_buf_chunk_t *buf_next_unused = buf->unused->next; - buf->unused->next = NULL; - buf->unused->used = 0; - - buf->last->next = buf->unused; - buf->unused = buf_next_unused; - } else /* Allocate */ - buf->last->next = - sfx_audbuf_alloc_chunk(); - - buf->last->prev = old; - } - - buf->last = buf->last->next; - } - } - -#ifdef TRACE_BUFFER - { - sfx_audio_buf_chunk_t *c = buf->first; - int t = buf->read_offset; - - while (c) { - fprintf(stderr, "-> ["); - for (; t < c->used; t++) - fprintf(stderr, " %02x", c->data[t]); - t = 0; - fprintf(stderr, " ] "); - c = c->next; - } - fprintf(stderr, "\n"); - } -#endif - - if (frames && (src - buf->framesize) != buf->last_frame) - /* Backup last frame, unless we're already filling from it */ - memcpy(buf->last_frame, src - buf->framesize, buf->framesize); -} - -int -sfx_audbuf_read(sfx_audio_buf_t *buf, unsigned char *dest, int frames) { - int written = 0; - - if (frames <= 0) - return 0; - - if (buf->read_timestamp.secs >= 0) { - /* Have a timestamp? Must update it! */ - buf->read_timestamp = - sfx_timestamp_add(buf->read_timestamp, - frames); - - } - - buf->frames_nr -= frames; - if (buf->frames_nr < 0) - buf->frames_nr = 0; - -#ifdef TRACE_BUFFER - { - sfx_audio_buf_chunk_t *c = buf->first; - int t = buf->read_offset; - - while (c) { - fprintf(stderr, "-> ["); - for (; t < c->used; t++) - fprintf(stderr, " %02x", c->data[t]); - t = 0; - fprintf(stderr, " ] "); - c = c->next; - } - fprintf(stderr, "\n"); - } -#endif - - while (frames) { - int data_needed = frames * buf->framesize; - int rdbytes = data_needed; - int rdframes; - - if (rdbytes > buf->first->used - buf->read_offset) - rdbytes = buf->first->used - buf->read_offset; - - memcpy(dest, buf->first->data + buf->read_offset, rdbytes); - - buf->read_offset += rdbytes; - dest += rdbytes; - - if (buf->read_offset == SFX_AUDIO_BUF_SIZE) { - /* Continue to next, enqueue the current chunk as - ** being unused */ - sfx_audio_buf_chunk_t *lastfirst = buf->first; - - buf->first = buf->first->next; - lastfirst->next = buf->unused; - buf->unused = lastfirst; - - buf->read_offset = 0; - } - - rdframes = (rdbytes / buf->framesize); - frames -= rdframes; - written += rdframes; - - if (frames && - (!buf->first || buf->read_offset == buf->first->used)) { - fprintf(stderr, "Underrun by %d frames at %d\n", frames, - buf->read_timestamp.frame_rate); - /* Buffer underrun! */ - if (!buffer_underrun_status == NO_BUFFER_UNDERRUN) { - buffer_underrun_status = SAW_BUFFER_UNDERRUN; - } - do { - memcpy(dest, buf->last_frame, buf->framesize); - dest += buf->framesize; - } while (--frames); - } - - } - - return written; -} - -#if 0 -static void -_sfx_audbuf_rewind_stream(sfx_audio_buf_t *buf, int delta) { - if (delta > buf->frames_nr) - delta = buf->frames_nr; - - - fprintf(stderr, "Rewinding %d\n", delta); - buf->frames_nr -= delta; - - /* From here on, 'delta' means the number of BYTES to remove */ - delta *= buf->framesize; - - while (delta) { - if (buf->last->used >= delta) { - fprintf(stderr, "Subtracting from %d %d\n", buf->last->used, delta); - buf->last->used -= delta; - delta = 0; - } else { - fprintf(stderr, "Must do block-unuse\n"); - delta -= buf->last->used; - buf->last->used = 0; - buf->last->next = buf->unused; - buf->unused = buf->last; - buf->last = buf->unused->prev; - buf->unused->prev = NULL; - } - } -} -#endif - -void -sfx_audbuf_write_timestamp(sfx_audio_buf_t *buf, sfx_timestamp_t ts) { - sfx_timestamp_t newstamp; - - newstamp = sfx_timestamp_add(ts, -buf->frames_nr); - - - if (buf->read_timestamp.secs <= 0) - /* Initial stamp */ - buf->read_timestamp = newstamp; - else { - int delta = sfx_timestamp_frame_diff(newstamp, buf->read_timestamp); - long s1, s2, s3, u1, u2, u3; - sfx_timestamp_gettime(&(buf->read_timestamp), &s1, &u1); - sfx_timestamp_gettime(&(newstamp), &s2, &u2); - sfx_timestamp_gettime(&(ts), &s3, &u3); - - if (delta < 0) { -#if 0 - /* fprintf(stderr, "[SFX-BUF] audiobuf.c: Timestamp delta %d at %d: Must rewind (not implemented yet)\n", - delta, buf->read_timestamp.frame_rate);*/ - _sfx_audbuf_rewind_stream(buf, -delta); - buf->read_timestamp = newstamp; -#endif - } else if (delta > 0) { - fprintf(stderr, "[SFX-BUF] audiobuf.c: Timestamp delta %d at %d: Filling in as silence frames\n", - delta, buf->read_timestamp.frame_rate); - /* Fill up with silence */ - while (delta--) { - sfx_audbuf_write(buf, buf->last_frame, 1); - } - buf->read_timestamp = newstamp; - } - } -} - -int -sfx_audbuf_read_timestamp(sfx_audio_buf_t *buf, sfx_timestamp_t *ts) { - if (buf->read_timestamp.secs > 0) { - *ts = buf->read_timestamp; - return 0; - } else { - ts->secs = -1; - ts->usecs = -1; - ts->frame_offset = -1; - ts->frame_rate = -1; - return 1; /* No timestamp */ - } -} diff --git a/engines/sci/sfx/pcm_device/audiobuf.h b/engines/sci/sfx/pcm_device/audiobuf.h deleted file mode 100644 index b2019aec17..0000000000 --- a/engines/sci/sfx/pcm_device/audiobuf.h +++ /dev/null @@ -1,140 +0,0 @@ -/*************************************************************************** - audiobuf.h Copyright (C) 2003 Christoph Reichenbach - - - This program may be modified and copied freely according to the terms of - the GNU general public license (GPL), as long as the above copyright - notice and the licensing information contained herein are preserved. - - Please refer to www.gnu.org for licensing details. - - This work is provided AS IS, without warranty of any kind, expressed or - implied, including but not limited to the warranties of merchantibility, - noninfringement, and fitness for a specific purpose. The author will not - be held liable for any damage caused by this work or derivatives of it. - - By using this source code, you agree to the licensing terms as stated - above. - - - Please contact the maintainer for bug reports or inquiries. - - Current Maintainer: - - Christoph Reichenbach (CR) <jameson@linuxgames.com> - -***************************************************************************/ - -/* Auxiliary audio buffer for PCM devices -** Polled PCM devices must store data written to them until it is explicitly -** requiested. This is facilitated by the structures and functions defined -** here. -** This is generic for all PCM devices; it implies no specific requirements. -** -** Usage: Introduce an sfx_audio_buf_t into your state and make sure to use -** each of the functions provided here at least once in the appropriate -** places. -*/ - - -#ifndef _AUDIOBUF_H_ -#define _AUDIOBUF_H_ - -#include <resource.h> -#include <sfx_time.h> -#include <sci_memory.h> -#include <sfx_pcm.h> - - -#define SFX_AUDIO_BUF_SIZE 8192 /* Must be multiple of framesize */ -#define SFX_AUDIO_MAX_FRAME 8 /* Max. individual frame size */ - -typedef struct _sfx_audio_buf_chunk { - unsigned char data[SFX_AUDIO_BUF_SIZE]; - int used; - struct _sfx_audio_buf_chunk *prev; - struct _sfx_audio_buf_chunk *next; -} sfx_audio_buf_chunk_t; - -typedef struct { - int read_offset; - sfx_audio_buf_chunk_t *first; /* Next to read-- can be = last */ - sfx_audio_buf_chunk_t *last; /* Next to write-- can be = first */ - sfx_audio_buf_chunk_t *unused; /* Unused chunk list, can be NULL */ - unsigned char last_frame[SFX_AUDIO_MAX_FRAME]; - /* Contains the last frame successfully read; used for buffer - ** underruns to avoid crack before silance */ - sfx_timestamp_t read_timestamp; /* Timestamp for reading */ - int frames_nr; /* Total number of frames currently in between reading and writing */ - int framesize; -} sfx_audio_buf_t; - - -void -sfx_audbuf_init(sfx_audio_buf_t *buf, sfx_pcm_config_t conf); -/* Initialises an audio buffer -** Parameters: (sfx_audio_buf_t *) buf: The buffer to initialise -** (sfx_pcm_config_t) conf: The configuration for which the buffer should -** be set up -** Modifies : (sfx_audio_buf_t) *buf -*/ - -void -sfx_audbuf_free(sfx_audio_buf_t *buf); -/* Frees all memory associated with an audio buffer -** Parameters: (sfx_audio_buf_t *) buf: The buffer whose associated memory -** should be freed -** Modifies : (sfx_audio_buf_t) *buf -*/ - -void -sfx_audbuf_write(sfx_audio_buf_t *buf, unsigned char *src, int frames); -/* Store data in an audion buffer -** Parameters: (sfx_audio_buf_t *) buf: The buffer to write to -** (unsigned char *) src: Pointer to the data that should be -** written -** (int) frames: Number of frames to write -** Modifies : (sfx_audio_buf_t) *buf -*/ - - -void -sfx_audbuf_write_timestamp(sfx_audio_buf_t *buf, sfx_timestamp_t ts); -/* Sets the most recently written timestamp for the buffer -** Parameters: (sfx_audio_buf_t *) buf: The buffer to operate on -** (sfx_timestamp_t) ts: The timestamp to set -** If a timestamp is already set, 'ts' is checked for consistency and -** 'silent' frames are introduced as padding for future writes. -*/ - - -int -sfx_audbuf_read_timestamp(sfx_audio_buf_t *buf, sfx_timestamp_t *ts); -/* Reads the timestamp describing the time right before the next frame being read -** Parameters: (sfx_audio_buf_t *) buf: The buffer to read from -** Returns : (sfx_timestamp_t) *ts: The requested timestamp, or nothing -** (int) zero on success, nonzero if no timestamp is known -*/ - - -int -sfx_audbuf_read(sfx_audio_buf_t *buf, unsigned char *dest, int frames); -/* Read data from audio buffer -** Parameters: (sfx_audio_buf_t *) buf: The buffer to write to -** (unsigned char *) dest: Pointer to the place the read data -** should be written to -** (int) frames: Number of frames to write -** Returns : (int) Number of frames actually read -** Affects : (sfx_audio_buf_t) *buf -** (unsigned char ) *dest -** global error stream -** If the returned number of frames is smaller than the number of frames -** requested to be written, this function will issue a buffer underrun -** warning and fill up the remaining space with the last frame it en-- -** countered, or a block of '0' if no such frame is known. -*/ - - - - -#endif /* !_AUDIOBUF_H_ */ diff --git a/engines/sci/sfx/pcm_device/pcm_devices.cpp b/engines/sci/sfx/pcm_device/pcm_devices.cpp deleted file mode 100644 index 866372a670..0000000000 --- a/engines/sci/sfx/pcm_device/pcm_devices.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/*************************************************************************** - pcmout.c Copyright (C) 2002 Solomon Peachy - - This program may be modified and copied freely according to the terms of - the GNU general public license (GPL), as long as the above copyright - notice and the licensing information contained herein are preserved. - - Please refer to www.gnu.org for licensing details. - - This work is provided AS IS, without warranty of any kind, expressed or - implied, including but not limited to the warranties of merchantibility, - noninfringement, and fitness for a specific purpose. The author will not - be held liable for any damage caused by this work or derivatives of it. - - By using this source code, you agree to the licensing terms as stated - above. - -***************************************************************************/ - -#include "sci/include/sfx_pcm.h" -#include "sci/include/resource.h" - -#ifndef NO_PCMOUT -extern sfx_pcm_device_t sfx_pcm_driver_scummvm; -#endif - -sfx_pcm_device_t *pcmout_drivers[] = { -#ifndef NO_PCMOUT - &sfx_pcm_driver_scummvm, -#endif - NULL -}; - -sfx_pcm_device_t * -sfx_pcm_find_device(char *name) { - int retval = 0; - - if (!name) { /* Find default driver */ - return pcmout_drivers[0]; - } - - while (pcmout_drivers[retval] && - scumm_stricmp(name, pcmout_drivers[retval]->name)) - retval++; - - return pcmout_drivers[retval]; -} - diff --git a/engines/sci/sfx/pcm_device/scummvm.cpp b/engines/sci/sfx/pcm_device/scummvm.cpp deleted file mode 100644 index e6bb5f9c25..0000000000 --- a/engines/sci/sfx/pcm_device/scummvm.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "sci/include/sfx_time.h" -#include "sci/include/sfx_pcm.h" -#include "engines/engine.h" -#include "sound/audiostream.h" -#include "sound/mixer.h" - - -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 void pcmout_scummvm_exit(sfx_pcm_device_t *self) { -} - -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 = { - "ScummVM", - "0.1", - &pcmout_scummvm_init, - &pcmout_scummvm_exit, - NULL, - &pcmout_scummvm_output, - NULL, - {0, 0, 0}, - 0, - NULL, - NULL -}; diff --git a/engines/sci/sfx/pcm_device/sdl.cpp b/engines/sci/sfx/pcm_device/sdl.cpp deleted file mode 100644 index c4c47ed2a1..0000000000 --- a/engines/sci/sfx/pcm_device/sdl.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/*************************************************************************** - sdl.c Copyright (C) 2002 Solomon Peachy, Claudio Matsuoka, - 2003,04 Christoph Reichenbach - - This program may be modified and copied freely according to the terms of - the GNU general public license (GPL), as long as the above copyright - notice and the licensing information contained herein are preserved. - - Please refer to www.gnu.org for licensing details. - - This work is provided AS IS, without warranty of any kind, expressed or - implied, including but not limited to the warranties of merchantibility, - noninfringement, and fitness for a specific purpose. The author will not - be held liable for any damage caused by this work or derivatives of it. - - By using this source code, you agree to the licensing terms as stated - above. - -***************************************************************************/ - -#include <sfx_pcm.h> -#include "audiobuf.h" - -#ifdef HAVE_SDL - -#if !defined(_MSC_VER) -# include <sys/time.h> -#endif - -#include <SDL_config.h> -#undef HAVE_ICONV -#undef HAVE_ICONV_H -#undef HAVE_ALLOCA_H - -#include <SDL.h> - -#define DELTA_TIME_LIMIT 10000 /* Report errors above this delta time */ - -static sfx_audio_buf_t audio_buffer; -static void (*sdl_sfx_timer_callback)(void *data); -static void *sdl_sfx_timer_data; -static int frame_size; -static int buf_size; -static int rate; -static long last_callback_secs, last_callback_usecs; -static int last_callback_len; - -static sfx_timestamp_t -pcmout_sdl_output_timestamp(sfx_pcm_device_t *self) { - /* Number of frames enqueued in the output device: */ - int delta = (buf_size - last_callback_len) / frame_size - /* Number of frames enqueued in the internal audio buffer: */ - + audio_buffer.frames_nr; - - return sfx_timestamp_add(sfx_new_timestamp(last_callback_secs, - last_callback_usecs, - rate), - delta); -} - -FILE *fil = NULL; - -static void -timer_sdl_internal_callback(void *userdata, byte *dest, int len) { - sci_gettime(&last_callback_secs, &last_callback_usecs); - last_callback_len = len; - - if (sdl_sfx_timer_callback) - sdl_sfx_timer_callback(sdl_sfx_timer_data); - -#if 0 - if (!sfx_audbuf_read_timestamp(&audio_buffer, &ts)) { - int delta = (buf_size - len) / frame_size; - sfx_timestamp_t real_ts; - long deltatime; - long sec2, usec2; - sci_gettime(&sec2, &usec2); - - real_ts = sfx_timestamp_add(sfx_new_timestamp(sec, usec, rate), delta); - - deltatime = sfx_timestamp_usecs_diff(ts, real_ts); - - fprintf(stderr, "[SDL] Frames requested: %d Playing %ld too late. Needed %ldus for computations.\n", - len / frame_size, deltatime, - (usec2 - usec) + (sec2 - sec)*1000000); - - if (abs(deltatime) > DELTA_TIME_LIMIT) - sciprintf("[SND:SDL] Very high delta time for PCM playback: %ld too late (%d frames in the future)\n", - deltatime, sfx_timestamp_frame_diff(sfx_new_timestamp(sec, usec, rate), ts)); - -#if 0 - if (deltatime < 0) { - /* Read and discard frames, explicitly underrunning */ - int max_read = len / frame_size; - int frames_to_kill = sfx_timestamp_frame_diff(real_ts, ts); - - while (frames_to_kill) { - int d = frames_to_kill > max_read ? max_read : frames_to_kill; - sfx_audbuf_read(&audio_buffer, dest, d); - frames_to_kill -= d; - } - } -#endif - } -#endif - sfx_audbuf_read(&audio_buffer, dest, len / frame_size); - -#if 0 - if (!fil) { - fil = fopen("/tmp/sdl.log", "w"); - } - { - int i; - int end = len / frame_size; - gint16 *d = dest; - fprintf(fil, "Writing %d/%d\n", len, frame_size); - for (i = 0; i < end; i++) { - fprintf(fil, "\t%d\t%d\n", d[0], d[1]); - d += 2; - } - } -#endif -} - - -static int -pcmout_sdl_init(sfx_pcm_device_t *self) { - SDL_AudioSpec a; - - if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE) != 0) { - fprintf(stderr, "[SND:SDL] Error while initialising: %s\n", SDL_GetError()); - return -1; - } - - a.freq = 44100; /* FIXME */ -#ifdef WORDS_BIGENDIAN - a.format = AUDIO_S16MSB; /* FIXME */ -#else - a.format = AUDIO_S16LSB; /* FIXME */ -#endif - a.channels = 2; /* FIXME */ - a.samples = 2048; /* FIXME */ - a.callback = timer_sdl_internal_callback; - a.userdata = NULL; - - if (SDL_OpenAudio(&a, NULL) < 0) { - fprintf(stderr, "[SND:SDL] Error while opening audio: %s\n", SDL_GetError()); - return SFX_ERROR; - } - - buf_size = a.samples; - rate = a.freq; - - self->buf_size = a.samples << 1; /* Looks like they're using double size */ - self->conf.rate = a.freq; - self->conf.stereo = a.channels > 1; - self->conf.format = SFX_PCM_FORMAT_S16_NATIVE; - - frame_size = SFX_PCM_FRAME_SIZE(self->conf); - - sfx_audbuf_init(&audio_buffer, self->conf); - SDL_PauseAudio(0); - - return SFX_OK; -} - -int -pcmout_sdl_output(sfx_pcm_device_t *self, byte *buf, - int count, sfx_timestamp_t *ts) { - if (ts) - sfx_audbuf_write_timestamp(&audio_buffer, *ts); - sfx_audbuf_write(&audio_buffer, buf, count); - return SFX_OK; -} - - -static int -pcmout_sdl_set_option(sfx_pcm_device_t *self, char *name, char *value) { - return SFX_ERROR; /* Option not supported */ -} - -static void -pcmout_sdl_exit(sfx_pcm_device_t *self) { - SDL_PauseAudio(1); - SDL_CloseAudio(); - sfx_audbuf_free(&audio_buffer); - - SDL_QuitSubSystem(SDL_INIT_AUDIO); - - if (!SDL_WasInit(SDL_INIT_EVERYTHING)) { - sciprintf("[SND:SDL] No active SDL subsystems found.. shutting down SDL\n"); - SDL_Quit(); - } -} - - -static int -timer_sdl_set_option(char *name, char *value) { - return SFX_ERROR; -} - - -static int -timer_sdl_init(void (*callback)(void *data), void *data) { - sdl_sfx_timer_callback = callback; - sdl_sfx_timer_data = data; - - - return SFX_OK; -} - -static int -timer_sdl_stop(void) { - sdl_sfx_timer_callback = NULL; - - return SFX_OK; -} - -static int -timer_sdl_block(void) { - SDL_LockAudio(); - - return SFX_OK; -} - -static int -timer_sdl_unblock(void) { - SDL_UnlockAudio(); - - return SFX_OK; -} - -#define SDL_PCM_VERSION "0.1" - -sfx_timer_t pcmout_sdl_timer = { - "sdl-pcm-timer", - SDL_PCM_VERSION, - 0, - 0, - timer_sdl_set_option, - timer_sdl_init, - timer_sdl_stop, - timer_sdl_block, - timer_sdl_unblock -}; - -sfx_pcm_device_t sfx_pcm_driver_sdl = { - "sdl", - SDL_PCM_VERSION, - pcmout_sdl_init, - pcmout_sdl_exit, - pcmout_sdl_set_option, - pcmout_sdl_output, - pcmout_sdl_output_timestamp, - {0, 0, 0}, - 0, - &pcmout_sdl_timer, - NULL -}; - -#endif |