From 375e6ccfe98d10f0f0ae28f87d2d3d42b65d7074 Mon Sep 17 00:00:00 2001
From: Olli Parviainen
Date: Sun, 11 Feb 2024 15:27:45 +0200
Subject: [PATCH] Windows: SoundStretch to accept wide-character command line
attributes to support asian/non-latin files names.
---
CMakeLists.txt | 2 +-
README.html | 8 +-
include/SoundTouch.h | 4 +-
source/SoundStretch/RunParameters.cpp | 69 +--
source/SoundStretch/RunParameters.h | 37 +-
source/SoundStretch/WavFile.cpp | 550 ++++++++++-----------
source/SoundStretch/WavFile.h | 13 +-
source/SoundStretch/main.cpp | 235 +++++----
source/SoundStretch/soundstretch.vcxproj | 18 +-
source/SoundTouch/SoundTouch.vcxproj | 8 +-
source/SoundTouchDLL/DllTest/DllTest.cpp | 15 +-
source/SoundTouchDLL/SoundTouchDLL.rc | 6 +-
source/SoundTouchDLL/SoundTouchDLL.vcxproj | 8 +-
13 files changed, 485 insertions(+), 488 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ee68b4b..131ea20 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.1)
-project(SoundTouch VERSION 2.3.2 LANGUAGES CXX)
+project(SoundTouch VERSION 2.3.3 LANGUAGES CXX)
include(GNUInstallDirs)
diff --git a/README.html b/README.html
index 02b1afc..23a4fd9 100644
--- a/README.html
+++ b/README.html
@@ -16,7 +16,7 @@
SoundTouch audio processing library v2.3.2
- SoundTouch library Copyright © Olli Parviainen 2001-2022
+ SoundTouch library Copyright © Olli Parviainen 2001-2024
1. Introduction
SoundTouch is an open-source audio processing library that allows
@@ -450,7 +450,7 @@
4. SoundStretch audio processing utility
SoundStretch audio processing utility
- Copyright (c) Olli Parviainen 2002-2022
+ Copyright (c) Olli Parviainen 2002-2024
SoundStretch is a simple command-line application that can change
tempo, pitch and playback rates of WAV sound files. This program is
intended primarily to demonstrate how the "SoundTouch" library can be
@@ -874,6 +874,10 @@
Initial release
5.2. SoundStretch application Change History
+ 2.3.3:
+
+ - Added support for Asian / non-latin filenames in Windows. Gnu platform has supported them already earlier.
+
1.9:
- Added support for WAV file 'fact' information chunk.
diff --git a/include/SoundTouch.h b/include/SoundTouch.h
index 0c22cb5..3337dad 100644
--- a/include/SoundTouch.h
+++ b/include/SoundTouch.h
@@ -72,10 +72,10 @@ namespace soundtouch
{
/// Soundtouch library version string
-#define SOUNDTOUCH_VERSION "2.3.2"
+#define SOUNDTOUCH_VERSION "2.3.3"
/// SoundTouch library version id
-#define SOUNDTOUCH_VERSION_ID (20302)
+#define SOUNDTOUCH_VERSION_ID (20303)
//
// Available setting IDs for the 'setSetting' & 'get_setting' functions:
diff --git a/source/SoundStretch/RunParameters.cpp b/source/SoundStretch/RunParameters.cpp
index 54b3b62..0b8cb23 100644
--- a/source/SoundStretch/RunParameters.cpp
+++ b/source/SoundStretch/RunParameters.cpp
@@ -30,15 +30,18 @@
////////////////////////////////////////////////////////////////////////////////
#include
-#include
+#include
#include "RunParameters.h"
using namespace std;
+namespace soundstretch
+{
+
// Program usage instructions
-static const char licenseText[] =
+static const char licenseText[] =
" LICENSE:\n"
" ========\n"
" \n"
@@ -61,12 +64,12 @@ static const char licenseText[] =
"This application is distributed with full source codes; however, if you\n"
"didn't receive them, please visit the author's homepage (see the link above).";
-static const char whatText[] =
+static const char whatText[] =
"This application processes WAV audio files by modifying the sound tempo,\n"
"pitch and playback rate properties independently from each other.\n"
"\n";
-static const char usage[] =
+static const char usage[] =
"Usage :\n"
" soundstretch infilename outfilename [switches]\n"
"\n"
@@ -94,9 +97,8 @@ static int _toLowerCase(int c)
return c;
}
-
// Constructor
-RunParameters::RunParameters(const int nParams, const char * const paramStr[])
+RunParameters::RunParameters(int nParams, const CHARTYPE* paramStr[])
{
int i;
int nFirstParam;
@@ -112,28 +114,17 @@ RunParameters::RunParameters(const int nParams, const char * const paramStr[])
}
string msg = whatText;
msg += usage;
- ST_THROW_RT_ERROR(msg.c_str());
+ throw(msg);
}
- inFileName = nullptr;
- outFileName = nullptr;
- tempoDelta = 0;
- pitchDelta = 0;
- rateDelta = 0;
- quick = 0;
- noAntiAlias = 0;
- goalBPM = 0;
- speech = false;
- detectBPM = false;
-
// Get input & output file names
- inFileName = (char*)paramStr[1];
- outFileName = (char*)paramStr[2];
+ inFileName = paramStr[1];
+ outFileName = paramStr[2];
if (outFileName[0] == '-')
{
- // no outputfile name was given but parameters
- outFileName = nullptr;
+ // outputfile name was omitted but other parameter switches given instead
+ outFileName = STRING_CONST("");
nFirstParam = 2;
}
else
@@ -182,25 +173,33 @@ void RunParameters::checkLimits()
}
}
-
-// Unknown switch parameter -- throws an exception with an error message
-void RunParameters::throwIllegalParamExp(const string &str) const
+// Convert STRING to std::string. Actually needed only if STRING is std::wstring, but conversion penalty is negligible
+std::string convertString(const STRING& str)
{
- string msg = "ERROR : Illegal parameter \"";
- msg += str;
- msg += "\".\n\n";
- msg += usage;
- ST_THROW_RT_ERROR(msg.c_str());
+ std::string res;
+ for (auto c : str)
+ {
+ res += (char)c;
+ }
+ return res;
}
+// Unknown switch parameter -- throws an exception with an error message
+void RunParameters::throwIllegalParamExp(const STRING &str) const
+{
+ string msg = "ERROR : Illegal parameter \"";
+ msg += convertString(str);
+ msg += "\".\n\n";
+ msg += usage;
+ ST_THROW_RT_ERROR(msg);
+}
void RunParameters::throwLicense() const
{
ST_THROW_RT_ERROR(licenseText);
}
-
-float RunParameters::parseSwitchValue(const string &str) const
+float RunParameters::parseSwitchValue(const STRING& str) const
{
int pos;
@@ -212,14 +211,14 @@ float RunParameters::parseSwitchValue(const string &str) const
}
// Read numerical parameter value after '='
- return (float)atof(str.substr(pos + 1).c_str());
+ return (float)stof(str.substr(pos + 1).c_str());
}
// Interprets a single switch parameter string of format "-switch=xx"
// Valid switches are "-tempo=xx", "-pitch=xx" and "-rate=xx". Stores
// switch values into 'params' structure.
-void RunParameters::parseSwitchParam(const string &str)
+void RunParameters::parseSwitchParam(const STRING& str)
{
int upS;
@@ -289,3 +288,5 @@ void RunParameters::parseSwitchParam(const string &str)
throwIllegalParamExp(str);
}
}
+
+}
diff --git a/source/SoundStretch/RunParameters.h b/source/SoundStretch/RunParameters.h
index 6c0142b..839d27f 100644
--- a/source/SoundStretch/RunParameters.h
+++ b/source/SoundStretch/RunParameters.h
@@ -32,34 +32,39 @@
#ifndef RUNPARAMETERS_H
#define RUNPARAMETERS_H
-#include "STTypes.h"
#include
+#include "STTypes.h"
+#include "SS_CharTypes.h"
+#include "WavFile.h"
-using namespace std;
+namespace soundstretch
+{
/// Parses command line parameters into program parameters
class RunParameters
{
private:
- void throwIllegalParamExp(const string &str) const;
+ void throwIllegalParamExp(const STRING& str) const;
void throwLicense() const;
- void parseSwitchParam(const string &str);
+ void parseSwitchParam(const STRING& str);
void checkLimits();
- float parseSwitchValue(const string &str) const;
+ float parseSwitchValue(const STRING& tr) const;
public:
- char *inFileName;
- char *outFileName;
- float tempoDelta;
- float pitchDelta;
- float rateDelta;
- int quick;
- int noAntiAlias;
- float goalBPM;
- bool detectBPM;
- bool speech;
+ STRING inFileName;
+ STRING outFileName;
+ float tempoDelta{ 0 };
+ float pitchDelta{ 0 };
+ float rateDelta{ 0 };
+ int quick{ 0 };
+ int noAntiAlias{ 0 };
+ float goalBPM{ 0 };
+ bool detectBPM{ false };
+ bool speech{ false };
- RunParameters(const int nParams, const char * const paramStr[]);
+ RunParameters(int nParams, const CHARTYPE* paramStr[]);
};
+}
+
#endif
diff --git a/source/SoundStretch/WavFile.cpp b/source/SoundStretch/WavFile.cpp
index b21e72f..0880668 100644
--- a/source/SoundStretch/WavFile.cpp
+++ b/source/SoundStretch/WavFile.cpp
@@ -42,17 +42,26 @@
#include
#include
#include
-#include
-#include
+#include
+#include
#include "WavFile.h"
#include "STTypes.h"
using namespace std;
+namespace soundstretch
+{
+
+#if _WIN32
+#define FOPEN(name, mode) _wfopen(name, STRING_CONST(mode))
+#else
+#define FOPEN(name, mode) fopen(name, mode)
+#endif
+
static const char riffStr[] = "RIFF";
static const char waveStr[] = "WAVE";
-static const char fmtStr[] = "fmt ";
+static const char fmtStr[] = "fmt ";
static const char factStr[] = "fact";
static const char dataStr[] = "data";
@@ -66,67 +75,67 @@ static const char dataStr[] = "data";
// while PowerPC of Mac's and many other RISC cpu's are big-endian.
#ifdef BYTE_ORDER
- // In gcc compiler detect the byte order automatically
- #if BYTE_ORDER == BIG_ENDIAN
- // big-endian platform.
- #define _BIG_ENDIAN_
- #endif
+// In gcc compiler detect the byte order automatically
+#if BYTE_ORDER == BIG_ENDIAN
+// big-endian platform.
+#define _BIG_ENDIAN_
#endif
-
+#endif
+
#ifdef _BIG_ENDIAN_
- // big-endian CPU, swap bytes in 16 & 32 bit words
+// big-endian CPU, swap bytes in 16 & 32 bit words
- // helper-function to swap byte-order of 32bit integer
- static inline int _swap32(int &dwData)
- {
- dwData = ((dwData >> 24) & 0x000000FF) |
- ((dwData >> 8) & 0x0000FF00) |
- ((dwData << 8) & 0x00FF0000) |
- ((dwData << 24) & 0xFF000000);
- return dwData;
- }
+// helper-function to swap byte-order of 32bit integer
+static inline int _swap32(int& dwData)
+{
+ dwData = ((dwData >> 24) & 0x000000FF) |
+ ((dwData >> 8) & 0x0000FF00) |
+ ((dwData << 8) & 0x00FF0000) |
+ ((dwData << 24) & 0xFF000000);
+ return dwData;
+}
- // helper-function to swap byte-order of 16bit integer
- static inline short _swap16(short &wData)
+// helper-function to swap byte-order of 16bit integer
+static inline short _swap16(short& wData)
+{
+ wData = ((wData >> 8) & 0x00FF) |
+ ((wData << 8) & 0xFF00);
+ return wData;
+}
+
+// helper-function to swap byte-order of buffer of 16bit integers
+static inline void _swap16Buffer(short* pData, int numWords)
+{
+ int i;
+
+ for (i = 0; i < numWords; i++)
{
- wData = ((wData >> 8) & 0x00FF) |
- ((wData << 8) & 0xFF00);
- return wData;
- }
-
- // helper-function to swap byte-order of buffer of 16bit integers
- static inline void _swap16Buffer(short *pData, int numWords)
- {
- int i;
-
- for (i = 0; i < numWords; i ++)
- {
- pData[i] = _swap16(pData[i]);
- }
+ pData[i] = _swap16(pData[i]);
}
+}
#else // BIG_ENDIAN
- // little-endian CPU, WAV file is ok as such
+// little-endian CPU, WAV file is ok as such
- // dummy helper-function
- static inline int _swap32(int &dwData)
- {
- // do nothing
- return dwData;
- }
+// dummy helper-function
+static inline int _swap32(int& dwData)
+{
+ // do nothing
+ return dwData;
+}
- // dummy helper-function
- static inline short _swap16(short &wData)
- {
- // do nothing
- return wData;
- }
+// dummy helper-function
+static inline short _swap16(short& wData)
+{
+ // do nothing
+ return wData;
+}
- // dummy helper-function
- static inline void _swap16Buffer(short *, int)
- {
- // do nothing
- }
+// dummy helper-function
+static inline void _swap16Buffer(short*, int)
+{
+ // do nothing
+}
#endif // BIG_ENDIAN
@@ -151,7 +160,7 @@ WavFileBase::~WavFileBase()
/// Get pointer to conversion buffer of at min. given size
-void *WavFileBase::getConvBuffer(int sizeBytes)
+void* WavFileBase::getConvBuffer(int sizeBytes)
{
if (convBuffSize < sizeBytes)
{
@@ -169,32 +178,26 @@ void *WavFileBase::getConvBuffer(int sizeBytes)
// Class WavInFile
//
-WavInFile::WavInFile(const char *fileName)
+WavInFile::WavInFile(const STRING& fileName)
{
// Try to open the file for reading
- fptr = fopen(fileName, "rb");
- if (fptr == nullptr)
+ fptr = FOPEN(fileName.c_str(), "rb");
+ if (fptr == nullptr)
{
- // didn't succeed
- string msg = "Error : Unable to open file \"";
- msg += fileName;
- msg += "\" for reading.";
- ST_THROW_RT_ERROR(msg.c_str());
+ ST_THROW_RT_ERROR("Error : Unable to open file for reading.");
}
init();
}
-WavInFile::WavInFile(FILE *file)
+WavInFile::WavInFile(FILE* file)
{
// Try to open the file for reading
fptr = file;
- if (!file)
+ if (!file)
{
- // didn't succeed
- string msg = "Error : Unable to access input stream for reading";
- ST_THROW_RT_ERROR(msg.c_str());
+ ST_THROW_RT_ERROR("Error : Unable to access input stream for reading");
}
init();
@@ -211,19 +214,17 @@ void WavInFile::init()
// Read the file headers
hdrsOk = readWavHeaders();
- if (hdrsOk != 0)
+ if (hdrsOk != 0)
{
- // Something didn't match in the wav file headers
ST_THROW_RT_ERROR("Input file is corrupt or not a WAV file");
}
// sanity check for format parameters
- if ((header.format.channel_number < 1) || (header.format.channel_number > 9) ||
- (header.format.sample_rate < 4000) || (header.format.sample_rate > 192000) ||
+ if ((header.format.channel_number < 1) || (header.format.channel_number > 9) ||
+ (header.format.sample_rate < 4000) || (header.format.sample_rate > 192000) ||
(header.format.byte_per_sample < 1) || (header.format.byte_per_sample > 320) ||
(header.format.bits_per_sample < 8) || (header.format.bits_per_sample > 32))
{
- // Something didn't match in the wav file headers
ST_THROW_RT_ERROR("Error: Illegal wav file header format parameters.");
}
@@ -260,7 +261,7 @@ int WavInFile::checkCharTags() const
}
-int WavInFile::read(unsigned char *buffer, int maxElems)
+int WavInFile::read(unsigned char* buffer, int maxElems)
{
int numBytes;
uint afterDataRead;
@@ -274,7 +275,7 @@ int WavInFile::read(unsigned char *buffer, int maxElems)
numBytes = maxElems;
afterDataRead = dataRead + numBytes;
- if (afterDataRead > header.data.data_len)
+ if (afterDataRead > header.data.data_len)
{
// Don't read more samples than are marked available in header
numBytes = (int)header.data.data_len - (int)dataRead;
@@ -289,7 +290,7 @@ int WavInFile::read(unsigned char *buffer, int maxElems)
}
-int WavInFile::read(short *buffer, int maxElems)
+int WavInFile::read(short* buffer, int maxElems)
{
unsigned int afterDataRead;
int numBytes;
@@ -298,53 +299,53 @@ int WavInFile::read(short *buffer, int maxElems)
assert(buffer);
switch (header.format.bits_per_sample)
{
- case 8:
- {
- // 8 bit format
- unsigned char *temp = (unsigned char*)getConvBuffer(maxElems);
- int i;
+ case 8:
+ {
+ // 8 bit format
+ unsigned char* temp = (unsigned char*)getConvBuffer(maxElems);
+ int i;
- numElems = read(temp, maxElems);
- // convert from 8 to 16 bit
- for (i = 0; i < numElems; i ++)
- {
- buffer[i] = (short)(((short)temp[i] - 128) * 256);
- }
- break;
+ numElems = read(temp, maxElems);
+ // convert from 8 to 16 bit
+ for (i = 0; i < numElems; i++)
+ {
+ buffer[i] = (short)(((short)temp[i] - 128) * 256);
+ }
+ break;
+ }
+
+ case 16:
+ {
+ // 16 bit format
+
+ assert(sizeof(short) == 2);
+
+ numBytes = maxElems * 2;
+ afterDataRead = dataRead + numBytes;
+ if (afterDataRead > header.data.data_len)
+ {
+ // Don't read more samples than are marked available in header
+ numBytes = (int)header.data.data_len - (int)dataRead;
+ assert(numBytes >= 0);
}
- case 16:
- {
- // 16 bit format
+ numBytes = (int)fread(buffer, 1, numBytes, fptr);
+ dataRead += numBytes;
+ numElems = numBytes / 2;
- assert(sizeof(short) == 2);
+ // 16bit samples, swap byte order if necessary
+ _swap16Buffer((short*)buffer, numElems);
+ break;
+ }
- numBytes = maxElems * 2;
- afterDataRead = dataRead + numBytes;
- if (afterDataRead > header.data.data_len)
- {
- // Don't read more samples than are marked available in header
- numBytes = (int)header.data.data_len - (int)dataRead;
- assert(numBytes >= 0);
- }
-
- numBytes = (int)fread(buffer, 1, numBytes, fptr);
- dataRead += numBytes;
- numElems = numBytes / 2;
-
- // 16bit samples, swap byte order if necessary
- _swap16Buffer((short *)buffer, numElems);
- break;
- }
-
- default:
- {
- stringstream ss;
- ss << "\nOnly 8/16 bit sample WAV files supported in integer compilation. Can't open WAV file with ";
- ss << (int)header.format.bits_per_sample;
- ss << " bit sample format. ";
- ST_THROW_RT_ERROR(ss.str().c_str());
- }
+ default:
+ {
+ stringstream ss;
+ ss << "\nOnly 8/16 bit sample WAV files supported in integer compilation. Can't open WAV file with ";
+ ss << (int)header.format.bits_per_sample;
+ ss << " bit sample format. ";
+ ST_THROW_RT_ERROR(ss.str().c_str());
+ }
};
return numElems;
@@ -353,7 +354,7 @@ int WavInFile::read(short *buffer, int maxElems)
/// Read data in float format. Notice that when reading in float format
/// 8/16/24/32 bit sample formats are supported
-int WavInFile::read(float *buffer, int maxElems)
+int WavInFile::read(float* buffer, int maxElems)
{
unsigned int afterDataRead;
int numBytes;
@@ -374,7 +375,7 @@ int WavInFile::read(float *buffer, int maxElems)
numBytes = maxElems * bytesPerSample;
afterDataRead = dataRead + numBytes;
- if (afterDataRead > header.data.data_len)
+ if (afterDataRead > header.data.data_len)
{
// Don't read more samples than are marked available in header
numBytes = (int)header.data.data_len - (int)dataRead;
@@ -382,7 +383,7 @@ int WavInFile::read(float *buffer, int maxElems)
}
// read raw data into temporary buffer
- char *temp = (char*)getConvBuffer(numBytes);
+ char* temp = (char*)getConvBuffer(numBytes);
numBytes = (int)fread(temp, 1, numBytes, fptr);
dataRead += numBytes;
@@ -391,56 +392,56 @@ int WavInFile::read(float *buffer, int maxElems)
// swap byte ordert & convert to float, depending on sample format
switch (bytesPerSample)
{
- case 1:
+ case 1:
+ {
+ unsigned char* temp2 = (unsigned char*)temp;
+ double conv = 1.0 / 128.0;
+ for (int i = 0; i < numElems; i++)
{
- unsigned char *temp2 = (unsigned char*)temp;
- double conv = 1.0 / 128.0;
- for (int i = 0; i < numElems; i ++)
- {
- buffer[i] = (float)(temp2[i] * conv - 1.0);
- }
- break;
+ buffer[i] = (float)(temp2[i] * conv - 1.0);
}
+ break;
+ }
- case 2:
+ case 2:
+ {
+ short* temp2 = (short*)temp;
+ double conv = 1.0 / 32768.0;
+ for (int i = 0; i < numElems; i++)
{
- short *temp2 = (short*)temp;
- double conv = 1.0 / 32768.0;
- for (int i = 0; i < numElems; i ++)
- {
- short value = temp2[i];
- buffer[i] = (float)(_swap16(value) * conv);
- }
- break;
+ short value = temp2[i];
+ buffer[i] = (float)(_swap16(value) * conv);
}
+ break;
+ }
- case 3:
+ case 3:
+ {
+ char* temp2 = (char*)temp;
+ double conv = 1.0 / 8388608.0;
+ for (int i = 0; i < numElems; i++)
{
- char *temp2 = (char *)temp;
- double conv = 1.0 / 8388608.0;
- for (int i = 0; i < numElems; i ++)
- {
- int value = *((int*)temp2);
- value = _swap32(value) & 0x00ffffff; // take 24 bits
- value |= (value & 0x00800000) ? 0xff000000 : 0; // extend minus sign bits
- buffer[i] = (float)(value * conv);
- temp2 += 3;
- }
- break;
+ int value = *((int*)temp2);
+ value = _swap32(value) & 0x00ffffff; // take 24 bits
+ value |= (value & 0x00800000) ? 0xff000000 : 0; // extend minus sign bits
+ buffer[i] = (float)(value * conv);
+ temp2 += 3;
}
+ break;
+ }
- case 4:
+ case 4:
+ {
+ int* temp2 = (int*)temp;
+ double conv = 1.0 / 2147483648.0;
+ assert(sizeof(int) == 4);
+ for (int i = 0; i < numElems; i++)
{
- int *temp2 = (int *)temp;
- double conv = 1.0 / 2147483648.0;
- assert(sizeof(int) == 4);
- for (int i = 0; i < numElems; i ++)
- {
- int value = temp2[i];
- buffer[i] = (float)(_swap32(value) * conv);
- }
- break;
+ int value = temp2[i];
+ buffer[i] = (float)(_swap32(value) * conv);
}
+ break;
+ }
}
return numElems;
@@ -462,15 +463,15 @@ static int isAlpha(char c)
// test if all characters are between a white space ' ' and little 'z'
-static int isAlphaStr(const char *str)
+static int isAlphaStr(const char* str)
{
char c;
c = str[0];
- while (c)
+ while (c)
{
if (isAlpha(c) == 0) return 0;
- str ++;
+ str++;
c = str[0];
}
@@ -483,7 +484,7 @@ int WavInFile::readRIFFBlock()
if (fread(&(header.riff), sizeof(WavRiff), 1, fptr) != 1) return -1;
// swap 32bit data byte order if necessary
- _swap32((int &)header.riff.package_len);
+ _swap32((int&)header.riff.package_len);
// header.riff.riff_char should equal to 'RIFF');
if (memcmp(riffStr, header.riff.riff_char, 4) != 0) return -1;
@@ -500,7 +501,7 @@ int WavInFile::readHeaderBlock()
string sLabel;
// lead label string
- if (fread(label, 1, 4, fptr) !=4) return -1;
+ if (fread(label, 1, 4, fptr) != 4) return -1;
label[4] = 0;
if (isAlphaStr(label) == 0) return -1; // not a valid label
@@ -536,12 +537,12 @@ int WavInFile::readHeaderBlock()
if (fread(&(header.format.fixed), nLen, 1, fptr) != 1) return -1;
// swap byte order if necessary
- _swap16((short &)header.format.fixed); // short int fixed;
- _swap16((short &)header.format.channel_number); // short int channel_number;
- _swap32((int &)header.format.sample_rate); // int sample_rate;
- _swap32((int &)header.format.byte_rate); // int byte_rate;
- _swap16((short &)header.format.byte_per_sample); // short int byte_per_sample;
- _swap16((short &)header.format.bits_per_sample); // short int bits_per_sample;
+ _swap16((short&)header.format.fixed); // short int fixed;
+ _swap16((short&)header.format.channel_number); // short int channel_number;
+ _swap32((int&)header.format.sample_rate); // int sample_rate;
+ _swap32((int&)header.format.byte_rate); // int byte_rate;
+ _swap16((short&)header.format.byte_per_sample); // short int byte_per_sample;
+ _swap16((short&)header.format.bits_per_sample); // short int bits_per_sample;
// if format_len is larger than expected, skip the extra data
if (nDump > 0)
@@ -581,7 +582,7 @@ int WavInFile::readHeaderBlock()
if (fread(&(header.fact.fact_sample_len), nLen, 1, fptr) != 1) return -1;
// swap byte order if necessary
- _swap32((int &)header.fact.fact_sample_len); // int sample_length;
+ _swap32((int&)header.fact.fact_sample_len); // int sample_length;
// if fact_len is larger than expected, skip the extra data
if (nDump > 0)
@@ -598,7 +599,7 @@ int WavInFile::readHeaderBlock()
if (fread(&(header.data.data_len), sizeof(uint), 1, fptr) != 1) return -1;
// swap byte order if necessary
- _swap32((int &)header.data.data_len);
+ _swap32((int&)header.data.data_len);
return 1;
}
@@ -611,7 +612,7 @@ int WavInFile::readHeaderBlock()
// read length
if (fread(&len, sizeof(len), 1, fptr) != 1) return -1;
// scan through the block
- for (i = 0; i < len; i ++)
+ for (i = 0; i < len; i++)
{
if (fread(&temp, 1, 1, fptr) != 1) return -1;
if (feof(fptr)) return -1; // unexpected eof
@@ -703,17 +704,13 @@ uint WavInFile::getElapsedMS() const
// Class WavOutFile
//
-WavOutFile::WavOutFile(const char *fileName, int sampleRate, int bits, int channels)
+WavOutFile::WavOutFile(const STRING& fileName, int sampleRate, int bits, int channels)
{
bytesWritten = 0;
- fptr = fopen(fileName, "wb");
- if (fptr == nullptr)
+ fptr = FOPEN(fileName.c_str(), "wb");
+ if (fptr == nullptr)
{
- string msg = "Error : Unable to open file \"";
- msg += fileName;
- msg += "\" for writing.";
- //pmsg = msg.c_str;
- ST_THROW_RT_ERROR(msg.c_str());
+ ST_THROW_RT_ERROR("Error : Unable to open file for writing.");
}
fillInHeader(sampleRate, bits, channels);
@@ -721,14 +718,13 @@ WavOutFile::WavOutFile(const char *fileName, int sampleRate, int bits, int chann
}
-WavOutFile::WavOutFile(FILE *file, int sampleRate, int bits, int channels)
+WavOutFile::WavOutFile(FILE* file, int sampleRate, int bits, int channels)
{
bytesWritten = 0;
fptr = file;
- if (fptr == nullptr)
+ if (fptr == nullptr)
{
- string msg = "Error : Unable to access output file stream.";
- ST_THROW_RT_ERROR(msg.c_str());
+ ST_THROW_RT_ERROR("Error : Unable to access output file stream.");
}
fillInHeader(sampleRate, bits, channels);
@@ -788,8 +784,8 @@ void WavOutFile::finishHeader()
// supplement the file length into the header structure
header.riff.package_len = bytesWritten + sizeof(WavHeader) - sizeof(WavRiff) + 4;
header.data.data_len = bytesWritten;
- header.fact.fact_sample_len = bytesWritten / header.format.byte_per_sample;
-
+ header.fact.fact_sample_len = bytesWritten / header.format.byte_per_sample;
+
writeHeader();
}
@@ -801,18 +797,18 @@ void WavOutFile::writeHeader()
// swap byte order if necessary
hdrTemp = header;
- _swap32((int &)hdrTemp.riff.package_len);
- _swap32((int &)hdrTemp.format.format_len);
- _swap16((short &)hdrTemp.format.fixed);
- _swap16((short &)hdrTemp.format.channel_number);
- _swap32((int &)hdrTemp.format.sample_rate);
- _swap32((int &)hdrTemp.format.byte_rate);
- _swap16((short &)hdrTemp.format.byte_per_sample);
- _swap16((short &)hdrTemp.format.bits_per_sample);
- _swap32((int &)hdrTemp.data.data_len);
- _swap32((int &)hdrTemp.fact.fact_len);
- _swap32((int &)hdrTemp.fact.fact_sample_len);
-
+ _swap32((int&)hdrTemp.riff.package_len);
+ _swap32((int&)hdrTemp.format.format_len);
+ _swap16((short&)hdrTemp.format.fixed);
+ _swap16((short&)hdrTemp.format.channel_number);
+ _swap32((int&)hdrTemp.format.sample_rate);
+ _swap32((int&)hdrTemp.format.byte_rate);
+ _swap16((short&)hdrTemp.format.byte_per_sample);
+ _swap16((short&)hdrTemp.format.bits_per_sample);
+ _swap32((int&)hdrTemp.data.data_len);
+ _swap32((int&)hdrTemp.fact.fact_len);
+ _swap32((int&)hdrTemp.fact.fact_sample_len);
+
// write the supplemented header in the beginning of the file
fseek(fptr, 0, SEEK_SET);
res = (int)fwrite(&hdrTemp, sizeof(hdrTemp), 1, fptr);
@@ -826,7 +822,7 @@ void WavOutFile::writeHeader()
}
-void WavOutFile::write(const unsigned char *buffer, int numElems)
+void WavOutFile::write(const unsigned char* buffer, int numElems)
{
int res;
@@ -837,7 +833,7 @@ void WavOutFile::write(const unsigned char *buffer, int numElems)
assert(sizeof(char) == 1);
res = (int)fwrite(buffer, 1, numElems, fptr);
- if (res != numElems)
+ if (res != numElems)
{
ST_THROW_RT_ERROR("Error while writing to a wav file.");
}
@@ -846,7 +842,7 @@ void WavOutFile::write(const unsigned char *buffer, int numElems)
}
-void WavOutFile::write(const short *buffer, int numElems)
+void WavOutFile::write(const short* buffer, int numElems)
{
int res;
@@ -855,47 +851,47 @@ void WavOutFile::write(const short *buffer, int numElems)
switch (header.format.bits_per_sample)
{
- case 8:
+ case 8:
+ {
+ int i;
+ unsigned char* temp = (unsigned char*)getConvBuffer(numElems);
+ // convert from 16bit format to 8bit format
+ for (i = 0; i < numElems; i++)
{
- int i;
- unsigned char *temp = (unsigned char *)getConvBuffer(numElems);
- // convert from 16bit format to 8bit format
- for (i = 0; i < numElems; i ++)
- {
- temp[i] = (unsigned char)(buffer[i] / 256 + 128);
- }
- // write in 8bit format
- write(temp, numElems);
- break;
+ temp[i] = (unsigned char)(buffer[i] / 256 + 128);
}
+ // write in 8bit format
+ write(temp, numElems);
+ break;
+ }
- case 16:
+ case 16:
+ {
+ // 16bit format
+
+ // use temp buffer to swap byte order if necessary
+ short* pTemp = (short*)getConvBuffer(numElems * sizeof(short));
+ memcpy(pTemp, buffer, (size_t)numElems * 2L);
+ _swap16Buffer(pTemp, numElems);
+
+ res = (int)fwrite(pTemp, 2, numElems, fptr);
+
+ if (res != numElems)
{
- // 16bit format
-
- // use temp buffer to swap byte order if necessary
- short *pTemp = (short *)getConvBuffer(numElems * sizeof(short));
- memcpy(pTemp, buffer, numElems * 2);
- _swap16Buffer(pTemp, numElems);
-
- res = (int)fwrite(pTemp, 2, numElems, fptr);
-
- if (res != numElems)
- {
- ST_THROW_RT_ERROR("Error while writing to a wav file.");
- }
- bytesWritten += 2 * numElems;
- break;
+ ST_THROW_RT_ERROR("Error while writing to a wav file.");
}
+ bytesWritten += 2 * numElems;
+ break;
+ }
- default:
- {
- stringstream ss;
- ss << "\nOnly 8/16 bit sample WAV files supported in integer compilation. Can't open WAV file with ";
- ss << (int)header.format.bits_per_sample;
- ss << " bit sample format. ";
- ST_THROW_RT_ERROR(ss.str().c_str());
- }
+ default:
+ {
+ stringstream ss;
+ ss << "\nOnly 8/16 bit sample WAV files supported in integer compilation. Can't open WAV file with ";
+ ss << (int)header.format.bits_per_sample;
+ ss << " bit sample format. ";
+ ST_THROW_RT_ERROR(ss.str().c_str());
+ }
}
}
@@ -903,10 +899,10 @@ void WavOutFile::write(const short *buffer, int numElems)
/// Convert from float to integer and saturate
inline int saturate(float fvalue, float minval, float maxval)
{
- if (fvalue > maxval)
+ if (fvalue > maxval)
{
fvalue = maxval;
- }
+ }
else if (fvalue < minval)
{
fvalue = minval;
@@ -915,7 +911,7 @@ inline int saturate(float fvalue, float minval, float maxval)
}
-void WavOutFile::write(const float *buffer, int numElems)
+void WavOutFile::write(const float* buffer, int numElems)
{
int numBytes;
int bytesPerSample;
@@ -924,63 +920,65 @@ void WavOutFile::write(const float *buffer, int numElems)
bytesPerSample = header.format.bits_per_sample / 8;
numBytes = numElems * bytesPerSample;
- void *temp = getConvBuffer(numBytes + 7); // round bit up to avoid buffer overrun with 24bit-value assignment
+ void* temp = getConvBuffer(numBytes + 7); // round bit up to avoid buffer overrun with 24bit-value assignment
switch (bytesPerSample)
{
- case 1:
+ case 1:
+ {
+ unsigned char* temp2 = (unsigned char*)temp;
+ for (int i = 0; i < numElems; i++)
{
- unsigned char *temp2 = (unsigned char *)temp;
- for (int i = 0; i < numElems; i ++)
- {
- temp2[i] = (unsigned char)saturate(buffer[i] * 128.0f + 128.0f, 0.0f, 255.0f);
- }
- break;
+ temp2[i] = (unsigned char)saturate(buffer[i] * 128.0f + 128.0f, 0.0f, 255.0f);
}
+ break;
+ }
- case 2:
+ case 2:
+ {
+ short* temp2 = (short*)temp;
+ for (int i = 0; i < numElems; i++)
{
- short *temp2 = (short *)temp;
- for (int i = 0; i < numElems; i ++)
- {
- short value = (short)saturate(buffer[i] * 32768.0f, -32768.0f, 32767.0f);
- temp2[i] = _swap16(value);
- }
- break;
+ short value = (short)saturate(buffer[i] * 32768.0f, -32768.0f, 32767.0f);
+ temp2[i] = _swap16(value);
}
+ break;
+ }
- case 3:
+ case 3:
+ {
+ char* temp2 = (char*)temp;
+ for (int i = 0; i < numElems; i++)
{
- char *temp2 = (char *)temp;
- for (int i = 0; i < numElems; i ++)
- {
- int value = saturate(buffer[i] * 8388608.0f, -8388608.0f, 8388607.0f);
- *((int*)temp2) = _swap32(value);
- temp2 += 3;
- }
- break;
+ int value = saturate(buffer[i] * 8388608.0f, -8388608.0f, 8388607.0f);
+ *((int*)temp2) = _swap32(value);
+ temp2 += 3;
}
+ break;
+ }
- case 4:
+ case 4:
+ {
+ int* temp2 = (int*)temp;
+ for (int i = 0; i < numElems; i++)
{
- int *temp2 = (int *)temp;
- for (int i = 0; i < numElems; i ++)
- {
- int value = saturate(buffer[i] * 2147483648.0f, -2147483648.0f, 2147483647.0f);
- temp2[i] = _swap32(value);
- }
- break;
+ int value = saturate(buffer[i] * 2147483648.0f, -2147483648.0f, 2147483647.0f);
+ temp2[i] = _swap32(value);
}
+ break;
+ }
- default:
- assert(false);
+ default:
+ assert(false);
}
int res = (int)fwrite(temp, 1, numBytes, fptr);
- if (res != numBytes)
+ if (res != numBytes)
{
ST_THROW_RT_ERROR("Error while writing to a wav file.");
}
bytesWritten += numBytes;
}
+
+}
diff --git a/source/SoundStretch/WavFile.h b/source/SoundStretch/WavFile.h
index 61a174e..57fedef 100644
--- a/source/SoundStretch/WavFile.h
+++ b/source/SoundStretch/WavFile.h
@@ -40,7 +40,12 @@
#ifndef WAVFILE_H
#define WAVFILE_H
-#include
+#include
+#include
+#include "SS_CharTypes.h"
+
+namespace soundstretch
+{
#ifndef uint
typedef unsigned int uint;
@@ -145,7 +150,7 @@ private:
public:
/// Constructor: Opens the given WAV file. If the file can't be opened,
/// throws 'runtime_error' exception.
- WavInFile(const char *filename);
+ WavInFile(const STRING& filename);
WavInFile(FILE *file);
@@ -241,7 +246,7 @@ private:
public:
/// Constructor: Creates a new WAV file. Throws a 'runtime_error' exception
/// if file creation fails.
- WavOutFile(const char *fileName, ///< Filename
+ WavOutFile(const STRING& fileName, ///< Filename
int sampleRate, ///< Sample rate (e.g. 44100 etc)
int bits, ///< Bits per sample (8 or 16 bits)
int channels ///< Number of channels (1=mono, 2=stereo)
@@ -271,4 +276,6 @@ public:
);
};
+ }
+
#endif
diff --git a/source/SoundStretch/main.cpp b/source/SoundStretch/main.cpp
index 1651ce7..8ae71fa 100644
--- a/source/SoundStretch/main.cpp
+++ b/source/SoundStretch/main.cpp
@@ -29,10 +29,12 @@
//
////////////////////////////////////////////////////////////////////////////////
+#include
+#include
#include
-#include
-#include
-#include
+#include
+#include
+#include
#include "RunParameters.h"
#include "WavFile.h"
#include "SoundTouch.h"
@@ -41,22 +43,25 @@
using namespace soundtouch;
using namespace std;
+namespace soundstretch
+{
+
// Processing chunk size (size chosen to be divisible by 2, 4, 6, 8, 10, 12, 14, 16 channels ...)
#define BUFF_SIZE 6720
#if _WIN32
- #include
- #include
+#include
+#include
- // Macro for Win32 standard input/output stream support: Sets a file stream into binary mode
- #define SET_STREAM_TO_BIN_MODE(f) (_setmode(_fileno(f), _O_BINARY))
+// Macro for Win32 standard input/output stream support: Sets a file stream into binary mode
+#define SET_STREAM_TO_BIN_MODE(f) (_setmode(_fileno(f), _O_BINARY))
#else
// Not needed for GNU environment...
- #define SET_STREAM_TO_BIN_MODE(f) {}
+#define SET_STREAM_TO_BIN_MODE(f) {}
#endif
-static const char _helloText[] =
+static const char _helloText[] =
"\n"
" SoundStretch v%s - Copyright (c) Olli Parviainen\n"
"=========================================================\n"
@@ -68,90 +73,81 @@ static const char _helloText[] =
"more information.\n"
"\n";
-static void openFiles(WavInFile **inFile, WavOutFile **outFile, const RunParameters *params)
+static void openFiles(unique_ptr& inFile, unique_ptr& outFile, const RunParameters& params)
{
- int bits, samplerate, channels;
-
- if (strcmp(params->inFileName, "stdin") == 0)
+ if (params.inFileName == STRING_CONST("stdin"))
{
// used 'stdin' as input file
SET_STREAM_TO_BIN_MODE(stdin);
- *inFile = new WavInFile(stdin);
+ inFile = make_unique(stdin);
}
else
{
// open input file...
- *inFile = new WavInFile(params->inFileName);
+ inFile = make_unique(params.inFileName.c_str());
}
// ... open output file with same sound parameters
- bits = (int)(*inFile)->getNumBits();
- samplerate = (int)(*inFile)->getSampleRate();
- channels = (int)(*inFile)->getNumChannels();
+ const int bits = (int)inFile->getNumBits();
+ const int samplerate = (int)inFile->getSampleRate();
+ const int channels = (int)inFile->getNumChannels();
- if (params->outFileName)
+ if (!params.outFileName.empty())
{
- if (strcmp(params->outFileName, "stdout") == 0)
+ if (params.outFileName == STRING_CONST("stdout"))
{
SET_STREAM_TO_BIN_MODE(stdout);
- *outFile = new WavOutFile(stdout, samplerate, bits, channels);
+ outFile = make_unique(stdout, samplerate, bits, channels);
}
else
{
- *outFile = new WavOutFile(params->outFileName, samplerate, bits, channels);
+ outFile = make_unique(params.outFileName.c_str(), samplerate, bits, channels);
}
}
- else
- {
- *outFile = nullptr;
- }
}
// Sets the 'SoundTouch' object up according to input file sound format &
// command line parameters
-static void setup(SoundTouch *pSoundTouch, const WavInFile *inFile, const RunParameters *params)
+static void setup(SoundTouch& soundTouch, const WavInFile& inFile, const RunParameters& params)
{
- int sampleRate;
- int channels;
+ const int sampleRate = (int)inFile.getSampleRate();
+ const int channels = (int)inFile.getNumChannels();
+ soundTouch.setSampleRate(sampleRate);
+ soundTouch.setChannels(channels);
- sampleRate = (int)inFile->getSampleRate();
- channels = (int)inFile->getNumChannels();
- pSoundTouch->setSampleRate(sampleRate);
- pSoundTouch->setChannels(channels);
+ soundTouch.setTempoChange(params.tempoDelta);
+ soundTouch.setPitchSemiTones(params.pitchDelta);
+ soundTouch.setRateChange(params.rateDelta);
- pSoundTouch->setTempoChange(params->tempoDelta);
- pSoundTouch->setPitchSemiTones(params->pitchDelta);
- pSoundTouch->setRateChange(params->rateDelta);
+ soundTouch.setSetting(SETTING_USE_QUICKSEEK, params.quick);
+ soundTouch.setSetting(SETTING_USE_AA_FILTER, !(params.noAntiAlias));
- pSoundTouch->setSetting(SETTING_USE_QUICKSEEK, params->quick);
- pSoundTouch->setSetting(SETTING_USE_AA_FILTER, !(params->noAntiAlias));
-
- if (params->speech)
+ if (params.speech)
{
// use settings for speech processing
- pSoundTouch->setSetting(SETTING_SEQUENCE_MS, 40);
- pSoundTouch->setSetting(SETTING_SEEKWINDOW_MS, 15);
- pSoundTouch->setSetting(SETTING_OVERLAP_MS, 8);
+ soundTouch.setSetting(SETTING_SEQUENCE_MS, 40);
+ soundTouch.setSetting(SETTING_SEEKWINDOW_MS, 15);
+ soundTouch.setSetting(SETTING_OVERLAP_MS, 8);
fprintf(stderr, "Tune processing parameters for speech processing.\n");
}
// print processing information
- if (params->outFileName)
+ if (!params.outFileName.empty())
{
#ifdef SOUNDTOUCH_INTEGER_SAMPLES
fprintf(stderr, "Uses 16bit integer sample type in processing.\n\n");
#else
- #ifndef SOUNDTOUCH_FLOAT_SAMPLES
- #error "Sampletype not defined"
- #endif
+#ifndef SOUNDTOUCH_FLOAT_SAMPLES
+#error "Sampletype not defined"
+#endif
fprintf(stderr, "Uses 32bit floating point sample type in processing.\n\n");
#endif
// print processing information only if outFileName given i.e. some processing will happen
fprintf(stderr, "Processing the file with the following changes:\n");
- fprintf(stderr, " tempo change = %+g %%\n", params->tempoDelta);
- fprintf(stderr, " pitch change = %+g semitones\n", params->pitchDelta);
- fprintf(stderr, " rate change = %+g %%\n\n", params->rateDelta);
+ fprintf(stderr, " tempo change = %+g %%\n", params.tempoDelta);
+ fprintf(stderr, " pitch change = %+g semitones\n", params.pitchDelta);
+ fprintf(stderr, " rate change = %+g %%\n\n", params.rateDelta);
fprintf(stderr, "Working...");
}
else
@@ -165,30 +161,24 @@ static void setup(SoundTouch *pSoundTouch, const WavInFile *inFile, const RunPar
// Processes the sound
-static void process(SoundTouch *pSoundTouch, WavInFile *inFile, WavOutFile *outFile)
+static void process(SoundTouch& soundTouch, WavInFile& inFile, WavOutFile& outFile)
{
- int nSamples;
- int nChannels;
- int buffSizeSamples;
SAMPLETYPE sampleBuffer[BUFF_SIZE];
+ int nSamples;
- if ((inFile == nullptr) || (outFile == nullptr)) return; // nothing to do.
-
- nChannels = (int)inFile->getNumChannels();
+ const int nChannels = (int)inFile.getNumChannels();
assert(nChannels > 0);
- buffSizeSamples = BUFF_SIZE / nChannels;
+ const int buffSizeSamples = BUFF_SIZE / nChannels;
// Process samples read from the input file
- while (inFile->eof() == 0)
+ while (inFile.eof() == 0)
{
- int num;
-
// Read a chunk of samples from the input file
- num = inFile->read(sampleBuffer, BUFF_SIZE);
- nSamples = num / (int)inFile->getNumChannels();
+ const int num = inFile.read(sampleBuffer, BUFF_SIZE);
+ int nSamples = num / (int)inFile.getNumChannels();
// Feed the samples into SoundTouch processor
- pSoundTouch->putSamples(sampleBuffer, nSamples);
+ soundTouch.putSamples(sampleBuffer, nSamples);
// Read ready samples from SoundTouch processor & write them output file.
// NOTES:
@@ -198,59 +188,55 @@ static void process(SoundTouch *pSoundTouch, WavInFile *inFile, WavOutFile *outF
// ready samples than would fit into 'sampleBuffer', and for this reason
// the 'receiveSamples' call is iterated for as many times as it
// outputs samples.
- do
+ do
{
- nSamples = pSoundTouch->receiveSamples(sampleBuffer, buffSizeSamples);
- outFile->write(sampleBuffer, nSamples * nChannels);
+ nSamples = soundTouch.receiveSamples(sampleBuffer, buffSizeSamples);
+ outFile.write(sampleBuffer, nSamples * nChannels);
} while (nSamples != 0);
}
// Now the input file is processed, yet 'flush' few last samples that are
// hiding in the SoundTouch's internal processing pipeline.
- pSoundTouch->flush();
- do
+ soundTouch.flush();
+ do
{
- nSamples = pSoundTouch->receiveSamples(sampleBuffer, buffSizeSamples);
- outFile->write(sampleBuffer, nSamples * nChannels);
+ nSamples = soundTouch.receiveSamples(sampleBuffer, buffSizeSamples);
+ outFile.write(sampleBuffer, nSamples * nChannels);
} while (nSamples != 0);
}
// Detect BPM rate of inFile and adjust tempo setting accordingly if necessary
-static void detectBPM(WavInFile *inFile, RunParameters *params)
+static void detectBPM(WavInFile& inFile, RunParameters& params)
{
- float bpmValue;
- int nChannels;
- BPMDetect bpm(inFile->getNumChannels(), inFile->getSampleRate());
+ BPMDetect bpm(inFile.getNumChannels(), inFile.getSampleRate());
SAMPLETYPE sampleBuffer[BUFF_SIZE];
// detect bpm rate
fprintf(stderr, "Detecting BPM rate...");
fflush(stderr);
- nChannels = (int)inFile->getNumChannels();
+ const int nChannels = (int)inFile.getNumChannels();
int readSize = BUFF_SIZE - BUFF_SIZE % nChannels; // round read size down to multiple of num.channels
// Process the 'inFile' in small blocks, repeat until whole file has
// been processed
- while (inFile->eof() == 0)
+ while (inFile.eof() == 0)
{
- int num, samples;
-
// Read sample data from input file
- num = inFile->read(sampleBuffer, readSize);
+ const int num = inFile.read(sampleBuffer, readSize);
// Enter the new samples to the bpm analyzer class
- samples = num / nChannels;
+ const int samples = num / nChannels;
bpm.inputSamples(sampleBuffer, samples);
}
// Now the whole song data has been analyzed. Read the resulting bpm.
- bpmValue = bpm.getBpm();
+ const float bpmValue = bpm.getBpm();
fprintf(stderr, "Done!\n");
// rewind the file after bpm detection
- inFile->rewind();
+ inFile.rewind();
if (bpmValue > 0)
{
@@ -262,61 +248,64 @@ static void detectBPM(WavInFile *inFile, RunParameters *params)
return;
}
- if (params->goalBPM > 0)
+ if (params.goalBPM > 0)
{
// adjust tempo to given bpm
- params->tempoDelta = (params->goalBPM / bpmValue - 1.0f) * 100.0f;
- fprintf(stderr, "The file will be converted to %.1f BPM\n\n", params->goalBPM);
+ params.tempoDelta = (params.goalBPM / bpmValue - 1.0f) * 100.0f;
+ fprintf(stderr, "The file will be converted to %.1f BPM\n\n", params.goalBPM);
}
}
-
-int main(const int nParams, const char * const paramStr[])
+void ss_main(RunParameters& params)
{
- WavInFile *inFile;
- WavOutFile *outFile;
- RunParameters *params;
+ unique_ptr inFile;
+ unique_ptr outFile;
SoundTouch soundTouch;
- fprintf(stderr, _helloText, SoundTouch::getVersionString());
+ fprintf(stderr, _helloText, soundTouch.getVersionString());
- try
+ // Open input & output files
+ openFiles(inFile, outFile, params);
+
+ if (params.detectBPM == true)
{
- // Parse command line parameters
- params = new RunParameters(nParams, paramStr);
+ // detect sound BPM (and adjust processing parameters
+ // accordingly if necessary)
+ detectBPM(*inFile, params);
+ }
- // Open input & output files
- openFiles(&inFile, &outFile, params);
+ // Setup the 'SoundTouch' object for processing the sound
+ setup(soundTouch, *inFile, params);
- if (params->detectBPM == true)
- {
- // detect sound BPM (and adjust processing parameters
- // accordingly if necessary)
- detectBPM(inFile, params);
- }
-
- // Setup the 'SoundTouch' object for processing the sound
- setup(&soundTouch, inFile, params);
-
- // clock_t cs = clock(); // for benchmarking processing duration
- // Process the sound
- process(&soundTouch, inFile, outFile);
- // clock_t ce = clock(); // for benchmarking processing duration
- // printf("duration: %lf\n", (double)(ce-cs)/CLOCKS_PER_SEC);
-
- // Close WAV file handles & dispose of the objects
- delete inFile;
- delete outFile;
- delete params;
-
- fprintf(stderr, "Done!\n");
- }
- catch (const runtime_error &e)
+ // clock_t cs = clock(); // for benchmarking processing duration
+ // Process the sound
+ if (inFile && outFile)
+ {
+ process(soundTouch, *inFile, *outFile);
+ }
+ // clock_t ce = clock(); // for benchmarking processing duration
+ // printf("duration: %lf\n", (double)(ce-cs)/CLOCKS_PER_SEC);
+
+ fprintf(stderr, "Done!\n");
+}
+
+}
+
+#if _WIN32
+int wmain(int argc, const wchar_t* args[])
+#else
+int main(int argc, const char* args[])
+#endif
+{
+ try
+ {
+ soundstretch::RunParameters params(argc, args);
+ soundstretch::ss_main(params);
+ }
+ catch (const runtime_error& e)
{
- // An exception occurred during processing, display an error message
fprintf(stderr, "%s\n", e.what());
return -1;
}
-
return 0;
}
diff --git a/source/SoundStretch/soundstretch.vcxproj b/source/SoundStretch/soundstretch.vcxproj
index 8f7ba3a..780d4e4 100644
--- a/source/SoundStretch/soundstretch.vcxproj
+++ b/source/SoundStretch/soundstretch.vcxproj
@@ -28,25 +28,25 @@
Application
v142
false
- MultiByte
+ Unicode
Application
v142
false
- MultiByte
+ Unicode
Application
v142
false
- MultiByte
+ Unicode
Application
v142
false
- MultiByte
+ Unicode
@@ -134,10 +134,7 @@
true
$(OutDir)$(TargetName).map
Console
- false
- MachineX86
- false
if not exist ..\..\bin mkdir ..\..\bin
@@ -183,9 +180,7 @@ copy $(OutDir)$(TargetName)$(TargetExt) ..\..\bin\
true
$(OutDir)$(TargetName).map
Console
- false
- MachineX86
if not exist ..\..\bin mkdir ..\..\bin
@@ -234,9 +229,7 @@ copy $(OutDir)$(TargetName)$(TargetExt) ..\..\bin\
true
$(OutDir)$(TargetName).map
Console
- false
- MachineX64
if not exist ..\..\bin mkdir ..\..\bin
@@ -284,9 +277,7 @@ copy $(OutDir)$(TargetName)$(TargetExt) ..\..\bin\
true
$(OutDir)$(TargetName).map
Console
- false
- MachineX64
if not exist ..\..\bin mkdir ..\..\bin
@@ -327,6 +318,7 @@ copy $(OutDir)$(TargetName)$(TargetExt) ..\..\bin\
+
diff --git a/source/SoundTouch/SoundTouch.vcxproj b/source/SoundTouch/SoundTouch.vcxproj
index 32d23de..553b6e8 100644
--- a/source/SoundTouch/SoundTouch.vcxproj
+++ b/source/SoundTouch/SoundTouch.vcxproj
@@ -27,25 +27,25 @@
StaticLibrary
v142
false
- MultiByte
+ Unicode
StaticLibrary
v142
false
- MultiByte
+ Unicode
StaticLibrary
v142
false
- MultiByte
+ Unicode
StaticLibrary
v142
false
- MultiByte
+ Unicode
diff --git a/source/SoundTouchDLL/DllTest/DllTest.cpp b/source/SoundTouchDLL/DllTest/DllTest.cpp
index 666405d..8fb7d09 100644
--- a/source/SoundTouchDLL/DllTest/DllTest.cpp
+++ b/source/SoundTouchDLL/DllTest/DllTest.cpp
@@ -16,9 +16,10 @@
#include "../../SoundStretch/WavFile.h"
using namespace std;
+using namespace soundstretch;
// DllTest main
-int main(int argc, char *argv[])
+int wmain(int argc, const wchar_t *argv[])
{
// Check program arguments
if (argc < 4)
@@ -27,22 +28,22 @@ int main(int argc, char *argv[])
return -1;
}
- const char *inFileName = argv[1];
- const char *outFileName = argv[2];
- string str_sampleType = argv[3];
+ wstring inFileName = argv[1];
+ wstring outFileName = argv[2];
+ wstring str_sampleType = argv[3];
bool floatSample;
- if (str_sampleType.compare("float") == 0)
+ if (str_sampleType == L"float")
{
floatSample = true;
}
- else if (str_sampleType.compare("short") == 0)
+ else if (str_sampleType == L"short")
{
floatSample = false;
}
else
{
- cerr << "Missing or invalid sampletype '" << str_sampleType << "'. Expected either short or float" << endl;
+ cerr << "Missing or invalid sampletype. Expected either short or float" << endl;
return -1;
}
diff --git a/source/SoundTouchDLL/SoundTouchDLL.rc b/source/SoundTouchDLL/SoundTouchDLL.rc
index e23ef72..3db03c6 100644
--- a/source/SoundTouchDLL/SoundTouchDLL.rc
+++ b/source/SoundTouchDLL/SoundTouchDLL.rc
@@ -69,12 +69,12 @@ BEGIN
BEGIN
VALUE "Comments", "SoundTouch Library licensed for 3rd party applications subject to LGPL license v2.1. Visit http://www.surina.net/soundtouch for more information about the SoundTouch library."
VALUE "FileDescription", "SoundTouch Dynamic Link Library"
- VALUE "FileVersion", "2.3.2.0"
+ VALUE "FileVersion", "2.3.3.0"
VALUE "InternalName", "SoundTouch"
- VALUE "LegalCopyright", "Copyright (C) Olli Parviainen 2023"
+ VALUE "LegalCopyright", "Copyright (C) Olli Parviainen 2024"
VALUE "OriginalFilename", "SoundTouch.dll"
VALUE "ProductName", " SoundTouch Dynamic Link Library"
- VALUE "ProductVersion", "2.3.2.0"
+ VALUE "ProductVersion", "2.3.3.0"
END
END
BLOCK "VarFileInfo"
diff --git a/source/SoundTouchDLL/SoundTouchDLL.vcxproj b/source/SoundTouchDLL/SoundTouchDLL.vcxproj
index 6ec3e1d..93e3238 100644
--- a/source/SoundTouchDLL/SoundTouchDLL.vcxproj
+++ b/source/SoundTouchDLL/SoundTouchDLL.vcxproj
@@ -27,22 +27,22 @@
DynamicLibrary
v142
- MultiByte
+ Unicode
DynamicLibrary
v142
- MultiByte
+ Unicode
DynamicLibrary
v142
- MultiByte
+ Unicode
DynamicLibrary
v142
- MultiByte
+ Unicode