viking-bloopsaphone 0.4

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.
@@ -0,0 +1,46 @@
1
+ //
2
+ // threads.h - threaded garments for the bloopsaphone
3
+ //
4
+ #ifndef BLOOPSAPHONE_THREADS_H
5
+ #define BLOOPSAPHONE_THREADS_H
6
+
7
+ #ifdef _WIN32
8
+ #include <windows.h>
9
+ typedef CRITICAL_SECTION bloopsalock;
10
+ static inline void bloops_lock_init(bloopsalock *lock) {
11
+ InitializeCriticalSection(lock);
12
+ }
13
+ static inline void bloops_lock_acquire(bloopsalock *lock) {
14
+ EnterCriticalSection(lock);
15
+ }
16
+ static inline int bloops_lock_try_acquire(bloopsalock *lock) {
17
+ return !!TryEnterCriticalSection(lock);
18
+ }
19
+ static inline void bloops_lock_release(bloopsalock *lock) {
20
+ LeaveCriticalSection(lock);
21
+ }
22
+ static inline void bloops_lock_finalize(bloopsalock *lock) {
23
+ DeleteCriticalSection(lock);
24
+ }
25
+ #else
26
+ #include <pthread.h>
27
+ #include <errno.h>
28
+ typedef pthread_mutex_t bloopsalock;
29
+ static inline void bloops_lock_init(bloopsalock *lock) {
30
+ pthread_mutex_init(lock, NULL);
31
+ }
32
+ static inline void bloops_lock_acquire(bloopsalock *lock) {
33
+ pthread_mutex_lock(lock);
34
+ }
35
+ static inline int bloops_lock_try_acquire(bloopsalock *lock) {
36
+ return !pthread_mutex_trylock(lock);
37
+ }
38
+ static inline void bloops_lock_release(bloopsalock *lock) {
39
+ pthread_mutex_unlock(lock);
40
+ }
41
+ static inline void bloops_lock_finalize(bloopsalock *lock) {
42
+ pthread_mutex_destroy(lock);
43
+ }
44
+ #endif
45
+
46
+ #endif
@@ -0,0 +1,15 @@
1
+ require 'mkmf'
2
+ require 'fileutils'
3
+
4
+ $CFLAGS << " -I../../c #{ENV['CFLAGS']}"
5
+ $LIBS << " -lm -lportaudio #{ENV['LDFLAGS']}"
6
+
7
+ %w[notation.c threads.h bloopsaphone.c bloopsaphone.h].each do |fn|
8
+ fn = "../../c/#{fn}"
9
+ abort "!! ERROR !!\n** #{fn} not found; type 'make ruby' in the top directory\n\n" \
10
+ unless File.exists? fn
11
+ FileUtils.cp(fn, ".")
12
+ end
13
+
14
+ have_library("portaudio")
15
+ create_makefile("bloops")
@@ -0,0 +1,332 @@
1
+ //
2
+ // rubyext.c
3
+ // the ruby binding to bloopsaphone
4
+ //
5
+ // (c) 2009 why the lucky stiff
6
+ //
7
+ #include <ruby.h>
8
+ #include "bloopsaphone.h"
9
+
10
+ static VALUE cBloops, cSound, cTrack;
11
+ static bloopsaphone *Pplain;
12
+
13
+ #ifndef RSTRING_LEN
14
+ #define RSTRING_LEN(str) RSTRING(str)->len
15
+ #define RSTRING_PTR(str) RSTRING(str)->ptr
16
+ #endif
17
+
18
+ //
19
+ // Main Bloops object
20
+ //
21
+ static void
22
+ rb_bloops_free(bloops *B)
23
+ {
24
+ bloops_destroy(B);
25
+ }
26
+
27
+ VALUE
28
+ rb_bloops_alloc(VALUE klass)
29
+ {
30
+ bloops *B = bloops_new();
31
+ return Data_Wrap_Struct(klass, NULL, rb_bloops_free, B);
32
+ }
33
+
34
+ VALUE
35
+ rb_bloops_clear(VALUE self)
36
+ {
37
+ bloops *B;
38
+ Data_Get_Struct(self, bloops, B);
39
+ bloops_clear(B);
40
+ return self;
41
+ }
42
+
43
+ VALUE
44
+ rb_bloops_play(VALUE self)
45
+ {
46
+ bloops *B;
47
+ Data_Get_Struct(self, bloops, B);
48
+ bloops_play(B);
49
+ return self;
50
+ }
51
+
52
+ VALUE
53
+ rb_bloops_is_stopped(VALUE self)
54
+ {
55
+ bloops *B;
56
+ Data_Get_Struct(self, bloops, B);
57
+ return bloops_is_done(B) ? Qtrue : Qfalse;
58
+ }
59
+
60
+ VALUE
61
+ rb_bloops_get_tempo(VALUE self)
62
+ {
63
+ bloops *B;
64
+ Data_Get_Struct(self, bloops, B);
65
+ return INT2NUM(B->tempo);
66
+ }
67
+
68
+ VALUE
69
+ rb_bloops_set_tempo(VALUE self, VALUE tempo)
70
+ {
71
+ bloops *B;
72
+ Data_Get_Struct(self, bloops, B);
73
+ bloops_tempo(B, NUM2INT(tempo));
74
+ return tempo;
75
+ }
76
+
77
+ //
78
+ // Instrument creation
79
+ //
80
+ static void
81
+ rb_bloops_sound_free(bloopsaphone *sound)
82
+ {
83
+ bloops_sound_destroy(sound);
84
+ }
85
+
86
+ VALUE
87
+ rb_bloops_load(VALUE self, VALUE fname)
88
+ {
89
+ bloops *B;
90
+ bloopsaphone *P;
91
+ Data_Get_Struct(self, bloops, B);
92
+
93
+ StringValue(fname);
94
+ P = bloops_sound_file(B, RSTRING_PTR(fname));
95
+ if (P == NULL) return Qnil;
96
+ return Data_Wrap_Struct(cSound, NULL, rb_bloops_sound_free, P);
97
+ }
98
+
99
+ VALUE
100
+ rb_bloops_sound(VALUE self, VALUE type)
101
+ {
102
+ bloopsaphone *P = bloops_square();
103
+ P->params.type = (unsigned char)NUM2INT(type);
104
+ return Data_Wrap_Struct(cSound, NULL, rb_bloops_sound_free, P);
105
+ }
106
+
107
+ VALUE
108
+ rb_bloops_sound_copy(VALUE self, VALUE other)
109
+ {
110
+ bloopsaphone *P;
111
+ bloopsaphone *O;
112
+ Data_Get_Struct(self, bloopsaphone, P);
113
+ Data_Get_Struct(other, bloopsaphone, O);
114
+ bloops_sound_copy(P, O);
115
+ return Qnil;
116
+ }
117
+
118
+ VALUE
119
+ rb_bloops_sound_str(VALUE self)
120
+ {
121
+ bloopsaphone *P;
122
+ Data_Get_Struct(self, bloopsaphone, P);
123
+ return rb_str_new2(bloops_sound_str(P));
124
+ }
125
+
126
+ VALUE
127
+ rb_bloops_reset(VALUE self)
128
+ {
129
+ bloopsaphone *P;
130
+ Data_Get_Struct(self, bloopsaphone, P);
131
+ bloops_sound_copy(P, Pplain);
132
+ return self;
133
+ }
134
+
135
+ VALUE
136
+ rb_bloops_test(VALUE self)
137
+ {
138
+ bloops *B;
139
+ bloopsatrack *T;
140
+ bloopsaphone *P;
141
+
142
+ Data_Get_Struct(self, bloopsaphone, P);
143
+
144
+ B = bloops_new();
145
+ bloops_tempo(B, 120);
146
+ T = bloops_track2(B, P, "C");
147
+ T->notes[0].tone = 'n';
148
+ memcpy(&T->params, &P->params, sizeof(bloopsaparams));
149
+ bloops_play(B);
150
+ bloops_track_destroy(T);
151
+ bloops_destroy(B);
152
+
153
+ return self;
154
+ }
155
+
156
+ VALUE
157
+ rb_bloops_get_type(VALUE self)
158
+ {
159
+ bloopsaphone *P;
160
+ Data_Get_Struct(self, bloopsaphone, P);
161
+ return INT2NUM((int)P->params.type);
162
+ }
163
+
164
+ VALUE
165
+ rb_bloops_set_type(VALUE self, VALUE type)
166
+ {
167
+ bloopsaphone *P;
168
+ Data_Get_Struct(self, bloopsaphone, P);
169
+ P->params.type = (unsigned char)NUM2INT(type);
170
+ return type;
171
+ }
172
+
173
+ #define SOUND_ACCESSOR(name) \
174
+ VALUE rb_bloops_get_##name(VALUE self) { \
175
+ bloopsaphone *P; \
176
+ Data_Get_Struct(self, bloopsaphone, P); \
177
+ return rb_float_new(P->params.name); \
178
+ } \
179
+ VALUE rb_bloops_set_##name(VALUE self, VALUE f) { \
180
+ bloopsaphone *P; \
181
+ Data_Get_Struct(self, bloopsaphone, P); \
182
+ P->params.name = (float)NUM2DBL(f); \
183
+ return f; \
184
+ }
185
+
186
+ SOUND_ACCESSOR(arp);
187
+ SOUND_ACCESSOR(aspeed);
188
+ SOUND_ACCESSOR(attack);
189
+ SOUND_ACCESSOR(decay);
190
+ SOUND_ACCESSOR(dslide);
191
+ SOUND_ACCESSOR(freq);
192
+ SOUND_ACCESSOR(hpf);
193
+ SOUND_ACCESSOR(hsweep);
194
+ SOUND_ACCESSOR(limit);
195
+ SOUND_ACCESSOR(lpf);
196
+ SOUND_ACCESSOR(lsweep);
197
+ SOUND_ACCESSOR(phase);
198
+ SOUND_ACCESSOR(psweep);
199
+ SOUND_ACCESSOR(repeat);
200
+ SOUND_ACCESSOR(resonance);
201
+ SOUND_ACCESSOR(slide);
202
+ SOUND_ACCESSOR(square);
203
+ SOUND_ACCESSOR(sustain);
204
+ SOUND_ACCESSOR(sweep);
205
+ SOUND_ACCESSOR(punch);
206
+ SOUND_ACCESSOR(vibe);
207
+ SOUND_ACCESSOR(vspeed);
208
+ SOUND_ACCESSOR(vdelay);
209
+ SOUND_ACCESSOR(volume);
210
+
211
+ //
212
+ // Individual track object
213
+ //
214
+ static void
215
+ rb_bloops_track_free(bloopsatrack *track)
216
+ {
217
+ bloops_track_destroy(track);
218
+ }
219
+
220
+ VALUE
221
+ rb_bloops_tune(VALUE self, VALUE sound, VALUE notes)
222
+ {
223
+ bloops *B;
224
+ bloopsaphone *phone;
225
+ bloopsatrack *track;
226
+ Data_Get_Struct(self, bloops, B);
227
+ Data_Get_Struct(sound, bloopsaphone, phone);
228
+
229
+ StringValue(notes);
230
+ track = bloops_track(B, phone, RSTRING_PTR(notes), RSTRING_LEN(notes));
231
+ return Data_Wrap_Struct(cTrack, NULL, rb_bloops_track_free, track);
232
+ }
233
+
234
+ VALUE
235
+ rb_bloops_track_str(VALUE self)
236
+ {
237
+ char *str;
238
+ VALUE obj;
239
+ bloopsatrack *track;
240
+ Data_Get_Struct(self, bloopsatrack, track);
241
+
242
+ str = bloops_track_str(track);
243
+ obj = rb_str_new2(str);
244
+ free(str);
245
+
246
+ return obj;
247
+ }
248
+
249
+ //
250
+ // Ruby extension startup
251
+ //
252
+ void
253
+ Init_bloops()
254
+ {
255
+ Pplain = bloops_square();
256
+
257
+ cBloops = rb_define_class("Bloops", rb_cObject);
258
+ rb_define_alloc_func(cBloops, rb_bloops_alloc);
259
+ rb_define_method(cBloops, "clear", rb_bloops_clear, 0);
260
+ rb_define_method(cBloops, "load", rb_bloops_load, 1);
261
+ rb_define_method(cBloops, "play", rb_bloops_play, 0);
262
+ rb_define_method(cBloops, "sound", rb_bloops_sound, 1);
263
+ rb_define_singleton_method(cBloops, "sound", rb_bloops_sound, 1);
264
+ rb_define_method(cBloops, "stopped?", rb_bloops_is_stopped, 0);
265
+ rb_define_method(cBloops, "tempo", rb_bloops_get_tempo, 0);
266
+ rb_define_method(cBloops, "tempo=", rb_bloops_set_tempo, 1);
267
+ rb_define_method(cBloops, "tune", rb_bloops_tune, 2);
268
+
269
+ rb_const_set(cBloops, rb_intern("SQUARE"), INT2NUM(BLOOPS_SQUARE));
270
+ rb_const_set(cBloops, rb_intern("SAWTOOTH"), INT2NUM(BLOOPS_SAWTOOTH));
271
+ rb_const_set(cBloops, rb_intern("SINE"), INT2NUM(BLOOPS_SINE));
272
+ rb_const_set(cBloops, rb_intern("NOISE"), INT2NUM(BLOOPS_NOISE));
273
+
274
+ cSound = rb_define_class_under(cBloops, "Sound", rb_cObject);
275
+ rb_define_method(cSound, "initialize_copy", rb_bloops_sound_copy, 1);
276
+ rb_define_method(cSound, "to_s", rb_bloops_sound_str, 0);
277
+ rb_define_method(cSound, "reset", rb_bloops_reset, 0);
278
+ rb_define_method(cSound, "test", rb_bloops_test, 0);
279
+ rb_define_method(cSound, "arp", rb_bloops_get_arp, 0);
280
+ rb_define_method(cSound, "arp=", rb_bloops_set_arp, 1);
281
+ rb_define_method(cSound, "aspeed", rb_bloops_get_aspeed, 0);
282
+ rb_define_method(cSound, "aspeed=", rb_bloops_set_aspeed, 1);
283
+ rb_define_method(cSound, "attack", rb_bloops_get_attack, 0);
284
+ rb_define_method(cSound, "attack=", rb_bloops_set_attack, 1);
285
+ rb_define_method(cSound, "decay", rb_bloops_get_decay, 0);
286
+ rb_define_method(cSound, "decay=", rb_bloops_set_decay, 1);
287
+ rb_define_method(cSound, "dslide", rb_bloops_get_dslide, 0);
288
+ rb_define_method(cSound, "dslide=", rb_bloops_set_dslide, 1);
289
+ rb_define_method(cSound, "freq", rb_bloops_get_freq, 0);
290
+ rb_define_method(cSound, "freq=", rb_bloops_set_freq, 1);
291
+ rb_define_method(cSound, "hpf", rb_bloops_get_hpf, 0);
292
+ rb_define_method(cSound, "hpf=", rb_bloops_set_hpf, 1);
293
+ rb_define_method(cSound, "hsweep", rb_bloops_get_hsweep, 0);
294
+ rb_define_method(cSound, "hsweep=", rb_bloops_set_hsweep, 1);
295
+ rb_define_method(cSound, "limit", rb_bloops_get_limit, 0);
296
+ rb_define_method(cSound, "limit=", rb_bloops_set_limit, 1);
297
+ rb_define_method(cSound, "lpf", rb_bloops_get_lpf, 0);
298
+ rb_define_method(cSound, "lpf=", rb_bloops_set_lpf, 1);
299
+ rb_define_method(cSound, "lsweep", rb_bloops_get_lsweep, 0);
300
+ rb_define_method(cSound, "lsweep=", rb_bloops_set_lsweep, 1);
301
+ rb_define_method(cSound, "phase", rb_bloops_get_phase, 0);
302
+ rb_define_method(cSound, "phase=", rb_bloops_set_phase, 1);
303
+ rb_define_method(cSound, "psweep", rb_bloops_get_psweep, 0);
304
+ rb_define_method(cSound, "psweep=", rb_bloops_set_psweep, 1);
305
+ rb_define_method(cSound, "punch", rb_bloops_get_punch, 0);
306
+ rb_define_method(cSound, "punch=", rb_bloops_set_punch, 1);
307
+ rb_define_method(cSound, "repeat", rb_bloops_get_repeat, 0);
308
+ rb_define_method(cSound, "repeat=", rb_bloops_set_repeat, 1);
309
+ rb_define_method(cSound, "resonance", rb_bloops_get_resonance, 0);
310
+ rb_define_method(cSound, "resonance=", rb_bloops_set_resonance, 1);
311
+ rb_define_method(cSound, "slide", rb_bloops_get_slide, 0);
312
+ rb_define_method(cSound, "slide=", rb_bloops_set_slide, 1);
313
+ rb_define_method(cSound, "square", rb_bloops_get_square, 0);
314
+ rb_define_method(cSound, "square=", rb_bloops_set_square, 1);
315
+ rb_define_method(cSound, "sweep", rb_bloops_get_sweep, 0);
316
+ rb_define_method(cSound, "sweep=", rb_bloops_set_sweep, 1);
317
+ rb_define_method(cSound, "sustain", rb_bloops_get_sustain, 0);
318
+ rb_define_method(cSound, "sustain=", rb_bloops_set_sustain, 1);
319
+ rb_define_method(cSound, "type", rb_bloops_get_type, 0);
320
+ rb_define_method(cSound, "type=", rb_bloops_set_type, 1);
321
+ rb_define_method(cSound, "vibe", rb_bloops_get_vibe, 0);
322
+ rb_define_method(cSound, "vibe=", rb_bloops_set_vibe, 1);
323
+ rb_define_method(cSound, "vspeed", rb_bloops_get_vspeed, 0);
324
+ rb_define_method(cSound, "vspeed=", rb_bloops_set_vspeed, 1);
325
+ rb_define_method(cSound, "vdelay", rb_bloops_get_vdelay, 0);
326
+ rb_define_method(cSound, "vdelay=", rb_bloops_set_vdelay, 1);
327
+ rb_define_method(cSound, "volume", rb_bloops_get_volume, 0);
328
+ rb_define_method(cSound, "volume=", rb_bloops_set_volume, 1);
329
+
330
+ cTrack = rb_define_class_under(cBloops, "Track", rb_cObject);
331
+ rb_define_method(cTrack, "to_s", rb_bloops_track_str, 0);
332
+ }
@@ -0,0 +1,41 @@
1
+ require './bloops'
2
+
3
+ # the song object
4
+ b = Bloops.new
5
+ b.tempo = 320
6
+
7
+ # an instrument
8
+ saw = b.sound Bloops::SAWTOOTH
9
+ saw.test
10
+
11
+ # assign a track to the song
12
+ b.tune saw, "c5 c6 b4 b5 d5 d6 e5 e6"
13
+
14
+ # make it go
15
+ b.play
16
+ sleep 1 while !b.stopped?
17
+
18
+ # a percussion
19
+ beat = b.sound Bloops::NOISE
20
+ beat.repeat = 0.6
21
+ beat2 = b.sound Bloops::NOISE
22
+ beat2.repeat = 0.2
23
+ beat3 = b.sound Bloops::SQUARE
24
+ beat3.sustain = 0.25
25
+ beat3.decay = 0.2
26
+ beat3.slide = 0.2
27
+ beat3.square = 0.3
28
+ beat3.vibe = 0.25
29
+ beat3.vspeed = 0.25
30
+
31
+ # assign a track to the song
32
+ b.tune beat, "4 4 4 b4 4 d5 4 e5"
33
+ b.tune beat2, "c2 4 c2 4 c2 4 c2 4"
34
+ b.tune beat3, "4 4 4 4 4 c2 c5 4"
35
+
36
+ # make it go
37
+ loop do
38
+ b.play
39
+ saw.test
40
+ sleep 0.02 while !b.stopped?
41
+ end
@@ -0,0 +1,25 @@
1
+ require './bloops'
2
+
3
+ b = Bloops.new
4
+
5
+ # ice #1
6
+ puts "** playing scale using ice.blu"
7
+ ice = b.load "../../sounds/ice.blu"
8
+ b.tune ice, "c c# d eb e f f# g ab a bb b + c"
9
+
10
+ b.play
11
+ sleep 1 while !b.stopped?
12
+
13
+ b.clear
14
+
15
+ # ice #2
16
+ puts "** same scale built from ruby"
17
+ ice2 = b.sound Bloops::SQUARE
18
+ ice2.punch = 0.441
19
+ ice2.sustain = 0.067
20
+ ice2.decay = 0.197
21
+ ice2.freq = 0.499
22
+ b.tune ice2, "c c# d eb e f f# g ab a bb b + c"
23
+
24
+ b.play
25
+ sleep 1 while !b.stopped?