CSL  5.2
CGestalt.h
Go to the documentation of this file.
1 ///
2 /// CGestalt.h -- the CSL 5.0 CGestalt (system utility) class specification,
3 /// system constants, logging, and utility methods; SAFE_MALLOC/SAFE_FREE macros
4 /// The logging system has a number of print methods that use the printf var-args format
5 /// and can be filtered on verbosity.
6 /// There's a variety of random-number functions.
7 /// The timer sleep methods are interruptable with a global flag.
8 ///
9 /// The MVC Observer/Subject or dependency pattern classes are also here.
10 ///
11 /// See the copyright notice and acknowledgment of authors in the file COPYRIGHT
12 ///
13 
14 #ifndef CSL_Gestalt_H
15 #define CSL_Gestalt_H
16 
17 #include "CSL_Types.h" // The system default values are defined there
18 
19 #include <stdarg.h> // for va_arg, vaList, etc.
20 #include <string>
21 
22 #ifdef USE_JUCE
23 #include "../JuceLibraryCode/JuceHeader.h"
24 using namespace juce;
25 #else
26 #include <sys/time.h>
27 #endif
28 
29 namespace csl {
30 
31 ///
32 /// The CSL system defaults class
33 ///
34 
35 class CGestalt {
36 
37 public: // Accessor (getter/setter) methods
38 
39  static unsigned frameRate(); ///< default frame rate
40  static void setFrameRate(unsigned frameRate);
41  static sample framePeriod(); ///< default frame rate
42 
43  static unsigned numInChannels(); ///< default number of input channels
44  static void setNumInChannels(unsigned numChannels);
45 
46  static unsigned numOutChannels(); ///< default number of output channels
47  static void setNumOutChannels(unsigned numChannels);
48 
49  static unsigned blockSize(); ///< the default block size
50  static void setBlockSize(unsigned blockSize);
51 
52  static unsigned maxBufferFrames(); ///< the max num frames that can be requested
53  static void setMaxBufferFrames(unsigned numFrames);
54 
55  static unsigned maxSndFileFrames(); ///< the max num frames that can be cached
56  static void setMaxSndFileFrames(unsigned numFrames);
57 
58  static unsigned sndFileFrames(); ///< the default num frames that are cached
59  static void setSndFileFrames(unsigned numFrames);
60 
61  static unsigned verbosity(); ///< the default logging verbosity
62  static void setVerbosity(unsigned verbosity); // (0 = only fatal errors, 1 = warnings,
63  // 2 = most msgs, 3 = include info msgs)
64 
65  static unsigned loggingPeriod(); ///< the default logging period
66  static void setLoggingPeriod(unsigned loggingPeriod);
67 
68  static unsigned outPort(); ///< the default RemoteIO output port
69  static void setOutPort(unsigned outPort);
70 
71  static std::string dataFolder(); ///< the default directory for test data
72  static void setDataFolder(std::string dFolder); ///< typ. "~/Code/CSL/CSL_Data/"
73 
74  static bool stopNow(); ///< flag to stop threads and timers
75  static void setStopNow();
76  static void clearStopNow();
77 
78  static std::string initFileText(char key); ///< read/write the init file (typ. ~/.cslrc)
79  static void storeToInitFile(char key, std::string data);
80 
81  static std::string sndFileName(); ///< pick a new sound file name to use based on OUT_SFILE_NAME
82 
83 };
84 
85 /////////////////////////////////////////////////////////////////////////
86 ///
87 /// Useful Macros
88 ///
89 
90 /// SAFE_MALLOC = safe malloc using new operator
91 /// used like: SAFE_MALLOC(mSampleBuffer, sample, mWindowSize);
92 
93 #define SAFE_MALLOC(ptr, type, len) \
94  ptr = new type[len]; \
95  if ((char *) ptr == NULL) \
96  throw MemoryError("can't allocate buffer")
97 
98 /// Matrix allocate
99 /// SAFE_MATMALLOC(mRealSpectrum, FloatArray, mNumFrames, float, mWinSize);
100 /// SAFE_MATMALLOC(mSpectBands, FloatArray, mNumFrames, float, NUM_BANDS)
101 
102 #define SAFE_MATMALLOC(ptr, mtype, num, type, len) \
103  ptr = new mtype[num]; \
104  if ((char *) ptr == NULL) \
105  throw MemoryError("can't allocate buffer"); \
106  for (unsigned i = 0; i < num; i++) { \
107  ptr[i] = new type[len]; \
108  if ((char *) ptr[i] == NULL) \
109  throw MemoryError("can't allocate buffer"); \
110  }
111 
112 /// Structure allocate
113 /// SAFE_STRUCTMALLOC(mRealSpectrum, FloatArray, mNumFrames, float);
114 
115 #define SAFE_STRUCTMALLOC(ptr, mtype, num, type) \
116  ptr = new mtype[num]; \
117  if ((char *) ptr == NULL) \
118  throw MemoryError("can't allocate buffer"); \
119  for (unsigned i = 0; i < num; i++) { \
120  ptr[i] = new type; \
121  if ((char *) ptr[i] == NULL) \
122  throw MemoryError("can't allocate buffer"); \
123  }
124 
125 // Safe free and matrix version
126 
127 #define SAFE_FREE(ptr) \
128  if (ptr) \
129  delete[] ptr
130 
131 #define SAFE_MATFREE(ptr, num) \
132  for (unsigned i = 0; i < num; i++) { \
133  if (ptr[i]) \
134  delete[] ptr[i]; \
135  } \
136  delete[] ptr
137 
138 /////////////////////////////////////////////////////////////////////////
139 ///
140 /// Logging functions are standard C functions
141 ///
142 
143 #ifdef CSL_ENUMS
144 typedef enum { ///< Enumeration for log message severity level
145  kLogInfo, ///< you can filter on this.
149 } LogLevel;
150 #else
151  #define kLogInfo 0
152  #define kLogWarning 1
153  #define kLogError 2
154  #define kLogFatal 3
155  typedef int LogLevel;
156 #endif
157 
158 ///
159 /// These are the public logging messages
160 ///
161 
162 void logMsg(const char * format, ...); ///< default is kLogInfo severity
163 void logMsg(LogLevel level, const char* format, ...);
164 
165 void logLine(); ///< Log the file & line #
166 void logURL(); ///< log file/line as a URL
167 
168 // These two are private -- for handling var-args
169 
170 void vlogMsg(const char * format, va_list args);
171 void vlogMsg(LogLevel level, const char * format, va_list args);
172 
173 /////////////////////////////////////////////////////////////////////////
174 ///
175 /// Misc. global functions in the csl namespace
176 ///
177 
178 /// Sleep for micro-seconds, milli-seconds or seconds
179 /// These are interruptable and return true if interrupted; false for normal termination
180 
181 bool sleepUsec(float dur); ///< sleep for dur usec, msec or sec
182 bool sleepMsec(float dur);
183 bool sleepSec(float dur);
184 
185 Timestamp timeNow(); ///< high-accuracy system or IO time in ticks
186 float fTimeNow(); ///< system or IO time in seconds
187 
188 /// Which kind of accurate timer to use?
189 
190 // #define C_TIME Time::getHighResolutionTicks()
191 #define C_TIME juce::Time::getMillisecondCounter()
192 
193 ///
194 /// A variety of useful random-number functions
195 ///
196 
197 float fRandZ(void); ///< 0 - 1 (name: zero)
198 float fRand1(void); ///< -1 - 1 (one)
199 float fRandV(float val); ///< 0 - v (val)
200 
201 float fRandM(float minV, float maxV); ///< min - max (min/max)
202 float fRandR(float base, float range); ///< b +- (r * b) (range)
203 float fRandB(float base, float range); ///< b +- r (base)
204 
205 /// Integer rands
206 
207 int iRandV(int val); ///< 0 - v (val)
208 int iRandM(int minV, int maxV); ///< min - max (min/max)
209 int iRandB(int base, int range); ///< b +- r (base)
210 
211 // Bool coin-toss rands
212 
213 bool coin(); ///< Answer true or false
214 bool coin(float bias); ///< Answer with a bias (1 --> always true)
215 
216 
217 /// MIDI Conversions
218 
219 /// keyToFreq -- converts from MIDI key numbers (1 - 127) to frequency in Hz.
220 
221 float keyToFreq(unsigned midiKey);
222 
223 /// freqToKey -- converts from frequency in Hz to MIDI key #
224 
225 unsigned freqToKey(float frequency);
226 
227 
228 /////////////////////////////////////////////////////////////////////////
229 ///
230 /// MVC Observer/Subject or dependency pattern
231 /// Advanced version with filtered observer updates
232 ///
233 
234 class Observer; ///< Forward declaration
235 typedef std::vector <Observer *> ObserverVector;
236 
237 ///
238 /// The Model/Observable/Subject class; instances of its subclasses should send themselves,
239 /// this->changed(some_data);
240 /// on "relevant" state changes; the code they inherit (from Model) manages updating the list
241 /// of observer/dependent objects in that they each receive
242 /// update(some_data);
243 /// and can access the model-passed data (the model might pass "this").
244 ///
245 /// Note the addition of timers, so observers can request no more than a certain rate of updates.
246 
247 class Model {
248 public:
249  Model() : mHasObservers(false), mHasObserverMap(false), mUpdateTime(0), mPeriod(0) { }; ///< constructor
250  virtual ~Model() { /* no-op */ }; ///< (possibly notify obersvers on my death)
251 
252  void attachObserver(Observer *); ///< register/remove observers
253  void detachObserver(Observer *);
254 
255  void changed(void * argument); ///< this is what I send to myself to notify my observers;
256  /// It's not overridden in general.
257  /// It results in the observers receiving update() calls
258  ///< override evaluate to filter updates to the observer map
259  virtual int evaluate(void * argument) { return 0; };
260 
261 private:
262  ObserverVector mObservers; ///< the private vector of observers
263  std::map<int, ObserverVector> mObsMap; ///< the private map-by-key of observers
264  bool mHasObservers; ///< whether there are any observers (for fast checking)
265  bool mHasObserverMap; ///< whether there are any observers (for fast checking)
266  float mUpdateTime; ///< when I last updated
267  float mPeriod; ///< update rate in sec
268 };
269 
270 ///
271 /// CSL Observer/Dependent/Monitor class -- instances receive update() messages from "models"
272 /// and handle some argument, which may be the model's "this" pointer, or any other data.
273 ///
274 /// Subclasses must override the update() method to do their stuff -- grabbing a data buffer,
275 /// operating on their model, or displaying something.
276 /// The mPeriod is the requested period for updates.
277 /// The mKey is an int value for the model's evaluate() function to filter updates
278 /// i.e., if the model implements evaluate(void*), and its return value is non-zero and
279 /// matches the observer's key, then an update will be sent. An example of using this is
280 /// a MIDI IO object's channel filtering for MIDI listeners (observers).
281 ///
282 
283 class Observer {
284 public:
285  Observer() { mPeriod = 0; mKey = 0; }; ///< constructor
286  virtual ~Observer() { }; ///< virtual destructor (don't notify or delete
287  /// observers in this version)
288  float mPeriod; ///< max update rate
289  int mKey; ///< key selector (e.g., MIDI chan)
290  /// I receive update() mesages from my model;
291  virtual void update(void * arg) = 0; ///< this will be implemented in subclasses.
292 };
293 
294 } // end of namespace
295 
296 #endif