summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2014-03-30 11:15:18 +0200
committerBent Bisballe Nyeng <deva@aasimon.org>2014-03-30 11:15:18 +0200
commitf271a3905a0e8d16f9258ba0b8743a8fd689e787 (patch)
tree24b25ebbd7f73f281f9ab15a491797de7103a4d4
parent63bf74ffaeb5580af677719485c40fe50e248f51 (diff)
Export as single file with multiple channels.
-rw-r--r--dgedit/audioextractor.cc179
-rw-r--r--dgedit/audioextractor.h2
2 files changed, 95 insertions, 86 deletions
diff --git a/dgedit/audioextractor.cc b/dgedit/audioextractor.cc
index 9692b0b..8395b7f 100644
--- a/dgedit/audioextractor.cc
+++ b/dgedit/audioextractor.cc
@@ -32,111 +32,121 @@
#include <sndfile.h>
+typedef struct {
+ SNDFILE *fh;
+ float *data;
+} audiodata_t;
+
AudioExtractor::AudioExtractor(QObject *parent)
: QObject(parent)
{
}
-float *AudioExtractor::load(QString file, size_t *size)
+void AudioExtractor::exportSelections(Selections selections,
+ Levels levels)
{
- float *data;
+ // Open all input audio files:
+ audiodata_t audiodata[audiofiles.size()];
- SF_INFO sf_info;
- SNDFILE *fh = sf_open(file.toStdString().c_str(), SFM_READ, &sf_info);
- if(!fh) {
- printf("Load error...\n");
- *size = 0;
- return NULL;
- }
-
- *size = sf_info.frames;
-
- data = new float[*size];
-
- sf_read_float(fh, data, *size);
+ int idx = 0;
+ AudioFileList::iterator j = audiofiles.begin();
+ while(j != audiofiles.end()) {
+ QString file = j->first;
- sf_close(fh);
+ SF_INFO sf_info;
+ audiodata[idx].fh = sf_open(file.toStdString().c_str(), SFM_READ, &sf_info);
+ if(!audiodata[idx].fh) {
+ printf("Load error '%s'\n", file.toStdString().c_str());
+ return;
+ }
- return data;
-}
+ audiodata[idx].data = NULL;
-void AudioExtractor::exportSelection(QString filename,
- int index,
- float *data, size_t size,
- Selection sel)
-{
- printf("Writing: %s (sz: %d, from %d to %d)\n",
- filename.toStdString().c_str(), (int)size, sel.from, sel.to);
-
- if(sel.from > (int)size ||
- sel.to > (int)size ||
- sel.to < 0 ||
- sel.from < 0 ||
- sel.to < sel.from) {
- printf("Out of bounds\n");
- return;
+ j++;
+ idx++;
}
+
+ idx = 0;
+ QMap<int, Selection>::iterator si = selections.begin();
+ while(si != selections.end()) {
+ Selection &sel = *si;
+ size_t offset = sel.from;
+ size_t size = sel.to - sel.from;
+ size_t fadein = sel.fadein;
+ size_t fadeout = sel.fadeout;
+
+
+ // Read all input audio file chunks:
+ for(int i = 0; i < audiofiles.size(); i++) {
+
+ // Clear out old buffer (if one exists)
+ if(audiodata[i].data) {
+ delete audiodata[i].data;
+ audiodata[i].data = NULL;
+ }
- // Apply linear fadein
- for(int i = 0; i < sel.fadein; i++) {
- float val = ((float)i / (float)sel.fadein);
- data[i + sel.from] *= val;
- }
+ SNDFILE *fh = audiodata[i].fh;
- // Apply fadeout
- for(int i = 0; i < sel.fadeout; i++) {
- float val = ((float)i / (float)sel.fadeout);
- data[sel.to - i] *= val;
- }
+ sf_seek(fh, offset, SEEK_SET);
- SF_INFO sf_info;
- sf_info.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT;
- sf_info.samplerate = 44100;
- sf_info.channels = 1;
+ float *data = new float[size];
+ sf_read_float(fh, data, size);
- SNDFILE *fh = sf_open(filename.toStdString().c_str(), SFM_WRITE, &sf_info);
- if(!fh) {
- printf("Open for write error...\n");
- return;
- }
- sf_write_float(fh, data + sel.from, sel.to - sel.from);
- sf_close(fh);
-}
+ // Apply linear fadein
+ for(size_t fi = 0; fi < fadein; fi++) {
+ float val = ((float)fi / (float)fadein);
+ data[fi] *= val;
+ }
-void AudioExtractor::exportSelections(Selections selections,
- Levels levels)
-{
- // Do the actual exporting one file at the time.
- AudioFileList::iterator j = audiofiles.begin();
- while(j != audiofiles.end()) {
+ // Apply fadeout
+ for(size_t fo = 0; fo < fadeout; fo++) {
+ float val = ((float)fo / (float)fadeout);
+ data[size - fo] *= val;
+ }
- QString file = j->first;
- QString name = j->second;
- size_t size;
+ audiodata[i].data = data;
+ }
- // TODO: Use sf_seek instead...
- float *data = load(file, &size);
- if(!data) continue;
+ // Create output path:
+ QString path = exportpath + "/" + prefix + "/samples";
+ QDir d;
+ d.mkpath(path);
- int index = 0;
- QMap<int, Selection>::iterator i = selections.begin();
- while(i != selections.end()) {
- index++;
+ // Write all sample chunks to single output file:
+ QString file = path + "/" + QString::number(idx) + "-" + prefix + ".wav";
+
+ SF_INFO sf_info;
+ sf_info.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT;
+ sf_info.samplerate = 44100;
+ sf_info.channels = audiofiles.size();
+
+ SNDFILE *ofh = sf_open(file.toStdString().c_str(), SFM_WRITE, &sf_info);
+ if(!ofh) {
+ printf("Open for write error...\n");
+ return;
+ }
- QString path = exportpath + "/" + prefix + "/samples";
- QString file = path + "/" + QString::number(index) +
- "-" + prefix + "-" + name + ".wav";
+ for(size_t ob = 0; ob < size; ob++) {
+ float obuf[audiofiles.size()];
+ for(int ai = 0; ai < audiofiles.size(); ai++) {
+ obuf[ai] = audiodata[ai].data[ob];
+ }
+ sf_write_float(ofh, obuf, audiofiles.size());
+ }
+ sf_close(ofh);
- QDir d;
- d.mkpath(path);
+ idx++;
+ si++;
+ }
- exportSelection(file, index, data, size, i.value());
- i++;
+ // Close all input audio files:
+ for(int i = 0; i < audiofiles.size(); i++) {
+ if(audiodata[i].data) {
+ delete audiodata[i].data;
+ audiodata[i].data = NULL;
}
- delete[] data;
-
- j++;
+ sf_close(audiodata[i].fh);
}
QDomDocument doc;
@@ -164,6 +174,7 @@ void AudioExtractor::exportSelections(Selections selections,
sample.setAttribute("power", QString::number(i->energy));
samples.appendChild(sample);
+ int channelnum = 1; // Filechannel numbers are 1-based.
AudioFileList::iterator j = audiofiles.begin();
while(j != audiofiles.end()) {
@@ -172,11 +183,11 @@ void AudioExtractor::exportSelections(Selections selections,
QDomElement audiofile = doc.createElement("audiofile");
audiofile.setAttribute("file", "samples/" +
- QString::number(index) + "-" + prefix +
- "-" + name + ".wav");
+ QString::number(index) + "-" + prefix + ".wav");
audiofile.setAttribute("channel", name);
+ audiofile.setAttribute("filechannel", QString::number(channelnum));
sample.appendChild(audiofile);
-
+ channelnum++;
j++;
}
diff --git a/dgedit/audioextractor.h b/dgedit/audioextractor.h
index 33ccf71..f18860b 100644
--- a/dgedit/audioextractor.h
+++ b/dgedit/audioextractor.h
@@ -52,8 +52,6 @@ public slots:
void setOutputPrefix(const QString &prefix);
private:
- float *load(QString file, size_t *size);
- void exportSelection(QString name, int index, float *data, size_t size, Selection sel);
AudioFileList audiofiles;
QString exportpath;
QString prefix;