beeps 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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