Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package libsidplayfp for openSUSE:Factory 
checked in at 2024-11-05 15:42:28
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libsidplayfp (Old)
 and      /work/SRC/openSUSE:Factory/.libsidplayfp.new.2020 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "libsidplayfp"

Tue Nov  5 15:42:28 2024 rev:17 rq:1221439 version:2.11.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/libsidplayfp/libsidplayfp.changes        
2024-10-21 16:26:09.748854615 +0200
+++ /work/SRC/openSUSE:Factory/.libsidplayfp.new.2020/libsidplayfp.changes      
2024-11-05 15:42:47.850541866 +0100
@@ -1,0 +2,9 @@
+Sun Nov  3 19:36:00 UTC 2024 - Martin Hauke <[email protected]>
+
+- Update to version 2.11.0
+  * Removed buffer size limit from mixer.
+  * residfp: avoid quantization noise.
+  * residfp: implemented 6581 DC drift.
+  * residfp: properly adjusted 8580 Vref value.
+
+-------------------------------------------------------------------

Old:
----
  libsidplayfp-2.10.1.tar.gz

New:
----
  libsidplayfp-2.11.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ libsidplayfp.spec ++++++
--- /var/tmp/diff_new_pack.NDSKZW/_old  2024-11-05 15:42:48.286560132 +0100
+++ /var/tmp/diff_new_pack.NDSKZW/_new  2024-11-05 15:42:48.286560132 +0100
@@ -19,14 +19,14 @@
 %define soname 6
 %define stilview_soname 0
 Name:           libsidplayfp
-Version:        2.10.1
+Version:        2.11.0
 Release:        0
 Summary:        A library to play Commodore 64 music
 License:        GPL-2.0-or-later
 Group:          System/Libraries
 #Git-Clone:     https://github.com/libsidplayfp/libsidplayfp.git
 URL:            https://sourceforge.net/projects/sidplay-residfp/
-Source0:        
https://sourceforge.net/projects/sidplay-residfp/files/libsidplayfp/2.10/libsidplayfp-%{version}.tar.gz
+Source0:        
https://sourceforge.net/projects/sidplay-residfp/files/libsidplayfp/2.11/libsidplayfp-%{version}.tar.gz
 BuildRequires:  gcc-c++
 BuildRequires:  libgcrypt-devel
 BuildRequires:  pkgconfig

++++++ libsidplayfp-2.10.1.tar.gz -> libsidplayfp-2.11.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsidplayfp-2.10.1/NEWS new/libsidplayfp-2.11.0/NEWS
--- old/libsidplayfp-2.10.1/NEWS        2024-10-20 11:22:32.000000000 +0200
+++ new/libsidplayfp-2.11.0/NEWS        2024-11-03 14:31:28.000000000 +0100
@@ -1,3 +1,11 @@
+2.11.0 2024-11-03
+* Remove buffer size limit from mixer (fixes #159)
+* residfp: avoid quantization noise (#156)
+* residfp: implemented 6581 DC drift (#155)
+* residfp: properly adjusted 8580 Vref value
+
+
+
 2.10.1 2024-10-20
 * residfp: fix digiboost (#157)
 * residfp: fix combined waveforms (#160)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsidplayfp-2.10.1/README 
new/libsidplayfp-2.11.0/README
--- old/libsidplayfp-2.10.1/README      2024-10-20 11:22:32.000000000 +0200
+++ new/libsidplayfp-2.11.0/README      2024-11-03 14:31:28.000000000 +0100
@@ -45,7 +45,7 @@
 
 This package uses autotools so the usual ./configure && make is enough to build
 the libraries. If cloning the bare sources the package need to be bootstrapped
-in advance with the autoreconf -i command. This step requires the xa 
cross-assembler
+in advance with the autoreconf -vfi command. This step requires the xa 
cross-assembler
 to compile the 6502 code, usually provided by distributions with the xa65 
package
 or available at http://www.floodgap.com/retrotech/xa/.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsidplayfp-2.10.1/configure 
new/libsidplayfp-2.11.0/configure
--- old/libsidplayfp-2.10.1/configure   2024-10-20 11:22:39.000000000 +0200
+++ new/libsidplayfp-2.11.0/configure   2024-11-03 14:31:34.000000000 +0100
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.71 for libsidplayfp 2.10.1.
+# Generated by GNU Autoconf 2.71 for libsidplayfp 2.11.0.
 #
 #
 # Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,
@@ -618,8 +618,8 @@
 # Identity of this package.
 PACKAGE_NAME='libsidplayfp'
 PACKAGE_TARNAME='libsidplayfp'
-PACKAGE_VERSION='2.10.1'
-PACKAGE_STRING='libsidplayfp 2.10.1'
+PACKAGE_VERSION='2.11.0'
+PACKAGE_STRING='libsidplayfp 2.11.0'
 PACKAGE_BUGREPORT=''
 PACKAGE_URL='https://github.com/libsidplayfp/libsidplayfp/'
 
@@ -1436,7 +1436,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures libsidplayfp 2.10.1 to adapt to many kinds of systems.
+\`configure' configures libsidplayfp 2.11.0 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1507,7 +1507,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of libsidplayfp 2.10.1:";;
+     short | recursive ) echo "Configuration of libsidplayfp 2.11.0:";;
    esac
   cat <<\_ACEOF
 
@@ -1652,7 +1652,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-libsidplayfp configure 2.10.1
+libsidplayfp configure 2.11.0
 generated by GNU Autoconf 2.71
 
 Copyright (C) 2021 Free Software Foundation, Inc.
@@ -2411,7 +2411,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by libsidplayfp $as_me 2.10.1, which was
+It was created by libsidplayfp $as_me 2.11.0, which was
 generated by GNU Autoconf 2.71.  Invocation command line was
 
   $ $0$ac_configure_args_raw
@@ -3901,7 +3901,7 @@
 
 # Define the identity of the package.
  PACKAGE='libsidplayfp'
- VERSION='2.10.1'
+ VERSION='2.11.0'
 
 
 printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
@@ -4006,8 +4006,8 @@
 
 
 LIB_MAJOR=2
-LIB_MINOR=10
-LIB_LEVEL=1
+LIB_MINOR=11
+LIB_LEVEL=0
 
 
 
@@ -20740,7 +20740,7 @@
 # Increase the age value only if the changes made to the ABI are backward 
compatible.
 
 LIBSIDPLAYCUR=11
-LIBSIDPLAYREV=35
+LIBSIDPLAYREV=36
 LIBSIDPLAYAGE=5
 LIBSIDPLAYVERSION=$LIBSIDPLAYCUR:$LIBSIDPLAYREV:$LIBSIDPLAYAGE
 
@@ -23245,7 +23245,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by libsidplayfp $as_me 2.10.1, which was
+This file was extended by libsidplayfp $as_me 2.11.0, which was
 generated by GNU Autoconf 2.71.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -23314,7 +23314,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config='$ac_cs_config_escaped'
 ac_cs_version="\\
-libsidplayfp config.status 2.10.1
+libsidplayfp config.status 2.11.0
 configured by $0, generated by GNU Autoconf 2.71,
   with options \\"\$ac_cs_config\\"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsidplayfp-2.10.1/configure.ac 
new/libsidplayfp-2.11.0/configure.ac
--- old/libsidplayfp-2.10.1/configure.ac        2024-10-20 11:22:32.000000000 
+0200
+++ new/libsidplayfp-2.11.0/configure.ac        2024-11-03 14:31:28.000000000 
+0100
@@ -1,6 +1,6 @@
 m4_define([lib_major], [2])
-m4_define([lib_minor], [10])
-m4_define([lib_level], [1])
+m4_define([lib_minor], [11])
+m4_define([lib_level], [0])
 m4_define([lib_version], [lib_major.lib_minor.lib_level])
 
 AC_PREREQ([2.62])
@@ -102,7 +102,7 @@
 # Increase the age value only if the changes made to the ABI are backward 
compatible.
 
 LIBSIDPLAYCUR=11
-LIBSIDPLAYREV=35
+LIBSIDPLAYREV=36
 LIBSIDPLAYAGE=5
 LIBSIDPLAYVERSION=$LIBSIDPLAYCUR:$LIBSIDPLAYREV:$LIBSIDPLAYAGE
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libsidplayfp-2.10.1/src/builders/resid-builder/resid-emu.cpp 
new/libsidplayfp-2.11.0/src/builders/resid-builder/resid-emu.cpp
--- old/libsidplayfp-2.10.1/src/builders/resid-builder/resid-emu.cpp    
2024-10-20 11:22:32.000000000 +0200
+++ new/libsidplayfp-2.11.0/src/builders/resid-builder/resid-emu.cpp    
2024-11-03 14:31:28.000000000 +0100
@@ -96,6 +96,8 @@
     reSID::cycle_count cycles = eventScheduler->getTime(EVENT_CLOCK_PHI1) - 
m_accessClk;
     m_accessClk += cycles;
     m_bufferpos += m_sid.clock(cycles, (short *) m_buffer + m_bufferpos, 
OUTPUTBUFFERSIZE - m_bufferpos, 1);
+    // Adjust in case not all cycles have been consumed
+    m_accessClk -= cycles;
 }
 
 void ReSID::filter(bool enable)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/Filter.h 
new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/Filter.h
--- old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/Filter.h       
2024-10-20 11:22:32.000000000 +0200
+++ new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/Filter.h       
2024-11-03 14:31:28.000000000 +0100
@@ -135,7 +135,7 @@
      * @param v3 voice 3 in
      * @return filtered output
      */
-    virtual unsigned short clock(float v1, float v2, float v3) = 0;
+    virtual unsigned short clock(int v1, int v2, int v3) = 0;
 
     /**
      * Enable filter.
@@ -182,7 +182,9 @@
      *
      * @param input a signed 16 bit sample
      */
-    void input(short input) { Ve = fmc.getNormalizedVoice(input/32768.f); }
+    void input(short input) { Ve = fmc.getNormalizedVoice(input/32768.f, 0); }
+
+    inline int getNormalizedVoice(float value, unsigned int env) const { 
return fmc.getNormalizedVoice(value, env); }
 };
 
 } // namespace reSIDfp
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/Filter6581.cpp 
new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/Filter6581.cpp
--- old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/Filter6581.cpp 
2024-10-20 11:22:32.000000000 +0200
+++ new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/Filter6581.cpp 
2024-11-03 14:31:28.000000000 +0100
@@ -27,12 +27,12 @@
 namespace reSIDfp
 {
 
-unsigned short Filter6581::clock(float voice1, float voice2, float voice3)
+unsigned short Filter6581::clock(int voice1, int voice2, int voice3)
 {
-    const int V1 = fmc.getNormalizedVoice(voice1);
-    const int V2 = fmc.getNormalizedVoice(voice2);
+    const int V1 = voice1;
+    const int V2 = voice2;
     // Voice 3 is silenced by voice3off if it is not routed through the filter.
-    const int V3 = (filt3 || !voice3off) ? fmc.getNormalizedVoice(voice3) : 0;
+    const int V3 = (filt3 || !voice3off) ? voice3 : 0;
 
     int Vsum = 0;
     int Vmix = 0;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/Filter6581.h 
new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/Filter6581.h
--- old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/Filter6581.h   
2024-10-20 11:22:32.000000000 +0200
+++ new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/Filter6581.h   
2024-11-03 14:31:28.000000000 +0100
@@ -344,7 +344,7 @@
 
     ~Filter6581() override;
 
-    unsigned short clock(float v1, float v2, float v3) override;
+    unsigned short clock(int v1, int v2, int v3) override;
 
     /**
      * Set filter curve type based on single parameter.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/Filter8580.cpp 
new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/Filter8580.cpp
--- old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/Filter8580.cpp 
2024-10-20 11:22:32.000000000 +0200
+++ new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/Filter8580.cpp 
2024-11-03 14:31:28.000000000 +0100
@@ -27,12 +27,12 @@
 namespace reSIDfp
 {
 
-unsigned short Filter8580::clock(float voice1, float voice2, float voice3)
+unsigned short Filter8580::clock(int voice1, int voice2, int voice3)
 {
-    const int V1 = fmc.getNormalizedVoice(voice1);
-    const int V2 = fmc.getNormalizedVoice(voice2);
+    const int V1 = voice1;
+    const int V2 = voice2;
     // Voice 3 is silenced by voice3off if it is not routed through the filter.
-    const int V3 = (filt3 || !voice3off) ? fmc.getNormalizedVoice(voice3) : 0;
+    const int V3 = (filt3 || !voice3off) ? voice3 : 0;
 
     int Vsum = 0;
     int Vmix = 0;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/Filter8580.h 
new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/Filter8580.h
--- old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/Filter8580.h   
2024-10-20 11:22:32.000000000 +0200
+++ new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/Filter8580.h   
2024-11-03 14:31:28.000000000 +0100
@@ -302,7 +302,7 @@
 
     ~Filter8580() override;
 
-    unsigned short clock(float v1, float v2, float v3) override;
+    unsigned short clock(int v1, int v2, int v3) override;
 
     /**
      * Set filter curve type based on single parameter.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/FilterModelConfig.cpp
 
new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/FilterModelConfig.cpp
--- 
old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/FilterModelConfig.cpp
  2024-10-20 11:22:32.000000000 +0200
+++ 
new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/FilterModelConfig.cpp
  2024-11-03 14:31:28.000000000 +0100
@@ -29,7 +29,6 @@
 
 FilterModelConfig::FilterModelConfig(
     double vvr,
-    double vdv,
     double c,
     double vdd,
     double vth,
@@ -46,8 +45,7 @@
     denorm(vmax - vmin),
     norm(1.0 / denorm),
     N16(norm * ((1 << 16) - 1)),
-    voice_voltage_range(vvr),
-    voice_DC_voltage(vdv)
+    voice_voltage_range(vvr)
 {
     setUCox(ucox);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/FilterModelConfig.h
 
new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/FilterModelConfig.h
--- 
old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/FilterModelConfig.h
    2024-10-20 11:22:32.000000000 +0200
+++ 
new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/FilterModelConfig.h
    2024-11-03 14:31:28.000000000 +0100
@@ -24,6 +24,7 @@
 #define FILTERMODELCONFIG_H
 
 #include <algorithm>
+#include <random>
 #include <cassert>
 
 #include "OpAmp.h"
@@ -36,6 +37,33 @@
 
 class FilterModelConfig
 {
+private:
+    /*
+     * Hack to add quick dither when converting values from float to int
+     * and avoid quantization noise.
+     * Hopefully this can be removed the day we move all the analog part
+     * processing to floats.
+     *
+     * Not sure about the effect of using such small buffer of numbers
+     * since the random sequence repeats every 1024 values but for
+     * now it seems to do the job.
+     */
+    class Randomnoise
+    {
+    private:
+        double buffer[1024];
+        mutable int index = 0;
+    public:
+        Randomnoise()
+        {
+            std::uniform_real_distribution<double> unif(0., 1.);
+            std::default_random_engine re;
+            for (int i=0; i<1024; i++)
+                buffer[i] = unif(re);
+        }
+        double getNoise() const { index = (index + 1) & 0x3ff; return 
buffer[index]; }
+    };
+
 protected:
     /// Capacitor value.
     const double C;
@@ -59,7 +87,6 @@
     const double N16;
 
     const double voice_voltage_range;
-    const double voice_DC_voltage;
 
     /// Current factor coefficient for op-amp integrators.
     double currFactorCoeff;
@@ -76,18 +103,20 @@
     unsigned short opamp_rev[1 << 16]; //-V730_NOINIT this is initialized in 
the derived class constructor
 
 private:
+    Randomnoise rnd;
+
+private:
     FilterModelConfig(const FilterModelConfig&) = delete;
     FilterModelConfig& operator= (const FilterModelConfig&) = delete;
 
-    inline double getVoiceVoltage(float value) const
+    inline double getVoiceVoltage(float value, unsigned int env) const
     {
-        return value * voice_voltage_range + voice_DC_voltage;
+        return value * voice_voltage_range + getVoiceDC(env);
     }
 
 protected:
     /**
      * @param vvr voice voltage range
-     * @param vdv voice DC voltage
      * @param c   capacitor value
      * @param vdd Vdd supply voltage
      * @param vth threshold voltage
@@ -97,7 +126,6 @@
      */
     FilterModelConfig(
         double vvr,
-        double vdv,
         double c,
         double vdd,
         double vth,
@@ -110,6 +138,8 @@
 
     void setUCox(double new_uCox);
 
+    virtual double getVoiceDC(unsigned int env) const = 0;
+
     /**
      * The filter summer operates at n ~ 1, and has 5 fundamentally different
      * input configurations (2 - 6 input "resistors").
@@ -231,11 +261,12 @@
     inline double getVth() const { return Vth; }
 
     // helper functions
+
     inline unsigned short getNormalizedValue(double value) const
     {
         const double tmp = N16 * (value - vmin);
-        assert(tmp > -0.5 && tmp < 65535.5);
-        return static_cast<unsigned short>(tmp + 0.5);
+        assert(tmp >= 0. && tmp <= 65535.);
+        return static_cast<unsigned short>(tmp + rnd.getNoise());
     }
 
     inline unsigned short getNormalizedCurrentFactor(double wl) const
@@ -252,9 +283,9 @@
         return static_cast<unsigned short>(tmp + 0.5);
     }
 
-    inline int getNormalizedVoice(float value) const
+    inline int getNormalizedVoice(float value, unsigned int env) const
     {
-        return static_cast<int>(getNormalizedValue(getVoiceVoltage(value)));
+        return static_cast<int>(getNormalizedValue(getVoiceVoltage(value, 
env)));
     }
 };
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/FilterModelConfig6581.cpp
 
new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/FilterModelConfig6581.cpp
--- 
old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/FilterModelConfig6581.cpp
      2024-10-20 11:22:32.000000000 +0200
+++ 
new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/FilterModelConfig6581.cpp
      2024-11-03 14:31:28.000000000 +0100
@@ -117,12 +117,11 @@
 
 FilterModelConfig6581::FilterModelConfig6581() :
     FilterModelConfig(
-        1.5,     // voice voltage range
-        5.075,   // voice DC voltage
-        470e-12, // capacitor value
-        12.18,   // Vdd
-        1.31,    // Vth
-        20e-6,   // uCox
+        1.5,                    // voice voltage range FIXME should 
theoretically be ~3,571V
+        470e-12,                // capacitor value
+        12. * VOLTAGE_SKEW,     // Vdd
+        1.31,                   // Vth
+        20e-6,                  // uCox
         opamp_voltage,
         OPAMP_SIZE
     ),
@@ -134,6 +133,16 @@
 {
     dac.kinkedDac(MOS6581);
 
+    {
+        Dac envDac(8);
+        envDac.kinkedDac(MOS6581);
+        for(int i=0; i<256; i++)
+        {
+            const double envI = envDac.getOutput(i);
+            voiceDC[i] = 5. * VOLTAGE_SKEW + (0.2143 * envI);
+        }
+    }
+
     // Create lookup tables for gains / summers.
 
     //
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/FilterModelConfig6581.h
 
new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/FilterModelConfig6581.h
--- 
old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/FilterModelConfig6581.h
        2024-10-20 11:22:32.000000000 +0200
+++ 
new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/FilterModelConfig6581.h
        2024-11-03 14:31:28.000000000 +0100
@@ -42,13 +42,18 @@
 class FilterModelConfig6581 final : public FilterModelConfig
 {
 private:
-    static constexpr unsigned int DAC_BITS = 11;
-
-private:
     static std::unique_ptr<FilterModelConfig6581> instance;
     // This allows access to the private constructor
     friend std::unique_ptr<FilterModelConfig6581>::deleter_type;
 
+private:
+    static constexpr unsigned int DAC_BITS = 11;
+
+    /**
+     * Power bricks generate voltages slightly out of spec
+     */
+    static constexpr double VOLTAGE_SKEW = 1.015;
+
     /// Transistor parameters.
     //@{
     const double WL_vcr;        ///< W/L for VCR
@@ -70,12 +75,25 @@
     double vcr_n_Ids_term[1 << 16];
     //@}
 
+    // Voice DC offset LUT
+    double voiceDC[256];
+
 private:
     double getDacZero(double adjustment) const { return dac_zero + (1. - 
adjustment); }
 
     FilterModelConfig6581();
     ~FilterModelConfig6581() = default;
 
+protected:
+    /**
+     * On 6581 the DC offset varies between ~5.0V and ~5.214V depending on
+     * the envelope value.
+     */
+    double getVoiceDC(unsigned int env) const override
+    {
+        return voiceDC[env];
+    }
+
 public:
     static FilterModelConfig6581* getInstance();
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/FilterModelConfig8580.cpp
 
new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/FilterModelConfig8580.cpp
--- 
old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/FilterModelConfig8580.cpp
      2024-10-20 11:22:32.000000000 +0200
+++ 
new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/FilterModelConfig8580.cpp
      2024-11-03 14:31:28.000000000 +0100
@@ -130,12 +130,11 @@
 
 FilterModelConfig8580::FilterModelConfig8580() :
     FilterModelConfig(
-        0.24,   // voice voltage range FIXME measure
-        4.84,   // voice DC voltage FIXME measure
-        22e-9,  // capacitor value
-        9.09,   // Vdd
-        0.80,   // Vth
-        100e-6, // uCox
+        0.24,               // voice voltage range FIXME should theoretically 
be ~0,474V
+        22e-9,              // capacitor value
+        9. * VOLTAGE_SKEW,  // Vdd
+        0.80,               // Vth
+        100e-6,             // uCox
         opamp_voltage,
         OPAMP_SIZE
     )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/FilterModelConfig8580.h
 
new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/FilterModelConfig8580.h
--- 
old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/FilterModelConfig8580.h
        2024-10-20 11:22:32.000000000 +0200
+++ 
new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/FilterModelConfig8580.h
        2024-11-03 14:31:28.000000000 +0100
@@ -45,11 +45,27 @@
     friend std::unique_ptr<FilterModelConfig8580>::deleter_type;
 
 private:
+    /**
+     * Reference voltage generated from Vcc by a voltage divider
+     */
+    static constexpr double Vref = 4.75;
+
+    /**
+     * Power bricks generate voltages slightly out of spec
+     */
+    static constexpr double VOLTAGE_SKEW = 1.01;
+
+private:
     FilterModelConfig8580();
     ~FilterModelConfig8580() = default;
 
+protected:
+    double getVoiceDC(unsigned int) const override { return getVref(); }
+
 public:
     static FilterModelConfig8580* getInstance();
+
+    inline double getVref() const { return Vref * VOLTAGE_SKEW; }
 };
 
 } // namespace reSIDfp
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/Integrator8580.h 
new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/Integrator8580.h
--- 
old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/Integrator8580.h   
    2024-10-20 11:22:32.000000000 +0200
+++ 
new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/Integrator8580.h   
    2024-11-03 14:31:28.000000000 +0100
@@ -83,9 +83,9 @@
     void setV(double v)
     {
         // Gate voltage is controlled by the switched capacitor voltage divider
-        // Ua = Ue * v = 4.76v  1<v<2
+        // Ua = Ue * v = 4.75v  1<v<2
         assert(v > 1.0 && v < 2.0);
-        const double Vg = 4.76 * v;
+        const double Vg = fmc.getVref() * v;
         const double Vgt = Vg - fmc.getVth();
 
         // Vg - Vth, normalized so that translated values can be subtracted:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/SID.cpp 
new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/SID.cpp
--- old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/SID.cpp        
2024-10-20 11:22:32.000000000 +0200
+++ new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/SID.cpp        
2024-11-03 14:31:28.000000000 +0100
@@ -248,7 +248,8 @@
         Dac dacBuilder(OSC_DAC_BITS);
         dacBuilder.kinkedDac(model);
 
-        const double offset = dacBuilder.getOutput(is6581 ? OFFSET_6581 : 
OFFSET_8580);
+        //const double offset = dacBuilder.getOutput(is6581 ? OFFSET_6581 : 
OFFSET_8580);
+        const double offset = dacBuilder.getOutput(0x7ff);
 
         for (unsigned int i = 0; i < (1 << OSC_DAC_BITS); i++)
         {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/SID.h 
new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/SID.h
--- old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/SID.h  
2024-10-20 11:22:32.000000000 +0200
+++ new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/SID.h  
2024-11-03 14:31:28.000000000 +0100
@@ -328,9 +328,17 @@
 RESID_INLINE
 int SID::output()
 {
-    const float v1 = voice[0].output(voice[2].wave());
-    const float v2 = voice[1].output(voice[0].wave());
-    const float v3 = voice[2].output(voice[1].wave());
+    const float o1 = voice[0].output(voice[2].wave());
+    const float o2 = voice[1].output(voice[0].wave());
+    const float o3 = voice[2].output(voice[1].wave());
+
+    const unsigned int env1 = voice[0].envelope()->output();
+    const unsigned int env2 = voice[1].envelope()->output();
+    const unsigned int env3 = voice[2].envelope()->output();
+
+    const int v1 = filter->getNormalizedVoice(o1, env1);
+    const int v2 = filter->getNormalizedVoice(o2, env2);
+    const int v3 = filter->getNormalizedVoice(o3, env3);
 
     const int input = static_cast<int>(filter->clock(v1, v2, v3));
     return externalFilter.clock(input);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/WaveformCalculator.cpp
 
new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/WaveformCalculator.cpp
--- 
old/libsidplayfp-2.10.1/src/builders/residfp-builder/residfp/WaveformCalculator.cpp
 2024-10-20 11:22:32.000000000 +0200
+++ 
new/libsidplayfp-2.11.0/src/builders/residfp-builder/residfp/WaveformCalculator.cpp
 2024-11-03 14:31:28.000000000 +0100
@@ -89,26 +89,26 @@
 const CombinedWaveformConfig configAverage[2][5] =
 {
     { /* 6581 R3 0486S sampled by Trurl */
-        // TS  error  3555 (324/32768)
+        // TS  error  3555 (324/32768) [RMS: 73.98]
         { exponentialDistance,  0.877322257f, 1.11349654f, 0.f, 2.14537621f, 
9.08618164f },
-        // PT  error  4608 (128/32768)
-        { linearDistance, 0.940469623f, 1.f, 1.7949537f, 0.0329838842f, 
0.232237294f },
-        // PS  error 19352 (763/32768)
+        // PT  error  4590 (124/32768) [RMS: 68.90]
+        { linearDistance, 0.941692829f, 1.f, 1.80072665f, 0.033124879f, 
0.232303441f },
+        // PS  error 19352 (763/32768) [RMS: 96.91]
         { linearDistance, 1.66494179f, 1.03760982f, 5.62705326f, 0.291590303f, 
0.283631504f },
-        // PTS error  5068 ( 94/32768)
+        // PTS error  5068 ( 94/32768) [RMS: 41.69]
         { linearDistance, 1.09762526f, 0.975265801f, 1.52196741f, 
0.151528224f, 0.841949463f },
         // NP  guessed
         { exponentialDistance, 0.96f, 1.f, 2.5f, 1.1f, 1.2f },
     },
     { /* 8580 R5 1088 sampled by reFX-Mike */
-        // TS  error 10788 (354/32768)
+        // TS  error 10788 (354/32768) [RMS: 58.31]
         { exponentialDistance, 0.841851234f, 1.09233654f, 0.f, 1.85262764f, 
6.22224379f },
-        // PT  error 10635 (289/32768)
+        // PT  error 10635 (289/32768) [RMS: 108.81]
         { exponentialDistance, 0.929835618f, 1.f, 1.12836814f, 1.10453653f, 
1.48065746f },
-        // PS  error 12259 (555/32768)
-        { quadraticDistance, 0.911715686f, 0.995952725f, 1.22720313f, 
0.000117408723f, 0.189491063f },
-        // PTS error  7665 (126/32768)
-        { exponentialDistance, 0.863748789f, 0.980024457f, 0.8020401f, 
0.972693145f, 1.51878834f },
+        // PS  error 12255 (554/32768) [RMS: 102.27]
+        { quadraticDistance, 0.911938608f, 0.996440411f, 1.2278074f, 
0.000117214302f, 0.18948476f },
+        // PTS error  6995 (139/32768) [RMS: 55.78]
+        { exponentialDistance, 0.932317019f, 1.03892183f, 1.2068342f, 
0.891974986f, 1.42451835f },
         // NP  guessed
         { exponentialDistance, 0.95f, 1.f, 1.15f, 1.f, 1.45f },
     },
@@ -117,26 +117,26 @@
 const CombinedWaveformConfig configWeak[2][5] =
 {
     { /* 6581 R2 4383 sampled by ltx128 */
-        // TS  error 1858 (204/32768)
+        // TS  error 1858 (204/32768) [RMS: 62.49]
         { exponentialDistance, 0.886832297f, 1.f, 0.f, 2.14438701f, 
9.51839447f },
-        // PT  error  612 (102/32768)
+        // PT  error  612 (102/32768) [RMS: 43.71]
         { linearDistance, 1.01262534f, 1.f, 2.46070528f, 0.0537485816f, 
0.0986242667f },
-        // PS  error 8135 (575/32768)
+        // PS  error 8135 (575/32768) [RMS: 75.10]
         { linearDistance, 2.14896345f, 1.0216713f, 10.5400085f, 0.244498149f, 
0.126134038f },
-        // PTS error 2505 (63/32768)
+        // PTS error 2505 (63/32768) [RMS: 24.37]
         { linearDistance, 1.29061747f, 0.9754318f, 3.15377498f, 0.0968349651f, 
0.318573922f },
         // NP  guessed
         { exponentialDistance, 0.96f, 1.f, 2.5f, 1.1f, 1.2f },
     },
     { /* 8580 R5 4887 sampled by reFX-Mike */
-        // TS  error  745 (77/32768)
+        // TS  error  745 (77/32768) [RMS: 53.74]
         { exponentialDistance, 0.816124022f, 1.31208789f, 0.f, 1.92347884f, 
2.35027933f },
-        // PT  error 7289 (156/32768)
-        { exponentialDistance, 0.93188405f, 1.f, 1.01624966f, 1.06709433f, 
1.38722277f },
-        // PS  error 9997 (345/32768)
-        { quadraticDistance, 0.978222013f, 1.01747012f, 1.32468057f, 
0.00975347217f, 0.147304252f },
-        // PTS error 4843 (63/32768)
-        { exponentialDistance, 0.944473684f, 1.06448221f, 1.00853336f, 
0.980868518f, 1.4067347f },
+        // PT  error 7199 (192/32768) [RMS: 88.43]
+        { exponentialDistance, 0.917997837f, 1.f, 1.01248944f, 1.05761552f, 
1.37529826f },
+        // PS  error 9864 (333/32768) [RMS: 86.29]
+        { quadraticDistance, 0.970038712f, 1.00844693f, 1.30298805f, 
0.0097996993f, 0.146854922f },
+        // PTS error 4809 (60/32768) [RMS: 45.37]
+        { exponentialDistance, 0.941834152f, 1.06401193f, 0.991132736f, 
0.995310068f, 1.41105855f },
         // NP  guessed
         { exponentialDistance, 0.95f, 1.f, 1.15f, 1.f, 1.45f },
     },
@@ -145,26 +145,26 @@
 const CombinedWaveformConfig configStrong[2][5] =
 {
     { /* 6581 R2 0384 sampled by Trurl */
-        // TS  error 20337 (1579/32768)
+        // TS  error 20337 (1579/32768) [RMS: 88.57]
         { exponentialDistance, 0.000637792516f, 1.56725872f, 0.f, 
0.00036806846f, 1.51800942f },
-        // PT  error  5194 (240/32768)
+        // PT  error  5194 (240/32768) [RMS: 83.54]
         { linearDistance, 0.924824238f, 1.f, 1.96749473f, 0.0891806409f, 
0.234794483f },
-        // PS  error 31015 (2181/32768)
+        // PS  error 31015 (2181/32768) [RMS: 114.99]
         { linearDistance, 1.2328074f, 0.73079139f, 3.9719491f, 0.00156516861f, 
0.314677745f },
-        // PTS error  9874 (201/32768)
+        // PTS error  9874 (201/32768) [RMS: 52.30]
         { linearDistance, 1.08558261f, 0.857638359f, 1.52781796f, 
0.152927235f, 1.02657032f },
         // NP  guessed
         { exponentialDistance, 0.96f, 1.f, 2.5f, 1.1f, 1.2f },
     },
     { /* 8580 R5 1489 sampled by reFX-Mike */
-        // TS  error 4837 (388/32768)
+        // TS  error  4837 (388/32768) [RMS: 76.07]
         { exponentialDistance, 0.89762634f, 56.7594185f, 0.f, 7.68995237f, 
12.0754194f },
-        // PT  error 9298 (506/32768)
+        // PT  error  9298 (506/32768) [RMS: 128.15]
         { exponentialDistance,  0.867885351f, 1.f, 1.4511894f, 1.07057536f, 
1.43333757f },
-        // PS  error 13168 (718/32768)
+        // PS  error 13168 (718/32768) [RMS: 123.35]
         { quadraticDistance, 0.89255774f, 1.2253896f, 1.75615835f, 
0.0245045591f, 0.12982437f },
-        // PTS error 6879 (309/32768)
-        { linearDistance, 0.913530529f, 0.96415776f, 0.931084037f, 
1.05731869f, 1.80506349f },
+        // PTS error  6702 (300/32768) [RMS: 71.01]
+        { linearDistance, 0.91124934f, 0.963609755f, 0.909965038f, 
1.07445884f, 1.82399702f },
         // NP  guessed
         { exponentialDistance, 0.95f, 1.f, 1.15f, 1.f, 1.45f },
     },
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsidplayfp-2.10.1/src/c64/Banks/ExtraSidBank.h 
new/libsidplayfp-2.11.0/src/c64/Banks/ExtraSidBank.h
--- old/libsidplayfp-2.10.1/src/c64/Banks/ExtraSidBank.h        2024-10-20 
11:22:32.000000000 +0200
+++ new/libsidplayfp-2.11.0/src/c64/Banks/ExtraSidBank.h        2024-11-03 
14:31:28.000000000 +0100
@@ -23,7 +23,6 @@
 
 #include "Bank.h"
 #include <vector>
-#include <algorithm>
 
 #include "c64/c64sid.h"
 
@@ -65,7 +64,8 @@
 
     void reset()
     {
-        std::for_each(sids.begin(), sids.end(), [](sids_t::value_type &e) { 
e->reset(0xf); });
+        for (c64sid* sid: sids)
+            sid->reset(0xf);
     }
 
     void resetSIDMapper(Bank *bank)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsidplayfp-2.10.1/src/c64/Banks/IOBank.h 
new/libsidplayfp-2.11.0/src/c64/Banks/IOBank.h
--- old/libsidplayfp-2.10.1/src/c64/Banks/IOBank.h      2024-10-20 
11:22:32.000000000 +0200
+++ new/libsidplayfp-2.11.0/src/c64/Banks/IOBank.h      2024-11-03 
14:31:28.000000000 +0100
@@ -54,12 +54,12 @@
 
     uint8_t peek(uint_least16_t addr) override
     {
-        return map[addr >> 8 & 0xf]->peek(addr);
+        return map[(addr >> 8) & 0xf]->peek(addr);
     }
 
     void poke(uint_least16_t addr, uint8_t data) override
     {
-        map[addr >> 8 & 0xf]->poke(addr, data);
+        map[(addr >> 8) & 0xf]->poke(addr, data);
     }
 };
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsidplayfp-2.10.1/src/c64/Banks/SystemRAMBank.h 
new/libsidplayfp-2.11.0/src/c64/Banks/SystemRAMBank.h
--- old/libsidplayfp-2.10.1/src/c64/Banks/SystemRAMBank.h       2024-10-20 
11:22:32.000000000 +0200
+++ new/libsidplayfp-2.11.0/src/c64/Banks/SystemRAMBank.h       2024-11-03 
14:31:28.000000000 +0100
@@ -64,7 +64,7 @@
             byte = ~byte;
             for (int i = 0x02; i < 0x4000; i += 0x08)
             {
-                memset(ram+j+i, byte, 0x04);
+                std::memset(ram+j+i, byte, 0x04);
             }
         }
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsidplayfp-2.10.1/src/c64/c64.cpp 
new/libsidplayfp-2.11.0/src/c64/c64.cpp
--- old/libsidplayfp-2.10.1/src/c64/c64.cpp     2024-10-20 11:22:32.000000000 
+0200
+++ new/libsidplayfp-2.11.0/src/c64/c64.cpp     2024-11-03 14:31:28.000000000 
+0100
@@ -22,8 +22,6 @@
 
 #include "c64.h"
 
-#include <algorithm>
-
 #include "c64/CIA/mos652x.h"
 #include "c64/VIC_II/mos656x.h"
 
@@ -125,7 +123,8 @@
     colorRAMBank.reset();
     mmu.reset();
 
-    std::for_each(extraSidBanks.begin(), extraSidBanks.end(), 
[](sidBankMap_t::value_type &e) { e.second->reset(); });
+    for (auto sidBank: extraSidBanks)
+        sidBank.second->reset();
 
     irqCount = 0;
     oldBAState = true;
@@ -185,7 +184,9 @@
 
 c64::~c64()
 {
-    std::for_each(extraSidBanks.begin(), extraSidBanks.end(), 
[](sidBankMap_t::value_type &s) { delete s.second; });
+    for (auto sidBank: extraSidBanks)
+        delete sidBank.second;
+
     extraSidBanks.clear();
 }
 
@@ -195,7 +196,8 @@
 
     resetIoBank();
 
-    std::for_each(extraSidBanks.begin(), extraSidBanks.end(), 
[](sidBankMap_t::value_type &s) { delete s.second; });
+    for (auto sidBank: extraSidBanks)
+        delete sidBank.second;
 
     extraSidBanks.clear();
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsidplayfp-2.10.1/src/mixer.cpp 
new/libsidplayfp-2.11.0/src/mixer.cpp
--- old/libsidplayfp-2.10.1/src/mixer.cpp       2024-10-20 11:22:32.000000000 
+0200
+++ new/libsidplayfp-2.11.0/src/mixer.cpp       2024-11-03 14:31:28.000000000 
+0100
@@ -23,7 +23,7 @@
 #include "mixer.h"
 
 #include <cassert>
-#include <algorithm>
+#include <cstring>
 
 #include "sidemu.h"
 
@@ -33,17 +33,19 @@
 
 void Mixer::clockChips()
 {
-    std::for_each(m_chips.begin(), m_chips.end(), [](sidemu *s) { s->clock(); 
});
+    for (sidemu* chip: m_chips)
+        chip->clock();
 }
 
 void Mixer::resetBufs()
 {
-    std::for_each(m_chips.begin(), m_chips.end(), [](sidemu *s) { 
s->bufferpos(0); });
+    for (sidemu* chip: m_chips)
+        chip->bufferpos(0);
 }
 
 void Mixer::doMix()
 {
-    short *buf = m_sampleBuffer + m_sampleIndex;
+    short *outputBuffer = m_sampleBuffer + m_sampleIndex;
 
     // extract buffer info now that the SID is updated.
     // clock() may update bufferpos.
@@ -51,19 +53,12 @@
     const int sampleCount = m_chips.front()->bufferpos();
 
     int i = 0;
-    while (i < sampleCount)
+    while (
+        (i < sampleCount) &&
+        (m_sampleIndex < m_sampleCount) &&      // Handle whatever output the 
sid has generated so far
+        (i + m_fastForwardFactor < sampleCount) // Are there enough samples to 
generate the next one?
+    )
     {
-        // Handle whatever output the sid has generated so far
-        if (m_sampleIndex >= m_sampleCount)
-        {
-            break;
-        }
-        // Are there enough samples to generate the next one?
-        if (i + m_fastForwardFactor >= sampleCount)
-        {
-            break;
-        }
-
         // This is a crude boxcar low-pass filter to
         // reduce aliasing during fast forward.
         for (size_t k = 0; k < m_buffers.size(); k++)
@@ -86,21 +81,22 @@
         {
             const int_least32_t tmp = (this->*(m_scale[ch]))(ch);
             assert(tmp >= -32768 && tmp <= 32767);
-            *buf++ = static_cast<short>(tmp);
+            *outputBuffer++ = static_cast<short>(tmp);
             m_sampleIndex++;
         }
     }
 
     // move the unhandled data to start of buffer, if any.
     const int samplesLeft = sampleCount - i;
-    std::for_each(m_buffers.begin(), m_buffers.end(), [i, samplesLeft](short 
*dest) {
-        const short* src = dest + i;
-        for (int j = 0; j < samplesLeft; j++)
-        {
-            dest[j] = src[j];
-        }
-    });
-    std::for_each(m_chips.begin(), m_chips.end(), [samplesLeft](sidemu *s) { 
s->bufferpos(samplesLeft); });
+    assert(samplesLeft >= 0);
+
+    for (short* buffer: m_buffers)
+        std::memmove(buffer, buffer+i, samplesLeft*2);
+
+    for (sidemu* chip: m_chips)
+        chip->bufferpos(samplesLeft);
+
+    m_wait = static_cast<uint_least32_t>(samplesLeft) > m_sampleCount;
 }
 
 void Mixer::begin(short *buffer, uint_least32_t count)
@@ -111,12 +107,6 @@
     if (m_stereo && (count & 1))
         throw badBufferSize();
 
-    // TODO short buffers make the emulator crash, should investigate why
-    //      in the meantime set a reasonable lower bound of 5ms
-    const uint_least32_t lowerBound = m_sampleRate / (m_stereo ? 100 : 200);
-    if (count && (count < lowerBound))
-        throw badBufferSize();
-
     m_sampleIndex  = 0;
     m_sampleCount  = count;
     m_sampleBuffer = buffer;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsidplayfp-2.10.1/src/mixer.h 
new/libsidplayfp-2.11.0/src/mixer.h
--- old/libsidplayfp-2.10.1/src/mixer.h 2024-10-20 11:22:32.000000000 +0200
+++ new/libsidplayfp-2.11.0/src/mixer.h 2024-11-03 14:31:28.000000000 +0100
@@ -77,13 +77,13 @@
     static constexpr int_least32_t C2 = static_cast<int_least32_t>(SQRT_0_5 / 
(1.0 + SQRT_0_5) * SCALE_FACTOR);
 
 private:
-    typedef int_least32_t (Mixer::*mixer_func_t)() const;
+    using mixer_func_t = int_least32_t (Mixer::*)() const;
 
-    typedef int (Mixer::*scale_func_t)(unsigned int);
+    using scale_func_t = int (Mixer::*)(unsigned int);
 
 public:
     /// Maximum allowed volume, must be a power of 2.
-    static const int_least32_t VOLUME_MAX = 1024;
+    static constexpr int_least32_t VOLUME_MAX = 1024;
 
 private:
     std::vector<sidemu*> m_chips;
@@ -107,6 +107,8 @@
 
     bool m_stereo = false;
 
+    bool m_wait = false;
+
     randomLCG<VOLUME_MAX> m_rand;
 
 private:
@@ -258,12 +260,17 @@
     /**
      * Check if the buffer have been filled.
      */
-    bool notFinished() const { return m_sampleIndex != m_sampleCount; }
+    bool notFinished() const { return m_sampleIndex < m_sampleCount; }
 
     /**
      * Get the number of samples generated up to now.
      */
     uint_least32_t samplesGenerated() const { return m_sampleIndex; }
+
+    /*
+     * Wait till we consume the buffer.
+     */
+    bool wait() const { return m_wait; }
 };
 
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsidplayfp-2.10.1/src/player.cpp 
new/libsidplayfp-2.11.0/src/player.cpp
--- old/libsidplayfp-2.10.1/src/player.cpp      2024-10-20 11:22:32.000000000 
+0200
+++ new/libsidplayfp-2.11.0/src/player.cpp      2024-11-03 14:31:28.000000000 
+0100
@@ -210,6 +210,8 @@
 
 uint_least32_t Player::play(short *buffer, uint_least32_t count)
 {
+    static constexpr unsigned int CYCLES = 3000;
+
     // Make sure a tune is loaded
     if (m_tune == nullptr)
         return 0;
@@ -234,7 +236,8 @@
                     // Clock chips and mix into output buffer
                     while ((m_isPlaying != state_t::STOPPED) && 
m_mixer.notFinished())
                     {
-                        run(sidemu::OUTPUTBUFFERSIZE);
+                        if (!m_mixer.wait())
+                            run(CYCLES);
 
                         m_mixer.clockChips();
                         m_mixer.doMix();
@@ -247,7 +250,7 @@
                     int size = m_c64.getMainCpuSpeed() / m_cfg.frequency;
                     while ((m_isPlaying != state_t::STOPPED) && --size)
                     {
-                        run(sidemu::OUTPUTBUFFERSIZE);
+                        run(CYCLES);
 
                         m_mixer.clockChips();
                         m_mixer.resetBufs();
@@ -260,7 +263,7 @@
                 int size = m_c64.getMainCpuSpeed() / m_cfg.frequency;
                 while ((m_isPlaying != state_t::STOPPED) && --size)
                 {
-                    run(sidemu::OUTPUTBUFFERSIZE);
+                    run(CYCLES);
                 }
             }
         }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsidplayfp-2.10.1/src/sidemu.cpp 
new/libsidplayfp-2.11.0/src/sidemu.cpp
--- old/libsidplayfp-2.10.1/src/sidemu.cpp      2024-10-20 11:22:32.000000000 
+0200
+++ new/libsidplayfp-2.11.0/src/sidemu.cpp      2024-11-03 14:31:28.000000000 
+0100
@@ -34,6 +34,8 @@
     switch (addr)
     {
     case 0x04:
+        // Ignore writes to control register to mute voices
+        // Leave test/ring/sync bits untouched
         if (isMuted[0]) data &= 0x0e;
         break;
     case 0x0b:
@@ -43,9 +45,13 @@
         if (isMuted[2]) data &= 0x0e;
         break;
     case 0x17:
+        // Ignore writes to filter register to disable filter
         if (isFilterDisabled) data &= 0xf0;
         break;
     case 0x18:
+        // Ignore writes to volume register to mute samples
+        // Works only for volume-based digis
+        // Trick suggested by LMan
         if (isMuted[3]) data |= 0x0f;
         break;
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsidplayfp-2.10.1/src/sidplayfp/sidbuilder.cpp 
new/libsidplayfp-2.11.0/src/sidplayfp/sidbuilder.cpp
--- old/libsidplayfp-2.10.1/src/sidplayfp/sidbuilder.cpp        2024-10-20 
11:22:32.000000000 +0200
+++ new/libsidplayfp-2.11.0/src/sidplayfp/sidbuilder.cpp        2024-11-03 
14:31:28.000000000 +0100
@@ -22,8 +22,6 @@
 
 #include "sidbuilder.h"
 
-#include <algorithm>
-
 #include "sidemu.h"
 
 #include "sidcxx11.h"
@@ -32,7 +30,7 @@
 {
     m_status = true;
 
-    for (auto sidobj : sidobjs)
+    for (auto sidobj: sidobjs)
     {
         libsidplayfp::sidemu *sid = (sidobj);
         if (sid->lock(env))
@@ -59,7 +57,8 @@
 
 void sidbuilder::remove()
 {
-    std::for_each(sidobjs.begin(), sidobjs.end(), [](emuset_t::value_type s) { 
delete s; });
+    for (auto sidobj: sidobjs)
+        delete sidobj;
 
     sidobjs.clear();
 }

Reply via email to