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