OSDN Git Service

WIP: Add support for sf3
authorStarg <starg@users.osdn.me>
Wed, 25 Apr 2018 23:05:51 +0000 (08:05 +0900)
committerStarg <starg@users.osdn.me>
Wed, 25 Apr 2018 23:21:46 +0000 (08:21 +0900)
CMakeLists.txt
cfgforsf/CMakeLists.txt
sf_view_gui/CMakeLists.txt
timidity/CMakeLists.txt
timidity/decode.c [new file with mode: 0644]
timidity/decode.h [new file with mode: 0644]
timidity/instrum.h
timidity/resample.c
timidity/sndfont.c
timidity/w32g_vorbis_dll.c
timidity/w32g_vorbisfile_dll.c [new file with mode: 0644]

index 9464e08..adebd15 100644 (file)
@@ -91,6 +91,7 @@ add_definitions(
     -DAU_VORBIS
     -DAU_VORBIS_DLL
     -DVORBIS_DLL_INCLUDE_VORBISENC
+    -DVORBIS_DLL_INCLUDE_VORBISFILE
     -DAU_FLAC
     -DAU_FLAC_DLL
     -DAU_OGGFLAC
index 20b4c69..116484d 100644 (file)
@@ -7,6 +7,7 @@ add_executable(
     ../interface/dumb_c.c
     ../timidity/common.c
     ../timidity/controls.c
+    ../timidity/decode.c
     ../timidity/envelope.c
     ../timidity/filter.c
     ../timidity/freq.c
@@ -24,9 +25,12 @@ add_executable(
     ../timidity/sndfont.c
     ../timidity/tables.c
     ../timidity/version.c
+    ../timidity/w32g_vorbis_dll.c
+    ../timidity/w32g_vorbisfile_dll.c
 
     ../timidity/common.h
     ../timidity/controls.h
+    ../timidity/decode.h
     ../timidity/envelope.h
     ../timidity/filter.h
     ../timidity/freq.h
index b4afa9a..c906dc1 100644 (file)
@@ -13,6 +13,7 @@ add_executable(
     ../interface/dumb_c.c
     ../timidity/common.c
     ../timidity/controls.c
+    ../timidity/decode.c
     ../timidity/envelope.c
     ../timidity/filter.c
     ../timidity/freq.c
@@ -29,12 +30,16 @@ add_executable(
     ../timidity/smplfile.c
     ../timidity/tables.c
     ../timidity/version.c
+    ../timidity/w32g_vorbis_dll.c
+    ../timidity/w32g_vorbisfile_dll.c
+
 
     OpenDlg.h
     resource.h
     ../libarc/arc.h
     ../timidity/common.h
     ../timidity/controls.h
+    ../timidity/decode.h
     ../timidity/envelope.h
     ../timidity/filter.h
     ../timidity/instrum.h
index 7bfaea5..544d91b 100644 (file)
@@ -26,6 +26,7 @@ set(
     audio_cnv.c
     common.c
     controls.c
+    decode.c
     effect.c
     envelope.c
     filter.c
@@ -87,6 +88,7 @@ set(
     w32_portaudio_dll.c
     w32g_vorbis_dll.c
     w32g_vorbisenc_dll.c
+    w32g_vorbisfile_dll.c
     w32g_opus_dll.c
     w32_libFLAC_dll.c
     w32_libOggFLAC_dll.c
@@ -100,6 +102,7 @@ set(
     audriv.h
     common.h
     controls.h
+    decode.h
     dlutils.h
     filter.h
     flac_a.h
diff --git a/timidity/decode.c b/timidity/decode.c
new file mode 100644 (file)
index 0000000..f78ab6a
--- /dev/null
@@ -0,0 +1,144 @@
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+#ifdef __POCC__
+#include <sys/types.h>
+#endif //for off_t
+#include <stdio.h>
+#ifndef NO_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif /* HAVE_STDLIB_H */
+#include <math.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include "timidity.h"
+#include "common.h"
+#include "controls.h"
+#include "decode.h"
+
+#ifdef HAVE_LIBVORBIS
+
+#include <vorbis/vorbisfile.h>
+
+extern int load_vorbis_dll(void);      // w32g_vorbis_dll.c
+
+#ifndef VORBIS_DLL_INCLUDE_VORBISFILE
+extern int load_vorbisfile_dll(void);  // w32g_vorbisfile_dll.c
+#endif
+
+static size_t oggvorbis_read_callback(void *ptr, size_t size, size_t nmemb, void *datasource)
+{
+    struct timidity_file *tf = (struct timidity_file *)datasource;
+    return tf_read(ptr, size, nmemb, tf);
+}
+
+static int oggvorbis_seek_callback(void *datasource, ogg_int64_t offset, int whence)
+{
+    struct timidity_file *tf = (struct timidity_file *)datasource;
+    return tf_seek(tf, offset, whence);
+}
+
+static long oggvorbis_tell_callback(void *datasource)
+{
+    struct timidity_file *tf = (struct timidity_file *)datasource;
+    return tf_tell(tf);
+}
+
+SampleDecodeResult decode_oggvorbis(struct timidity_file *tf)
+{
+    SampleDecodeResult sdr = {0};
+    OggVorbis_File vf;
+
+    if (load_vorbis_dll() != 0) {
+        ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "unable to load vorbis dll");
+        return sdr;
+    }
+#ifndef VORBIS_DLL_INCLUDE_VORBISFILE
+    if (load_vorbisfile_dll() != 0) {
+        ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "unable to load vorbisfile dll");
+        return sdr;
+    }
+#endif
+
+    int result = ov_open_callbacks(
+        tf, &vf, 0, 0,
+        (ov_callbacks){.read_func = &oggvorbis_read_callback, .seek_func = &oggvorbis_seek_callback, .tell_func = &oggvorbis_tell_callback}
+    );
+
+    if (result != 0) {
+        ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "unable to open ogg vorbis data; ov_open_callbacks() failed");
+        return sdr;
+    }
+
+    vorbis_info *info = ov_info(&vf, -1);
+
+    if (!info) {
+        ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "unable to read ogg vorbis info; ov_info() failed");
+        goto cleanup;
+    }
+
+    sdr.channels = info->channels;
+    int64 total = ov_pcm_total(&vf, -1);
+
+    if (total < 0) {
+        ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "unable to get data length; ov_pcm_total() failed");
+        goto cleanup;
+    }
+
+    ptr_size_t data_length = info->channels * sizeof(sample_t) * total;
+       data_length = (data_length > 0 ? data_length : 4096);
+       ptr_size_t current_size = 0;
+    sdr.data = (sample_t *)safe_large_malloc(data_length);
+
+    while (1) {
+        int bitstream = 0;
+        long ret = ov_read(&vf, (char *)(sdr.data) + current_size, data_length - current_size, 0, 2, 1, &bitstream);
+
+        if (ret < 0) {
+            ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "unable to decode ogg vorbis data; ov_read() failed");
+            goto cleanup;
+        } else if (ret == 0) {
+                       sdr.data_length = (splen_t)(current_size / 2) << FRACTION_BITS;
+            break;
+        }
+
+               current_size += ret;
+
+               if (data_length - current_size < 512) {
+                       ptr_size_t new_data_length = data_length + data_length / 2;
+                       sdr.data = (sample_t *)safe_large_realloc(sdr.data, new_data_length);
+                       data_length = new_data_length;
+               }
+    }
+
+    memset(((char *)sdr.data) + current_size, 0, data_length - current_size);
+       ov_clear(&vf);
+       return sdr;
+
+cleanup:
+    ov_clear(&vf);
+
+    if (sdr.data) {
+        safe_free(sdr.data);
+        sdr.data = NULL;
+    }
+
+    return sdr;
+}
+
+#else // HAVE_LIBVORBIS
+
+SampleDecodeResult decode_oggvorbis(struct timidity_file *tf)
+{
+    ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "ogg vorbis decoder support is disabled");
+    return (SampleDecodeResult){.data = NULL, .data_type = 0};
+}
+
+#endif // HAVE_LIBVORBIS
diff --git a/timidity/decode.h b/timidity/decode.h
new file mode 100644 (file)
index 0000000..a1f926c
--- /dev/null
@@ -0,0 +1,10 @@
+
+#pragma once
+
+typedef struct SampleDecodeResult {
+    sample_t *data;
+    splen_t data_length;
+    int channels;
+} SampleDecodeResult;
+
+SampleDecodeResult decode_oggvorbis(struct timidity_file *tf);
index 2c936ea..225ac4f 100644 (file)
@@ -116,6 +116,7 @@ enum {
 #define SF_SAMPLETYPE_RIGHT 2
 #define SF_SAMPLETYPE_LEFT 4
 #define SF_SAMPLETYPE_LINKED 8
+#define SF_SAMPLETYPE_VORBIS 0x10
 #define SF_SAMPLETYPE_ROM 0x8000
 
 typedef struct {
index f4aebe9..87bd85e 100644 (file)
@@ -4981,6 +4981,21 @@ static DATA_T *resample_multi_lagrange_m128(Voice *vp, DATA_T *dest, int32 *i, i
 
 #endif
 
+static void process_loop(resample_rec_t *resrc)
+{
+    if (resrc->loop_end < resrc->offset) {
+        if (resrc->mode == RESAMPLE_MODE_LOOP) {
+            resrc->offset -= resrc->loop_end - resrc->loop_start;
+        }
+        else if (resrc->mode == RESAMPLE_MODE_BIDIR_LOOP && resrc->increment > 0) {
+            resrc->increment = -resrc->increment;
+        }
+    }
+    else if (resrc->mode == RESAMPLE_MODE_BIDIR_LOOP && resrc->increment < 0 && resrc->offset < resrc->loop_start) {
+        resrc->increment = -resrc->increment;
+    }
+}
+
 static void resample_lagrange_multi(Voice *vp, DATA_T *dest, int32 count)
 {
        const sample_t *src = vp->sample->data;
@@ -5090,6 +5105,8 @@ static void resample_lagrange_multi(Voice *vp, DATA_T *dest, int32 count)
                                i++;
                        }
 
+            process_loop(resrc);
+
                        while (i < count) {
                                spos_t ofsi = resrc->offset >> FRACTION_BITS;
 
@@ -5101,15 +5118,7 @@ static void resample_lagrange_multi(Voice *vp, DATA_T *dest, int32 count)
                                resrc->offset += resrc->increment;
                                i++;
 
-                               if (resrc->loop_end < resrc->offset) {
-                                       if (resrc->mode == RESAMPLE_MODE_LOOP) {
-                                               resrc->offset -= resrc->loop_end - resrc->loop_start;
-                                       } else if (resrc->mode == RESAMPLE_MODE_BIDIR_LOOP && resrc->increment > 0) {
-                                               resrc->increment = -resrc->increment;
-                                       }
-                               } else if (resrc->mode == RESAMPLE_MODE_BIDIR_LOOP && resrc->increment < 0 && resrc->offset < resrc->loop_start) {
-                                       resrc->increment = -resrc->increment;
-                               }
+                process_loop(resrc);
                        }
                }
        }
index a766491..f6b3258 100644 (file)
@@ -62,6 +62,7 @@
 #include "resample.h"
 
 #include "sndfontini.h"
+#include "decode.h"
 
 ///r
 int8 sf_attenuation_neg = 0;
@@ -824,72 +825,127 @@ static Instrument *load_from_file(SFInsts *rec, InstList *ip)
                }
                tf = sp->sfrom ? sfrom_sfrec->tf : rec->tf; ///r
 
+               if (rec->version >= 4) {
+                       ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "unsupported soundfont version: %d", rec->version);
+               } else if (rec->version == 3) {
+                       off_size_t length = sp->len / 2;
+                       off_size_t start_offset = (sp->start - rec->samplepos) / 2;
+            char *compressed_data = (char *)safe_large_malloc(length);
+                       // sp->start is SAMPLEPOS + START * 2 but we want SAMPLEPOS + START
+                       tf_seek(tf, sp->start - start_offset, SEEK_SET);
+            tf_read(compressed_data, length, 1, tf);
+
+            struct timidity_file *ctf = open_with_mem(compressed_data, length, OF_VERBOSE);
+
+            if (ctf) {
+                SampleDecodeResult sdr = decode_oggvorbis(ctf);
+                close_file(ctf);
+                sample->data = sdr.data;
+                sample->data_alloced = 1;
+                sample->data_type = SAMPLE_TYPE_INT16;
+                               sample->data_length = sdr.data_length;
+
+                               if (!(sample->modes & MODES_LOOPING)) {
+                                       sample->loop_start = sdr.data_length;
+                                       sample->loop_end = sdr.data_length + (1 << FRACTION_BITS);
+                               } else {
+                                       sample->loop_start = 0;
+                                       sample->loop_end = sdr.data_length;
+                               }
+
+                               if (sdr.channels > 1) {
+                                       sample->sample_type &= ~SF_SAMPLETYPE_MONO;
+                               } else {
+                                       sample->sample_type |= SF_SAMPLETYPE_MONO;
+                               }
+                       } else {
+                               ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "unable to read compressed sample; open_with_mem() failed");
+                       }
+
+                       safe_free(compressed_data);
+        } else {
+
 #if defined(SF2_24BIT) && (defined(DATA_T_DOUBLE) || defined(DATA_T_FLOAT))
-               if(sp->lowbit > 0 ){
-                   /* 24 bit */
-                   splen_t cnt;
-                   uint8 *lowbit;
-                       uint16 *highbit;
-                       uint32 *tmp_data;
-
-                       frames = divi_2(sp->len);
-                   sample->data = (sample_t*)safe_large_malloc(sizeof(int32) * (frames + 128));
-                   sample->data_alloced = 1;
-                       sample->data_type = SAMPLE_TYPE_INT32;
-
-                   highbit = (uint16 *)safe_large_malloc(sizeof(int16) * frames); // 16bit
-                   lowbit = (uint8 *)safe_large_malloc(sizeof(int8) * frames); // 8bit
-                       
-                       tf_seek(tf, sp->start, SEEK_SET);
-                       tf_read(highbit, sp->len, 1, tf);
-                   tf_seek(tf, sp->lowbit, SEEK_SET);
-                   tf_read(lowbit, frames, 1, tf);
-
-                       tmp_data = (uint32 *)sample->data;
-                   for(j = 0; j < frames; j++) {
-                               // 24bit to int32full
-                           uint32 tmp_i = 0; // 1byte 00\82Ã…\82¢\82¢\82ç\82µ\82¢\81H
-                               tmp_i |= (uint32)lowbit[j] << 8; // 2byte
-                           tmp_i |= (uint32)highbit[j] << 16; // 3-4byte
+                       if (sp->lowbit > 0) {
+                               /* 24 bit */
+                               splen_t cnt;
+                               uint8 *lowbit;
+                               uint16 *highbit;
+                               uint32 *tmp_data;
+
+                               frames = divi_2(sp->len);
+                               sample->data = (sample_t*)safe_large_malloc(sizeof(int32) * (frames + 128));
+                               sample->data_alloced = 1;
+                               sample->data_type = SAMPLE_TYPE_INT32;
+
+                               highbit = (uint16 *)safe_large_malloc(sizeof(int16) * frames); // 16bit
+                               lowbit = (uint8 *)safe_large_malloc(sizeof(int8) * frames); // 8bit
+
+                               tf_seek(tf, sp->start, SEEK_SET);
+                               tf_read(highbit, sp->len, 1, tf);
+                               tf_seek(tf, sp->lowbit, SEEK_SET);
+                               tf_read(lowbit, frames, 1, tf);
+
+                               tmp_data = (uint32 *)sample->data;
+                               for (j = 0; j < frames; j++) {
+                                       // 24bit to int32full
+                                       uint32 tmp_i = 0; // 1byte 00\82Ã…\82¢\82¢\82ç\82µ\82¢\81H
+                                       tmp_i |= (uint32)lowbit[j] << 8; // 2byte
+                                       tmp_i |= (uint32)highbit[j] << 16; // 3-4byte
 #ifndef LITTLE_ENDIAN
-                               XCHG_LONG(tmp_i)
+                                       XCHG_LONG(tmp_i)
 #endif
-                               tmp_data[j] = tmp_i;
-                   }
-                   safe_free(highbit);
-                   safe_free(lowbit);
+                                               tmp_data[j] = tmp_i;
+                               }
+                               safe_free(highbit);
+                               safe_free(lowbit);
 
-                       /* set a small blank loop at the tail for avoiding abnormal loop. */
-               //      tmp_data[frames] = tmp_data[frames + 1] = tmp_data[frames + 2] = 0;                     
-                       memset(&tmp_data[frames], 0, sizeof(int32) * 128);
+                               /* set a small blank loop at the tail for avoiding abnormal loop. */
+                       //      tmp_data[frames] = tmp_data[frames + 1] = tmp_data[frames + 2] = 0;                     
+                               memset(&tmp_data[frames], 0, sizeof(int32) * 128);
 
-                       if (antialiasing_allowed)
-                         antialiasing_int32((int32 *)sample->data, sample->data_length >> FRACTION_BITS, sample->sample_rate, play_mode->rate);
+                               if (antialiasing_allowed)
+                                       antialiasing_int32((int32 *)sample->data, sample->data_length >> FRACTION_BITS, sample->sample_rate, play_mode->rate);
 
-               }else
+                       }
+                       else
 #endif
-               {
-                   /* 16 bit */
-                       frames = divi_2(sp->len);
-                       sample->data = (sample_t *)safe_large_malloc(sizeof(sample_t) * (frames + 128));
-                       memset(sample->data, 0, sizeof(sample_t) * (frames + 128));
-                       sample->data_alloced = 1;
-                       sample->data_type = SAMPLE_TYPE_INT16;
+                       {
+                               /* 16 bit */
+                               frames = divi_2(sp->len);
+                               sample->data = (sample_t *)safe_large_malloc(sizeof(sample_t) * (frames + 128));
+                               memset(sample->data, 0, sizeof(sample_t) * (frames + 128));
+                               sample->data_alloced = 1;
+                               sample->data_type = SAMPLE_TYPE_INT16;
 
-                       tf_seek(tf, sp->start, SEEK_SET);
-                       tf_read(sample->data, sp->len, 1, tf);
+                               tf_seek(tf, sp->start, SEEK_SET);
+                               tf_read(sample->data, sp->len, 1, tf);
 
 #ifndef LITTLE_ENDIAN
-                       for (j = 0; j < frames; j++)
-                               sample->data[j] = (int16)(LE_SHORT(tmp_data[j]));
+                               for (j = 0; j < frames; j++)
+                                       sample->data[j] = (int16)(LE_SHORT(tmp_data[j]));
 #endif
-                       /* set a small blank loop at the tail for avoiding abnormal loop. */
-               //      sample->data[frames] = sample->data[frames + 1] = sample->data[frames + 2] = 0;
-                       memset(&sample->data[frames], 0, sizeof(sample_t) * 128);
+                               /* set a small blank loop at the tail for avoiding abnormal loop. */
+                       //      sample->data[frames] = sample->data[frames + 1] = sample->data[frames + 2] = 0;
+                               memset(&sample->data[frames], 0, sizeof(sample_t) * 128);
 
-                       if (antialiasing_allowed)
-                               antialiasing((int16 *)sample->data, sample->data_length >> FRACTION_BITS, sample->sample_rate, play_mode->rate);
+                               if (antialiasing_allowed)
+                                       antialiasing((int16 *)sample->data, sample->data_length >> FRACTION_BITS, sample->sample_rate, play_mode->rate);
+                       }
                }
+
+               //if (sample->loop_end > sample->data_length + 1)
+               //      sample->loop_end = sample->data_length + 1;
+               //if (sample->loop_start > sample->data_length)
+               //      sample->loop_start = sample->data_length;
+               //if (sample->loop_start < 0)
+               //      sample->loop_start = 0;
+               //if (sample->loop_start >= sample->loop_end)
+               //{
+               //      sample->loop_start = sample->data_length;
+               //      sample->loop_end = sample->data_length + 1;
+               //}
+
 ///r
                /* resample it if possible */
                if (opt_pre_resamplation && sample->note_to_use && !(sample->modes & MODES_LOOPING))
index 1ef33a2..9ca901c 100644 (file)
@@ -37,6 +37,9 @@
 #ifdef VORBIS_DLL_INCLUDE_VORBISENC
 #include <vorbis/vorbisenc.h>
 #endif
+#ifdef VORBIS_DLL_INCLUDE_VORBISFILE
+#include <vorbis/vorbisfile.h>
+#endif
 
 extern int load_vorbis_dll(void);
 extern void free_vorbis_dll(void);
@@ -74,6 +77,16 @@ typedef int(*type_vorbis_encode_init_vbr)(vorbis_info *vi, long channels, long r
 typedef int(*type_vorbis_encode_ctl)(vorbis_info *vi, int number, void *arg);
 #endif
 
+#ifdef VORBIS_DLL_INCLUDE_VORBISFILE
+typedef int (*type_ov_clear)(OggVorbis_File *vf);
+typedef int (*type_ov_open_callbacks)(void *datasource, OggVorbis_File *vf,
+       const char *initial, long ibytes, ov_callbacks callbacks);
+typedef ogg_int64_t(*type_ov_pcm_total)(OggVorbis_File *vf, int i);
+typedef vorbis_info *(*type_ov_info)(OggVorbis_File *vf, int link);
+typedef long (*type_ov_read)(OggVorbis_File *vf, char *buffer, int length,
+       int bigendianp, int word, int sgned, int *bitstream);
+#endif
+
 static struct vorbis_dll_ {
         type_vorbis_info_init vorbis_info_init;
         type_vorbis_info_clear vorbis_info_clear;
@@ -106,6 +119,13 @@ static struct vorbis_dll_ {
         type_vorbis_encode_init_vbr vorbis_encode_init_vbr;
         type_vorbis_encode_ctl vorbis_encode_ctl;
 #endif
+#ifdef VORBIS_DLL_INCLUDE_VORBISFILE
+        type_ov_clear ov_clear;
+        type_ov_open_callbacks ov_open_callbacks;
+        type_ov_pcm_total ov_pcm_total;
+        type_ov_info ov_info;
+        type_ov_read ov_read;
+#endif
 } vorbis_dll;
 
 static volatile HANDLE h_vorbis_dll = NULL;
@@ -125,67 +145,79 @@ int load_vorbis_dll(void)
                h_vorbis_dll = LoadLibrary(TEXT("vorbis.dll"));
                if (!h_vorbis_dll) h_vorbis_dll = LoadLibrary(TEXT("libvorbis.dll"));
                if (!h_vorbis_dll) return -1;
-       }
-       vorbis_dll.vorbis_info_init = (type_vorbis_info_init) GetProcAddress(h_vorbis_dll, "vorbis_info_init");
-       if (!vorbis_dll.vorbis_info_init) { free_vorbis_dll(); return -1; }
-       vorbis_dll.vorbis_info_clear = (type_vorbis_info_clear) GetProcAddress(h_vorbis_dll, "vorbis_info_clear");
-       if (!vorbis_dll.vorbis_info_clear) { free_vorbis_dll(); return -1; }
-       vorbis_dll.vorbis_comment_init = (type_vorbis_comment_init) GetProcAddress(h_vorbis_dll, "vorbis_comment_init");
-       if (!vorbis_dll.vorbis_comment_init) { free_vorbis_dll(); return -1; }
-       vorbis_dll.vorbis_comment_add = (type_vorbis_comment_add) GetProcAddress(h_vorbis_dll, "vorbis_comment_add");
-       if (!vorbis_dll.vorbis_comment_add) { free_vorbis_dll(); return -1; }
-       vorbis_dll.vorbis_comment_add_tag = (type_vorbis_comment_add_tag) GetProcAddress(h_vorbis_dll, "vorbis_comment_add_tag");
-       if (!vorbis_dll.vorbis_comment_add_tag) { free_vorbis_dll(); return -1; }
-//     vorbis_dll.vorbis_comment_query = (type_vorbis_comment_query) GetProcAddress(h_vorbis_dll, "vorbis_comment_query");
-//     if (!vorbis_dll.vorbis_comment_query) { free_vorbis_dll(); return -1; }
-//     vorbis_dll.vorbis_comment_query_count = (type_vorbis_comment_query_count) GetProcAddress(h_vorbis_dll, "vorbis_comment_query_count");
-//     if (!vorbis_dll.vorbis_comment_query_count) { free_vorbis_dll(); return -1; }
-       vorbis_dll.vorbis_comment_clear = (type_vorbis_comment_clear) GetProcAddress(h_vorbis_dll, "vorbis_comment_clear");
-       if (!vorbis_dll.vorbis_comment_clear) { free_vorbis_dll(); return -1; }
-       vorbis_dll.vorbis_block_init = (type_vorbis_block_init) GetProcAddress(h_vorbis_dll, "vorbis_block_init");
-       if (!vorbis_dll.vorbis_block_init) { free_vorbis_dll(); return -1; }
-       vorbis_dll.vorbis_block_clear = (type_vorbis_block_clear) GetProcAddress(h_vorbis_dll, "vorbis_block_clear");
-       if (!vorbis_dll.vorbis_block_clear) { free_vorbis_dll(); return -1; }
-       vorbis_dll.vorbis_dsp_clear = (type_vorbis_dsp_clear) GetProcAddress(h_vorbis_dll, "vorbis_dsp_clear");
-       if (!vorbis_dll.vorbis_dsp_clear) { free_vorbis_dll(); return -1; }
-       vorbis_dll.vorbis_analysis_init = (type_vorbis_analysis_init) GetProcAddress(h_vorbis_dll, "vorbis_analysis_init");
-       if (!vorbis_dll.vorbis_analysis_init) { free_vorbis_dll(); return -1; }
-////   vorbis_dll.vorbis_commentheader_out = (type_vorbis_commentheader_out) GetProcAddress(h_vorbis_dll, "vorbis_commentheader_out");
-////   if (!vorbis_dll.vorbis_commentheader_out) { free_vorbis_dll(); return -1; }
-       vorbis_dll.vorbis_analysis_headerout = (type_vorbis_analysis_headerout) GetProcAddress(h_vorbis_dll, "vorbis_analysis_headerout");
-       if (!vorbis_dll.vorbis_analysis_headerout) { free_vorbis_dll(); return -1; }
-       vorbis_dll.vorbis_analysis_buffer = (type_vorbis_analysis_buffer) GetProcAddress(h_vorbis_dll, "vorbis_analysis_buffer");
-       if (!vorbis_dll.vorbis_analysis_buffer) { free_vorbis_dll(); return -1; }
-       vorbis_dll.vorbis_analysis_wrote = (type_vorbis_analysis_wrote) GetProcAddress(h_vorbis_dll, "vorbis_analysis_wrote");
-       if (!vorbis_dll.vorbis_analysis_wrote) { free_vorbis_dll(); return -1; }
-       vorbis_dll.vorbis_analysis_blockout = (type_vorbis_analysis_blockout) GetProcAddress(h_vorbis_dll, "vorbis_analysis_blockout");
-       if (!vorbis_dll.vorbis_analysis_blockout) { free_vorbis_dll(); return -1; }
-       vorbis_dll.vorbis_analysis = (type_vorbis_analysis) GetProcAddress(h_vorbis_dll, "vorbis_analysis");
-       if (!vorbis_dll.vorbis_analysis) { free_vorbis_dll(); return -1; }
-       vorbis_dll.vorbis_bitrate_addblock = (type_vorbis_bitrate_addblock) GetProcAddress(h_vorbis_dll, "vorbis_bitrate_addblock");
-       if (!vorbis_dll.vorbis_bitrate_addblock) { free_vorbis_dll(); return -1; }
-       vorbis_dll.vorbis_bitrate_flushpacket = (type_vorbis_bitrate_flushpacket) GetProcAddress(h_vorbis_dll, "vorbis_bitrate_flushpacket");
-       if (!vorbis_dll.vorbis_bitrate_flushpacket) { free_vorbis_dll(); return -1; }
-//     vorbis_dll.vorbis_synthesis_headerin = (type_vorbis_synthesis_headerin) GetProcAddress(h_vorbis_dll, "vorbis_synthesis_headerin");
-//     if (!vorbis_dll.vorbis_synthesis_headerin) { free_vorbis_dll(); return -1; }
-//     vorbis_dll.vorbis_synthesis_init = (type_vorbis_synthesis_init) GetProcAddress(h_vorbis_dll, "vorbis_synthesis_init");
-//     if (!vorbis_dll.vorbis_synthesis_init) { free_vorbis_dll(); return -1; }
-//     vorbis_dll.vorbis_synthesis = (type_vorbis_synthesis) GetProcAddress(h_vorbis_dll, "vorbis_synthesis");
-//     if (!vorbis_dll.vorbis_synthesis) { free_vorbis_dll(); return -1; }
-//     vorbis_dll.vorbis_synthesis_blockin = (type_vorbis_synthesis_blockin) GetProcAddress(h_vorbis_dll, "vorbis_synthesis_blockin");
-//     if (!vorbis_dll.vorbis_synthesis_blockin) { free_vorbis_dll(); return -1; }
-//     vorbis_dll.vorbis_synthesis_pcmout = (type_vorbis_synthesis_pcmout) GetProcAddress(h_vorbis_dll, "vorbis_synthesis_pcmout");
-//     if (!vorbis_dll.vorbis_synthesis_pcmout) { free_vorbis_dll(); return -1; }
-//     vorbis_dll.vorbis_synthesis_read = (type_vorbis_synthesis_read) GetProcAddress(h_vorbis_dll, "vorbis_synthesis_read");
-//     if (!vorbis_dll.vorbis_synthesis_read) { free_vorbis_dll(); return -1; }
+        vorbis_dll.vorbis_info_init = (type_vorbis_info_init)GetProcAddress(h_vorbis_dll, "vorbis_info_init");
+        if (!vorbis_dll.vorbis_info_init) { free_vorbis_dll(); return -1; }
+        vorbis_dll.vorbis_info_clear = (type_vorbis_info_clear)GetProcAddress(h_vorbis_dll, "vorbis_info_clear");
+        if (!vorbis_dll.vorbis_info_clear) { free_vorbis_dll(); return -1; }
+        vorbis_dll.vorbis_comment_init = (type_vorbis_comment_init)GetProcAddress(h_vorbis_dll, "vorbis_comment_init");
+        if (!vorbis_dll.vorbis_comment_init) { free_vorbis_dll(); return -1; }
+        vorbis_dll.vorbis_comment_add = (type_vorbis_comment_add)GetProcAddress(h_vorbis_dll, "vorbis_comment_add");
+        if (!vorbis_dll.vorbis_comment_add) { free_vorbis_dll(); return -1; }
+        vorbis_dll.vorbis_comment_add_tag = (type_vorbis_comment_add_tag)GetProcAddress(h_vorbis_dll, "vorbis_comment_add_tag");
+        if (!vorbis_dll.vorbis_comment_add_tag) { free_vorbis_dll(); return -1; }
+        //     vorbis_dll.vorbis_comment_query = (type_vorbis_comment_query) GetProcAddress(h_vorbis_dll, "vorbis_comment_query");
+        //     if (!vorbis_dll.vorbis_comment_query) { free_vorbis_dll(); return -1; }
+        //     vorbis_dll.vorbis_comment_query_count = (type_vorbis_comment_query_count) GetProcAddress(h_vorbis_dll, "vorbis_comment_query_count");
+        //     if (!vorbis_dll.vorbis_comment_query_count) { free_vorbis_dll(); return -1; }
+        vorbis_dll.vorbis_comment_clear = (type_vorbis_comment_clear)GetProcAddress(h_vorbis_dll, "vorbis_comment_clear");
+        if (!vorbis_dll.vorbis_comment_clear) { free_vorbis_dll(); return -1; }
+        vorbis_dll.vorbis_block_init = (type_vorbis_block_init)GetProcAddress(h_vorbis_dll, "vorbis_block_init");
+        if (!vorbis_dll.vorbis_block_init) { free_vorbis_dll(); return -1; }
+        vorbis_dll.vorbis_block_clear = (type_vorbis_block_clear)GetProcAddress(h_vorbis_dll, "vorbis_block_clear");
+        if (!vorbis_dll.vorbis_block_clear) { free_vorbis_dll(); return -1; }
+        vorbis_dll.vorbis_dsp_clear = (type_vorbis_dsp_clear)GetProcAddress(h_vorbis_dll, "vorbis_dsp_clear");
+        if (!vorbis_dll.vorbis_dsp_clear) { free_vorbis_dll(); return -1; }
+        vorbis_dll.vorbis_analysis_init = (type_vorbis_analysis_init)GetProcAddress(h_vorbis_dll, "vorbis_analysis_init");
+        if (!vorbis_dll.vorbis_analysis_init) { free_vorbis_dll(); return -1; }
+        ////   vorbis_dll.vorbis_commentheader_out = (type_vorbis_commentheader_out) GetProcAddress(h_vorbis_dll, "vorbis_commentheader_out");
+        ////   if (!vorbis_dll.vorbis_commentheader_out) { free_vorbis_dll(); return -1; }
+        vorbis_dll.vorbis_analysis_headerout = (type_vorbis_analysis_headerout)GetProcAddress(h_vorbis_dll, "vorbis_analysis_headerout");
+        if (!vorbis_dll.vorbis_analysis_headerout) { free_vorbis_dll(); return -1; }
+        vorbis_dll.vorbis_analysis_buffer = (type_vorbis_analysis_buffer)GetProcAddress(h_vorbis_dll, "vorbis_analysis_buffer");
+        if (!vorbis_dll.vorbis_analysis_buffer) { free_vorbis_dll(); return -1; }
+        vorbis_dll.vorbis_analysis_wrote = (type_vorbis_analysis_wrote)GetProcAddress(h_vorbis_dll, "vorbis_analysis_wrote");
+        if (!vorbis_dll.vorbis_analysis_wrote) { free_vorbis_dll(); return -1; }
+        vorbis_dll.vorbis_analysis_blockout = (type_vorbis_analysis_blockout)GetProcAddress(h_vorbis_dll, "vorbis_analysis_blockout");
+        if (!vorbis_dll.vorbis_analysis_blockout) { free_vorbis_dll(); return -1; }
+        vorbis_dll.vorbis_analysis = (type_vorbis_analysis)GetProcAddress(h_vorbis_dll, "vorbis_analysis");
+        if (!vorbis_dll.vorbis_analysis) { free_vorbis_dll(); return -1; }
+        vorbis_dll.vorbis_bitrate_addblock = (type_vorbis_bitrate_addblock)GetProcAddress(h_vorbis_dll, "vorbis_bitrate_addblock");
+        if (!vorbis_dll.vorbis_bitrate_addblock) { free_vorbis_dll(); return -1; }
+        vorbis_dll.vorbis_bitrate_flushpacket = (type_vorbis_bitrate_flushpacket)GetProcAddress(h_vorbis_dll, "vorbis_bitrate_flushpacket");
+        if (!vorbis_dll.vorbis_bitrate_flushpacket) { free_vorbis_dll(); return -1; }
+        //     vorbis_dll.vorbis_synthesis_headerin = (type_vorbis_synthesis_headerin) GetProcAddress(h_vorbis_dll, "vorbis_synthesis_headerin");
+        //     if (!vorbis_dll.vorbis_synthesis_headerin) { free_vorbis_dll(); return -1; }
+        //     vorbis_dll.vorbis_synthesis_init = (type_vorbis_synthesis_init) GetProcAddress(h_vorbis_dll, "vorbis_synthesis_init");
+        //     if (!vorbis_dll.vorbis_synthesis_init) { free_vorbis_dll(); return -1; }
+        //     vorbis_dll.vorbis_synthesis = (type_vorbis_synthesis) GetProcAddress(h_vorbis_dll, "vorbis_synthesis");
+        //     if (!vorbis_dll.vorbis_synthesis) { free_vorbis_dll(); return -1; }
+        //     vorbis_dll.vorbis_synthesis_blockin = (type_vorbis_synthesis_blockin) GetProcAddress(h_vorbis_dll, "vorbis_synthesis_blockin");
+        //     if (!vorbis_dll.vorbis_synthesis_blockin) { free_vorbis_dll(); return -1; }
+        //     vorbis_dll.vorbis_synthesis_pcmout = (type_vorbis_synthesis_pcmout) GetProcAddress(h_vorbis_dll, "vorbis_synthesis_pcmout");
+        //     if (!vorbis_dll.vorbis_synthesis_pcmout) { free_vorbis_dll(); return -1; }
+        //     vorbis_dll.vorbis_synthesis_read = (type_vorbis_synthesis_read) GetProcAddress(h_vorbis_dll, "vorbis_synthesis_read");
+        //     if (!vorbis_dll.vorbis_synthesis_read) { free_vorbis_dll(); return -1; }
 #ifdef VORBIS_DLL_INCLUDE_VORBISENC
-       vorbis_dll.vorbis_encode_init = (type_vorbis_encode_init) GetProcAddress(h_vorbis_dll, "vorbis_encode_init");
-       if (!vorbis_dll.vorbis_encode_init) { free_vorbis_dll(); return -1; }
-       vorbis_dll.vorbis_encode_init_vbr = (type_vorbis_encode_init_vbr) GetProcAddress(h_vorbis_dll, "vorbis_encode_init_vbr");
-       if (!vorbis_dll.vorbis_encode_init_vbr) { free_vorbis_dll(); return -1; }
-       vorbis_dll.vorbis_encode_ctl = (type_vorbis_encode_ctl) GetProcAddress(h_vorbis_dll, "vorbis_encode_ctl");
-       if (!vorbis_dll.vorbis_encode_ctl) { free_vorbis_dll(); return -1; }
+        vorbis_dll.vorbis_encode_init = (type_vorbis_encode_init)GetProcAddress(h_vorbis_dll, "vorbis_encode_init");
+        if (!vorbis_dll.vorbis_encode_init) { free_vorbis_dll(); return -1; }
+        vorbis_dll.vorbis_encode_init_vbr = (type_vorbis_encode_init_vbr)GetProcAddress(h_vorbis_dll, "vorbis_encode_init_vbr");
+        if (!vorbis_dll.vorbis_encode_init_vbr) { free_vorbis_dll(); return -1; }
+        vorbis_dll.vorbis_encode_ctl = (type_vorbis_encode_ctl)GetProcAddress(h_vorbis_dll, "vorbis_encode_ctl");
+        if (!vorbis_dll.vorbis_encode_ctl) { free_vorbis_dll(); return -1; }
 #endif
+#ifdef VORBIS_DLL_INCLUDE_VORBISFILE
+        vorbis_dll.ov_clear = (type_ov_clear)GetProcAddress(h_vorbis_dll, "ov_clear");
+        if (!vorbis_dll.ov_clear) { free_vorbis_dll(); return -1; }
+        vorbis_dll.ov_open_callbacks = (type_ov_open_callbacks)GetProcAddress(h_vorbis_dll, "ov_open_callbacks");
+        if (!vorbis_dll.ov_open_callbacks) { free_vorbis_dll(); return -1; }
+        vorbis_dll.ov_pcm_total = (type_ov_pcm_total)GetProcAddress(h_vorbis_dll, "ov_pcm_total");
+        if (!vorbis_dll.ov_pcm_total) { free_vorbis_dll(); return -1; }
+        vorbis_dll.ov_info = (type_ov_info)GetProcAddress(h_vorbis_dll, "ov_info");
+        if (!vorbis_dll.ov_info) { free_vorbis_dll(); return -1; }
+        vorbis_dll.ov_read = (type_ov_read)GetProcAddress(h_vorbis_dll, "ov_read");
+        if (!vorbis_dll.ov_read) { free_vorbis_dll(); return -1; }
+#endif
+       }
        return 0;
 }
 
@@ -420,5 +452,56 @@ int vorbis_encode_ctl(vorbis_info *vi, int number, void *arg)
 }
 #endif
 
+#ifdef VORBIS_DLL_INCLUDE_VORBISFILE
+
+int ov_clear(OggVorbis_File *vf)
+{
+       if (h_vorbis_dll) {
+               return vorbis_dll.ov_clear(vf);
+       }
+
+       return -1;
+}
+
+int ov_open_callbacks(void *datasource, OggVorbis_File *vf,
+       const char *initial, long ibytes, ov_callbacks callbacks)
+{
+       if (h_vorbis_dll) {
+               return vorbis_dll.ov_open_callbacks(datasource, vf, initial, ibytes, callbacks);
+       }
+
+       return -1;
+}
+
+ogg_int64_t ov_pcm_total(OggVorbis_File *vf, int i)
+{
+       if (h_vorbis_dll) {
+               return vorbis_dll.ov_pcm_total(vf, i);
+       }
+
+       return -1;
+}
+
+vorbis_info *ov_info(OggVorbis_File *vf, int link)
+{
+       if (h_vorbis_dll) {
+               return vorbis_dll.ov_info(vf, link);
+       }
+
+       return NULL;
+}
+
+long ov_read(OggVorbis_File *vf, char *buffer, int length,
+       int bigendianp, int word, int sgned, int *bitstream)
+{
+       if (h_vorbis_dll) {
+               return vorbis_dll.ov_read(vf, buffer, length, bigendianp, word, sgned, bitstream);
+       }
+
+       return -1;
+}
+
+#endif
+
 /***************************************************************/
 #endif /* AU_VORBIS_DLL */
diff --git a/timidity/w32g_vorbisfile_dll.c b/timidity/w32g_vorbisfile_dll.c
new file mode 100644 (file)
index 0000000..b92a3d0
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+TiMidity++ -- MIDI to WAVE converter and player
+Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>
+Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
+
+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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/***************************************************************
+name: vorbisfile_dll  dll: vorbisfile.dll
+***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include "common.h"
+
+#ifndef VORBIS_DLL_INCLUDE_VORBISFILE
+
+#ifdef AU_VORBIS_DLL
+
+#include <windows.h>
+#include <vorbis/vorbisfile.h>
+
+extern int load_vorbisfile_dll(void);
+extern void free_vorbisfile_dll(void);
+
+typedef int (*type_ov_clear)(OggVorbis_File *vf);
+typedef int (*type_ov_open_callbacks)(void *datasource, OggVorbis_File *vf,
+       const char *initial, long ibytes, ov_callbacks callbacks);
+typedef ogg_int64_t(*type_ov_pcm_total)(OggVorbis_File *vf, int i);
+typedef vorbis_info *(*type_ov_info)(OggVorbis_File *vf, int link);
+typedef long (*type_ov_read)(OggVorbis_File *vf, char *buffer, int length,
+       int bigendianp, int word, int sgned, int *bitstream);
+
+static struct vorbisfile_dll_ {
+       type_ov_clear ov_clear;
+       type_ov_open_callbacks ov_open_callbacks;
+       type_ov_pcm_total ov_pcm_total;
+       type_ov_info ov_info;
+       type_ov_read ov_read;
+} vorbisfile_dll;
+
+static volatile HANDLE h_vorbisfile_dll = NULL;
+
+void free_vorbisfile_dll(void)
+{
+       if (h_vorbisfile_dll) {
+               FreeLibrary(h_vorbisfile_dll);
+               h_vorbisfile_dll = NULL;
+       }
+}
+
+int load_vorbisfile_dll(void)
+{
+       if (!h_vorbisfile_dll) {
+               w32_reset_dll_directory();
+               h_vorbisfile_dll = LoadLibrary(TEXT("vorbisfile.dll"));
+               if (!h_vorbisfile_dll) h_vorbisfile_dll = LoadLibrary(TEXT("libvorbisfile-2.dll"));
+               if (!h_vorbisfile_dll) h_vorbisfile_dll = LoadLibrary(TEXT("libvorbisfile.dll"));
+               if (!h_vorbisfile_dll) return -1;
+               vorbisfile_dll.ov_clear = (type_ov_clear)GetProcAddress(h_vorbisfile_dll, "ov_clear");
+               if (!vorbisfile_dll.ov_clear) { free_vorbisfile_dll(); return -1; }
+               vorbisfile_dll.ov_open_callbacks = (type_ov_open_callbacks)GetProcAddress(h_vorbisfile_dll, "ov_open_callbacks");
+               if (!vorbisfile_dll.ov_open_callbacks) { free_vorbisfile_dll(); return -1; }
+               vorbisfile_dll.ov_pcm_total = (type_ov_pcm_total) GetProcAddress(h_vorbisfile_dll, "ov_pcm_total");
+               if (!vorbisfile_dll.ov_pcm_total) { free_vorbisfile_dll(); return -1; }
+               vorbisfile_dll.ov_info = (type_ov_info)GetProcAddress(h_vorbisfile_dll, "ov_info");
+               if (!vorbisfile_dll.ov_info) { free_vorbisfile_dll(); return -1; }
+               vorbisfile_dll.ov_read = (type_ov_read)GetProcAddress(h_vorbisfile_dll, "ov_read");
+               if (!vorbisfile_dll.ov_read) { free_vorbisfile_dll(); return -1; }
+       }
+       return 0;
+}
+
+int ov_clear(OggVorbis_File *vf)
+{
+       if (h_vorbisfile_dll) {
+               return vorbisfile_dll.ov_clear(vf);
+       }
+
+       return -1;
+}
+
+int ov_open_callbacks(void *datasource, OggVorbis_File *vf,
+       const char *initial, long ibytes, ov_callbacks callbacks)
+{
+       if (h_vorbisfile_dll) {
+               return vorbisfile_dll.ov_open_callbacks(datasource, vf, initial, ibytes, callbacks);
+       }
+
+       return -1;
+}
+
+ogg_int64_t ov_pcm_total(OggVorbis_File *vf, int i)
+{
+       if (h_vorbisfile_dll) {
+               return vorbisfile_dll.ov_pcm_total(vf, i);
+       }
+
+       return -1;
+}
+
+vorbis_info *ov_info(OggVorbis_File *vf, int link)
+{
+       if (h_vorbisfile_dll) {
+               return vorbisfile_dll.ov_info(vf, link);
+       }
+
+       return NULL;
+}
+
+long ov_read(OggVorbis_File *vf, char *buffer, int length,
+       int bigendianp, int word, int sgned, int *bitstream)
+{
+       if (h_vorbisfile_dll) {
+               return vorbisfile_dll.ov_read(vf, buffer, length, bigendianp, word, sgned, bitstream);
+       }
+
+       return -1;
+}
+
+/***************************************************************/
+#endif /* AU_VORBIS_DLL */
+#endif /* ! VORBIS_DLL_INCLUDE_VORBISFILE */