Forgot to add ux_audio.c
authorDavid Griffith <dave@661.org>
Sun, 1 Dec 2013 22:02:00 +0000 (14:02 -0800)
committerDavid Griffith <dave@661.org>
Sun, 1 Dec 2013 22:02:00 +0000 (14:02 -0800)
src/curses/ux_audio.c [new file with mode: 0644]

diff --git a/src/curses/ux_audio.c b/src/curses/ux_audio.c
new file mode 100644 (file)
index 0000000..0ecb2c8
--- /dev/null
@@ -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 <ncurses.h>
+#else
+#include <curses.h>
+#endif
+
+#include <string.h>
+#include <ao/ao.h>
+#include <math.h>
+
+#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 */
+