summaryrefslogtreecommitdiffstats
path: root/src/sound/SoundFile.h
blob: bc1cfca3a122cab705cdaa525134458fe93f0d1c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*
  Rosegarden
  A sequencer and musical notation editor.

  This program is Copyright 2000-2008
  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.
*/


#ifndef _SOUNDFILE_H_
#define _SOUNDFILE_H_

// SoundFile is an abstract base class defining behaviour for both
// MidiFiles and AudioFiles.  The getBytes routine is buffered into
// suitably sized chunks to prevent excessive file reads.
// 
//

#include <iostream>
#include <fstream>
#include <string>

#include "Exception.h"

namespace Rosegarden
{


// Constants related to RIFF/WAV files
//
const std::string AUDIO_RIFF_ID = "RIFF";
const std::string AUDIO_WAVE_ID = "WAVE";
const std::string AUDIO_FORMAT_ID = "fmt ";   // Always four bytes

const std::string AUDIO_BWF_ID = "bext";       // BWF chunk id
const std::string AUDIO_BWF_PEAK_ID = "levl";  // BWF peak chunk id


const float SAMPLE_MAX_8BIT  = (float)(0xff);
const float SAMPLE_MAX_16BIT = (float)(0xffff/2);
const float SAMPLE_MAX_24BIT = (float)(0xffffff/2);



typedef unsigned char FileByte; 

class SoundFile
{
public:
    SoundFile(const std::string &fileName);
    virtual ~SoundFile();

    class BadSoundFileException : public Exception
    {
    public:
        BadSoundFileException(std::string path) :
            Exception("Bad sound file " + path), m_path(path) { }
        BadSoundFileException(std::string path, std::string message) :
            Exception("Bad sound file " + path + ": " + message), m_path(path) { }
        BadSoundFileException(std::string path, std::string file, int line) :
            Exception("Bad sound file " + path, file, line), m_path(path) { }

        ~BadSoundFileException() throw() { }

        std::string getPath() const { return m_path; }

    private:
        std::string m_path;
    };

    // All files should be able open, write and close
    virtual bool open() = 0;
    virtual bool write() = 0;
    virtual void close() = 0;

    std::string getShortFilename() const;
    std::string getFilename() const { return m_fileName; }
    void setFilename(const std::string &fileName) { m_fileName = fileName; }

    // Useful methods that operate on our file data
    //
    int getIntegerFromLittleEndian(const std::string &s);
    std::string getLittleEndianFromInteger(unsigned int value,
                                           unsigned int length);

    int getIntegerFromBigEndian(const std::string &s);
    std::string getBigEndianFromInteger(unsigned int value,
                                        unsigned int length);

    // Buffered read - allow this to be public
    //
    std::string getBytes(unsigned int numberOfBytes);

    // Return file size
    //
    unsigned int getSize() const { return m_fileSize; }

    void resetStream() { m_inFile->seekg(0); m_inFile->clear(); }

    // check EOF status
    //
    bool isEof() const 
        { if (m_inFile) return m_inFile->eof(); else return true; }

protected:
    std::string m_fileName;

    // get some bytes from an input stream - unbuffered as we can
    // modify the file stream
    std::string getBytes(std::ifstream *file, unsigned int numberOfBytes);

    // Get n bytes from an input stream and write them into buffer.
    // Return the actual number of bytes read.
    size_t getBytes(std::ifstream *file, char *buffer, size_t n);

    // write some bytes to an output stream
    void putBytes(std::ofstream *file, const std::string outputString);

    // write some bytes to an output stream
    void putBytes(std::ofstream *file, const char *buffer, size_t n);

    // Read buffering - define chunk size and buffer file reading
    //
    int            m_readChunkPtr;
    int            m_readChunkSize;
    std::string    m_readBuffer;

    std::ifstream *m_inFile;
    std::ofstream *m_outFile;
    
    bool           m_loseBuffer; // do we need to dump the read buffer
                                 // and re-fill it?

    unsigned int   m_fileSize;

};

}


#endif // _SOUNDFILE_H_