diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-03-01 18:37:05 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-03-01 18:37:05 +0000 |
commit | 145364a8af6a1fec06556221e66d4b724a62fc9a (patch) | |
tree | 53bd71a544008c518034f208d64c932dc2883f50 /src/sound/WAVAudioFile.cpp | |
download | rosegarden-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.cpp | 255 |
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; +} + + +} |