diff options
Diffstat (limited to 'src/sound/SoundFile.cpp')
-rw-r--r-- | src/sound/SoundFile.cpp | 295 |
1 files changed, 295 insertions, 0 deletions
diff --git a/src/sound/SoundFile.cpp b/src/sound/SoundFile.cpp new file mode 100644 index 0000000..b87cef0 --- /dev/null +++ b/src/sound/SoundFile.cpp @@ -0,0 +1,295 @@ +// -*- c-indentation-style:"stroustrup" 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 "SoundFile.h" +#include "Profiler.h" + + +//#define DEBUG_SOUNDFILE 1 + +namespace Rosegarden + +{ + +SoundFile::SoundFile(const std::string &fileName): + m_fileName(fileName), + m_readChunkPtr( -1), + m_readChunkSize(4096), // 4k blocks + m_inFile(0), + m_outFile(0), + m_loseBuffer(false), + m_fileSize(0) +{} + +// Tidies up for any dervied classes +// +SoundFile::~SoundFile() +{ + if (m_inFile) { + m_inFile->close(); + delete m_inFile; + } + + if (m_outFile) { + m_outFile->close(); + delete m_outFile; + } + +} + +// Read in a specified number of bytes and return them +// as a string. +// +std::string +SoundFile::getBytes(std::ifstream *file, unsigned int numberOfBytes) +{ + if (file->eof()) { + // Reset the input stream so it's operational again + // + file->clear(); + + throw(BadSoundFileException(m_fileName, "SoundFile::getBytes() - EOF encountered")); + } + + if (!(*file)) { + std::cerr << "SoundFile::getBytes() - stream is not well"; + } + + + std::string rS; + char *fileBytes = new char[numberOfBytes]; + + file->read(fileBytes, numberOfBytes); + + for (int i = 0; i < file->gcount(); i++) + rS += (unsigned char)fileBytes[i]; + +#ifdef DEBUG_SOUNDFILE + // complain but return + // + if (rS.length() < numberOfBytes) + std::cerr << "SoundFile::getBytes() - couldn't get all bytes (" + << rS.length() << " from " << numberOfBytes << ")" + << std::endl; +#endif + + // clear down + delete [] fileBytes; + + return rS; +} + +// Read a specified number of bytes into a buffer. +// +size_t +SoundFile::getBytes(std::ifstream *file, char *buf, size_t n) +{ + if (!(*file)) { + std::cerr << "SoundFile::getBytes() - stream is not well"; + return 0; + } + + if (file->eof()) { + file->clear(); + return 0; + } + + file->read(buf, n); + return file->gcount(); +} + +// A buffered read based on the current file handle. +// +std::string +SoundFile::getBytes(unsigned int numberOfBytes) +{ + if (m_inFile == 0) + throw(BadSoundFileException(m_fileName, "SoundFile::getBytes - no open file handle")); + + if (m_inFile->eof()) { + // Reset the input stream so it's operational again + // + m_inFile->clear(); + + throw(BadSoundFileException(m_fileName, "SoundFile::getBytes() - EOF encountered")); + } + + + // If this flag is set we dump the buffer and re-read it - + // should be set if specialised class is scanning about + // when we're doing buffered reads + // + if (m_loseBuffer) { + m_readChunkPtr = -1; + m_loseBuffer = false; + } + + std::string rS; + char *fileBytes = new char[m_readChunkSize]; + int oldLength; + + while (rS.length() < numberOfBytes && !m_inFile->eof()) { + if (m_readChunkPtr == -1) { + // clear buffer + m_readBuffer = ""; + + // reset read pointer + m_readChunkPtr = 0; + + // Try to read the whole chunk + // + m_inFile->read(fileBytes, m_readChunkSize); + + // file->gcount holds the number of bytes we've actually read + // so copy them across into our string + // + for (int i = 0; i < m_inFile->gcount(); i++) + m_readBuffer += (unsigned char)fileBytes[i]; + } + + // Can we fulfill our request at this pass? If so read the + // bytes across and we'll exit at the end of this loop. + // m_readChunkPtr keeps our position for next time. + // + if (numberOfBytes - rS.length() <= m_readBuffer.length() - + m_readChunkPtr) { + oldLength = rS.length(); + + rS += m_readBuffer.substr(m_readChunkPtr, + numberOfBytes - oldLength); + + m_readChunkPtr += rS.length() - oldLength; + } else { + // Fill all we can this time and reset the m_readChunkPtr + // so that we fetch another chunk of bytes from the file. + // + rS += m_readBuffer.substr(m_readChunkPtr, + m_readChunkSize - m_readChunkPtr); + m_readChunkPtr = -1; + } + + // If we're EOF here we must've read and copied across everything + // we can do. Reset and break out. + // + if (m_inFile->eof()) { + m_inFile->clear(); + break; + } + + } + +#ifdef DEBUG_SOUNDFILE + // complain but return + // + if (rS.length() < numberOfBytes) + std::cerr << "SoundFile::getBytes() buffered - couldn't get all bytes (" + << rS.length() << " from " << numberOfBytes << ")" + << std::endl; +#endif + + delete [] fileBytes; + + // Reset and return if EOF + // + if (m_inFile->eof()) + m_inFile->clear(); + + return rS; +} + + +// Write out a sequence of FileBytes to the stream +// +void +SoundFile::putBytes(std::ofstream *file, + const std::string oS) +{ + for (unsigned int i = 0; i < oS.length(); i++) + *file << (FileByte) oS[i]; +} + +void +SoundFile::putBytes(std::ofstream *file, const char *buffer, size_t n) +{ + file->write(buffer, n); +} + + +// Clip off any path from the filename +std::string +SoundFile::getShortFilename() const +{ + std::string rS = m_fileName; + unsigned int pos = rS.find_last_of("/"); + + if (pos > 0 && ( pos + 1 ) < rS.length()) + rS = rS.substr(pos + 1, rS.length()); + + return rS; +} + + +// Turn a little endian binary std::string into an integer +// +int +SoundFile::getIntegerFromLittleEndian(const std::string &s) +{ + int r = 0; + + for (unsigned int i = 0; i < s.length(); i++) { + r += (int)(((FileByte)s[i]) << (i * 8)); + } + + return r; +} + + +// Turn a value into a little endian string of "length" +// +std::string +SoundFile::getLittleEndianFromInteger(unsigned int value, unsigned int length) +{ + std::string r = ""; + + do { + r += (unsigned char)((long)((value >> (8 * r.length())) & 0xff)); + } while (r.length() < length); + + return r; +} + +int +SoundFile::getIntegerFromBigEndian(const std::string &s) +{ + return 0; +} + +std::string +SoundFile::getBigEndianFromInteger(unsigned int value, unsigned int length) +{ + std::string r; + + return r; +} + + +} + |