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.
- data/COPYING +27 -0
- data/README +164 -0
- data/c/bloopsaphone.c +443 -0
- data/c/bloopsaphone.h +94 -0
- data/c/notation.c +1209 -0
- data/ext/ruby/extconf.rb +13 -0
- data/ext/ruby/rubyext.c +282 -0
- data/ext/ruby/test.rb +26 -0
- data/ext/ruby/test_load.rb +25 -0
- data/sounds/dart.blu +10 -0
- data/sounds/error.blu +13 -0
- data/sounds/ice.blu +5 -0
- data/sounds/jump.blu +8 -0
- data/sounds/pogo.blu +19 -0
- data/sounds/stun.blu +6 -0
- metadata +70 -0
data/ext/ruby/extconf.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
$CFLAGS << " -I../../c "
|
5
|
+
|
6
|
+
%w[../../c/notation.c ../../c/bloopsaphone.c ../../c/bloopsaphone.h].each do |fn|
|
7
|
+
abort "!! ERROR !!\n** #{fn} not found; type 'make ruby' in the top directory\n\n" \
|
8
|
+
unless File.exists? fn
|
9
|
+
FileUtils.cp(fn, ".")
|
10
|
+
end
|
11
|
+
|
12
|
+
have_library("portaudio")
|
13
|
+
create_makefile("bloops")
|
data/ext/ruby/rubyext.c
ADDED
@@ -0,0 +1,282 @@
|
|
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
|
+
|
12
|
+
#ifndef RSTRING_LEN
|
13
|
+
#define RSTRING_LEN(str) RSTRING(str)->len
|
14
|
+
#define RSTRING_PTR(str) RSTRING(str)->ptr
|
15
|
+
#endif
|
16
|
+
|
17
|
+
//
|
18
|
+
// Main Bloops object
|
19
|
+
//
|
20
|
+
static void
|
21
|
+
rb_bloops_free(bloops *B)
|
22
|
+
{
|
23
|
+
bloops_destroy(B);
|
24
|
+
}
|
25
|
+
|
26
|
+
VALUE
|
27
|
+
rb_bloops_alloc(VALUE klass)
|
28
|
+
{
|
29
|
+
bloops *B = bloops_new();
|
30
|
+
return Data_Wrap_Struct(klass, NULL, rb_bloops_free, B);
|
31
|
+
}
|
32
|
+
|
33
|
+
VALUE
|
34
|
+
rb_bloops_clear(VALUE self)
|
35
|
+
{
|
36
|
+
bloops *B;
|
37
|
+
Data_Get_Struct(self, bloops, B);
|
38
|
+
bloops_clear(B);
|
39
|
+
return self;
|
40
|
+
}
|
41
|
+
|
42
|
+
VALUE
|
43
|
+
rb_bloops_play(VALUE self)
|
44
|
+
{
|
45
|
+
bloops *B;
|
46
|
+
Data_Get_Struct(self, bloops, B);
|
47
|
+
bloops_play(B);
|
48
|
+
return self;
|
49
|
+
}
|
50
|
+
|
51
|
+
VALUE
|
52
|
+
rb_bloops_is_stopped(VALUE self)
|
53
|
+
{
|
54
|
+
bloops *B;
|
55
|
+
Data_Get_Struct(self, bloops, B);
|
56
|
+
return bloops_is_done(B) ? Qtrue : Qfalse;
|
57
|
+
}
|
58
|
+
|
59
|
+
VALUE
|
60
|
+
rb_bloops_get_tempo(VALUE self)
|
61
|
+
{
|
62
|
+
bloops *B;
|
63
|
+
Data_Get_Struct(self, bloops, B);
|
64
|
+
return INT2NUM(B->tempo);
|
65
|
+
}
|
66
|
+
|
67
|
+
VALUE
|
68
|
+
rb_bloops_set_tempo(VALUE self, VALUE tempo)
|
69
|
+
{
|
70
|
+
bloops *B;
|
71
|
+
Data_Get_Struct(self, bloops, B);
|
72
|
+
bloops_tempo(B, NUM2INT(tempo));
|
73
|
+
return tempo;
|
74
|
+
}
|
75
|
+
|
76
|
+
//
|
77
|
+
// Instrument creation
|
78
|
+
//
|
79
|
+
static void
|
80
|
+
rb_bloops_sound_free(bloopsaphone *sound)
|
81
|
+
{
|
82
|
+
free(sound);
|
83
|
+
}
|
84
|
+
|
85
|
+
VALUE
|
86
|
+
rb_bloops_load(VALUE self, VALUE fname)
|
87
|
+
{
|
88
|
+
bloops *B;
|
89
|
+
bloopsaphone *P;
|
90
|
+
Data_Get_Struct(self, bloops, B);
|
91
|
+
|
92
|
+
StringValue(fname);
|
93
|
+
P = bloops_sound_file(B, RSTRING_PTR(fname));
|
94
|
+
if (P == NULL) return Qnil;
|
95
|
+
return Data_Wrap_Struct(cSound, NULL, rb_bloops_sound_free, P);
|
96
|
+
}
|
97
|
+
|
98
|
+
VALUE
|
99
|
+
rb_bloops_sound(VALUE self, VALUE type)
|
100
|
+
{
|
101
|
+
bloopsaphone *P = bloops_square();
|
102
|
+
P->type = (unsigned char)NUM2INT(type);
|
103
|
+
return Data_Wrap_Struct(cSound, NULL, rb_bloops_sound_free, P);
|
104
|
+
}
|
105
|
+
|
106
|
+
VALUE
|
107
|
+
rb_bloops_get_type(VALUE self)
|
108
|
+
{
|
109
|
+
bloopsaphone *P;
|
110
|
+
Data_Get_Struct(self, bloopsaphone, P);
|
111
|
+
return INT2NUM((int)P->type);
|
112
|
+
}
|
113
|
+
|
114
|
+
VALUE
|
115
|
+
rb_bloops_set_type(VALUE self, VALUE type)
|
116
|
+
{
|
117
|
+
bloopsaphone *P;
|
118
|
+
Data_Get_Struct(self, bloopsaphone, P);
|
119
|
+
P->type = (unsigned char)NUM2INT(type);
|
120
|
+
return type;
|
121
|
+
}
|
122
|
+
|
123
|
+
#define SOUND_ACCESSOR(name) \
|
124
|
+
VALUE rb_bloops_get_##name(VALUE self) { \
|
125
|
+
bloopsaphone *P; \
|
126
|
+
Data_Get_Struct(self, bloopsaphone, P); \
|
127
|
+
return rb_float_new(P->name); \
|
128
|
+
} \
|
129
|
+
VALUE rb_bloops_set_##name(VALUE self, VALUE f) { \
|
130
|
+
bloopsaphone *P; \
|
131
|
+
Data_Get_Struct(self, bloopsaphone, P); \
|
132
|
+
P->name = (float)NUM2DBL(f); \
|
133
|
+
return f; \
|
134
|
+
}
|
135
|
+
|
136
|
+
SOUND_ACCESSOR(arp);
|
137
|
+
SOUND_ACCESSOR(aspeed);
|
138
|
+
SOUND_ACCESSOR(attack);
|
139
|
+
SOUND_ACCESSOR(decay);
|
140
|
+
SOUND_ACCESSOR(dslide);
|
141
|
+
SOUND_ACCESSOR(freq);
|
142
|
+
SOUND_ACCESSOR(hpf);
|
143
|
+
SOUND_ACCESSOR(hsweep);
|
144
|
+
SOUND_ACCESSOR(limit);
|
145
|
+
SOUND_ACCESSOR(lpf);
|
146
|
+
SOUND_ACCESSOR(lsweep);
|
147
|
+
SOUND_ACCESSOR(phase);
|
148
|
+
SOUND_ACCESSOR(psweep);
|
149
|
+
SOUND_ACCESSOR(repeat);
|
150
|
+
SOUND_ACCESSOR(resonance);
|
151
|
+
SOUND_ACCESSOR(slide);
|
152
|
+
SOUND_ACCESSOR(square);
|
153
|
+
SOUND_ACCESSOR(sustain);
|
154
|
+
SOUND_ACCESSOR(sweep);
|
155
|
+
SOUND_ACCESSOR(punch);
|
156
|
+
SOUND_ACCESSOR(vibe);
|
157
|
+
SOUND_ACCESSOR(vspeed);
|
158
|
+
SOUND_ACCESSOR(vdelay);
|
159
|
+
SOUND_ACCESSOR(volume);
|
160
|
+
|
161
|
+
//
|
162
|
+
// Individual track object
|
163
|
+
//
|
164
|
+
static void
|
165
|
+
rb_bloops_track_free(bloopsatrack *track)
|
166
|
+
{
|
167
|
+
bloops_track_destroy(track);
|
168
|
+
}
|
169
|
+
|
170
|
+
VALUE
|
171
|
+
rb_bloops_tune(VALUE self, VALUE sound, VALUE notes)
|
172
|
+
{
|
173
|
+
int i;
|
174
|
+
bloops *B;
|
175
|
+
bloopsaphone *phone;
|
176
|
+
bloopsatrack *track;
|
177
|
+
Data_Get_Struct(self, bloops, B);
|
178
|
+
Data_Get_Struct(sound, bloopsaphone, phone);
|
179
|
+
|
180
|
+
StringValue(notes);
|
181
|
+
track = bloops_track(B, phone, RSTRING_PTR(notes), RSTRING_LEN(notes));
|
182
|
+
|
183
|
+
for (i = 0; i < BLOOPS_MAX_TRACKS; i++)
|
184
|
+
if (B->tracks[i] == NULL) {
|
185
|
+
bloops_track_at(B, track, i);
|
186
|
+
break;
|
187
|
+
}
|
188
|
+
return Data_Wrap_Struct(cTrack, NULL, rb_bloops_track_free, track);
|
189
|
+
}
|
190
|
+
|
191
|
+
VALUE
|
192
|
+
rb_bloops_track_str(VALUE self)
|
193
|
+
{
|
194
|
+
char *str;
|
195
|
+
VALUE obj;
|
196
|
+
bloopsatrack *track;
|
197
|
+
Data_Get_Struct(self, bloopsatrack, track);
|
198
|
+
|
199
|
+
str = bloops_track_str(track);
|
200
|
+
obj = rb_str_new2(str);
|
201
|
+
free(str);
|
202
|
+
|
203
|
+
return obj;
|
204
|
+
}
|
205
|
+
|
206
|
+
//
|
207
|
+
// Ruby extension startup
|
208
|
+
//
|
209
|
+
void
|
210
|
+
Init_bloops()
|
211
|
+
{
|
212
|
+
cBloops = rb_define_class("Bloops", rb_cObject);
|
213
|
+
rb_define_alloc_func(cBloops, rb_bloops_alloc);
|
214
|
+
rb_define_method(cBloops, "clear", rb_bloops_clear, 0);
|
215
|
+
rb_define_method(cBloops, "load", rb_bloops_load, 1);
|
216
|
+
rb_define_method(cBloops, "play", rb_bloops_play, 0);
|
217
|
+
rb_define_method(cBloops, "sound", rb_bloops_sound, 1);
|
218
|
+
rb_define_method(cBloops, "stopped?", rb_bloops_is_stopped, 0);
|
219
|
+
rb_define_method(cBloops, "tempo", rb_bloops_get_tempo, 0);
|
220
|
+
rb_define_method(cBloops, "tempo=", rb_bloops_set_tempo, 1);
|
221
|
+
rb_define_method(cBloops, "tune", rb_bloops_tune, 2);
|
222
|
+
|
223
|
+
rb_const_set(cBloops, rb_intern("SQUARE"), INT2NUM(BLOOPS_SQUARE));
|
224
|
+
rb_const_set(cBloops, rb_intern("SAWTOOTH"), INT2NUM(BLOOPS_SAWTOOTH));
|
225
|
+
rb_const_set(cBloops, rb_intern("SINE"), INT2NUM(BLOOPS_SINE));
|
226
|
+
rb_const_set(cBloops, rb_intern("NOISE"), INT2NUM(BLOOPS_NOISE));
|
227
|
+
|
228
|
+
cSound = rb_define_class_under(cBloops, "Sound", rb_cObject);
|
229
|
+
rb_define_method(cSound, "arp", rb_bloops_get_arp, 0);
|
230
|
+
rb_define_method(cSound, "arp=", rb_bloops_set_arp, 1);
|
231
|
+
rb_define_method(cSound, "aspeed", rb_bloops_get_aspeed, 0);
|
232
|
+
rb_define_method(cSound, "aspeed=", rb_bloops_set_aspeed, 1);
|
233
|
+
rb_define_method(cSound, "attack", rb_bloops_get_attack, 0);
|
234
|
+
rb_define_method(cSound, "attack=", rb_bloops_set_attack, 1);
|
235
|
+
rb_define_method(cSound, "decay", rb_bloops_get_decay, 0);
|
236
|
+
rb_define_method(cSound, "decay=", rb_bloops_set_decay, 1);
|
237
|
+
rb_define_method(cSound, "dslide", rb_bloops_get_dslide, 0);
|
238
|
+
rb_define_method(cSound, "dslide=", rb_bloops_set_dslide, 1);
|
239
|
+
rb_define_method(cSound, "freq", rb_bloops_get_freq, 0);
|
240
|
+
rb_define_method(cSound, "freq=", rb_bloops_set_freq, 1);
|
241
|
+
rb_define_method(cSound, "hpf", rb_bloops_get_hpf, 0);
|
242
|
+
rb_define_method(cSound, "hpf=", rb_bloops_set_hpf, 1);
|
243
|
+
rb_define_method(cSound, "hsweep", rb_bloops_get_hsweep, 0);
|
244
|
+
rb_define_method(cSound, "hsweep=", rb_bloops_set_hsweep, 1);
|
245
|
+
rb_define_method(cSound, "limit", rb_bloops_get_limit, 0);
|
246
|
+
rb_define_method(cSound, "limit=", rb_bloops_set_limit, 1);
|
247
|
+
rb_define_method(cSound, "lpf", rb_bloops_get_lpf, 0);
|
248
|
+
rb_define_method(cSound, "lpf=", rb_bloops_set_lpf, 1);
|
249
|
+
rb_define_method(cSound, "lsweep", rb_bloops_get_lsweep, 0);
|
250
|
+
rb_define_method(cSound, "lsweep=", rb_bloops_set_lsweep, 1);
|
251
|
+
rb_define_method(cSound, "phase", rb_bloops_get_phase, 0);
|
252
|
+
rb_define_method(cSound, "phase=", rb_bloops_set_phase, 1);
|
253
|
+
rb_define_method(cSound, "psweep", rb_bloops_get_psweep, 0);
|
254
|
+
rb_define_method(cSound, "psweep=", rb_bloops_set_psweep, 1);
|
255
|
+
rb_define_method(cSound, "punch", rb_bloops_get_punch, 0);
|
256
|
+
rb_define_method(cSound, "punch=", rb_bloops_set_punch, 1);
|
257
|
+
rb_define_method(cSound, "repeat", rb_bloops_get_repeat, 0);
|
258
|
+
rb_define_method(cSound, "repeat=", rb_bloops_set_repeat, 1);
|
259
|
+
rb_define_method(cSound, "resonance", rb_bloops_get_resonance, 0);
|
260
|
+
rb_define_method(cSound, "resonance=", rb_bloops_set_resonance, 1);
|
261
|
+
rb_define_method(cSound, "slide", rb_bloops_get_slide, 0);
|
262
|
+
rb_define_method(cSound, "slide=", rb_bloops_set_slide, 1);
|
263
|
+
rb_define_method(cSound, "square", rb_bloops_get_square, 0);
|
264
|
+
rb_define_method(cSound, "square=", rb_bloops_set_square, 1);
|
265
|
+
rb_define_method(cSound, "sweep", rb_bloops_get_sweep, 0);
|
266
|
+
rb_define_method(cSound, "sweep=", rb_bloops_set_sweep, 1);
|
267
|
+
rb_define_method(cSound, "sustain", rb_bloops_get_sustain, 0);
|
268
|
+
rb_define_method(cSound, "sustain=", rb_bloops_set_sustain, 1);
|
269
|
+
rb_define_method(cSound, "type", rb_bloops_get_type, 0);
|
270
|
+
rb_define_method(cSound, "type=", rb_bloops_set_type, 1);
|
271
|
+
rb_define_method(cSound, "vibe", rb_bloops_get_vibe, 0);
|
272
|
+
rb_define_method(cSound, "vibe=", rb_bloops_set_vibe, 1);
|
273
|
+
rb_define_method(cSound, "vspeed", rb_bloops_get_vspeed, 0);
|
274
|
+
rb_define_method(cSound, "vspeed=", rb_bloops_set_vspeed, 1);
|
275
|
+
rb_define_method(cSound, "vdelay", rb_bloops_get_vdelay, 0);
|
276
|
+
rb_define_method(cSound, "vdelay=", rb_bloops_set_vdelay, 1);
|
277
|
+
rb_define_method(cSound, "volume", rb_bloops_get_volume, 0);
|
278
|
+
rb_define_method(cSound, "volume=", rb_bloops_set_volume, 1);
|
279
|
+
|
280
|
+
cTrack = rb_define_class_under(cBloops, "Track", rb_cObject);
|
281
|
+
rb_define_method(cTrack, "to_s", rb_bloops_track_str, 0);
|
282
|
+
}
|
data/ext/ruby/test.rb
ADDED
@@ -0,0 +1,26 @@
|
|
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
|
+
|
10
|
+
# assign a track to the song
|
11
|
+
b.tune saw, "c5 c6 b4 b5 d5 d6 e5 e6"
|
12
|
+
|
13
|
+
# make it go
|
14
|
+
b.play
|
15
|
+
sleep 1 while !b.stopped?
|
16
|
+
|
17
|
+
# a percussion
|
18
|
+
beat = b.sound Bloops::NOISE
|
19
|
+
beat.repeat = 0.6
|
20
|
+
|
21
|
+
# assign a track to the song
|
22
|
+
b.tune beat, "4 4 b4 4 d5 4 e5 e6"
|
23
|
+
|
24
|
+
# make it go
|
25
|
+
b.play
|
26
|
+
sleep 1 while !b.stopped?
|
@@ -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?
|
data/sounds/dart.blu
ADDED
data/sounds/error.blu
ADDED
data/sounds/ice.blu
ADDED
data/sounds/jump.blu
ADDED
data/sounds/pogo.blu
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
type square
|
2
|
+
volume 0.977
|
3
|
+
punch 0.190
|
4
|
+
sustain 0.165
|
5
|
+
slide 0.100
|
6
|
+
dslide 0.030
|
7
|
+
square 0.048
|
8
|
+
sweep -0.055
|
9
|
+
vibe 0.437
|
10
|
+
vspeed 0.310
|
11
|
+
lpf 0.355
|
12
|
+
resonance 0.185
|
13
|
+
hpf 0.205
|
14
|
+
hsweep 0.255
|
15
|
+
arp 0.677
|
16
|
+
aspeed 0.275
|
17
|
+
phase 0.200
|
18
|
+
psweep -0.565
|
19
|
+
repeat 0.500
|
data/sounds/stun.blu
ADDED
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bloopsaphone
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0.4"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- why the lucky stiff
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-02-12 00:00:00 +08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: arcade sounds and chiptunes
|
17
|
+
email: why@ruby-lang.org
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions:
|
21
|
+
- ext/ruby/extconf.rb
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README
|
24
|
+
- COPYING
|
25
|
+
files:
|
26
|
+
- COPYING
|
27
|
+
- README
|
28
|
+
- c/bloopsaphone.c
|
29
|
+
- c/bloopsaphone.h
|
30
|
+
- c/notation.c
|
31
|
+
- ext/ruby/extconf.rb
|
32
|
+
- ext/ruby/rubyext.c
|
33
|
+
- ext/ruby/test.rb
|
34
|
+
- ext/ruby/test_load.rb
|
35
|
+
- sounds/dart.blu
|
36
|
+
- sounds/error.blu
|
37
|
+
- sounds/ice.blu
|
38
|
+
- sounds/jump.blu
|
39
|
+
- sounds/pogo.blu
|
40
|
+
- sounds/stun.blu
|
41
|
+
has_rdoc: true
|
42
|
+
homepage: http://github.com/why/bloopsaphone
|
43
|
+
licenses: []
|
44
|
+
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options: []
|
47
|
+
|
48
|
+
require_paths:
|
49
|
+
- lib
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "0"
|
55
|
+
version:
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: "0"
|
61
|
+
version:
|
62
|
+
requirements: []
|
63
|
+
|
64
|
+
rubyforge_project:
|
65
|
+
rubygems_version: 1.3.5
|
66
|
+
signing_key:
|
67
|
+
specification_version: 3
|
68
|
+
summary: arcade sounds and chiptunes
|
69
|
+
test_files: []
|
70
|
+
|