beeps 0.1.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/.doc/ext/beeps/beeps.cpp +46 -0
  3. data/.doc/ext/beeps/file_in.cpp +59 -0
  4. data/.doc/ext/beeps/native.cpp +41 -0
  5. data/.doc/ext/beeps/processor.cpp +49 -0
  6. data/.doc/ext/beeps/sawtooth_wave.cpp +66 -0
  7. data/.doc/ext/beeps/sine_wave.cpp +66 -0
  8. data/.doc/ext/beeps/sound.cpp +69 -0
  9. data/.doc/ext/beeps/square_wave.cpp +66 -0
  10. data/README.md +4 -0
  11. data/Rakefile +27 -0
  12. data/VERSION +1 -0
  13. data/beeps.gemspec +43 -0
  14. data/ext/beeps/beeps.cpp +48 -0
  15. data/ext/beeps/defs.h +13 -0
  16. data/ext/beeps/extconf.rb +25 -0
  17. data/ext/beeps/file_in.cpp +61 -0
  18. data/ext/beeps/native.cpp +41 -0
  19. data/ext/beeps/processor.cpp +50 -0
  20. data/ext/beeps/sawtooth_wave.cpp +69 -0
  21. data/ext/beeps/sine_wave.cpp +69 -0
  22. data/ext/beeps/sound.cpp +72 -0
  23. data/ext/beeps/square_wave.cpp +69 -0
  24. data/include/beeps.h +12 -0
  25. data/include/beeps/beeps.h +25 -0
  26. data/include/beeps/defs.h +23 -0
  27. data/include/beeps/exception.h +47 -0
  28. data/include/beeps/openal.h +34 -0
  29. data/include/beeps/processor.h +132 -0
  30. data/include/beeps/ruby.h +10 -0
  31. data/include/beeps/ruby/beeps.h +21 -0
  32. data/include/beeps/ruby/processor.h +86 -0
  33. data/include/beeps/ruby/sound.h +42 -0
  34. data/include/beeps/signals.h +53 -0
  35. data/include/beeps/sound.h +44 -0
  36. data/lib/beeps.rb +9 -0
  37. data/lib/beeps/autoinit.rb +10 -0
  38. data/lib/beeps/beeps.rb +49 -0
  39. data/lib/beeps/ext.rb +4 -0
  40. data/lib/beeps/module.rb +49 -0
  41. data/lib/beeps/processor.rb +60 -0
  42. data/lib/beeps/sound.rb +19 -0
  43. data/src/beeps.cpp +93 -0
  44. data/src/exception.cpp +43 -0
  45. data/src/openal.cpp +216 -0
  46. data/src/openal.h +25 -0
  47. data/src/processor.cpp +201 -0
  48. data/src/signals.cpp +90 -0
  49. data/src/sound.cpp +125 -0
  50. data/src/stk/include/Blit.h +151 -0
  51. data/src/stk/include/BlitSaw.h +148 -0
  52. data/src/stk/include/BlitSquare.h +170 -0
  53. data/src/stk/include/FileRead.h +141 -0
  54. data/src/stk/include/FileWvIn.h +195 -0
  55. data/src/stk/include/Generator.h +50 -0
  56. data/src/stk/include/SineWave.h +159 -0
  57. data/src/stk/include/Stk.h +589 -0
  58. data/src/stk/include/WvIn.h +46 -0
  59. data/src/stk/src/Blit.cpp +78 -0
  60. data/src/stk/src/BlitSaw.cpp +91 -0
  61. data/src/stk/src/BlitSquare.cpp +95 -0
  62. data/src/stk/src/FileRead.cpp +903 -0
  63. data/src/stk/src/FileWvIn.cpp +260 -0
  64. data/src/stk/src/SineWave.cpp +78 -0
  65. data/src/stk/src/Stk.cpp +395 -0
  66. data/test/helper.rb +17 -0
  67. data/test/test_beeps.rb +18 -0
  68. data/test/test_sound.rb +26 -0
  69. metadata +177 -0
@@ -0,0 +1,260 @@
1
+ /***************************************************/
2
+ /*! \class FileWvIn
3
+ \brief STK audio file input class.
4
+
5
+ This class inherits from WvIn. It provides a "tick-level"
6
+ interface to the FileRead class. It also provides variable-rate
7
+ playback functionality. Audio file support is provided by the
8
+ FileRead class. Linear interpolation is used for fractional read
9
+ rates.
10
+
11
+ FileWvIn supports multi-channel data. It is important to
12
+ distinguish the tick() method that computes a single frame (and
13
+ returns only the specified sample of a multi-channel frame) from
14
+ the overloaded one that takes an StkFrames object for
15
+ multi-channel and/or multi-frame data.
16
+
17
+ FileWvIn will either load the entire content of an audio file into
18
+ local memory or incrementally read file data from disk in chunks.
19
+ This behavior is controlled by the optional constructor arguments
20
+ \e chunkThreshold and \e chunkSize. File sizes greater than \e
21
+ chunkThreshold (in sample frames) will be read incrementally in
22
+ chunks of \e chunkSize each (also in sample frames).
23
+
24
+ When the file end is reached, subsequent calls to the tick()
25
+ functions return zeros and isFinished() returns \e true.
26
+
27
+ See the FileRead class for a description of the supported audio
28
+ file formats.
29
+
30
+ by Perry R. Cook and Gary P. Scavone, 1995--2014.
31
+ */
32
+ /***************************************************/
33
+
34
+ #include "FileWvIn.h"
35
+ #include <cmath>
36
+
37
+ namespace stk {
38
+
39
+ FileWvIn :: FileWvIn( unsigned long chunkThreshold, unsigned long chunkSize )
40
+ : finished_(true), interpolate_(false), time_(0.0), rate_(0.0),
41
+ chunkThreshold_(chunkThreshold), chunkSize_(chunkSize)
42
+ {
43
+ Stk::addSampleRateAlert( this );
44
+ }
45
+
46
+ FileWvIn :: FileWvIn( std::string fileName, bool raw, bool doNormalize,
47
+ unsigned long chunkThreshold, unsigned long chunkSize )
48
+ : finished_(true), interpolate_(false), time_(0.0), rate_(0.0),
49
+ chunkThreshold_(chunkThreshold), chunkSize_(chunkSize)
50
+ {
51
+ openFile( fileName, raw, doNormalize );
52
+ Stk::addSampleRateAlert( this );
53
+ }
54
+
55
+ FileWvIn :: ~FileWvIn()
56
+ {
57
+ this->closeFile();
58
+ Stk::removeSampleRateAlert( this );
59
+ }
60
+
61
+ void FileWvIn :: sampleRateChanged( StkFloat newRate, StkFloat oldRate )
62
+ {
63
+ if ( !ignoreSampleRateChange_ )
64
+ this->setRate( oldRate * rate_ / newRate );
65
+ }
66
+
67
+ void FileWvIn :: closeFile( void )
68
+ {
69
+ if ( file_.isOpen() ) file_.close();
70
+ finished_ = true;
71
+ lastFrame_.resize( 0, 0 );
72
+ }
73
+
74
+ void FileWvIn :: openFile( std::string fileName, bool raw, bool doNormalize )
75
+ {
76
+ // Call close() in case another file is already open.
77
+ this->closeFile();
78
+
79
+ // Attempt to open the file ... an error might be thrown here.
80
+ file_.open( fileName, raw );
81
+
82
+ // Determine whether chunking or not.
83
+ if ( file_.fileSize() > chunkThreshold_ ) {
84
+ chunking_ = true;
85
+ chunkPointer_ = 0;
86
+ data_.resize( chunkSize_, file_.channels() );
87
+ if ( doNormalize ) normalizing_ = true;
88
+ else normalizing_ = false;
89
+ }
90
+ else {
91
+ chunking_ = false;
92
+ data_.resize( (size_t) file_.fileSize(), file_.channels() );
93
+ }
94
+
95
+ // Load all or part of the data.
96
+ file_.read( data_, 0, doNormalize );
97
+
98
+ // Resize our lastFrame container.
99
+ lastFrame_.resize( 1, file_.channels() );
100
+
101
+ // Set default rate based on file sampling rate.
102
+ this->setRate( data_.dataRate() / Stk::sampleRate() );
103
+
104
+ if ( doNormalize & !chunking_ ) this->normalize();
105
+
106
+ this->reset();
107
+ }
108
+
109
+ void FileWvIn :: reset(void)
110
+ {
111
+ time_ = (StkFloat) 0.0;
112
+ for ( unsigned int i=0; i<lastFrame_.size(); i++ ) lastFrame_[i] = 0.0;
113
+ finished_ = false;
114
+ }
115
+
116
+ void FileWvIn :: normalize(void)
117
+ {
118
+ this->normalize( 1.0 );
119
+ }
120
+
121
+ // Normalize all channels equally by the greatest magnitude in all of the data.
122
+ void FileWvIn :: normalize( StkFloat peak )
123
+ {
124
+ // When chunking, the "normalization" scaling is performed by FileRead.
125
+ if ( chunking_ ) return;
126
+
127
+ size_t i;
128
+ StkFloat max = 0.0;
129
+
130
+ for ( i=0; i<data_.size(); i++ ) {
131
+ if ( fabs( data_[i] ) > max )
132
+ max = (StkFloat) fabs((double) data_[i]);
133
+ }
134
+
135
+ if ( max > 0.0 ) {
136
+ max = 1.0 / max;
137
+ max *= peak;
138
+ for ( i=0; i<data_.size(); i++ )
139
+ data_[i] *= max;
140
+ }
141
+ }
142
+
143
+ void FileWvIn :: setRate( StkFloat rate )
144
+ {
145
+ rate_ = rate;
146
+
147
+ // If negative rate and at beginning of sound, move pointer to end
148
+ // of sound.
149
+ if ( (rate_ < 0) && (time_ == 0.0) ) time_ = file_.fileSize() - 1.0;
150
+
151
+ if ( fmod( rate_, 1.0 ) != 0.0 ) interpolate_ = true;
152
+ else interpolate_ = false;
153
+ }
154
+
155
+ void FileWvIn :: addTime( StkFloat time )
156
+ {
157
+ // Add an absolute time in samples
158
+ time_ += time;
159
+
160
+ if ( time_ < 0.0 ) time_ = 0.0;
161
+ if ( time_ > file_.fileSize() - 1.0 ) {
162
+ time_ = file_.fileSize() - 1.0;
163
+ for ( unsigned int i=0; i<lastFrame_.size(); i++ ) lastFrame_[i] = 0.0;
164
+ finished_ = true;
165
+ }
166
+ }
167
+
168
+ StkFloat FileWvIn :: tick( unsigned int channel )
169
+ {
170
+ #if defined(_STK_DEBUG_)
171
+ if ( channel >= data_.channels() ) {
172
+ oStream_ << "FileWvIn::tick(): channel argument and soundfile data are incompatible!";
173
+ handleError( StkError::FUNCTION_ARGUMENT );
174
+ }
175
+ #endif
176
+
177
+ if ( finished_ ) return 0.0;
178
+
179
+ if ( time_ < 0.0 || time_ > (StkFloat) ( file_.fileSize() - 1.0 ) ) {
180
+ for ( unsigned int i=0; i<lastFrame_.size(); i++ ) lastFrame_[i] = 0.0;
181
+ finished_ = true;
182
+ return 0.0;
183
+ }
184
+
185
+ StkFloat tyme = time_;
186
+ if ( chunking_ ) {
187
+
188
+ // Check the time address vs. our current buffer limits.
189
+ if ( ( time_ < (StkFloat) chunkPointer_ ) ||
190
+ ( time_ > (StkFloat) ( chunkPointer_ + chunkSize_ - 1 ) ) ) {
191
+
192
+ while ( time_ < (StkFloat) chunkPointer_ ) { // negative rate
193
+ chunkPointer_ -= chunkSize_ - 1; // overlap chunks by one frame
194
+ if ( chunkPointer_ < 0 ) chunkPointer_ = 0;
195
+ }
196
+ while ( time_ > (StkFloat) ( chunkPointer_ + chunkSize_ - 1 ) ) { // positive rate
197
+ chunkPointer_ += chunkSize_ - 1; // overlap chunks by one frame
198
+ if ( chunkPointer_ + chunkSize_ > file_.fileSize() ) // at end of file
199
+ chunkPointer_ = file_.fileSize() - chunkSize_;
200
+ }
201
+
202
+ // Load more data.
203
+ file_.read( data_, chunkPointer_, normalizing_ );
204
+ }
205
+
206
+ // Adjust index for the current buffer.
207
+ tyme -= chunkPointer_;
208
+ }
209
+
210
+ if ( interpolate_ ) {
211
+ for ( unsigned int i=0; i<lastFrame_.size(); i++ )
212
+ lastFrame_[i] = data_.interpolate( tyme, i );
213
+ }
214
+ else {
215
+ for ( unsigned int i=0; i<lastFrame_.size(); i++ )
216
+ lastFrame_[i] = data_( (size_t) tyme, i );
217
+ }
218
+
219
+ // Increment time, which can be negative.
220
+ time_ += rate_;
221
+
222
+ return lastFrame_[channel];
223
+ }
224
+
225
+ StkFrames& FileWvIn :: tick( StkFrames& frames, unsigned int channel)
226
+ {
227
+ if ( !file_.isOpen() ) {
228
+ #if defined(_STK_DEBUG_)
229
+ oStream_ << "FileWvIn::tick(): no file data is loaded!";
230
+ handleError( StkError::DEBUG_PRINT );
231
+ #endif
232
+ return frames;
233
+ }
234
+
235
+ unsigned int nChannels = lastFrame_.channels();
236
+ #if defined(_STK_DEBUG_)
237
+ if ( channel > frames.channels() - nChannels ) {
238
+ oStream_ << "FileWvIn::tick(): channel and StkFrames arguments are incompatible!";
239
+ handleError( StkError::FUNCTION_ARGUMENT );
240
+ }
241
+ #endif
242
+
243
+ StkFloat *samples = &frames[channel];
244
+ unsigned int j, hop = frames.channels() - nChannels;
245
+ if ( nChannels == 1 ) {
246
+ for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
247
+ *samples++ = tick();
248
+ }
249
+ else {
250
+ for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
251
+ *samples++ = tick();
252
+ for ( j=1; j<nChannels; j++ )
253
+ *samples++ = lastFrame_[j];
254
+ }
255
+ }
256
+ return frames;
257
+
258
+ }
259
+
260
+ } // stk namespace
@@ -0,0 +1,78 @@
1
+ /***************************************************/
2
+ /*! \class SineWave
3
+ \brief STK sinusoid oscillator class.
4
+
5
+ This class computes and saves a static sine "table" that can be
6
+ shared by multiple instances. It has an interface similar to the
7
+ WaveLoop class but inherits from the Generator class. Output
8
+ values are computed using linear interpolation.
9
+
10
+ The "table" length, set in SineWave.h, is 2048 samples by default.
11
+
12
+ by Perry R. Cook and Gary P. Scavone, 1995--2014.
13
+ */
14
+ /***************************************************/
15
+
16
+ #include "SineWave.h"
17
+ #include <cmath>
18
+
19
+ namespace stk {
20
+
21
+ StkFrames SineWave :: table_;
22
+
23
+ SineWave :: SineWave( void )
24
+ : time_(0.0), rate_(1.0), phaseOffset_(0.0)
25
+ {
26
+ if ( table_.empty() ) {
27
+ table_.resize( TABLE_SIZE + 1, 1 );
28
+ StkFloat temp = 1.0 / TABLE_SIZE;
29
+ for ( unsigned long i=0; i<=TABLE_SIZE; i++ )
30
+ table_[i] = sin( TWO_PI * i * temp );
31
+ }
32
+
33
+ Stk::addSampleRateAlert( this );
34
+ }
35
+
36
+ SineWave :: ~SineWave()
37
+ {
38
+ Stk::removeSampleRateAlert( this );
39
+ }
40
+
41
+ void SineWave :: sampleRateChanged( StkFloat newRate, StkFloat oldRate )
42
+ {
43
+ if ( !ignoreSampleRateChange_ )
44
+ this->setRate( oldRate * rate_ / newRate );
45
+ }
46
+
47
+ void SineWave :: reset( void )
48
+ {
49
+ time_ = 0.0;
50
+ lastFrame_[0] = 0;
51
+ }
52
+
53
+ void SineWave :: setFrequency( StkFloat frequency )
54
+ {
55
+ // This is a looping frequency.
56
+ this->setRate( TABLE_SIZE * frequency / Stk::sampleRate() );
57
+ }
58
+
59
+ void SineWave :: addTime( StkFloat time )
60
+ {
61
+ // Add an absolute time in samples.
62
+ time_ += time;
63
+ }
64
+
65
+ void SineWave :: addPhase( StkFloat phase )
66
+ {
67
+ // Add a time in cycles (one cycle = TABLE_SIZE).
68
+ time_ += TABLE_SIZE * phase;
69
+ }
70
+
71
+ void SineWave :: addPhaseOffset( StkFloat phaseOffset )
72
+ {
73
+ // Add a phase offset relative to any previous offset value.
74
+ time_ += ( phaseOffset - phaseOffset_ ) * TABLE_SIZE;
75
+ phaseOffset_ = phaseOffset;
76
+ }
77
+
78
+ } // stk namespace
@@ -0,0 +1,395 @@
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 "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
+ if ( data_ ) free( data_ );
285
+ data_ = 0;
286
+ size_ = 0;
287
+ bufferSize_ = 0;
288
+ resize( f.frames(), f.channels() );
289
+ dataRate_ = Stk::sampleRate();
290
+ for ( unsigned int i=0; i<size_; i++ ) data_[i] = f[i];
291
+ return *this;
292
+ }
293
+
294
+ void StkFrames :: resize( size_t nFrames, unsigned int nChannels )
295
+ {
296
+ nFrames_ = nFrames;
297
+ nChannels_ = nChannels;
298
+
299
+ size_ = nFrames_ * nChannels_;
300
+ if ( size_ > bufferSize_ ) {
301
+ if ( data_ ) free( data_ );
302
+ data_ = (StkFloat *) malloc( size_ * sizeof( StkFloat ) );
303
+ #if defined(_STK_DEBUG_)
304
+ if ( data_ == NULL ) {
305
+ std::string error = "StkFrames::resize: memory allocation error!";
306
+ Stk::handleError( error, StkError::MEMORY_ALLOCATION );
307
+ }
308
+ #endif
309
+ bufferSize_ = size_;
310
+ }
311
+ }
312
+
313
+ void StkFrames :: resize( size_t nFrames, unsigned int nChannels, StkFloat value )
314
+ {
315
+ this->resize( nFrames, nChannels );
316
+
317
+ for ( size_t i=0; i<size_; i++ ) data_[i] = value;
318
+ }
319
+
320
+ StkFrames& StkFrames::getChannel(unsigned int sourceChannel,StkFrames& destinationFrames, unsigned int destinationChannel) const
321
+ {
322
+ #if defined(_STK_DEBUG_)
323
+ if (sourceChannel > channels() - 1) {
324
+ std::ostringstream error;
325
+ error << "StkFrames::getChannel invalid sourceChannel (" << sourceChannel << ")";
326
+ Stk::handleError( error.str(), StkError::FUNCTION_ARGUMENT);
327
+ }
328
+ if (destinationChannel > destinationFrames.channels() - 1) {
329
+ std::ostringstream error;
330
+ error << "StkFrames::getChannel invalid destinationChannel (" << destinationChannel << ")";
331
+ Stk::handleError( error.str(), StkError::FUNCTION_ARGUMENT );
332
+ }
333
+ if (destinationFrames.frames() < frames()) {
334
+ std::ostringstream error;
335
+ error << "StkFrames::getChannel destination.frames() < frames()";
336
+ Stk::handleError( error.str(), StkError::MEMORY_ACCESS);
337
+ }
338
+ #endif
339
+ int sourceHop = nChannels_;
340
+ int destinationHop = destinationFrames.nChannels_;
341
+ for (int i = sourceChannel, j= destinationChannel; i < nFrames_ * nChannels_; i+=sourceHop,j+=destinationHop) {
342
+ destinationFrames[j] = data_[i];
343
+ }
344
+ return destinationFrames;
345
+
346
+ }
347
+
348
+ void StkFrames::setChannel(unsigned int destinationChannel, const stk::StkFrames &sourceFrames,unsigned int sourceChannel)
349
+ {
350
+ #if defined(_STK_DEBUG_)
351
+ if (sourceChannel > sourceFrames.channels() - 1) {
352
+ std::ostringstream error;
353
+ error << "StkFrames::setChannel invalid sourceChannel (" << sourceChannel << ")";
354
+ Stk::handleError( error.str(), StkError::FUNCTION_ARGUMENT);
355
+ }
356
+ if (destinationChannel > channels() - 1) {
357
+ std::ostringstream error;
358
+ error << "StkFrames::setChannel invalid channel (" << destinationChannel << ")";
359
+ Stk::handleError( error.str(), StkError::FUNCTION_ARGUMENT );
360
+ }
361
+ if (sourceFrames.frames() != frames()) {
362
+ std::ostringstream error;
363
+ error << "StkFrames::setChannel sourceFrames.frames() != frames()";
364
+ Stk::handleError( error.str(), StkError::MEMORY_ACCESS);
365
+ }
366
+ #endif
367
+ unsigned int sourceHop = sourceFrames.nChannels_;
368
+ unsigned int destinationHop = nChannels_;
369
+ for (int i = destinationChannel,j = sourceChannel ; i < nFrames_ * nChannels_; i+=destinationHop,j+=sourceHop) {
370
+ data_[i] = sourceFrames[j];
371
+ }
372
+ }
373
+
374
+ StkFloat StkFrames :: interpolate( StkFloat frame, unsigned int channel ) const
375
+ {
376
+ #if defined(_STK_DEBUG_)
377
+ if ( frame < 0.0 || frame > (StkFloat) ( nFrames_ - 1 ) || channel >= nChannels_ ) {
378
+ std::ostringstream error;
379
+ error << "StkFrames::interpolate: invalid frame (" << frame << ") or channel (" << channel << ") value!";
380
+ Stk::handleError( error.str(), StkError::MEMORY_ACCESS );
381
+ }
382
+ #endif
383
+
384
+ size_t iIndex = ( size_t ) frame; // integer part of index
385
+ StkFloat output, alpha = frame - (StkFloat) iIndex; // fractional part of index
386
+
387
+ iIndex = iIndex * nChannels_ + channel;
388
+ output = data_[ iIndex ];
389
+ if ( alpha > 0.0 )
390
+ output += ( alpha * ( data_[ iIndex + nChannels_ ] - output ) );
391
+
392
+ return output;
393
+ }
394
+
395
+ } // stk namespace