Logo Search packages:      
Sourcecode: rosegarden version File versions

SoundFile.cpp

// -*- c-indentation-style:"stroustrup" c-basic-offset: 4 -*-
/*
  Rosegarden-4
  A sequencer and musical notation editor.

  This program is Copyright 2000-2006
  Guillaume Laurent   <glaurent@telegraph-road.org>,
  Chris Cannam        <cannam@all-day-breakfast.com>,
  Richard Bown        <bownie@bownie.com>

  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;
}


}


Generated by  Doxygen 1.6.0   Back to index