From fda050157888a59f65b14344c5879ab9ca7e764b Mon Sep 17 00:00:00 2001
From: "Tim E. Real" <termtech@rogers.com>
Date: Fri, 29 Jan 2010 19:04:34 +0000
Subject: See ChangeLog

---
 muse/ChangeLog                        |   3 +
 muse/muse/app.cpp                     |   9 +--
 muse/muse/audioconvert.cpp            |  31 ++++++++-
 muse/muse/audioconvert.h              |  24 +++++++
 muse/muse/conf.cpp                    |   6 ++
 muse/muse/driver/dummyaudio.cpp       |  32 +++++++--
 muse/muse/event.cpp                   |  45 +++++++++++--
 muse/muse/event.h                     |   5 ++
 muse/muse/gconfig.cpp                 |   4 +-
 muse/muse/gconfig.h                   |   2 +
 muse/muse/part.h                      |   4 ++
 muse/muse/waveevent.cpp               |   9 +++
 muse/muse/waveevent.h                 |   4 +-
 muse/muse/widgets/genset.cpp          |  18 +++++
 muse/muse/widgets/gensetbase.ui       | 119 +++++++++++++++++++++++++++++++++-
 muse/muse/widgets/musewidgetsplug.cpp |   2 +
 16 files changed, 296 insertions(+), 21 deletions(-)

diff --git a/muse/ChangeLog b/muse/ChangeLog
index 9d027c74..5991b30d 100644
--- a/muse/ChangeLog
+++ b/muse/ChangeLog
@@ -1,3 +1,6 @@
+29.01.2010
+      * Feature: Dummy audio driver: Added global settings for sample rate and period size. (T356)
+        - The period size affects midi resolution, and the default was just too long. So this was added.
 27.01.2010
       * Changed: Don't process audio prefetch, or getData() in Audio::copyData(), if track is 'Off'. (T356)
       * Added: Arranger track list: Quick 'right-click' or 'ctrl-click' or 'ctrl-mouse-wheel' toggling of Track On/Off. (T356) 
diff --git a/muse/muse/app.cpp b/muse/muse/app.cpp
index ac06f3de..e3ec67fe 100644
--- a/muse/muse/app.cpp
+++ b/muse/muse/app.cpp
@@ -462,7 +462,8 @@ bool MusE::seqStart()
       
       int counter=0;
       while (++counter) {
-        if (counter > 10) {
+        //if (counter > 10) {
+        if (counter > 1000) {
             fprintf(stderr,"midi sequencer thread does not start!? Exiting...\n");
             exit(33);
         }
@@ -2526,9 +2527,9 @@ int main(int argc, char* argv[])
       else if (noAudio) {
             initDummyAudio();
             realTimeScheduling = true;
-            if (debugMode) {
-                      realTimeScheduling = false;
-                      }
+            //if (debugMode) {              // ??
+            //          realTimeScheduling = false;
+            //          }
             }
       else if (initJackAudio()) {
             if (!debugMode)
diff --git a/muse/muse/audioconvert.cpp b/muse/muse/audioconvert.cpp
index 47159140..0c8fa657 100644
--- a/muse/muse/audioconvert.cpp
+++ b/muse/muse/audioconvert.cpp
@@ -17,6 +17,30 @@
 //#define AUDIOCONVERT_DEBUG
 //#define AUDIOCONVERT_DEBUG_PRC
 
+//---------------------------------------------------------
+//   AudioConvertMap
+//---------------------------------------------------------
+
+/*
+void AudioConvertMap::remapEvents(const EventList*)  
+{
+
+}
+
+iAudioConvertMap AudioConvertMap::addEventBase(const EventBase*)
+{
+
+}
+
+AudioConverter* AudioConvertMap::findConverter(const EventBase* eb)
+{
+  iAudioConvertMap iacm = find(eb);
+  if(iacm != end())
+    return iacm->second;
+  return 0;
+}
+*/
+
 //---------------------------------------------------------
 //   AudioConverter
 //---------------------------------------------------------
@@ -50,11 +74,12 @@ AudioConverter* AudioConverter::release(AudioConverter* cv)
 {
   if(!cv)
     return 0;
+  //if(cv->incRefCount(-1) <= 0)
+  cv->_refCount -= 1;
   #ifdef AUDIOCONVERT_DEBUG
-  printf("AudioConverter::release converter:%p\n", cv);
+  printf("AudioConverter::release converter:%p current refcount:%d\n", cv, cv->_refCount);
   #endif
-  //if(cv->incRefCount(-1) <= 0)
-  if((cv->_refCount -= 1) <= 0)
+  if(cv->_refCount <= 0)
   {
     #ifdef AUDIOCONVERT_DEBUG
     printf("AudioConverter::release deleting converter:%p\n", cv);
diff --git a/muse/muse/audioconvert.h b/muse/muse/audioconvert.h
index ca0c3f88..4c69d679 100644
--- a/muse/muse/audioconvert.h
+++ b/muse/muse/audioconvert.h
@@ -11,6 +11,8 @@
 #ifndef __AUDIOCONVERT_H__
 #define __AUDIOCONVERT_H__
 
+//#include <map>
+
 #ifdef RUBBERBAND_SUPPORT
 #include <RubberBandStretcher.h>
 #endif
@@ -18,6 +20,10 @@
 #include <samplerate.h>
 #include <sys/types.h>
 
+//#include "eventbase.h"
+//class EventBase;
+//class EventList;
+
 class SndFileR;
 
 //---------------------------------------------------------
@@ -91,5 +97,23 @@ class RubberBandAudioConverter : public AudioConverter
 
 #endif // RUBBERBAND_SUPPORT
 
+//---------------------------------------------------------
+//   AudioConvertMap
+//---------------------------------------------------------
+
+/*
+typedef std::map<EventBase*, AudioConverter*, std::less<EventBase*> >::iterator iAudioConvertMap;
+typedef std::map<EventBase*, AudioConverter*, std::less<EventBase*> >::const_iterator ciAudioConvertMap;
+
+//typedef std::map<EventBase*, AudioConverter*, std::less<EventBase*> > AudioConvertMap;
+class AudioConvertMap : public std::map<EventBase*, AudioConverter*, std::less<EventBase*> > 
+{
+   public:
+      void remapEvents(const EventList*);  
+      iAudioConvertMap addEventBase(const EventBase*);
+      AudioConverter* findConverter(const EventBase*);
+};
+*/
+
 #endif
 
diff --git a/muse/muse/conf.cpp b/muse/muse/conf.cpp
index 33a1a965..54554684 100644
--- a/muse/muse/conf.cpp
+++ b/muse/muse/conf.cpp
@@ -747,6 +747,10 @@ void readConfiguration(Xml& xml, bool readOnlySequencer)
                               config.useOutputLimiter = xml.parseInt();
                         else if (tag == "vstInPlace")
                               config.vstInPlace = xml.parseInt();
+                        else if (tag == "dummyAudioSampleRate")
+                              config.dummyAudioSampleRate = xml.parseInt();
+                        else if (tag == "dummyAudioBufSize")
+                              config.dummyAudioBufSize = xml.parseInt();
                         else if (tag == "guiRefresh")
                               config.guiRefresh = xml.parseInt();
                         else if (tag == "helpBrowser")
@@ -999,6 +1003,8 @@ void MusE::writeGlobalConfiguration(int level, Xml& xml) const
       xml.intTag(level, "didYouKnow", config.showDidYouKnow);
       xml.intTag(level, "outputLimiter", config.useOutputLimiter);
       xml.intTag(level, "vstInPlace", config.vstInPlace);
+      xml.intTag(level, "dummyAudioBufSize", config.dummyAudioBufSize);
+      xml.intTag(level, "dummyAudioSampleRate", config.dummyAudioSampleRate);
 
       xml.intTag(level, "guiRefresh", config.guiRefresh);
       xml.strTag(level, "helpBrowser", config.helpBrowser);
diff --git a/muse/muse/driver/dummyaudio.cpp b/muse/muse/driver/dummyaudio.cpp
index 20750692..5007485c 100644
--- a/muse/muse/driver/dummyaudio.cpp
+++ b/muse/muse/driver/dummyaudio.cpp
@@ -19,13 +19,14 @@
 #include "song.h"
 #include "driver/alsatimer.h"
 #include "pos.h"
+#include "gconfig.h"
 
 #define DEBUG_DUMMY 0
 //---------------------------------------------------------
 //   DummyAudioDevice
 //---------------------------------------------------------
 
-static const unsigned dummyFrames = 1024;
+//static const unsigned dummyFrames = 1024;
 
 enum Cmd {
 trSeek,
@@ -72,8 +73,12 @@ class DummyAudioDevice : public AudioDevice {
 
       virtual float* getBuffer(void* /*port*/, unsigned long nframes)
             {
-            if (nframes > dummyFrames) {
-                  printf("error: segment size > 1024\n");
+            // p3.3.30
+            //if (nframes > dummyFrames) {
+                  //printf("error: segment size > 1024\n");
+            if (nframes > segmentSize) {
+                  printf("DummyAudioDevice::getBuffer nframes > segment size\n");
+                  
                   exit(-1);
                   }
             return buffer;
@@ -162,7 +167,9 @@ DummyAudioDevice* dummyAudio = 0;
 DummyAudioDevice::DummyAudioDevice() 
       {
       // Added by Tim. p3.3.15
-      posix_memalign((void**)&buffer, 16, sizeof(float) * dummyFrames);
+      // p3.3.30
+      //posix_memalign((void**)&buffer, 16, sizeof(float) * dummyFrames);
+      posix_memalign((void**)&buffer, 16, sizeof(float) * config.dummyAudioBufSize);
       
       realtimeFlag = false;
       state = Audio::STOP;
@@ -225,9 +232,14 @@ std::list<QString> DummyAudioDevice::inputPorts()
 static void* dummyLoop(void* ptr)
       {
       //unsigned int tickRate = 25;
-      sampleRate = 25600;
-      segmentSize = dummyFrames;
-      unsigned int tickRate = sampleRate / dummyFrames;
+      
+      // P3.3.30
+      //sampleRate = 25600;
+      sampleRate = config.dummyAudioSampleRate;
+      //segmentSize = dummyFrames;
+      segmentSize = config.dummyAudioBufSize;
+      //unsigned int tickRate = sampleRate / dummyFrames;
+      unsigned int tickRate = sampleRate / segmentSize;
       
       AlsaTimer timer;
       fprintf(stderr, "Finding best alsa timer for dummy driver:\n");
@@ -240,6 +252,12 @@ static void* dummyLoop(void* ptr)
        * consistent.
        */
       tickRate = timer.setTimerFreq( /*250*/ tickRate );
+      
+      // p3.3.31
+      // If it didn't work, get the actual rate.
+      if(tickRate == 0)
+        tickRate = timer.getTimerFreq();
+        
       sampleRate = tickRate * segmentSize;
       timer.startTimer();
 
diff --git a/muse/muse/event.cpp b/muse/muse/event.cpp
index 5e5398fe..e0ef9a30 100644
--- a/muse/muse/event.cpp
+++ b/muse/muse/event.cpp
@@ -65,7 +65,16 @@ void EventBase::dump(int n) const
 
 Event Event::clone()
       {
+      // p3.3.31
+      printf("Event::clone() this:%p\n", this);
+      
+      // p3.3.31
+      //return Event(ev->clone());
+      #ifdef USE_SAMPLERATE
+      return Event(ev->clone(), _audConv);
+      #else
       return Event(ev->clone());
+      #endif
       }
 
 Event::Event() 
@@ -113,7 +122,19 @@ Event::Event(EventBase* eb) {
               _audConv = new SRCAudioConverter(ev->sndFile().channels(), SRC_SINC_MEDIUM_QUALITY);
             #endif  
             }
-
+#ifdef USE_SAMPLERATE
+Event::Event(EventBase* eb, AudioConverter* cv) {
+            _sfCurFrame = 0;
+            _audConv = 0;
+            
+            ev = eb;
+            ++(ev->refCount);
+            
+            if(cv)
+              _audConv = cv->reference();
+            }
+#endif  
+            
 Event::~Event() {
             if (ev && --(ev->refCount) == 0) {
                   delete ev;
@@ -254,14 +275,30 @@ void Event::setSndFile(SndFileR& sf)
   
   #ifdef USE_SAMPLERATE
   //if(_audConv)
-  if(_audConv && !sf.isNull())
-  { 
+//  if(_audConv && !sf.isNull())
+//  { 
     //_audConv->setSndFile(sf);
     //if(sf.isNull())
     //  AudioConverter::release(_audConv);
     //else
+//      _audConv->setChannels(sf.channels());
+//  }  
+  
+  if(_audConv)
+  { 
+    // Do we release? Or keep the converter around, while gaining speed since no rapid creation/destruction. 
+    //if(sf.isNull())
+    //  _audConv = AudioConverter::release(_audConv);
+    //else
+    //  _audConv->setChannels(sf.channels());
+    if(!sf.isNull())
       _audConv->setChannels(sf.channels());
-  }  
+  }
+  else
+  {
+    if(!sf.isNull())
+      _audConv = new SRCAudioConverter(ev->sndFile().channels(), SRC_SINC_MEDIUM_QUALITY);
+  }
   #endif
 }
 
diff --git a/muse/muse/event.h b/muse/muse/event.h
index 2a034a36..37d3c963 100644
--- a/muse/muse/event.h
+++ b/muse/muse/event.h
@@ -40,6 +40,11 @@ class Event {
       Event(EventType t);
       Event(const Event& e);
       Event(EventBase* eb);
+      
+      //#ifdef USE_SAMPLERATE
+      //Event(EventBase* eb, AudioConverter* cv); 
+      //#endif  
+      
       virtual ~Event();
 
       bool empty() const;
diff --git a/muse/muse/gconfig.cpp b/muse/muse/gconfig.cpp
index 8072e656..5d46a175 100644
--- a/muse/muse/gconfig.cpp
+++ b/muse/muse/gconfig.cpp
@@ -127,6 +127,8 @@ GlobalConfigValues config = {
       true,                         // useDenormalBias
       false,                        // useOutputLimiter
       true,                         // showDidYouKnow
-      false                         // vstInPlace  Enable VST in-place processing
+      false,                        // vstInPlace  Enable VST in-place processing
+      44100,                        // Dummy audio preferred sample rate
+      512                           // Dummy audio buffer size
     };
 
diff --git a/muse/muse/gconfig.h b/muse/muse/gconfig.h
index 5d4d98a8..b763e993 100644
--- a/muse/muse/gconfig.h
+++ b/muse/muse/gconfig.h
@@ -121,6 +121,8 @@ struct GlobalConfigValues {
       bool useOutputLimiter;
       bool showDidYouKnow;
       bool vstInPlace; // Enable VST in-place processing
+      int dummyAudioSampleRate; 
+      int dummyAudioBufSize;
       };
 
 extern GlobalConfigValues config;
diff --git a/muse/muse/part.h b/muse/muse/part.h
index fe45cad4..911c8806 100644
--- a/muse/muse/part.h
+++ b/muse/muse/part.h
@@ -23,6 +23,7 @@ class MidiTrack;
 class WaveTrack;
 class Xml;
 class Part;
+class AudioConvertMap;
 
 // typedef std::multimap<unsigned, Event*, std::less<unsigned> >::iterator iEvent;
 
@@ -121,6 +122,9 @@ class MidiPart : public Part {
 
 class WavePart : public Part {
 
+      // p3.3.31
+      //AudioConvertMap _converters;
+      
    public:
       WavePart(WaveTrack* t);
       WavePart(WaveTrack* t, EventList* ev);
diff --git a/muse/muse/waveevent.cpp b/muse/muse/waveevent.cpp
index dd18a2ff..a7a707c8 100644
--- a/muse/muse/waveevent.cpp
+++ b/muse/muse/waveevent.cpp
@@ -31,6 +31,15 @@ WaveEventBase::WaveEventBase(EventType t)
       deleted = false;
       }
 
+//---------------------------------------------------------
+//   WaveEventBase::clone
+//---------------------------------------------------------
+
+EventBase* WaveEventBase::clone() 
+{ 
+  return new WaveEventBase(*this); 
+}
+
 //---------------------------------------------------------
 //   WaveEvent::mid
 //---------------------------------------------------------
diff --git a/muse/muse/waveevent.h b/muse/muse/waveevent.h
index 926e9c64..c68a3923 100644
--- a/muse/muse/waveevent.h
+++ b/muse/muse/waveevent.h
@@ -26,7 +26,9 @@ class WaveEventBase : public EventBase {
       int _spos;        // start sample position in WaveFile
       bool deleted;
 
-      virtual EventBase* clone() { return new WaveEventBase(*this); }
+      // p3.3.31
+      //virtual EventBase* clone() { return new WaveEventBase(*this); }
+      virtual EventBase* clone();
 
    public:
       WaveEventBase(EventType t);
diff --git a/muse/muse/widgets/genset.cpp b/muse/muse/widgets/genset.cpp
index 7d2741d5..fddf7c12 100644
--- a/muse/muse/widgets/genset.cpp
+++ b/muse/muse/widgets/genset.cpp
@@ -13,6 +13,7 @@
 #include <qlineedit.h>
 #include <qbuttongroup.h>
 #include <qcheckbox.h>
+#include <qlabel.h>
 
 #include "genset.h"
 #include "app.h"
@@ -26,6 +27,9 @@ static int rtcResolutions[] = {
 static int divisions[] = {
       48, 96, 192, 384, 768, 1536, 3072, 6144, 12288
       };
+static int dummyAudioBufSizes[] = {
+      16, 32, 64, 128, 256, 512, 1024, 2048
+      };
 
 //---------------------------------------------------------
 //   GlobalSettingsConfig
@@ -52,6 +56,12 @@ GlobalSettingsConfig::GlobalSettingsConfig(QWidget* parent, const char* name)
                   break;
                   }
             }
+      for (unsigned i = 0; i < sizeof(dummyAudioBufSizes)/sizeof(*dummyAudioBufSizes); ++i) {
+            if (dummyAudioBufSizes[i] == config.dummyAudioBufSize) {
+                  dummyAudioSize->setCurrentItem(i);
+                  break;
+                  }
+            }
       
       guiRefreshSelect->setValue(config.guiRefresh);
       minSliderSelect->setValue(int(config.minSlider));
@@ -60,6 +70,11 @@ GlobalSettingsConfig::GlobalSettingsConfig(QWidget* parent, const char* name)
       denormalCheckBox->setChecked(config.useDenormalBias);
       outputLimiterCheckBox->setChecked(config.useOutputLimiter);
       vstInPlaceCheckBox->setChecked(config.vstInPlace);
+      dummyAudioRate->setValue(config.dummyAudioSampleRate);
+      
+      //DummyAudioDevice* dad = dynamic_cast<DummyAudioDevice*>(audioDevice);
+      //dummyAudioRealRate->setText(dad ? QString().setNum(sampleRate) : "---");
+      dummyAudioRealRate->setText(QString().setNum(sampleRate));
       
       helpBrowser->setText(config.helpBrowser);
       startSongEntry->setText(config.startSong);
@@ -137,6 +152,9 @@ void GlobalSettingsConfig::apply()
       config.helpBrowser = helpBrowser->text();
       config.startSong   = startSongEntry->text();
       config.startMode   = startSongGroup->selectedId();
+      int das = dummyAudioSize->currentItem();
+      config.dummyAudioBufSize = dummyAudioBufSizes[das];
+      config.dummyAudioSampleRate = dummyAudioRate->value();
 
       int div            = midiDivisionSelect->currentItem();
       config.division    = divisions[div];
diff --git a/muse/muse/widgets/gensetbase.ui b/muse/muse/widgets/gensetbase.ui
index cd6f2888..9f94fac4 100644
--- a/muse/muse/widgets/gensetbase.ui
+++ b/muse/muse/widgets/gensetbase.ui
@@ -725,7 +725,7 @@
                                     <cstring>TextLabel2_2</cstring>
                                 </property>
                                 <property name="text">
-                                    <string>min.Slider Val</string>
+                                    <string>min. Slider Val</string>
                                 </property>
                             </widget>
                             <widget class="QSpinBox" row="1" column="1">
@@ -888,6 +888,123 @@
                             </widget>
                         </grid>
                     </widget>
+                    <widget class="QGroupBox" row="2" column="0">
+                      <property name="name">
+                        <cstring>dummyAudioGroupBox</cstring>
+                      </property>
+                      <property name="title">
+                        <string>Dummy Audio Driver (settings require restart)</string>
+                      </property>
+                      <grid>
+                        <property name="name">
+                          <cstring>unnamed</cstring>
+                        </property>
+                        <widget class="QLabel" row="0" column="0">
+                          <property name="name">
+                            <cstring>dummyAudioRateLabel</cstring>
+                          </property>
+                          <property name="text">
+                            <string>Preferred sample rate</string>
+                          </property>
+                        </widget>
+                        <widget class="QSpinBox" row="0" column="1">
+                          <property name="name">
+                            <cstring>dummyAudioRate</cstring>
+                          </property>
+                          <property name="suffix">
+                            <string>Hz</string>
+                          </property>
+                          <property name="maxValue">
+                            <number>200000</number>
+                          </property>
+                          <property name="minValue">
+                            <number>3000</number>
+                          </property>
+                          <property name="lineStep">
+                            <number>10</number>
+                          </property>
+                          <property name="value">
+                            <number>44100</number>
+                          </property>
+                          <property name="whatsThis" stdset="0">
+                            <string>Actual rate used depends on limitations of
+ timer used. If a high rate timer is available,
+ short periods can be used with high sample rates. 
+Period affects midi playback resolution. 
+Shorter periods are desirable.</string>
+                          </property>
+                        </widget>
+                        <widget class="QLabel" row="1" column="0">
+                          <property name="name">
+                            <cstring>dummyAudioRealRateLabel</cstring>
+                          </property>
+                          <property name="text">
+                            <string>Actual rate used now (dummy or not):</string>
+                          </property>
+                        </widget>
+                        <widget class="QLabel" row="1" column="1">
+                          <property name="name">
+                            <cstring>dummyAudioRealRate</cstring>
+                          </property>
+                          <property name="text">
+                            <string>---</string>
+                          </property>
+                        </widget>
+                        <widget class="QLabel" row="2" column="0">
+                          <property name="name">
+                            <cstring>dummyAudioSizeLabel</cstring>
+                          </property>
+                          <property name="text">
+                            <string>Period size (Frames per period):</string>
+                          </property>
+                        </widget>
+                        <widget class="QComboBox" row="2" column="1">
+                          <property name="name">
+                            <cstring>dummyAudioSize</cstring>
+                          </property>
+                          <item>
+                            <property name="text">
+                              <string>16</string>
+                            </property>
+                          </item>
+                          <item>
+                            <property name="text">
+                              <string>32</string>
+                            </property>
+                          </item>
+                          <item>
+                            <property name="text">
+                              <string>64</string>
+                            </property>
+                          </item>
+                          <item>
+                            <property name="text">
+                              <string>128</string>
+                            </property>
+                          </item>
+                          <item>
+                            <property name="text">
+                              <string>256</string>
+                            </property>
+                          </item>
+                          <item>
+                            <property name="text">
+                              <string>512</string>
+                            </property>
+                          </item>
+                          <item>
+                            <property name="text">
+                              <string>1024</string>
+                            </property>
+                          </item>
+                          <item>
+                            <property name="text">
+                              <string>2048</string>
+                            </property>
+                          </item>
+                        </widget>
+                      </grid>
+                    </widget>
                 </grid>
             </widget>
             <widget class="QWidget">
diff --git a/muse/muse/widgets/musewidgetsplug.cpp b/muse/muse/widgets/musewidgetsplug.cpp
index a32707e5..ea9cfe12 100644
--- a/muse/muse/widgets/musewidgetsplug.cpp
+++ b/muse/muse/widgets/musewidgetsplug.cpp
@@ -155,6 +155,8 @@ GlobalConfigValues config = {
       false,                        // useOutputLimiter
       true,                         // showDidYouKnow
       false                         // vstInPlace  Enable VST in-place processing
+      44100,                        // Dummy audio preferred sample rate
+      512                           // Dummy audio buffer size
       };
 
 //---------------------------------------------------------
-- 
cgit v1.2.3