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
data/src/signals.cpp ADDED
@@ -0,0 +1,90 @@
1
+ #include "beeps/signals.h"
2
+
3
+
4
+ #include <boost/scoped_ptr.hpp>
5
+ #include "Stk.h"
6
+ #include "beeps/beeps.h"
7
+ #include "beeps/exception.h"
8
+
9
+
10
+ namespace Beeps
11
+ {
12
+
13
+
14
+ struct Signals::Data
15
+ {
16
+
17
+ boost::scoped_ptr<stk::StkFrames> frames;
18
+
19
+ };// Signals::Data
20
+
21
+
22
+ Signals::Signals (float seconds, uint channels)
23
+ {
24
+ if (seconds <= 0 || channels <= 0)
25
+ return;
26
+
27
+ self->frames.reset(new stk::StkFrames(seconds * sampling_rate(), channels));
28
+ }
29
+
30
+ Signals::~Signals ()
31
+ {
32
+ }
33
+
34
+ Signals
35
+ Signals::copy () const
36
+ {
37
+ Signals t;
38
+ if (self->frames)
39
+ t.self->frames.reset(new stk::StkFrames(*self->frames));
40
+ return t;
41
+ }
42
+
43
+ float
44
+ Signals::seconds () const
45
+ {
46
+ double sec = samples() / (double) sampling_rate();
47
+ return (float) sec;
48
+ }
49
+
50
+ uint
51
+ Signals::samples () const
52
+ {
53
+ Data* p = self.get();
54
+ return p ? p->frames->frames() : 0;
55
+ }
56
+
57
+ uint
58
+ Signals::channels () const
59
+ {
60
+ Data* p = self.get();
61
+ return p ? p->frames->channels() : 0;
62
+ }
63
+
64
+ stk::StkFrames*
65
+ Signals::frames ()
66
+ {
67
+ Data* p = self.get();
68
+ return p ? p->frames.get() : NULL;
69
+ }
70
+
71
+ const stk::StkFrames*
72
+ Signals::frames () const
73
+ {
74
+ return const_cast<Signals*>(this)->frames();
75
+ }
76
+
77
+ Signals::operator bool () const
78
+ {
79
+ const stk::StkFrames* f = frames();
80
+ return f && f->frames() > 0 && f->channels() > 0;
81
+ }
82
+
83
+ bool
84
+ Signals::operator ! () const
85
+ {
86
+ return !operator bool();
87
+ }
88
+
89
+
90
+ }// Beeps
data/src/sound.cpp ADDED
@@ -0,0 +1,125 @@
1
+ #include "beeps/sound.h"
2
+
3
+
4
+ #include <limits.h>
5
+ #include "Stk.h"
6
+ #include "beeps/openal.h"
7
+ #include "beeps/signals.h"
8
+ #include "beeps/processor.h"
9
+ #include "beeps/exception.h"
10
+ #include "openal.h"
11
+
12
+
13
+ namespace Beeps
14
+ {
15
+
16
+
17
+ struct Sound::Data
18
+ {
19
+
20
+ ALint id;
21
+
22
+ Data ()
23
+ : id(-1)
24
+ {
25
+ }
26
+
27
+ ~Data ()
28
+ {
29
+ clear();
30
+ }
31
+
32
+ void create ()
33
+ {
34
+ if (is_valid()) return;
35
+
36
+ ALuint id_ = 0;
37
+ alGenBuffers(1, &id_);
38
+ check_error(__FILE__, __LINE__);
39
+
40
+ id = id_;
41
+ }
42
+
43
+ void clear ()
44
+ {
45
+ if (id >= 0)
46
+ {
47
+ ALuint id_ = id;
48
+ alDeleteBuffers(1, &id_);
49
+ check_error(__FILE__, __LINE__);
50
+ }
51
+
52
+ id = -1;
53
+ }
54
+
55
+ bool is_valid () const
56
+ {
57
+ return id >= 0;
58
+ }
59
+
60
+ };// Sound::Data
61
+
62
+
63
+ Sound::Sound ()
64
+ {
65
+ }
66
+
67
+ Sound::Sound (Processor* processor, float seconds)
68
+ {
69
+ if (!processor || !*processor || seconds <= 0)
70
+ return;
71
+
72
+ self->create();
73
+
74
+ Signals signals(seconds, 1);
75
+ processor->process(&signals);
76
+
77
+ stk::StkFrames* frames = signals.frames();
78
+ if (!frames)
79
+ return;
80
+
81
+ ALsizei size = frames->frames();
82
+ if (size <= 0)
83
+ return;
84
+
85
+ std::vector<short> buffer;
86
+ buffer.reserve(size);
87
+ for (ALsizei i = 0; i < size; ++i)
88
+ buffer.push_back((*frames)[i] * SHRT_MAX);
89
+
90
+ alBufferData(
91
+ self->id, AL_FORMAT_MONO16, &buffer[0], sizeof(short) * size,
92
+ frames->dataRate());
93
+ check_error(__FILE__, __LINE__);
94
+ }
95
+
96
+ Sound::~Sound ()
97
+ {
98
+ }
99
+
100
+ void
101
+ Sound::play ()
102
+ {
103
+ play_sound(*this);
104
+ }
105
+
106
+ Sound::operator bool () const
107
+ {
108
+ return self->is_valid();
109
+ }
110
+
111
+ bool
112
+ Sound::operator ! () const
113
+ {
114
+ return !operator bool();
115
+ }
116
+
117
+
118
+ ALuint
119
+ get_sound_buffer_id (const Sound& sound)
120
+ {
121
+ return sound.self->id;
122
+ }
123
+
124
+
125
+ }// Beeps
@@ -0,0 +1,151 @@
1
+ #ifndef STK_BLIT_H
2
+ #define STK_BLIT_H
3
+
4
+ #include "Generator.h"
5
+ #include <cmath>
6
+ #include <limits>
7
+
8
+ namespace stk {
9
+
10
+ /***************************************************/
11
+ /*! \class Blit
12
+ \brief STK band-limited impulse train class.
13
+
14
+ This class generates a band-limited impulse train using a
15
+ closed-form algorithm reported by Stilson and Smith in "Alias-Free
16
+ Digital Synthesis of Classic Analog Waveforms", 1996. The user
17
+ can specify both the fundamental frequency of the impulse train
18
+ and the number of harmonics contained in the resulting signal.
19
+
20
+ The signal is normalized so that the peak value is +/-1.0.
21
+
22
+ If nHarmonics is 0, then the signal will contain all harmonics up
23
+ to half the sample rate. Note, however, that this setting may
24
+ produce aliasing in the signal when the frequency is changing (no
25
+ automatic modification of the number of harmonics is performed by
26
+ the setFrequency() function).
27
+
28
+ Original code by Robin Davies, 2005.
29
+ Revisions by Gary Scavone for STK, 2005.
30
+ */
31
+ /***************************************************/
32
+
33
+ class Blit: public Generator
34
+ {
35
+ public:
36
+ //! Default constructor that initializes BLIT frequency to 220 Hz.
37
+ Blit( StkFloat frequency = 220.0 );
38
+
39
+ //! Class destructor.
40
+ ~Blit();
41
+
42
+ //! Resets the oscillator state and phase to 0.
43
+ void reset();
44
+
45
+ //! Set the phase of the signal.
46
+ /*!
47
+ Set the phase of the signal, in the range 0 to 1.
48
+ */
49
+ void setPhase( StkFloat phase ) { phase_ = PI * phase; };
50
+
51
+ //! Get the current phase of the signal.
52
+ /*!
53
+ Get the phase of the signal, in the range [0 to 1.0).
54
+ */
55
+ StkFloat getPhase() const { return phase_ / PI; };
56
+
57
+ //! Set the impulse train rate in terms of a frequency in Hz.
58
+ void setFrequency( StkFloat frequency );
59
+
60
+ //! Set the number of harmonics generated in the signal.
61
+ /*!
62
+ This function sets the number of harmonics contained in the
63
+ resulting signal. It is equivalent to (2 * M) + 1 in the BLIT
64
+ algorithm. The default value of 0 sets the algorithm for maximum
65
+ harmonic content (harmonics up to half the sample rate). This
66
+ parameter is not checked against the current sample rate and
67
+ fundamental frequency. Thus, aliasing can result if one or more
68
+ harmonics for a given fundamental frequency exceeds fs / 2. This
69
+ behavior was chosen over the potentially more problematic solution
70
+ of automatically modifying the M parameter, which can produce
71
+ audible clicks in the signal.
72
+ */
73
+ void setHarmonics( unsigned int nHarmonics = 0 );
74
+
75
+ //! Return the last computed output value.
76
+ StkFloat lastOut( void ) const { return lastFrame_[0]; };
77
+
78
+ //! Compute and return one output sample.
79
+ StkFloat tick( void );
80
+
81
+ //! Fill a channel of the StkFrames object with computed outputs.
82
+ /*!
83
+ The \c channel argument must be less than the number of
84
+ channels in the StkFrames argument (the first channel is specified
85
+ by 0). However, range checking is only performed if _STK_DEBUG_
86
+ is defined during compilation, in which case an out-of-range value
87
+ will trigger an StkError exception.
88
+ */
89
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
90
+
91
+ protected:
92
+
93
+ void updateHarmonics( void );
94
+
95
+ unsigned int nHarmonics_;
96
+ unsigned int m_;
97
+ StkFloat rate_;
98
+ StkFloat phase_;
99
+ StkFloat p_;
100
+
101
+ };
102
+
103
+ inline StkFloat Blit :: tick( void )
104
+ {
105
+ // The code below implements the SincM algorithm of Stilson and
106
+ // Smith with an additional scale factor of P / M applied to
107
+ // normalize the output.
108
+
109
+ // A fully optimized version of this code would replace the two sin
110
+ // calls with a pair of fast sin oscillators, for which stable fast
111
+ // two-multiply algorithms are well known. In the spirit of STK,
112
+ // which favors clarity over performance, the optimization has not
113
+ // been made here.
114
+
115
+ // Avoid a divide by zero at the sinc peak, which has a limiting
116
+ // value of 1.0.
117
+ StkFloat tmp, denominator = sin( phase_ );
118
+ if ( denominator <= std::numeric_limits<StkFloat>::epsilon() )
119
+ tmp = 1.0;
120
+ else {
121
+ tmp = sin( m_ * phase_ );
122
+ tmp /= m_ * denominator;
123
+ }
124
+
125
+ phase_ += rate_;
126
+ if ( phase_ >= PI ) phase_ -= PI;
127
+
128
+ lastFrame_[0] = tmp;
129
+ return lastFrame_[0];
130
+ }
131
+
132
+ inline StkFrames& Blit :: tick( StkFrames& frames, unsigned int channel )
133
+ {
134
+ #if defined(_STK_DEBUG_)
135
+ if ( channel >= frames.channels() ) {
136
+ oStream_ << "Blit::tick(): channel and StkFrames arguments are incompatible!";
137
+ handleError( StkError::FUNCTION_ARGUMENT );
138
+ }
139
+ #endif
140
+
141
+ StkFloat *samples = &frames[channel];
142
+ unsigned int hop = frames.channels();
143
+ for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
144
+ *samples = Blit::tick();
145
+
146
+ return frames;
147
+ }
148
+
149
+ } // stk namespace
150
+
151
+ #endif
@@ -0,0 +1,148 @@
1
+ #ifndef STK_BLITSAW_H
2
+ #define STK_BLITSAW_H
3
+
4
+ #include "Generator.h"
5
+ #include <cmath>
6
+ #include <limits>
7
+
8
+ namespace stk {
9
+
10
+ /***************************************************/
11
+ /*! \class BlitSaw
12
+ \brief STK band-limited sawtooth wave class.
13
+
14
+ This class generates a band-limited sawtooth waveform using a
15
+ closed-form algorithm reported by Stilson and Smith in "Alias-Free
16
+ Digital Synthesis of Classic Analog Waveforms", 1996. The user
17
+ can specify both the fundamental frequency of the sawtooth and the
18
+ number of harmonics contained in the resulting signal.
19
+
20
+ If nHarmonics is 0, then the signal will contain all harmonics up
21
+ to half the sample rate. Note, however, that this setting may
22
+ produce aliasing in the signal when the frequency is changing (no
23
+ automatic modification of the number of harmonics is performed by
24
+ the setFrequency() function).
25
+
26
+ Based on initial code of Robin Davies, 2005.
27
+ Modified algorithm code by Gary Scavone, 2005.
28
+ */
29
+ /***************************************************/
30
+
31
+ class BlitSaw: public Generator
32
+ {
33
+ public:
34
+ //! Class constructor.
35
+ BlitSaw( StkFloat frequency = 220.0 );
36
+
37
+ //! Class destructor.
38
+ ~BlitSaw();
39
+
40
+ //! Resets the oscillator state and phase to 0.
41
+ void reset();
42
+
43
+ //! Set the sawtooth oscillator rate in terms of a frequency in Hz.
44
+ void setFrequency( StkFloat frequency );
45
+
46
+ //! Set the number of harmonics generated in the signal.
47
+ /*!
48
+ This function sets the number of harmonics contained in the
49
+ resulting signal. It is equivalent to (2 * M) + 1 in the BLIT
50
+ algorithm. The default value of 0 sets the algorithm for maximum
51
+ harmonic content (harmonics up to half the sample rate). This
52
+ parameter is not checked against the current sample rate and
53
+ fundamental frequency. Thus, aliasing can result if one or more
54
+ harmonics for a given fundamental frequency exceeds fs / 2. This
55
+ behavior was chosen over the potentially more problematic solution
56
+ of automatically modifying the M parameter, which can produce
57
+ audible clicks in the signal.
58
+ */
59
+ void setHarmonics( unsigned int nHarmonics = 0 );
60
+
61
+ //! Return the last computed output value.
62
+ StkFloat lastOut( void ) const { return lastFrame_[0]; };
63
+
64
+ //! Compute and return one output sample.
65
+ StkFloat tick( void );
66
+
67
+ //! Fill a channel of the StkFrames object with computed outputs.
68
+ /*!
69
+ The \c channel argument must be less than the number of
70
+ channels in the StkFrames argument (the first channel is specified
71
+ by 0). However, range checking is only performed if _STK_DEBUG_
72
+ is defined during compilation, in which case an out-of-range value
73
+ will trigger an StkError exception.
74
+ */
75
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
76
+
77
+ protected:
78
+
79
+ void updateHarmonics( void );
80
+
81
+ unsigned int nHarmonics_;
82
+ unsigned int m_;
83
+ StkFloat rate_;
84
+ StkFloat phase_;
85
+ StkFloat p_;
86
+ StkFloat C2_;
87
+ StkFloat a_;
88
+ StkFloat state_;
89
+
90
+ };
91
+
92
+ inline StkFloat BlitSaw :: tick( void )
93
+ {
94
+ // The code below implements the BLIT algorithm of Stilson and
95
+ // Smith, followed by a summation and filtering operation to produce
96
+ // a sawtooth waveform. After experimenting with various approaches
97
+ // to calculate the average value of the BLIT over one period, I
98
+ // found that an estimate of C2_ = 1.0 / period (in samples) worked
99
+ // most consistently. A "leaky integrator" is then applied to the
100
+ // difference of the BLIT output and C2_. (GPS - 1 October 2005)
101
+
102
+ // A fully optimized version of this code would replace the two sin
103
+ // calls with a pair of fast sin oscillators, for which stable fast
104
+ // two-multiply algorithms are well known. In the spirit of STK,
105
+ // which favors clarity over performance, the optimization has
106
+ // not been made here.
107
+
108
+ // Avoid a divide by zero, or use of a denormalized divisor
109
+ // at the sinc peak, which has a limiting value of m_ / p_.
110
+ StkFloat tmp, denominator = sin( phase_ );
111
+ if ( fabs(denominator) <= std::numeric_limits<StkFloat>::epsilon() )
112
+ tmp = a_;
113
+ else {
114
+ tmp = sin( m_ * phase_ );
115
+ tmp /= p_ * denominator;
116
+ }
117
+
118
+ tmp += state_ - C2_;
119
+ state_ = tmp * 0.995;
120
+
121
+ phase_ += rate_;
122
+ if ( phase_ >= PI ) phase_ -= PI;
123
+
124
+ lastFrame_[0] = tmp;
125
+ return lastFrame_[0];
126
+ }
127
+
128
+ inline StkFrames& BlitSaw :: tick( StkFrames& frames, unsigned int channel )
129
+ {
130
+ #if defined(_STK_DEBUG_)
131
+ if ( channel >= frames.channels() ) {
132
+ oStream_ << "BlitSaw::tick(): channel and StkFrames arguments are incompatible!";
133
+ handleError( StkError::FUNCTION_ARGUMENT );
134
+ }
135
+ #endif
136
+
137
+
138
+ StkFloat *samples = &frames[channel];
139
+ unsigned int hop = frames.channels();
140
+ for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
141
+ *samples = BlitSaw::tick();
142
+
143
+ return frames;
144
+ }
145
+
146
+ } // stk namespace
147
+
148
+ #endif