\96Tabs -> Spaces
[rtaudio-cdist.git] / RtAudio.cpp
old mode 100755 (executable)
new mode 100644 (file)
index 8cac299..9ebe49d
@@ -1,4 +1,4 @@
-/************************************************************************/\r
+/************************************************************************/\r
 /*! \class RtAudio\r
     \brief Realtime audio i/o C++ classes.\r
 \r
@@ -10,7 +10,7 @@
     RtAudio WWW site: http://www.music.mcgill.ca/~gary/rtaudio/\r
 \r
     RtAudio: realtime audio i/o C++ classes\r
-    Copyright (c) 2001-2014 Gary P. Scavone\r
+    Copyright (c) 2001-2016 Gary P. Scavone\r
 \r
     Permission is hereby granted, free of charge, to any person\r
     obtaining a copy of this software and associated documentation files\r
@@ -38,7 +38,7 @@
 */\r
 /************************************************************************/\r
 \r
-// RtAudio: Version 4.1.1\r
+// RtAudio: Version 4.1.2\r
 \r
 #include "RtAudio.h"\r
 #include <iostream>\r
@@ -1405,7 +1405,6 @@ void RtApiCore :: closeStream( void )
   }\r
 \r
   CoreHandle *handle = (CoreHandle *) stream_.apiHandle;\r
-  if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {\r
   if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {\r
     if (handle) {\r
       AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices,\r
@@ -3860,54 +3859,139 @@ private:
 // In order to satisfy WASAPI's buffer requirements, we need a means of converting sample rate\r
 // between HW and the user. The convertBufferWasapi function is used to perform this conversion\r
 // between HwIn->UserIn and UserOut->HwOut during the stream callback loop.\r
-// This sample rate converter favors speed over quality, and works best with conversions between\r
-// one rate and its multiple.\r
-void convertBufferWasapi( char* outBuffer,\r
-                          const char* inBuffer,\r
-                          const unsigned int& channelCount,\r
-                          const unsigned int& inSampleRate,\r
-                          const unsigned int& outSampleRate,\r
-                          const unsigned int& inSampleCount,\r
-                          unsigned int& outSampleCount,\r
-                          const RtAudioFormat& format )\r
-{\r
-  // calculate the new outSampleCount and relative sampleStep\r
-  float sampleRatio = ( float ) outSampleRate / inSampleRate;\r
-  float sampleStep = 1.0f / sampleRatio;\r
-  float inSampleFraction = 0.0f;\r
-\r
-  outSampleCount = ( unsigned int ) roundf( inSampleCount * sampleRatio );\r
-\r
-  // frame-by-frame, copy each relative input sample into it's corresponding output sample\r
-  for ( unsigned int outSample = 0; outSample < outSampleCount; outSample++ )\r
-  {\r
-    unsigned int inSample = ( unsigned int ) inSampleFraction;\r
-\r
-    switch ( format )\r
+// This sample rate converter works best with conversions between one rate and its multiple.\r
+void convertBufferWasapi(char* outBuffer,\r
+    const char* inBuffer,\r
+    const unsigned int& channelCount,\r
+    const unsigned int& inSampleRate,\r
+    const unsigned int& outSampleRate,\r
+    const unsigned int& inSampleCount,\r
+    unsigned int& outSampleCount,\r
+    const RtAudioFormat& format)\r
+{\r
+    // calculate the new outSampleCount and relative sampleStep\r
+    float sampleRatio = (float)outSampleRate / inSampleRate;\r
+    float sampleRatioInv = (float)1 / sampleRatio;\r
+    float sampleStep = 1.0f / sampleRatio;\r
+    float inSampleFraction = 0.0f;\r
+\r
+    outSampleCount = (unsigned int)roundf(inSampleCount * sampleRatio);\r
+\r
+    // if inSampleRate is a multiple of outSampleRate (or vice versa) there's no need to interpolate\r
+    if (floor(sampleRatio) == sampleRatio || floor(sampleRatioInv) == sampleRatioInv)\r
     {\r
-      case RTAUDIO_SINT8:\r
-        memcpy( &( ( char* ) outBuffer )[ outSample * channelCount ], &( ( char* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( char ) );\r
-        break;\r
-      case RTAUDIO_SINT16:\r
-        memcpy( &( ( short* ) outBuffer )[ outSample * channelCount ], &( ( short* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( short ) );\r
-        break;\r
-      case RTAUDIO_SINT24:\r
-        memcpy( &( ( S24* ) outBuffer )[ outSample * channelCount ], &( ( S24* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( S24 ) );\r
-        break;\r
-      case RTAUDIO_SINT32:\r
-        memcpy( &( ( int* ) outBuffer )[ outSample * channelCount ], &( ( int* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( int ) );\r
-        break;\r
-      case RTAUDIO_FLOAT32:\r
-        memcpy( &( ( float* ) outBuffer )[ outSample * channelCount ], &( ( float* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( float ) );\r
-        break;\r
-      case RTAUDIO_FLOAT64:\r
-        memcpy( &( ( double* ) outBuffer )[ outSample * channelCount ], &( ( double* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( double ) );\r
-        break;\r
+        // frame-by-frame, copy each relative input sample into it's corresponding output sample\r
+        for (unsigned int outSample = 0; outSample < outSampleCount; outSample++)\r
+        {\r
+            unsigned int inSample = (unsigned int)inSampleFraction;\r
+\r
+            switch (format)\r
+            {\r
+            case RTAUDIO_SINT8:\r
+                memcpy(&((char*)outBuffer)[outSample * channelCount], &((char*)inBuffer)[inSample * channelCount], channelCount * sizeof(char));\r
+                break;\r
+            case RTAUDIO_SINT16:\r
+                memcpy(&((short*)outBuffer)[outSample * channelCount], &((short*)inBuffer)[inSample * channelCount], channelCount * sizeof(short));\r
+                break;\r
+            case RTAUDIO_SINT24:\r
+                memcpy(&((S24*)outBuffer)[outSample * channelCount], &((S24*)inBuffer)[inSample * channelCount], channelCount * sizeof(S24));\r
+                break;\r
+            case RTAUDIO_SINT32:\r
+                memcpy(&((int*)outBuffer)[outSample * channelCount], &((int*)inBuffer)[inSample * channelCount], channelCount * sizeof(int));\r
+                break;\r
+            case RTAUDIO_FLOAT32:\r
+                memcpy(&((float*)outBuffer)[outSample * channelCount], &((float*)inBuffer)[inSample * channelCount], channelCount * sizeof(float));\r
+                break;\r
+            case RTAUDIO_FLOAT64:\r
+                memcpy(&((double*)outBuffer)[outSample * channelCount], &((double*)inBuffer)[inSample * channelCount], channelCount * sizeof(double));\r
+                break;\r
+            }\r
+\r
+            // jump to next in sample\r
+            inSampleFraction += sampleStep;\r
+        }\r
     }\r
+    else // else interpolate\r
+    {\r
+        // frame-by-frame, copy each relative input sample into it's corresponding output sample\r
+        for (unsigned int outSample = 0; outSample < outSampleCount; outSample++)\r
+        {\r
+            unsigned int inSample = (unsigned int)inSampleFraction;\r
+\r
+            switch (format)\r
+            {\r
+            case RTAUDIO_SINT8:\r
+            {\r
+                for (unsigned int channel = 0; channel < channelCount; channel++)\r
+                {\r
+                    char fromSample = ((char*)inBuffer)[(inSample * channelCount) + channel];\r
+                    char toSample = ((char*)inBuffer)[((inSample + 1) * channelCount) + channel];\r
+                    float sampleDiff = (toSample - fromSample) * (inSampleFraction - floor(inSampleFraction));\r
+                    ((char*)outBuffer)[(outSample * channelCount) + channel] = fromSample + (char)sampleDiff;\r
+                }\r
+                break;\r
+            }\r
+            case RTAUDIO_SINT16:\r
+            {\r
+                for (unsigned int channel = 0; channel < channelCount; channel++)\r
+                {\r
+                    short fromSample = ((short*)inBuffer)[(inSample * channelCount) + channel];\r
+                    short toSample = ((short*)inBuffer)[((inSample + 1) * channelCount) + channel];\r
+                    float sampleDiff = (toSample - fromSample) * (inSampleFraction - floor(inSampleFraction));\r
+                    ((short*)outBuffer)[(outSample * channelCount) + channel] = fromSample + (short)sampleDiff;\r
+                }\r
+                break;\r
+            }\r
+            case RTAUDIO_SINT24:\r
+            {\r
+                for (unsigned int channel = 0; channel < channelCount; channel++)\r
+                {\r
+                    int fromSample = ((S24*)inBuffer)[(inSample * channelCount) + channel].asInt();\r
+                    int toSample = ((S24*)inBuffer)[((inSample + 1) * channelCount) + channel].asInt();\r
+                    float sampleDiff = (toSample - fromSample) * (inSampleFraction - floor(inSampleFraction));\r
+                    ((S24*)outBuffer)[(outSample * channelCount) + channel] = fromSample + (int)sampleDiff;\r
+                }\r
+                break;\r
+            }\r
+            case RTAUDIO_SINT32:\r
+            {\r
+                for (unsigned int channel = 0; channel < channelCount; channel++)\r
+                {\r
+                    int fromSample = ((int*)inBuffer)[(inSample * channelCount) + channel];\r
+                    int toSample = ((int*)inBuffer)[((inSample + 1) * channelCount) + channel];\r
+                    float sampleDiff = (toSample - fromSample) * (inSampleFraction - floor(inSampleFraction));\r
+                    ((int*)outBuffer)[(outSample * channelCount) + channel] = fromSample + (int)sampleDiff;\r
+                }\r
+                break;\r
+            }\r
+            case RTAUDIO_FLOAT32:\r
+            {\r
+                for (unsigned int channel = 0; channel < channelCount; channel++)\r
+                {\r
+                    float fromSample = ((float*)inBuffer)[(inSample * channelCount) + channel];\r
+                    float toSample = ((float*)inBuffer)[((inSample + 1) * channelCount) + channel];\r
+                    float sampleDiff = (toSample - fromSample) * (inSampleFraction - floor(inSampleFraction));\r
+                    ((float*)outBuffer)[(outSample * channelCount) + channel] = fromSample + sampleDiff;\r
+                }\r
+                break;\r
+            }\r
+            case RTAUDIO_FLOAT64:\r
+            {\r
+                for (unsigned int channel = 0; channel < channelCount; channel++)\r
+                {\r
+                    double fromSample = ((double*)inBuffer)[(inSample * channelCount) + channel];\r
+                    double toSample = ((double*)inBuffer)[((inSample + 1) * channelCount) + channel];\r
+                    double sampleDiff = (toSample - fromSample) * (inSampleFraction - floor(inSampleFraction));\r
+                    ((double*)outBuffer)[(outSample * channelCount) + channel] = fromSample + sampleDiff;\r
+                }\r
+                break;\r
+            }\r
+            }\r
 \r
-    // jump to next in sample\r
-    inSampleFraction += sampleStep;\r
-  }\r
+            // jump to next in sample\r
+            inSampleFraction += sampleStep;\r
+        }\r
+    }\r
 }\r
 \r
 //-----------------------------------------------------------------------------\r
@@ -5159,10 +5243,10 @@ void RtApiWasapi::wasapiThread()
     // if the callback buffer was pushed renderBuffer reset callbackPulled flag\r
     if ( callbackPushed ) {\r
       callbackPulled = false;\r
+      // tick stream time\r
+      RtApi::tickStreamTime();\r
     }\r
 \r
-    // tick stream time\r
-    RtApi::tickStreamTime();\r
   }\r
 \r
 Exit:\r
@@ -6439,6 +6523,7 @@ void RtApiDs :: callbackEvent()
       if ( FAILED( result ) ) {\r
         errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!";\r
         errorText_ = errorStream_.str();\r
+        MUTEX_UNLOCK( &stream_.mutex );\r
         error( RtAudioError::SYSTEM_ERROR );\r
         return;\r
       }\r
@@ -8071,7 +8156,7 @@ static void *alsaCallbackHandler( void *ptr )
   bool *isRunning = &info->isRunning;\r
 \r
 #ifdef SCHED_RR // Undefined with some OSes (eg: NetBSD 1.6.x with GNU Pthread)\r
-  if ( &info->doRealtime ) {\r
+  if ( info->doRealtime ) {\r
     pthread_t tID = pthread_self();     // ID of this thread\r
     sched_param prio = { info->priority }; // scheduling priority of thread\r
     pthread_setschedparam( tID, SCHED_RR, &prio );\r
@@ -8523,7 +8608,7 @@ bool RtApiPulse::probeDeviceOpen( unsigned int device, StreamMode mode,
     }\r
     break;\r
   case OUTPUT:\r
-    pah->s_play = pa_simple_new( NULL, "RtAudio", PA_STREAM_PLAYBACK, NULL, "Playback", &ss, NULL, NULL, &error );\r
+    pah->s_play = pa_simple_new( NULL, streamName.c_str(), PA_STREAM_PLAYBACK, NULL, "Playback", &ss, NULL, NULL, &error );\r
     if ( !pah->s_play ) {\r
       errorText_ = "RtApiPulse::probeDeviceOpen: error connecting output to PulseAudio server.";\r
       goto error;\r
@@ -10143,8 +10228,8 @@ void RtApi :: convertBuffer( char *outBuffer, char *inBuffer, ConvertInfo &info
 \r
 void RtApi :: byteSwapBuffer( char *buffer, unsigned int samples, RtAudioFormat format )\r
 {\r
-  register char val;\r
-  register char *ptr;\r
+  char val;\r
+  char *ptr;\r
 \r
   ptr = buffer;\r
   if ( format == RTAUDIO_SINT16 ) {\r