From 1c39da77b61a301dedc048f6c753ac3ac9483ca1 Mon Sep 17 00:00:00 2001 From: David Griffith Date: Sun, 1 Dec 2013 14:02:00 -0800 Subject: [PATCH] Forgot to add ux_audio.c --- src/curses/ux_audio.c | 335 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 335 insertions(+) create mode 100644 src/curses/ux_audio.c diff --git a/src/curses/ux_audio.c b/src/curses/ux_audio.c new file mode 100644 index 0000000..0ecb2c8 --- /dev/null +++ b/src/curses/ux_audio.c @@ -0,0 +1,335 @@ +/* + * ux_audio_none.c - Unix interface, sound support + * + * This file is part of Frotz. + * + * Frotz 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. + * + * Frotz 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#define __UNIX_PORT_FILE + +#ifdef USE_NCURSES_H +#include +#else +#include +#endif + +#include +#include +#include + +#include "ux_frotz.h" +#include "ux_blorb.h" + +enum {SFX_TYPE, MOD_TYPE}; + +typedef struct EFFECT { + void (*destroy)(struct EFFECT *); + int number; + int type; + int active; + int voice; + char *buffer; + int buflen; + int repeats; + int volume; + int ended; + zword eos; + ulong endtime; +} EFFECT; + +/* no effects cache */ + +static EFFECT *e_sfx = NULL; +static EFFECT *e_mod = NULL; + + +int audiorunning = 0; + +static ao_device *device; + +static EFFECT *getaiff(FILE *, size_t, int, int); +static EFFECT *geteffect(int); +static EFFECT *new_effect(int, int); + + +int ux_initsound(void) +{ + ao_sample_format format; + + int default_driver; + + if (audiorunning) return 1; + if (!f_setup.sound) return 0; + audiorunning = 1; + + ao_initialize(); + + default_driver = ao_default_driver_id(); + + memset(&format, 0, sizeof(format)); + + format.bits = 16; + format.channels = 2; + format.rate = 44100; + format.byte_format = AO_FMT_BIG; + + device = ao_open_live(default_driver, &format, NULL); + if (device == NULL) { + printf("Error opening audio device.\n"); + exit(1); + } + printf("Audio ready.\n"); + return 1; +} + +void ux_stopsound(void) +{ + ao_close(device); + ao_shutdown(); +} + +static EFFECT *geteffect(int num) +{ + myresource res; + EFFECT *result = NULL; + unsigned int id; + + if ((e_sfx) && (e_sfx->number == num)) return e_sfx; + if ((e_mod) && (e_mod->number == num)) return e_mod; + + if (ux_getresource(num,0,bb_method_FilePos,&res) != bb_err_None) + return NULL; + + /* Look for a recognized format. */ + + id = res.type; + + if (id == bb_make_id('F','O','R','M')) { + result = getaiff(res.fp, res.bbres.data.startpos, res.bbres.length, num); + } +/* + else if (id == bb_make_id('M','O','D',' ') { + result = getmodule(res.file, res.bbres.data.startpos, res.bbres.length, num); + } else { + result = getogg(res.file, res.bbres.data.startpos, res.bbres.length, num); + } +*/ + ux_freeresource(&res); + return result; +} + + +static void baredestroy(EFFECT * r) +{ + if (r) { + if (r->buffer != NULL) free(r->buffer); + free(r); + } +} + + +static EFFECT *new_effect(int type, int num) +{ + EFFECT * reader = (EFFECT *)calloc(1, sizeof(EFFECT)); + + if (reader) { + reader->type = type; + reader->number = num; + reader->destroy = baredestroy; + } + return (EFFECT *)reader; +} + + +static EFFECT *getaiff(FILE *f, size_t pos, int len, int num) +{ + EFFECT *sample; + void *data; + int size; + int count; + +/* +printf("start position: %d\n", pos); +printf("length: %d\n", len); +printf("num: %d\n", num); +*/ + + sample = new_effect(SFX_TYPE, num); + if (sample == NULL || sample == 0) + return sample; + + count = 0; + sample->buffer = malloc(sizeof(int) * len); + + while (count <= len) { + fread(sample->buffer, 1, 1, f); + count++; + } + +//ao_play(device, sample->buffer, len); + + return sample; +} + +static void startsample() +{ + if (e_sfx == NULL) return; + ao_play(device, e_sfx->buffer, e_sfx->buflen); + printf(" Boop\n"); +} + +static void stopsample() +{ + /* nothing yet */ +} + +/* + * os_beep + * + * Play a beep sound. Ideally, the sound should be high- (number == 1) + * or low-pitched (number == 2). + * + */ + +void os_beep (int number) +{ +// beep(); + + ao_sample_format format; + char *buffer; + int buf_size; + int sample; + float freq; + int i; + + if (number == 1) + freq = 880.0; + else + freq = 440.0; + + format.bits = 16; + format.channels = 2; + format.rate = 44100; + format.byte_format = AO_FMT_LITTLE; + + buf_size = format.bits/8 * format.channels * format.rate; + buffer = calloc(buf_size, sizeof(char)); + + for (i = 0; i < format.rate; i++) { + sample = (int)(0.75 * 32768.0 * + sin(2 * M_PI * freq * ((float) i/format.rate))); + + /* Put the same stuff in left and right channel */ + buffer[4*i] = buffer[4*i+2] = sample & 0xff; + buffer[4*i+1] = buffer[4*i+3] = (sample >> 8) & 0xff; + } + ao_play(device, buffer, buf_size); + +}/* os_beep */ + +/* + * os_prepare_sample + * + * Load the sample from the disk. + * + */ + +void os_prepare_sample (int number) +{ + + /* Not implemented */ + +}/* os_prepare_sample */ + +/* + * os_start_sample + * + * Play the given sample at the given volume (ranging from 1 to 8 and + * 255 meaning a default volume). The sound is played once or several + * times in the background (255 meaning forever). In Z-code 3 the + * repeats value is always 0 and the number of repeats is taken from + * the sound file itself. The end_of_sound function is called as soon + * as the sound finishes. + * + */ + +void os_start_sample (int number, int volume, int repeats, zword eos) +{ + EFFECT *e; + + if (!audiorunning) return; + e = geteffect(number); + if (e == NULL) return; +// if (e->type == SFX_TYPE) stopsample(); + stopsample(); + if (repeats < 1) repeats = 1; + if (repeats == 255) repeats = -1; + if (volume < 0) volume = 0; + if (volume > 8) volume = 8; + if (e->type == SFX_TYPE && repeats > 0) repeats--; + e->repeats = repeats; + e->volume = 32*volume; + e->eos = eos; + e->ended = 0; + if (e->type == SFX_TYPE) { + if ((e_sfx) && (e_sfx != e)) e_sfx->destroy(e_sfx); + e_sfx = e; + startsample(); + } +}/* os_start_sample */ + +/* + * os_stop_sample + * + * Turn off the current sample. + * + */ + +void os_stop_sample (int number) +{ + + /* Not implemented */ + +}/* os_stop_sample */ + +/* + * os_finish_with_sample + * + * Remove the current sample from memory (if any). + * + */ + +void os_finish_with_sample (number) +{ + + /* Not implemented */ + +}/* os_finish_with_sample */ + +/* + * os_wait_sample + * + * Stop repeating the current sample and wait until it finishes. + * + */ + +void os_wait_sample (void) +{ + + /* Not implemented */ + +}/* os_wait_sample */ + -- 2.34.1