875c95a98020 — Chris Cannam 15 days ago
Merge
M src/AudioWriteStreamFactory.cpp +8 -1
@@ 60,7 60,7 @@ AudioWriteStreamFactory::createWriteStre
 
     AudioWriteStreamFactoryImpl *f = AudioWriteStreamFactoryImpl::getInstance();
 
-    if (extension == "") {
+    if (extension == "" || extension.size() > 4) {
         // We explicitly support extension-less filenames and write
         // them in RIFF/WAVE format. (This is in order to support
         // programmatically generated temporary files created with

          
@@ 141,8 141,15 @@ AudioWriteStreamFactory::isExtensionSupp
 // #ifdef'd out if the implementation is not selected, so there is no
 // overhead.
 
+// WavFileWriteStream uses libsndfile, which is mostly trustworthy
 #include "WavFileWriteStream.cpp"
+
+// SimpleWavFileWriteStream writes only 24-bit WAV files. The
+// dedicated WavFileReadStream using libsndfile is generally much
+// better and goes first
 #include "SimpleWavFileWriteStream.cpp"
+
 #include "CoreAudioWriteStream.cpp"
+
 #include "OpusWriteStream.cpp"
 

          
M src/OpusWriteStream.cpp +3 -1
@@ 33,6 33,7 @@ 
 */
 
 #ifdef HAVE_OPUS
+#ifndef HAVE_OPUS_READ_ONLY
 
 //#define DEBUG_OPUS_WRITE 1
 

          
@@ 157,4 158,5 @@ OpusWriteStream::putInterleavedFrames(si
 
 }
 
-#endif
+#endif // !HAVE_OPUS_READ_ONLY
+#endif // HAVE_OPUS

          
M src/OpusWriteStream.h +3 -1
@@ 38,6 38,7 @@ 
 #include "../bqaudiostream/AudioWriteStream.h"
 
 #ifdef HAVE_OPUS
+#ifndef HAVE_OPUS_READ_ONLY
 
 namespace breakfastquay
 {

          
@@ 61,6 62,7 @@ protected:
 
 }
 
-#endif
+#endif // !HAVE_OPUS_READ_ONLY
+#endif // HAVE_OPUS
 
 #endif

          
M src/SimpleWavFileReadStream.cpp +18 -3
@@ 68,9 68,24 @@ SimpleWavFileReadStream::SimpleWavFileRe
     m_dataReadStart(0),
     m_retryCount(0)
 {
-    m_file = new std::ifstream(filename.c_str(),
-                               std::ios::in | std::ios::binary);
-
+#ifdef _MSC_VER
+    // This is behind _MSC_VER not _WIN32 because the fstream
+    // constructors from wchar bufs are an MSVC extension not
+    // available in e.g. MinGW
+    int wlen = MultiByteToWideChar
+        (CP_UTF8, 0, m_path.c_str(), m_path.length(), 0, 0);
+    if (wlen > 0) {
+        wchar_t *buf = new wchar_t[wlen+1];
+        (void)MultiByteToWideChar
+            (CP_UTF8, 0, m_path.c_str(), m_path.length(), buf, wlen);
+        buf[wlen] = L'\0';
+        m_file = new std::ifstream(buf, std::ios::in | std::ios::binary);
+        delete[] buf;
+    }
+#else
+    m_file = new std::ifstream(m_path.c_str(), std::ios::in | std::ios::binary);
+#endif
+    
     if (!*m_file) {
         delete m_file;
         m_file = 0;

          
M src/SimpleWavFileReadStream.h +4 -0
@@ 37,6 37,10 @@ 
 
 #include "../bqaudiostream/AudioReadStream.h"
 
+#ifdef _MSC_VER
+#include <windows.h>
+#endif
+
 #include <fstream>
 #include <string>
 #include <vector>

          
M src/SimpleWavFileWriteStream.cpp +31 -10
@@ 62,14 62,32 @@ SimpleWavFileWriteStream::SimpleWavFileW
     m_bitDepth(24),
     m_file(0)
 {
-    m_file = new std::ofstream(getPath().c_str(), std::ios::out | std::ios::binary);
+    std::string path = getPath();
+    
+#ifdef _MSC_VER
+    // This is behind _MSC_VER not _WIN32 because the fstream
+    // constructors from wchar bufs are an MSVC extension not
+    // available in e.g. MinGW
+    int wlen = MultiByteToWideChar
+        (CP_UTF8, 0, path.c_str(), path.length(), 0, 0);
+    if (wlen > 0) {
+        wchar_t *buf = new wchar_t[wlen+1];
+        (void)MultiByteToWideChar
+            (CP_UTF8, 0, path.c_str(), path.length(), buf, wlen);
+        buf[wlen] = L'\0';
+        m_file = new std::ofstream(buf, std::ios::out | std::ios::binary);
+        delete[] buf;
+    }
+#else
+    m_file = new std::ofstream(path.c_str(), std::ios::out | std::ios::binary);
+#endif
 
     if (!*m_file) {
         delete m_file;
         m_file = 0;
         m_error = std::string("Failed to open audio file '") +
-            getPath() + "' for writing";
-        throw FailedToWriteFile(getPath());
+            path + "' for writing";
+        throw FailedToWriteFile(path);
     }
 
     writeFormatChunk();

          
@@ 96,19 114,24 @@ SimpleWavFileWriteStream::~SimpleWavFile
     }
 
     m_file->seekp(0, std::ios::end);
-    uint32_t totalSize = m_file->tellp();
+
+    std::streamoff totalSize = m_file->tellp();
+    uint32_t effSize = uint32_t(-1);
+    if (totalSize < std::streamoff(effSize)) {
+        effSize = uint32_t(totalSize);
+    }
 
     // seek to first length position
     m_file->seekp(4, std::ios::beg);
 
     // write complete file size minus 8 bytes to here
-    putBytes(int2le(totalSize - 8, 4));
+    putBytes(int2le(effSize - 8, 4));
 
     // reseek from start forward 40
     m_file->seekp(40, std::ios::beg);
 
     // write the data chunk size to end
-    putBytes(int2le(totalSize - 44, 4));
+    putBytes(int2le(effSize - 44, 4));
 
     m_file->close();
 

          
@@ 117,12 140,10 @@ SimpleWavFileWriteStream::~SimpleWavFile
 }
 
 void
-SimpleWavFileWriteStream::putBytes(std::string s)
+SimpleWavFileWriteStream::putBytes(const std::string &s)
 {
     if (!m_file) return;
-    for (uint32_t i = 0; i < s.length(); i++) {
-        *m_file << (uint8_t)s[i];
-    }
+    m_file->write(s.data(), s.length());
 }
 
 void

          
M src/SimpleWavFileWriteStream.h +5 -1
@@ 37,6 37,10 @@ 
 
 #include "../bqaudiostream/AudioWriteStream.h"
 
+#ifdef _MSC_VER
+#include <windows.h>
+#endif
+
 #include <fstream>
 #include <string>
 

          
@@ 59,7 63,7 @@ protected:
     std::ofstream *m_file;
 
     void writeFormatChunk();
-    void putBytes(std::string);
+    void putBytes(const std::string &);
     void putBytes(const unsigned char *, size_t);
 };
 

          
M src/WavFileWriteStream.cpp +17 -3
@@ 66,12 66,26 @@ WavFileWriteStream::WavFileWriteStream(T
     m_fileInfo.channels = getChannelCount();
     m_fileInfo.samplerate = getSampleRate();
 
-    m_file = sf_open(getPath().c_str(), SFM_WRITE, &m_fileInfo);
+    auto path = getPath();
+#ifdef _WIN32
+    int wlen = MultiByteToWideChar
+        (CP_UTF8, 0, path.c_str(), path.length(), 0, 0);
+    if (wlen > 0) {
+        wchar_t *buf = new wchar_t[wlen+1];
+        (void)MultiByteToWideChar
+            (CP_UTF8, 0, path.c_str(), path.length(), buf, wlen);
+        buf[wlen] = L'\0';
+        m_file = sf_wchar_open(buf, SFM_WRITE, &m_fileInfo);
+        delete[] buf;
+    }
+#else
+    m_file = sf_open(path.c_str(), SFM_WRITE, &m_fileInfo);
+#endif
 
     if (!m_file) {
         m_error = std::string("Failed to open audio file '") +
-            getPath() + "' for writing";
-        throw FailedToWriteFile(getPath());
+            path + "' for writing";
+        throw FailedToWriteFile(path);
     }
 }
 

          
M src/WavFileWriteStream.h +5 -0
@@ 39,6 39,11 @@ 
 
 #if defined(HAVE_LIBSNDFILE) || defined(HAVE_SNDFILE)
 
+#ifdef _WIN32
+#include <windows.h>
+#define ENABLE_SNDFILE_WINDOWS_PROTOTYPES 1
+#endif
+
 #include <sndfile.h>
 
 namespace breakfastquay