CSL 5.2

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

SoundFile.h
Go to the documentation of this file.
1 ///
2 /// SoundFile.h -- CSL's abstract sound file class, a sample player UGen, SoundCue & SoundFileBuffer.
3 /// The concrete subclasses represent sound file APIs, not individual formats.
4 ///
5 /// Classes: SoundFileMetadata, Abst_SoundFile, SoundCue, SoundFileBuffer (unfinished)
6 /// We read ID3-style tags from MP4/3, AAC, FLAC, etc. files using TagLib, http://developer.kde.org/~wheeler/taglib.html
7 ///
8 /// The sound file player is actually a powerful sampler, supporting arbitrary transposition
9 /// using wavetable interpolation or a sample rate convertor; Sound files are seekable and also writeable.
10 ///
11 /// See the copyright notice and acknowledgment of authors in the file COPYRIGHT
12 ///
13
14 #ifndef CSL_SoundFile_H
15 #define CSL_SoundFile_H
16
17 #include "CSL_Core.h" // the core of CSL 5
18 #include "Oscillator.h" // the superclass of sound files
19
20 #include <string.h>
21
22 //#define USE_TAGS
23
24 namespace csl {
25
26 /// Sound file constants
27
28 #ifdef CSL_ENUMS // use enumerations or integers?
29
30 typedef enum { ///< File I/O r/w mode
31 kSoundFileClosed,
32 kSoundFileRead,
33 kSoundFileWrite,
34 kSoundFileReadWrite
35 } SoundFileMode;
36
37 typedef enum { /// File format
38 kSoundFileFormatAIFF, ///< AIFF
39 kSoundFileFormatWAV, ///< WAV
40 kSoundFileFormatMP3, ///< MP3
41 kSoundFileFormatMP4, ///< MP4, M4A
42 kSoundFileFormatAAC, ///< AAC
43 kSoundFileFormatFLAC, ///< FLAC
44 kSoundFileFormatCAF, ///< CoreAudio format
45 kSoundFileFormatOGG, ///< Ogg/Vorbis
46 kSoundFileFormatSHN, ///< Shorten
47 kSoundFileFormatSND, ///< Sun/NeXT SND/AU
48 kSoundFileFormatEBICSF, ///< Extended BIC (Berkeley/IRCAM/CARL) data
49 kSoundFileFormatRaw, ///< Raw data
50 kSoundFileFormatOther, ///< Other formats
51 } SoundFileFormat;
52
53 #else
54 #define kSoundFileRead 0
55 #define kSoundFileWrite 1
56 #define kSoundFileReadWrite 2
57 typedef int SoundFileMode;
58
59 #define kSoundFileFormatWAV 0
60 #define kSoundFileFormatAIFF 1
61 #define kSoundFileFormatSND 2
62 #define kSoundFileFormatEBICSF 3
63 #define kSoundFileFormatRaw 4
64 #define kSoundFileFormatOther 5
65 typedef int SoundFileFormat;
66 #endif
67
68 ///
69 /// Class SndFileMetadata holds the ID3 tags of a sound file
70 ///
71
72 class SoundFileMetadata {
73 public:
74 std::string mTitle; ///< ID3 tag fields
75 std::string mArtist;
76 std::string mAlbum;
77 unsigned mYear;
78 std::string mComment;
79 unsigned mTrack;
80 std::string mGenre;
81
82 unsigned mBitRate; ///< encoding data
83 unsigned mSampleRate;
84 unsigned mChannels;
85 unsigned mLength;
86
87 SoundFileMetadata();
88 ~SoundFileMetadata() { };
89
90 void dump(); ///< pretty-print the receiver
91 };
92
93 ///
94 /// Here's the abstract sound file reader/writer class, a sample player UGen.
95 /// The concrete subclasses represent sound file APIs, not individual formats.
96 ///
97 /// The sound file player is actually a powerful sampler, supporting arbitrary transposition
98 /// using wavetable interpolation or a sample rate convertor; Sound files are seekable and also writeable.
99 ///
100
101 class Abst_SoundFile : public WavetableOscillator, public Writeable, public Seekable {
102 public: /// Constructor. Values not passed default to null.
103 Abst_SoundFile(string path, int start = -1, int stop = -1);
104 Abst_SoundFile(Abst_SoundFile & otherSndFile); ///< Copy constructor -- shares sample buffer
105 ~Abst_SoundFile();
106
107 ///< open file and get stats; read it if "load"
108 virtual void openForRead(bool load = true) throw (CException) = 0;
109 /// Open a file for writing.
110 /// Default values are some common format.
111 virtual void openForWrite(SoundFileFormat format = kSoundFileFormatAIFF,
112 unsigned channels = 1,
113 unsigned rate = 44100,
114 unsigned bitDepth = 16) throw (CException) = 0;
115 /// seek to some position relative to "whence"
116 virtual unsigned seekTo(int position, SeekPosition whence) throw(CException) = 0;
117 unsigned seekTo(int position) throw(CException) { return seekTo(position, kPositionStart); }
118
119 ///< read a buffer from the file (possibly all of it)
120 virtual void readBufferFromFile(unsigned numFr) = 0;
121
122 /// UGen operations are implemented here
123 /// copy next buffer from file cache
124 virtual void nextBuffer(Buffer &outB) throw (CException);
125 /// write a buffer of data into the file
126 virtual void writeBuffer(Buffer &inB) throw (CException) = 0;
127 virtual SampleBuffer buffer(unsigned bufNum) { return mWavetable.buffer(bufNum); }
128
129 /// accessors
130 unsigned channels() const; ///< # chans
131 unsigned duration() { return mNumFrames; }; ///< number of frames in the sound file
132 float durationInSecs(); ///< actual duration of the selected portion in sec
133 // virtual SoundFileFormat format() = 0; ///< get format
134 unsigned sampleSize() { return mBytesPerSample; } ///< get the bytes-per-sample
135 SoundFileMode mode() { return mMode; } ///< r/w mode
136 unsigned cacheSize() { return mWavetable.mNumAlloc; } ///< size in frames of cached portion
137
138 void mergeToMono(); ///< average all the channels to mono
139 virtual void setToEnd(); ///< set to end position
140 virtual void trigger(); ///< reset to start
141 virtual void close() = 0; ///< close file
142 virtual void freeBuffer(); ///< free the file cache
143 void convertRate(int fromRate, int toRate); ///< perform sample-rate conversion
144
145 bool isValid() { return mIsValid; } ///< answer if a valid file/buffer
146 bool isActive(); ///< answer if currently active
147 virtual bool isCached(); ///< answer if file is loaded into RAM
148 virtual bool isCached(unsigned samps); ///< answer if file has X samples in RAM
149
150 virtual void setPath(string path); ///< set file name path string
151 string path() { return mPath; } ///< file name
152 virtual void dump(); ///< log snd file props
153
154 int startFrame() { return mStart; } ///< get/set start frame
155 void setStart(int val);
156 void setStartSec(float val);
157 void setStartRatio(float val);
158 int stopFrame() { return mStop; } ///< get/set stop frame
159 void setStop(int val);
160 void setStopSec(float val);
161 void setStopRatio(float val);
162 void setBase(int val);
163 unsigned int base() { return mBase; };
164
165 double playbackRate() { return mRate; } ///< playback rate (pitch ratio)
166 void setRate(UnitGenerator & frequency); ///< set the receiver's playback rate (pitch ratio)
167 void setRate(float frequency);
168
169 bool isLooping() { return mIsLooping; } ///< get/set looping state
170 void setIsLooping(bool tLooping) { mIsLooping = tLooping; }
171
172 SoundFileMetadata * mProperties; ///< the ID3 tags properties
173
174 protected:
175 string mPath; ///< file name
176 SoundFileMode mMode; ///< r/w mode
177 SoundFileFormat mFormat; ///< sf format
178 bool mIsValid; ///< is my file valid?
179 bool mIsLooping; ///< am i looping start-stop?
180 int mStart, mStop; ///< starting/ending frames (or -1 if not used)
181 double mRate; ///< sample rate ratio
182 unsigned mNumFrames; ///< # sample frames
183 unsigned mBytesPerSample; ///< the # of bytes per sample
184 unsigned mBase; ///< starting frame in file of buffer
185
186 virtual void initFromSndfile() = 0; ///< read SF header
187 void checkBuffer(unsigned numFrames); ///< allocate buffer lazily
188 void checkBuffer(unsigned numChans, unsigned numFrames);
189 bool readTags() throw (CException); ///< read the ID3 or other tags. Returns true if able to read them.
190 };
191
192 ///
193 /// SoundCue -- a pointer to a segment of a sound file
194 ///
195
196 class SoundCue : public UnitGenerator {
197
198 public:
199 SoundCue(); /// Constructor
200 SoundCue(string name, Abst_SoundFile *file = 0, int start = 1, int stop = -1);
201 // SoundCue(string name, int start = 1, int stop = -1);
202 ~SoundCue();
203
204 string mName; ///< my name
205 Abst_SoundFile * mFile; ///< the file I point into
206 int mStart, mStop, mCurrent; ///< the start/stop samples I represent
207 UnitGenerator *mReadRate; ///< my playback rate
208
209 void readFrom(FILE *input); ///< for loading file lists
210 void dump(void); ///< pretty-print me
211 /// UGen operations
212 void nextBuffer(Buffer & outputBuffer) throw(CException); ///< copy next buffer from cache
213
214 bool isActive();
215 unsigned channels() const { return (mFile->channels()); }
216 void setToEnd(void);
217 void trigger(void);
218 float duration() const { return (float) (mStop - mStart); } ///< duration in frames
219
220 protected:
221 float mFloatCurrent; ///< current pointer as a float
222 };
223
224 #ifdef USE_SNDFILEBUFFER
225
226 ///
227 /// SoundFileBuffer is a buffer that streams a sound file
228 ///
229
230 class SoundFileBuffer : public Buffer {
231 public: /// Constructor. Values not passed default to null.
232 SoundFileBuffer(string path, unsigned numFrames = CSL_mSndFileFrames);
233 SoundFileBuffer(Abst_SoundFile & otherSndFile); ///< Copy constructor -- shares sample buffer
234 ~SoundFileBuffer();
235
236 /// answer a samp ptr with offset
237 virtual SampleBuffer samplePtrFor(unsigned channel, unsigned offset);
238 /// answer a samp ptr tested for extent (offset + maxFrame)
239 virtual SampleBuffer samplePtrFor(unsigned channel, unsigned offset, unsigned maxFrame);
240
241 /// convenience accessors for sample buffers
242 virtual SampleBuffer monoBuffer(unsigned bufNum) { return mBuffers[bufNum]; }
243 virtual SampleBuffer buffer(unsigned bufNum) { return mBuffers[bufNum]; }
244
245 /// Set the buffer pointer (rare; used in joiners)
246 virtual void setBuffer(unsigned bufNum, SampleBuffer sPtr) {
247 throw LogicError("Cannot set pointer to file buffer"); };
248 virtual void setBuffer(unsigned bufNum, unsigned offset, sample samp) {
249 throw LogicError("Cannot set pointer to file buffer"); };
250
251 protected:
252 // ///< check if the buffer's big enough -- allocate it lazily
253 // virtual void checkBuffer(unsigned numFrames);
254 // virtual void checkBuffer(unsigned numChans, unsigned numFrames);
255
256 Abst_SoundFile * mFile; ///< the file I point into
257
258 };
259
260 #endif
261
262 #ifdef UNDEFINED // this was never completed...
263
264 class SampleFile : public Abst_SoundFile {
265 public:
266 SampleFile(); /// Constructor
267 SampleFile(string name, Abst_SoundFile *file = 0, int start = 1, int stop = -1);
268 ~SampleFile();
269 /// Data members
270 unsigned mMIDIKey; // sample's MIDI key #
271 double mFrequency; // sample's actual frequency
272 double mMinRatio; // min transp.
273 double mMaxRatio; // max transp. (often 1.0)
274
275 double ratioForKey(int desiredMIDI);
276 double ratioForPitch(int desiredMIDI);
277 };
278
279 #endif
280
281 }
282
283 #endif