viking-bloopsaphone 0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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?