Mercurial > hg > apm2s
comparison stk/src/Stk.cpp @ 0:4606bd505630 tip
first import
author | Fiore Martin <f.martin@qmul.ac.uk> |
---|---|
date | Sat, 13 Jun 2015 15:08:10 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4606bd505630 |
---|---|
1 /***************************************************/ | |
2 /*! \class Stk | |
3 \brief STK base class | |
4 | |
5 Nearly all STK classes inherit from this class. | |
6 The global sample rate can be queried and | |
7 modified via Stk. In addition, this class | |
8 provides error handling and byte-swapping | |
9 functions. | |
10 | |
11 The Synthesis ToolKit in C++ (STK) is a set of open source audio | |
12 signal processing and algorithmic synthesis classes written in the | |
13 C++ programming language. STK was designed to facilitate rapid | |
14 development of music synthesis and audio processing software, with | |
15 an emphasis on cross-platform functionality, realtime control, | |
16 ease of use, and educational example code. STK currently runs | |
17 with realtime support (audio and MIDI) on Linux, Macintosh OS X, | |
18 and Windows computer platforms. Generic, non-realtime support has | |
19 been tested under NeXTStep, Sun, and other platforms and should | |
20 work with any standard C++ compiler. | |
21 | |
22 STK WWW site: http://ccrma.stanford.edu/software/stk/ | |
23 | |
24 The Synthesis ToolKit in C++ (STK) | |
25 Copyright (c) 1995--2014 Perry R. Cook and Gary P. Scavone | |
26 | |
27 Permission is hereby granted, free of charge, to any person | |
28 obtaining a copy of this software and associated documentation files | |
29 (the "Software"), to deal in the Software without restriction, | |
30 including without limitation the rights to use, copy, modify, merge, | |
31 publish, distribute, sublicense, and/or sell copies of the Software, | |
32 and to permit persons to whom the Software is furnished to do so, | |
33 subject to the following conditions: | |
34 | |
35 The above copyright notice and this permission notice shall be | |
36 included in all copies or substantial portions of the Software. | |
37 | |
38 Any person wishing to distribute modifications to the Software is | |
39 asked to send the modifications to the original developer so that | |
40 they can be incorporated into the canonical version. This is, | |
41 however, not a binding provision of this license. | |
42 | |
43 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
44 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
45 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
46 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR | |
47 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF | |
48 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
49 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
50 */ | |
51 /***************************************************/ | |
52 | |
53 #include "../include/Stk.h" | |
54 #include <stdlib.h> | |
55 | |
56 namespace stk { | |
57 | |
58 StkFloat Stk :: srate_ = (StkFloat) SRATE; | |
59 std::string Stk :: rawwavepath_ = RAWWAVE_PATH; | |
60 const Stk::StkFormat Stk :: STK_SINT8 = 0x1; | |
61 const Stk::StkFormat Stk :: STK_SINT16 = 0x2; | |
62 const Stk::StkFormat Stk :: STK_SINT24 = 0x4; | |
63 const Stk::StkFormat Stk :: STK_SINT32 = 0x8; | |
64 const Stk::StkFormat Stk :: STK_FLOAT32 = 0x10; | |
65 const Stk::StkFormat Stk :: STK_FLOAT64 = 0x20; | |
66 bool Stk :: showWarnings_ = true; | |
67 bool Stk :: printErrors_ = true; | |
68 std::vector<Stk *> Stk :: alertList_; | |
69 std::ostringstream Stk :: oStream_; | |
70 | |
71 Stk :: Stk( void ) | |
72 : ignoreSampleRateChange_(false) | |
73 { | |
74 } | |
75 | |
76 Stk :: ~Stk( void ) | |
77 { | |
78 } | |
79 | |
80 void Stk :: setSampleRate( StkFloat rate ) | |
81 { | |
82 if ( rate > 0.0 && rate != srate_ ) { | |
83 StkFloat oldRate = srate_; | |
84 srate_ = rate; | |
85 | |
86 for ( unsigned int i=0; i<alertList_.size(); i++ ) | |
87 alertList_[i]->sampleRateChanged( srate_, oldRate ); | |
88 } | |
89 } | |
90 | |
91 void Stk :: sampleRateChanged( StkFloat /*newRate*/, StkFloat /*oldRate*/ ) | |
92 { | |
93 // This function should be reimplemented in classes that need to | |
94 // make internal variable adjustments in response to a global sample | |
95 // rate change. | |
96 } | |
97 | |
98 void Stk :: addSampleRateAlert( Stk *ptr ) | |
99 { | |
100 for ( unsigned int i=0; i<alertList_.size(); i++ ) | |
101 if ( alertList_[i] == ptr ) return; | |
102 | |
103 alertList_.push_back( ptr ); | |
104 } | |
105 | |
106 void Stk :: removeSampleRateAlert( Stk *ptr ) | |
107 { | |
108 for ( unsigned int i=0; i<alertList_.size(); i++ ) { | |
109 if ( alertList_[i] == ptr ) { | |
110 alertList_.erase( alertList_.begin() + i ); | |
111 return; | |
112 } | |
113 } | |
114 } | |
115 | |
116 void Stk :: setRawwavePath( std::string path ) | |
117 { | |
118 if ( !path.empty() ) | |
119 rawwavepath_ = path; | |
120 | |
121 // Make sure the path includes a "/" | |
122 if ( rawwavepath_[rawwavepath_.length()-1] != '/' ) | |
123 rawwavepath_ += "/"; | |
124 } | |
125 | |
126 void Stk :: swap16(unsigned char *ptr) | |
127 { | |
128 unsigned char val; | |
129 | |
130 // Swap 1st and 2nd bytes | |
131 val = *(ptr); | |
132 *(ptr) = *(ptr+1); | |
133 *(ptr+1) = val; | |
134 } | |
135 | |
136 void Stk :: swap32(unsigned char *ptr) | |
137 { | |
138 unsigned char val; | |
139 | |
140 // Swap 1st and 4th bytes | |
141 val = *(ptr); | |
142 *(ptr) = *(ptr+3); | |
143 *(ptr+3) = val; | |
144 | |
145 //Swap 2nd and 3rd bytes | |
146 ptr += 1; | |
147 val = *(ptr); | |
148 *(ptr) = *(ptr+1); | |
149 *(ptr+1) = val; | |
150 } | |
151 | |
152 void Stk :: swap64(unsigned char *ptr) | |
153 { | |
154 unsigned char val; | |
155 | |
156 // Swap 1st and 8th bytes | |
157 val = *(ptr); | |
158 *(ptr) = *(ptr+7); | |
159 *(ptr+7) = val; | |
160 | |
161 // Swap 2nd and 7th bytes | |
162 ptr += 1; | |
163 val = *(ptr); | |
164 *(ptr) = *(ptr+5); | |
165 *(ptr+5) = val; | |
166 | |
167 // Swap 3rd and 6th bytes | |
168 ptr += 1; | |
169 val = *(ptr); | |
170 *(ptr) = *(ptr+3); | |
171 *(ptr+3) = val; | |
172 | |
173 // Swap 4th and 5th bytes | |
174 ptr += 1; | |
175 val = *(ptr); | |
176 *(ptr) = *(ptr+1); | |
177 *(ptr+1) = val; | |
178 } | |
179 | |
180 #if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__)) | |
181 #include <unistd.h> | |
182 #elif defined(__OS_WINDOWS__) | |
183 #include <windows.h> | |
184 #endif | |
185 | |
186 void Stk :: sleep(unsigned long milliseconds) | |
187 { | |
188 #if defined(__OS_WINDOWS__) | |
189 Sleep((DWORD) milliseconds); | |
190 #elif (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__)) | |
191 usleep( (unsigned long) (milliseconds * 1000.0) ); | |
192 #endif | |
193 } | |
194 | |
195 void Stk :: handleError( StkError::Type type ) const | |
196 { | |
197 handleError( oStream_.str(), type ); | |
198 oStream_.str( std::string() ); // reset the ostringstream buffer | |
199 } | |
200 | |
201 void Stk :: handleError( const char *message, StkError::Type type ) | |
202 { | |
203 std::string msg( message ); | |
204 handleError( msg, type ); | |
205 } | |
206 | |
207 void Stk :: handleError( std::string message, StkError::Type type ) | |
208 { | |
209 if ( type == StkError::WARNING || type == StkError::STATUS ) { | |
210 if ( !showWarnings_ ) return; | |
211 std::cerr << '\n' << message << '\n' << std::endl; | |
212 } | |
213 else if (type == StkError::DEBUG_PRINT) { | |
214 #if defined(_STK_DEBUG_) | |
215 std::cerr << '\n' << message << '\n' << std::endl; | |
216 #endif | |
217 } | |
218 else { | |
219 if ( printErrors_ ) { | |
220 // Print error message before throwing. | |
221 std::cerr << '\n' << message << '\n' << std::endl; | |
222 } | |
223 throw StkError(message, type); | |
224 } | |
225 } | |
226 | |
227 // | |
228 // StkFrames definitions | |
229 // | |
230 | |
231 StkFrames :: StkFrames( unsigned int nFrames, unsigned int nChannels ) | |
232 : data_( 0 ), nFrames_( nFrames ), nChannels_( nChannels ) | |
233 { | |
234 size_ = nFrames_ * nChannels_; | |
235 bufferSize_ = size_; | |
236 | |
237 if ( size_ > 0 ) { | |
238 data_ = (StkFloat *) calloc( size_, sizeof( StkFloat ) ); | |
239 #if defined(_STK_DEBUG_) | |
240 if ( data_ == NULL ) { | |
241 std::string error = "StkFrames: memory allocation error in constructor!"; | |
242 Stk::handleError( error, StkError::MEMORY_ALLOCATION ); | |
243 } | |
244 #endif | |
245 } | |
246 | |
247 dataRate_ = Stk::sampleRate(); | |
248 } | |
249 | |
250 StkFrames :: StkFrames( const StkFloat& value, unsigned int nFrames, unsigned int nChannels ) | |
251 : data_( 0 ), nFrames_( nFrames ), nChannels_( nChannels ) | |
252 { | |
253 size_ = nFrames_ * nChannels_; | |
254 bufferSize_ = size_; | |
255 if ( size_ > 0 ) { | |
256 data_ = (StkFloat *) malloc( size_ * sizeof( StkFloat ) ); | |
257 #if defined(_STK_DEBUG_) | |
258 if ( data_ == NULL ) { | |
259 std::string error = "StkFrames: memory allocation error in constructor!"; | |
260 Stk::handleError( error, StkError::MEMORY_ALLOCATION ); | |
261 } | |
262 #endif | |
263 for ( long i=0; i<(long)size_; i++ ) data_[i] = value; | |
264 } | |
265 | |
266 dataRate_ = Stk::sampleRate(); | |
267 } | |
268 | |
269 StkFrames :: ~StkFrames() | |
270 { | |
271 if ( data_ ) free( data_ ); | |
272 } | |
273 | |
274 StkFrames :: StkFrames( const StkFrames& f ) | |
275 : data_(0), size_(0), bufferSize_(0) | |
276 { | |
277 resize( f.frames(), f.channels() ); | |
278 dataRate_ = Stk::sampleRate(); | |
279 for ( unsigned int i=0; i<size_; i++ ) data_[i] = f[i]; | |
280 } | |
281 | |
282 StkFrames& StkFrames :: operator= ( const StkFrames& f ) | |
283 { | |
284 data_ = 0; | |
285 size_ = 0; | |
286 bufferSize_ = 0; | |
287 resize( f.frames(), f.channels() ); | |
288 dataRate_ = Stk::sampleRate(); | |
289 for ( unsigned int i=0; i<size_; i++ ) data_[i] = f[i]; | |
290 return *this; | |
291 } | |
292 | |
293 void StkFrames :: resize( size_t nFrames, unsigned int nChannels ) | |
294 { | |
295 nFrames_ = nFrames; | |
296 nChannels_ = nChannels; | |
297 | |
298 size_ = nFrames_ * nChannels_; | |
299 if ( size_ > bufferSize_ ) { | |
300 if ( data_ ) free( data_ ); | |
301 data_ = (StkFloat *) malloc( size_ * sizeof( StkFloat ) ); | |
302 #if defined(_STK_DEBUG_) | |
303 if ( data_ == NULL ) { | |
304 std::string error = "StkFrames::resize: memory allocation error!"; | |
305 Stk::handleError( error, StkError::MEMORY_ALLOCATION ); | |
306 } | |
307 #endif | |
308 bufferSize_ = size_; | |
309 } | |
310 } | |
311 | |
312 void StkFrames :: resize( size_t nFrames, unsigned int nChannels, StkFloat value ) | |
313 { | |
314 this->resize( nFrames, nChannels ); | |
315 | |
316 for ( size_t i=0; i<size_; i++ ) data_[i] = value; | |
317 } | |
318 | |
319 StkFloat StkFrames :: interpolate( StkFloat frame, unsigned int channel ) const | |
320 { | |
321 #if defined(_STK_DEBUG_) | |
322 if ( frame < 0.0 || frame > (StkFloat) ( nFrames_ - 1 ) || channel >= nChannels_ ) { | |
323 std::ostringstream error; | |
324 error << "StkFrames::interpolate: invalid frame (" << frame << ") or channel (" << channel << ") value!"; | |
325 Stk::handleError( error.str(), StkError::MEMORY_ACCESS ); | |
326 } | |
327 #endif | |
328 | |
329 size_t iIndex = ( size_t ) frame; // integer part of index | |
330 StkFloat output, alpha = frame - (StkFloat) iIndex; // fractional part of index | |
331 | |
332 iIndex = iIndex * nChannels_ + channel; | |
333 output = data_[ iIndex ]; | |
334 if ( alpha > 0.0 ) | |
335 output += ( alpha * ( data_[ iIndex + nChannels_ ] - output ) ); | |
336 | |
337 return output; | |
338 } | |
339 | |
340 } // stk namespace |