summaryrefslogtreecommitdiffstats
path: root/src/sound/WAVAudioFile.cpp
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-01 18:37:05 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-01 18:37:05 +0000
commit145364a8af6a1fec06556221e66d4b724a62fc9a (patch)
tree53bd71a544008c518034f208d64c932dc2883f50 /src/sound/WAVAudioFile.cpp
downloadrosegarden-145364a8af6a1fec06556221e66d4b724a62fc9a.tar.gz
rosegarden-145364a8af6a1fec06556221e66d4b724a62fc9a.zip
Added old abandoned KDE3 version of the RoseGarden MIDI tool
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/rosegarden@1097595 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/sound/WAVAudioFile.cpp')
-rw-r--r--src/sound/WAVAudioFile.cpp255
1 files changed, 255 insertions, 0 deletions
diff --git a/src/sound/WAVAudioFile.cpp b/src/sound/WAVAudioFile.cpp
new file mode 100644
index 0000000..4e3b3bd
--- /dev/null
+++ b/src/sound/WAVAudioFile.cpp
@@ -0,0 +1,255 @@
+// -*- c-basic-offset: 4 -*-
+
+/*
+ Rosegarden
+ A sequencer and musical notation editor.
+
+ This program is Copyright 2000-2008
+ Guillaume Laurent <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ The moral right of the authors to claim authorship of this work
+ has been asserted.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version. See the file
+ COPYING included with this distribution for more information.
+*/
+
+#include "WAVAudioFile.h"
+#include "RealTime.h"
+
+#if (__GNUC__ < 3)
+#include <strstream>
+#define stringstream strstream
+#else
+#include <sstream>
+#endif
+
+using std::cout;
+using std::cerr;
+using std::endl;
+
+//#define DEBUG_DECODE 1
+
+namespace Rosegarden
+{
+
+WAVAudioFile::WAVAudioFile(const unsigned int &id,
+ const std::string &name,
+ const std::string &fileName):
+ RIFFAudioFile(id, name, fileName)
+{
+ m_type = WAV;
+}
+
+WAVAudioFile::WAVAudioFile(const std::string &fileName,
+ unsigned int channels = 1,
+ unsigned int sampleRate = 48000,
+ unsigned int bytesPerSecond = 6000,
+ unsigned int bytesPerFrame = 2,
+ unsigned int bitsPerSample = 16):
+ RIFFAudioFile(fileName, channels, sampleRate, bytesPerSecond, bytesPerFrame, bitsPerSample)
+{
+ m_type = WAV;
+}
+
+WAVAudioFile::~WAVAudioFile()
+{}
+
+bool
+WAVAudioFile::open()
+{
+ // if already open
+ if (m_inFile && (*m_inFile))
+ return true;
+
+ m_inFile = new std::ifstream(m_fileName.c_str(),
+ std::ios::in | std::ios::binary);
+
+ if (!(*m_inFile)) {
+ m_type = UNKNOWN;
+ return false;
+ }
+
+ // Get the file size and store it for comparison later
+ m_fileSize = m_fileInfo->size();
+
+ try {
+ parseHeader();
+ } catch (BadSoundFileException e) {
+ std::cerr << "ERROR: WAVAudioFile::open(): parseHeader: " << e.getMessage() << endl;
+ return false;
+ }
+
+ return true;
+}
+
+// Open the file for writing, write out the header and move
+// to the data chunk to accept samples. We fill in all the
+// totals when we close().
+//
+bool
+WAVAudioFile::write()
+{
+ // close if we're open
+ if (m_outFile) {
+ m_outFile->close();
+ delete m_outFile;
+ }
+
+ // open for writing
+ m_outFile = new std::ofstream(m_fileName.c_str(),
+ std::ios::out | std::ios::binary);
+
+ if (!(*m_outFile))
+ return false;
+
+ // write out format header chunk and prepare for sample writing
+ //
+ writeFormatChunk();
+
+ return true;
+}
+
+void
+WAVAudioFile::close()
+{
+ if (m_outFile == 0)
+ return ;
+
+ m_outFile->seekp(0, std::ios::end);
+ unsigned int totalSize = m_outFile->tellp();
+
+ // seek to first length position
+ m_outFile->seekp(4, std::ios::beg);
+
+ // write complete file size minus 8 bytes to here
+ putBytes(m_outFile, getLittleEndianFromInteger(totalSize - 8, 4));
+
+ // reseek from start forward 40
+ m_outFile->seekp(40, std::ios::beg);
+
+ // write the data chunk size to end
+ putBytes(m_outFile, getLittleEndianFromInteger(totalSize - 44, 4));
+
+ m_outFile->close();
+
+ delete m_outFile;
+ m_outFile = 0;
+}
+
+// Set the AudioFile meta data according to WAV file format specification.
+//
+void
+WAVAudioFile::parseHeader()
+{
+ // Read the format chunk and populate the file data. A plain WAV
+ // file only has this chunk. Exceptions tumble through.
+ //
+ readFormatChunk();
+
+}
+
+std::streampos
+WAVAudioFile::getDataOffset()
+{
+ return 0;
+}
+
+bool
+WAVAudioFile::decode(const unsigned char *ubuf,
+ size_t sourceBytes,
+ size_t targetSampleRate,
+ size_t targetChannels,
+ size_t nframes,
+ std::vector<float *> &target,
+ bool adding)
+{
+ size_t sourceChannels = getChannels();
+ size_t sourceSampleRate = getSampleRate();
+ size_t fileFrames = sourceBytes / getBytesPerFrame();
+
+ int bitsPerSample = getBitsPerSample();
+ if (bitsPerSample != 8 &&
+ bitsPerSample != 16 &&
+ bitsPerSample != 24 &&
+ bitsPerSample != 32) { // 32-bit is IEEE-float (enforced in RIFFAudioFile)
+ std::cerr << "WAVAudioFile::decode: unsupported " <<
+ bitsPerSample << "-bit sample size" << std::endl;
+ return false;
+ }
+
+#ifdef DEBUG_DECODE
+ std::cerr << "WAVAudioFile::decode: " << sourceBytes << " bytes -> " << nframes << " frames, SSR " << getSampleRate() << ", TSR " << targetSampleRate << ", sch " << getChannels() << ", tch " << targetChannels << std::endl;
+#endif
+
+ // If we're reading a stereo file onto a mono target, we mix the
+ // two channels. If we're reading mono to stereo, we duplicate
+ // the mono channel. Otherwise if the numbers of channels differ,
+ // we just copy across the ones that do match and zero the rest.
+
+ bool reduceToMono = (targetChannels == 1 && sourceChannels == 2);
+
+ for (size_t ch = 0; ch < sourceChannels; ++ch) {
+
+ if (!reduceToMono || ch == 0) {
+ if (ch >= targetChannels)
+ break;
+ if (!adding)
+ memset(target[ch], 0, nframes * sizeof(float));
+ }
+
+ int tch = ch; // target channel for this data
+ if (reduceToMono && ch == 1) {
+ tch = 0;
+ }
+
+ float ratio = 1.0;
+ if (sourceSampleRate != targetSampleRate) {
+ ratio = float(sourceSampleRate) / float(targetSampleRate);
+ }
+
+ for (size_t i = 0; i < nframes; ++i) {
+
+ size_t j = i;
+ if (sourceSampleRate != targetSampleRate) {
+ j = size_t(i * ratio);
+ }
+ if (j >= fileFrames)
+ j = fileFrames - 1;
+
+ float sample = convertBytesToSample
+ (&ubuf[(bitsPerSample / 8) * (ch + j * sourceChannels)]);
+
+ target[tch][i] += sample;
+ }
+ }
+
+ // Now deal with any excess target channels
+
+ for (int ch = sourceChannels; ch < targetChannels; ++ch) {
+ if (ch == 1 && targetChannels == 2) {
+ // copy mono to stereo
+ if (!adding) {
+ memcpy(target[ch], target[ch - 1], nframes * sizeof(float));
+ } else {
+ for (size_t i = 0; i < nframes; ++i) {
+ target[ch][i] += target[ch - 1][i];
+ }
+ }
+ } else {
+ if (!adding) {
+ memset(target[ch], 0, nframes * sizeof(float));
+ }
+ }
+ }
+
+ return true;
+}
+
+
+}