diff data/fileio/WavFileWriter.cpp @ 1527:710e6250a401 zoom

Merge from default branch
author Chris Cannam
date Mon, 17 Sep 2018 13:51:14 +0100
parents 8988b27ebf38
children 70e172e6cc59
line wrap: on
line diff
--- a/data/fileio/WavFileWriter.cpp	Mon Dec 12 15:18:52 2016 +0000
+++ b/data/fileio/WavFileWriter.cpp	Mon Sep 17 13:51:14 2018 +0100
@@ -19,16 +19,21 @@
 #include "base/Selection.h"
 #include "base/TempWriteFile.h"
 #include "base/Exceptions.h"
+#include "base/Debug.h"
+
+#include <bqvec/Allocators.h>
+#include <bqvec/VectorOps.h>
 
 #include <QFileInfo>
 
 #include <iostream>
 #include <cmath>
+#include <string>
 
 using namespace std;
 
 WavFileWriter::WavFileWriter(QString path,
-			     sv_samplerate_t sampleRate,
+                             sv_samplerate_t sampleRate,
                              int channels,
                              FileWriteMode mode) :
     m_path(path),
@@ -41,7 +46,7 @@
 
     int fileRate = int(round(m_sampleRate));
     if (m_sampleRate != sv_samplerate_t(fileRate)) {
-        cerr << "WavFileWriter: WARNING: Non-integer sample rate "
+        SVCERR << "WavFileWriter: WARNING: Non-integer sample rate "
              << m_sampleRate << " presented, rounding to " << fileRate
              << endl;
     }
@@ -50,25 +55,27 @@
     fileInfo.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT;
 
     try {
+        QString writePath = m_path;
         if (mode == WriteToTemporary) {
             m_temp = new TempWriteFile(m_path);
-            m_file = sf_open(m_temp->getTemporaryFilename().toLocal8Bit(),
-                             SFM_WRITE, &fileInfo);
-            if (!m_file) {
-                cerr << "WavFileWriter: Failed to open file ("
-                          << sf_strerror(m_file) << ")" << endl;
-                m_error = QString("Failed to open audio file '%1' for writing")
-                    .arg(m_temp->getTemporaryFilename());
+            writePath = m_temp->getTemporaryFilename();
+        }
+#ifdef Q_OS_WIN
+        m_file = sf_wchar_open((LPCWSTR)writePath.utf16(), SFM_WRITE, &fileInfo);
+#else
+        m_file = sf_open(writePath.toLocal8Bit(), SFM_WRITE, &fileInfo);
+#endif
+        if (!m_file) {
+            SVCERR << "WavFileWriter: Failed to create float-WAV file of "
+                   << m_channels << " channels at rate " << fileRate << " ("
+                   << sf_strerror(m_file) << ")" << endl;
+            m_error = QString("Failed to open audio file '%1' for writing")
+                .arg(writePath);
+            if (m_temp) {
+                delete m_temp;
+                m_temp = 0;
             }
-        } else {
-            m_file = sf_open(m_path.toLocal8Bit(), SFM_WRITE, &fileInfo);
-            if (!m_file) {
-                cerr << "WavFileWriter: Failed to open file ("
-                          << sf_strerror(m_file) << ")" << endl;
-                m_error = QString("Failed to open audio file '%1' for writing")
-                    .arg(m_path);
-            }
-        }            
+        }
     } catch (FileOperationFailed &f) {
         m_error = f.what();
         m_temp = 0;
@@ -119,59 +126,59 @@
     if (!m_file) {
         m_error = QString("Failed to write model to audio file '%1': File not open")
             .arg(getWriteFilename());
-	return false;
+        return false;
     }
 
     bool ownSelection = false;
     if (!selection) {
-	selection = new MultiSelection;
-	selection->setSelection(Selection(source->getStartFrame(),
-					  source->getEndFrame()));
+        selection = new MultiSelection;
+        selection->setSelection(Selection(source->getStartFrame(),
+                                          source->getEndFrame()));
         ownSelection = true;
     }
 
     sv_frame_t bs = 2048;
 
     for (MultiSelection::SelectionList::iterator i =
-	     selection->getSelections().begin();
-	 i != selection->getSelections().end(); ++i) {
-	
-	sv_frame_t f0(i->getStartFrame()), f1(i->getEndFrame());
+         selection->getSelections().begin();
+         i != selection->getSelections().end(); ++i) {
+        
+        sv_frame_t f0(i->getStartFrame()), f1(i->getEndFrame());
 
-	for (sv_frame_t f = f0; f < f1; f += bs) {
-	    
-	    sv_frame_t n = min(bs, f1 - f);
-            vector<float> interleaved(n * m_channels, 0.f);
+        for (sv_frame_t f = f0; f < f1; f += bs) {
+            
+            sv_frame_t n = min(bs, f1 - f);
+            floatvec_t interleaved(n * m_channels, 0.f);
 
-	    for (int c = 0; c < int(m_channels); ++c) {
-                vector<float> chanbuf = source->getData(c, f, n);
-		for (int i = 0; in_range_for(chanbuf, i); ++i) {
-		    interleaved[i * m_channels + c] = chanbuf[i];
-		}
-	    }	    
+            for (int c = 0; c < int(m_channels); ++c) {
+                auto chanbuf = source->getData(c, f, n);
+                for (int i = 0; in_range_for(chanbuf, i); ++i) {
+                    interleaved[i * m_channels + c] = chanbuf[i];
+                }
+            }
 
-	    sf_count_t written = sf_writef_float(m_file, interleaved.data(), n);
+            sf_count_t written = sf_writef_float(m_file, interleaved.data(), n);
 
-	    if (written < n) {
-		m_error = QString("Only wrote %1 of %2 frames at file frame %3")
-		    .arg(written).arg(n).arg(f);
-		break;
-	    }
-	}
+            if (written < n) {
+                m_error = QString("Only wrote %1 of %2 frames at file frame %3")
+                        .arg(written).arg(n).arg(f);
+                break;
+            }
+        }
     }
 
     if (ownSelection) delete selection;
 
     return isOK();
 }
-	
+        
 bool
-WavFileWriter::writeSamples(float **samples, sv_frame_t count)
+WavFileWriter::writeSamples(const float *const *samples, sv_frame_t count)
 {
     if (!m_file) {
         m_error = QString("Failed to write model to audio file '%1': File not open")
             .arg(getWriteFilename());
-	return false;
+        return false;
     }
 
     float *b = new float[count * m_channels];
@@ -192,7 +199,20 @@
 
     return isOK();
 }
-    
+
+bool
+WavFileWriter::putInterleavedFrames(const floatvec_t &frames)
+{
+    sv_frame_t count = frames.size() / m_channels;
+    float **samples =
+        breakfastquay::allocate_channels<float>(m_channels, count);
+    breakfastquay::v_deinterleave
+        (samples, frames.data(), m_channels, int(count));
+    bool result = writeSamples(samples, count);
+    breakfastquay::deallocate_channels(samples, m_channels);
+    return result;
+}
+
 bool
 WavFileWriter::close()
 {