changeset 835:d508c7c4bc69

Add libSIDPlay2-FP backend interface module.
author Matti Hamalainen <ccr@tnsp.org>
date Thu, 08 Nov 2012 20:47:49 +0200
parents a7ee5dc23e78
children ccfe44f567c0
files Makefile.am src/xmms-sid.c src/xs_config.h src/xs_sidplayfp.cpp src/xs_sidplayfp.h
diffstat 5 files changed, 426 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.am	Thu Nov 08 20:47:05 2012 +0200
+++ b/Makefile.am	Thu Nov 08 20:47:49 2012 +0200
@@ -118,6 +118,7 @@
 	src/xs_sidplay.h				\
 	src/xs_sidplay1.cpp	src/xs_sidplay1.h	\
 	src/xs_sidplay2.cpp	src/xs_sidplay2.h	\
+	src/xs_sidplayfp.cpp	src/xs_sidplayfp.h	\
 	src/xs_slsup.c		src/xs_slsup.h		\
 	src/xs_player.h		\
 	src/xmms-sid.c		src/xmms-sid.h
--- a/src/xmms-sid.c	Thu Nov 08 20:47:05 2012 +0200
+++ b/src/xmms-sid.c	Thu Nov 08 20:47:49 2012 +0200
@@ -44,10 +44,13 @@
 /* List of emulator engines
  */
 #ifdef HAVE_SIDPLAY1
-#include "xs_sidplay1.h"
+#  include "xs_sidplay1.h"
 #endif
 #ifdef HAVE_SIDPLAY2
-#include "xs_sidplay2.h"
+#  include "xs_sidplay2.h"
+#endif
+#ifdef HAVE_SIDPLAY2
+#  include "xs_sidplay2.h"
 #endif
 
 static XSEngine xs_enginelist[] =
@@ -74,6 +77,17 @@
         xs_sidplay2_flush
     },
 #endif
+#ifdef HAVE_SIDPLAY2_FP
+    {
+        XS_ENG_SIDPLAY2_FP,
+        xs_sidplayfp_probe,
+        xs_sidplayfp_init, xs_sidplayfp_close,
+        xs_sidplayfp_initsong, xs_sidplayfp_fillbuffer,
+        xs_sidplayfp_load, xs_sidplayfp_delete,
+        xs_sidplayfp_getinfo, xs_sidplayfp_updateinfo,
+        xs_sidplayfp_flush
+    },
+#endif
 };
 
 static const gint xs_nenginelist = sizeof(xs_enginelist) / sizeof(xs_enginelist[0]);
--- a/src/xs_config.h	Thu Nov 08 20:47:05 2012 +0200
+++ b/src/xs_config.h	Thu Nov 08 20:47:49 2012 +0200
@@ -13,7 +13,8 @@
  */
 enum XS_EMUENGINE {
     XS_ENG_SIDPLAY1 = 1,
-    XS_ENG_SIDPLAY2
+    XS_ENG_SIDPLAY2,
+    XS_ENG_SIDPLAY2_FP
 };
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/xs_sidplayfp.cpp	Thu Nov 08 20:47:49 2012 +0200
@@ -0,0 +1,382 @@
+/*
+   XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS)
+
+   libSIDPlay v2-FP support
+
+   Programmed and designed by Matti 'ccr' Hamalainen <ccr@tnsp.org>
+   (C) Copyright 1999-2012 Tecnic Software productions (TNSP)
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#include "xmms-sid.h"
+
+#ifdef HAVE_SIDPLAY2_FP
+
+#include <stdio.h>
+#include "xs_sidplay2.h"
+#include "xs_config.h"
+
+
+#ifdef HAVE_SIDPLAY2_FP_V1
+#  include <sidplayfp/SidTune.h>
+#  include <sidplayfp/sidplayfp.h>
+#  include <sidplayfp/event.h>
+#  include <sidplayfp/SidConfig.h>
+#  include <sidplayfp/SidTuneInfo.h>
+#else
+#  include <sidplayfp/sidplay2.h>
+#  include <sidplayfp/SidTuneMod.h>
+#  include <sidplayfp/event.h>
+#endif
+
+
+class XSSIDPlayFP {
+public:
+#ifdef HAVE_SIDPLAY2_FP_V1
+    sidplayfp emu;
+    SidConfig config;
+#else
+    sidplay2 emu;
+    sid2_config_t config;
+#endif
+    SidTune tune;
+
+    XSSIDPlayFP(void);
+    virtual ~XSSIDPlayFP(void);
+};
+
+
+#ifdef HAVE_RESID_BUILDER
+#  include <sidplayfp/builders/residfp.h>
+#  include <sidplayfp/builders/resid.h>
+#endif
+
+#ifdef HAVE_HARDSID_BUILDER
+#  include <sidplayfp/builders/hardsid.h>
+#endif
+
+
+XSSIDPlayFP::XSSIDPlayFP(void) : tune(0)
+{
+}
+
+
+XSSIDPlayFP::~XSSIDPlayFP(void)
+{
+    emu.load(NULL);
+}
+
+
+/* We need to 'export' all this pseudo-C++ crap */
+extern "C" {
+
+
+/* Return song information
+ */
+#define TFUNCTION              xs_sidplayfp_getinfo
+#define TFUNCTION2             xs_sidplayfp_updateinfo
+#define TENGINE                XSSIDPlayFP
+#define TTUNEINFO              SidTuneInfo
+#define TTUNE                  SidTune
+
+#ifdef HAVE_SIDPLAY2_FP_V1
+#define sid2_mono              SidConfig::MONO
+#define sid2_stereo            SidConfig::STEREO
+#define SID2_MOS8580           SidConfig::MOS8580
+#define SID2_MOS6581           SidConfig::MOS6581
+#define SID2_CLOCK_PAL         SidConfig::CLOCK_PAL
+#define SID2_CLOCK_NTSC        SidConfig::CLOCK_NTSC
+#define SIDTUNE_CLOCK_UNKNOWN  SidTuneInfo::CLOCK_UNKNOWN
+#define SIDTUNE_CLOCK_PAL      SidTuneInfo::CLOCK_PAL
+#define SIDTUNE_CLOCK_NTSC     SidTuneInfo::CLOCK_NTSC
+#define SIDTUNE_CLOCK_ANY      SidTuneInfo::CLOCK_ANY
+#define SIDTUNE_SPEED_VBI      SidTuneInfo::SPEED_VBI
+#define SIDTUNE_SPEED_CIA_1A   SidTuneInfo::SPEED_CIA_1A
+#endif
+
+#include "xs_sidplay.h"
+
+
+/* Check if we can play the given file
+ */
+gboolean xs_sidplayfp_probe(XSFile *f)
+{
+    gchar tmpBuf[5];
+    
+    if (!f) return FALSE;
+    
+    if (xs_fread(tmpBuf, sizeof(gchar), 4, f) != 4)
+        return FALSE;
+    
+    if (!strncmp(tmpBuf, "PSID", 4) || !strncmp(tmpBuf, "RSID", 4))
+        return TRUE;
+    else
+        return FALSE;
+}
+
+
+/* Initialize SIDPlay2
+ */
+gboolean xs_sidplayfp_init(XSEngineState * state)
+{
+    XSSIDPlayFP *engine;
+    assert(state);
+
+    /* Allocate internal structures */
+    engine = new XSSIDPlayFP();
+    state->internal = engine;
+    if (!engine)
+        return FALSE;
+
+    /* Get current configuration */
+    engine->config = engine->emu.config();
+
+    /* Configure channels and stuff */
+    engine->config.playback = (state->audioChannels == XS_CHN_MONO) ? sid2_mono : sid2_stereo;
+
+    /* Audio parameters sanity checking and setup */
+    state->audioBitsPerSample = XS_RES_16BIT;
+    engine->config.samplingMethod = SID2_RESAMPLE_INTERPOLATE;
+    engine->config.frequency = state->audioFrequency;
+
+    /* Initialize builder object */
+    XSDEBUG("init builder #%i, maxsids=%i\n", xs_cfg.sid2Builder, (engine->emu.info()).maxsids);
+
+    switch (xs_cfg.sid2Builder)
+    {
+#ifdef HAVE_RESID_BUILDER
+        case XS_BLD_RESID:
+            {
+                ReSIDBuilder *rs = new ReSIDBuilder("ReSID builder");
+#ifdef HAVE_SIDPLAY2_FP_V1
+                if (rs && rs->getStatus())
+                {
+                }
+#else
+                if (rs)
+                {
+                    engine->config.sidEmulation = rs;
+                    if (!*rs) return FALSE;
+                    rs->create((engine->emu.info()).maxsids);
+                    if (!*rs) return FALSE;
+                    rs->bias(0.0f);
+                }
+#endif // HAVE_SIDPLAY2_FP_V1
+            }
+            break;
+#endif // HAVE_RESID_BUILDER
+
+
+#ifdef HAVE_RESID_FP_BUILDER
+        case XS_BLD_RESID_FP:
+            {
+                ReSIDfpBuilder *rs = new ReSIDfpBuilder("ReSID builder FP!");
+                if (rs)
+                {
+                    engine->config.sidEmulation = rs;
+                    if (!*rs) return FALSE;
+                    rs->create((engine->emu.info()).maxsids);
+                    if (!*rs) return FALSE;
+
+                    rs->filter6581Curve(0.0);
+                    rs->filter8580Curve(0.0);
+                }
+            }
+            break;
+#endif
+
+#ifdef HAVE_HARDSID_BUILDER
+        case XS_BLD_HARDSID:
+            {
+                HardSIDBuilder *hs = new HardSIDBuilder("HardSID builder (FP)");
+                engine->config.sidEmulation = (sidbuilder *) hs;
+                if (hs)
+                {
+                    hs->create((engine->emu.info()).maxsids);
+                    if (!*hs)
+                    {
+                        xs_error("hardSID->create() failed.\n");
+                        return FALSE;
+                    }
+                }
+            }
+            break;
+#endif
+        
+        default:
+            xs_error("[SIDPlay2] Invalid or unsupported builder selected.\n");
+            break;
+    }
+
+    if (!engine->config.sidEmulation)
+    {
+        xs_error("[SIDPlay2] Could not initialize SIDBuilder object.\n");
+        return FALSE;
+    }
+
+    // Setup filter
+    engine->config.sidEmulation->filter(xs_cfg.emulateFilters);
+    if (!*(engine->config.sidEmulation))
+    {
+        xs_error("builder->filter(%d) failed.\n", xs_cfg.emulateFilters);
+        return FALSE;
+    }
+
+    XSDEBUG("%s\n", engine->config.sidEmulation->credits());
+
+    /* Clockspeed settings */
+    switch (xs_cfg.clockSpeed)
+    {
+        case XS_CLOCK_NTSC:
+            engine->config.clockDefault = SID2_CLOCK_NTSC;
+            break;
+
+        default:
+        case XS_CLOCK_PAL:
+            engine->config.clockDefault = SID2_CLOCK_PAL;
+            xs_cfg.clockSpeed = XS_CLOCK_PAL;
+            break;
+    }
+
+
+    /* Configure rest of the emulation */
+    engine->config.sidDefault  = xs_cfg.mos8580 ? SID2_MOS8580 : SID2_MOS6581;
+    engine->config.clockForced = xs_cfg.forceSpeed;
+
+#ifndef HAVE_SIDPLAY2_FP_V1
+    engine->config.sidSamples  = TRUE;
+    engine->config.sidModel    = xs_cfg.forceModel ? engine->config.sidDefault : SID2_MODEL_CORRECT;
+    engine->config.clockSpeed  = xs_cfg.forceSpeed ? engine->config.clockDefault : SID2_CLOCK_CORRECT;
+#endif
+    
+    return TRUE;
+}
+
+
+/* Close SIDPlay2 engine
+ */
+void xs_sidplayfp_close(XSEngineState * state)
+{
+    XSSIDPlayFP *engine = (XSSIDPlayFP *) state->internal;
+
+    xs_sidplayfp_delete(state);
+
+    if (engine)
+    {
+        delete engine;
+        engine = NULL;
+    }
+
+    state->internal = NULL;
+}
+
+
+/* Initialize current song and sub-tune
+ */
+gboolean xs_sidplayfp_initsong(XSEngineState * state)
+{
+    XSSIDPlayFP *engine = (XSSIDPlayFP *) state->internal;
+
+    if (!engine)
+        return FALSE;
+
+    if (!engine->tune.selectSong(state->currSong))
+    {
+        xs_error("[SIDPlay2] tune.selectSong() failed\n");
+        return FALSE;
+    }
+
+    if (engine->emu.load(&(engine->tune)) < 0)
+    {
+        xs_error("[SIDPlay2] emu.load() failed\n");
+        return FALSE;
+    }
+
+    if (engine->emu.config(engine->config) < 0)
+    {
+        xs_error("[SIDPlay2] Emulator engine configuration failed!\n");
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+
+/* Emulate and render audio data to given buffer
+ */
+guint xs_sidplayfp_fillbuffer(XSEngineState * state, gchar * audioBuffer, guint audioBufSize)
+{
+    XSSIDPlayFP *engine = (XSSIDPlayFP *) state->internal;
+
+    if (!engine)
+        return 0;
+
+#if 1
+    int nsamples = audioBufSize / sizeof(short);
+    return engine->emu.play((short *) audioBuffer, nsamples) * sizeof(short);
+#else
+    int nsamples = audioBufSize / sizeof(short);
+    fprintf(stderr, "%p, %d -> %d\n", audioBuffer, audioBufSize, nsamples);
+    return 0;
+#endif
+}
+
+
+/* Load a given SID-tune file
+ */
+gboolean xs_sidplayfp_load(XSEngineState * state, gchar * filename)
+{
+    XSSIDPlayFP *engine = (XSSIDPlayFP *) state->internal;
+
+    if (!engine || !filename)
+        return FALSE;
+    
+    engine->tune.load(filename);
+    if (!engine->tune)
+    {
+        xs_error("Could not load file '%s': %s\n",
+            filename, (engine->tune.getInfo()).statusString);
+        return FALSE;
+    }
+    
+    return TRUE;
+}
+
+
+/* Delete INTERNAL information
+ */
+void xs_sidplayfp_delete(XSEngineState * state)
+{
+    XSSIDPlayFP *engine = (XSSIDPlayFP *) state->internal;
+}
+
+
+/* Hardware backend flushing
+ */
+void xs_sidplayfp_flush(XSEngineState * state)
+{
+    XSSIDPlayFP *engine = (XSSIDPlayFP *) state->internal;
+
+#ifdef HAVE_HARDSID_BUILDER
+    if (xs_cfg.sid2Builder == XS_BLD_HARDSID)
+    {
+        ((HardSIDBuilder *) engine->config.sidEmulation)->flush();
+    }
+#endif
+}
+
+
+}    /* extern "C" */
+#endif    /* HAVE_SIDPLAY2_FP */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/xs_sidplayfp.h	Thu Nov 08 20:47:49 2012 +0200
@@ -0,0 +1,25 @@
+#ifndef XS_SIDPLAYFP_H
+#define XS_SIDPLAYFP_H
+
+#include "xs_player.h"
+#include "xs_support.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+gboolean    xs_sidplayfp_probe(XSFile *);
+void        xs_sidplayfp_close(XSEngineState *);
+gboolean    xs_sidplayfp_init(XSEngineState *);
+gboolean    xs_sidplayfp_initsong(XSEngineState *);
+guint       xs_sidplayfp_fillbuffer(XSEngineState *, gchar *, guint);
+gboolean    xs_sidplayfp_load(XSEngineState *, gchar *);
+void        xs_sidplayfp_delete(XSEngineState *);
+XSTuneInfo* xs_sidplayfp_getinfo(const gchar *);
+gboolean    xs_sidplayfp_updateinfo(XSEngineState *);
+void        xs_sidplayfp_flush(XSEngineState *);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* XS_SIDPLAYFP_H */