├── COPYING
├── Makefile
├── README
├── bloopsaphone.gemspec
├── c
├── bloopsaphone-internal.h
├── bloopsaphone.c
├── bloopsaphone.h
├── bloopsawhat.c
├── notation.c
└── notation.rl
├── ext
└── ruby
│ ├── extconf.rb
│ ├── rubyext.c
│ ├── test.rb
│ ├── test_load.rb
│ ├── tune_cheeky_drat.rb
│ └── tune_warp.rb
├── misc
└── Makefile-dll
└── sounds
├── dart.blu
├── error.blu
├── ice.blu
├── jump.blu
├── pogo.blu
└── stun.blu
/COPYING:
--------------------------------------------------------------------------------
1 |
2 | :$: BLOOPSAPHONE :$:
3 | Copyright (c) 2009 why the lucky stiff
4 | Based on sfxr (c) 2007 Tomas Pettersson
5 | (Also released under the MIT license)
6 |
7 | Permission is hereby granted, free of charge, to any person
8 | obtaining a copy of this software and associated documentation
9 | files (the "Software"), to deal in the Software without restriction,
10 | including without limitation the rights to use, copy, modify, merge,
11 | publish, distribute, sublicense, and/or sell copies of the Software,
12 | and to permit persons to whom the Software is furnished to do so,
13 | subject to the following conditions:
14 |
15 | The above copyright notice and this permission notice shall be
16 | included in all copies or substantial portions of the Software.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
19 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
20 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
21 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
22 | SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
24 | OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | SOFTWARE.
27 |
28 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | SRC = c/bloopsaphone.c c/notation.c
2 | OBJ = ${SRC:.c=.o}
3 |
4 | PREFIX = /usr/local
5 | CC = gcc
6 | AR = ar
7 | ARFLAGS = cr
8 | CFLAGS ?= -Wall
9 | DEBUG ?= 0
10 | ECHO = /bin/echo
11 | INCS = -Ic
12 | LDFLAGS ?=
13 | LIBS = -lm -lportaudio
14 | RAGEL = ragel
15 |
16 | RAGELV = `${RAGEL} -v | sed "/ version /!d; s/.* version //; s/ .*//"`
17 |
18 | all: bloopsaphone
19 |
20 | rebuild: clean bloopsaphone
21 |
22 | bloopsaphone: bloopsawhat bloopsalib
23 |
24 | bloopsawhat: ${OBJ} c/bloopsawhat.o
25 | @${ECHO} LINK bloopsawhat
26 | @${CC} ${CFLAGS} ${OBJ} c/bloopsawhat.o ${LDFLAGS} ${LIBS} -o bloopsawhat
27 |
28 | bloopsalib: ${OBJ}
29 | @${ECHO} LINK bloopsalib
30 | @${AR} ${ARFLAGS} libbloopsaphone.a ${OBJ}
31 |
32 | c/notation.c: c/notation.rl
33 | @if [ "${RAGELV}" != "6.3" ]; then \
34 | if [ "${RAGELV}" != "6.2" ]; then \
35 | ${ECHO} "** bloopsaphone may not work with ragel ${RAGELV}! try version 6.2 or 6.3."; \
36 | fi; \
37 | fi
38 | @${ECHO} RAGEL c/notation.rl
39 | @${RAGEL} c/notation.rl -C -o $@
40 |
41 | %.o: %.c
42 | @${ECHO} CC $<
43 | @${CC} -c ${CFLAGS} ${INCS} -o $@ $<
44 |
45 | clean:
46 | @${ECHO} cleaning
47 | @rm -f ${OBJ}
48 | @rm -f c/notation.c c/*.o
49 | @rm -f bloopsawhat libbloopsaphone.a bloopsaphone.so
50 | @cd ext/ruby && make distclean || true
51 |
52 | ruby: c/notation.c c/bloopsaphone.c
53 | @${ECHO} RUBY extconf.rb
54 | @cd ext/ruby && CFLAGS="${CFLAGS}" LDFLAGS="${LDFLAGS}" ruby extconf.rb && make
55 | @${ECHO} ""
56 | @${ECHO} "To test: cd ext/ruby"
57 | @${ECHO} "Then: ruby test.rb"
58 | @${ECHO} ""
59 |
60 | .PHONY: all bloopsaphone clean rebuild ruby
61 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 |
2 | |~~ |~~
3 | | |
4 | :$: bloopsaphone :$:
5 | `''''''''''''''''`
6 |
7 | for writing chiptune-style songs
8 | in c or ruby. you know: the sounds
9 | of ataris, gameboys and the like.
10 |
11 | ~
12 |
13 | -$- ABOUT
14 |
15 | this is a small c library for sending
16 | chiptunes through portaudio, which is
17 | a rather light cross-platform audio lib.
18 |
19 |
20 | right now i'm only including ruby
21 | bindings. you are welcome to contribute
22 | code to hook up to other languages,
23 | though.
24 |
25 | i wrote this for h-ety h.
26 |
27 |
28 | i don't have binaries ready for this yet,
29 | so if you're on windows or os x, you may
30 | have to wait until HH comes out at ART
31 | AND CODE. the tribulations you face.
32 |
33 | ~
34 |
35 | -$- THE BLOOPSAPHONE THEME SONG
36 | (in ruby)
37 |
38 | require 'bloops'
39 |
40 | # the bloops o' phone
41 | b = Bloops.new
42 | b.tempo = 320
43 |
44 | # melodious
45 | s1 = b.sound Bloops::SQUARE
46 | s1.punch = 0.5
47 | s1.sustain = 0.4
48 | s1.decay = 0.2
49 | s1.arp = 0.4
50 | s1.aspeed = 0.6
51 | s1.repeat = 0.6
52 | s1.phase = 0.2
53 | s1.psweep = 0.2
54 |
55 | # beats
56 | s2 = b.sound Bloops::NOISE
57 | s2.punch = 0.5
58 | s2.sustain = 0.2
59 | s2.decay = 0.4
60 | s2.slide = -0.4
61 | s2.phase = 0.2
62 | s2.psweep = 0.2
63 |
64 | # the tracks
65 | b.tune s1, "f#5 c6 e4 b6 g5 d6 4 f#5 e5 c5 b6 c6 d6 4 "
66 | b.tune s2, "4 c6 4 b5 4 4 e4 4 c6 4 b5 4 4 e4"
67 |
68 | # and away we go
69 | b.play
70 | sleep 1 while !b.stopped?
71 |
72 | ~
73 |
74 | -$- BUILDING FOR RUBY
75 |
76 | If Ruby is in your path and PortAudio 1.9
77 | or greater is installed:
78 |
79 | make ruby
80 |
81 | To install PortAudio 1.9 under Ubuntu:
82 |
83 | aptitude install portaudio19-dev
84 |
85 | To build from source isn't too bad.
86 | Download PortAudio 1.9 and build it.
87 |
88 |
89 | Like this:
90 |
91 | $ tar xzvf pa_stable_v19_20071207.tar.gz
92 | $ cd portaudio
93 | $ ./configure
94 | $ make
95 | $ sudo make install
96 |
97 | Then go back to Bloopsaphone and do
98 | a `make ruby`.
99 |
100 | ~
101 |
102 | -$- THE IDEALS,
103 |
104 | -1- ASYNCHRONOUS.
105 | You send it a song and it plays in
106 | the background. You'll get an event
107 | when it finishes.
108 |
109 | -2- SMALL.
110 | This is just a toy, I don't want it
111 | to be very big and comprehensive.
112 | Just to play little tunes with a
113 | nostalgic arcade sound rather than
114 | the CASIO-stylings of most MIDI.
115 |
116 | -3- CUSTOM NOTATION.
117 | Someone told me about Nokring, iMelody,
118 | numbered musical notation and I did
119 | some reading. They're little languages
120 | for texting yourself a ringtone.
121 |
122 |
123 |
124 |
125 | Bloopsaphone uses a variation on RTTTL.
126 |
127 | Instead of commas, I use whitespace.
128 | A rest is simply a number. A plus sign
129 | moves everything up an octave. A minus
130 | down an octave.
131 |
132 | The Simpsons' Theme, for instance, would be:
133 |
134 | 32 + C E F# 8:A G E C - 8:A 8:F# 8:F# 8:F# 2:G
135 |
136 | Which translates into:
137 |
138 | * a 1/32nd note rest.
139 | * change one octave up.
140 | * C quarter note.
141 | * E quarter note.
142 | * F# quarter note.
143 | * A eighth note.
144 | * G quarter.
145 | * E quarter.
146 | * C one-quarter note.
147 | * change one octave down.
148 | * A eighth.
149 | * Three F# eighths.
150 | * G half note.
151 |
152 | The colons are optional. They are there because you
153 | can place an octave number after each note. Somehow
154 | "8B6" (an eighth note of B at the sixth octave) looks
155 | more confusing than "8:B6". I guess I figured that
156 | the timing "8" is conceptually separate from the
157 | actual tone "B6", even though they both comprise
158 | the note itself.
159 |
160 | -4- SERIALIZE SOUNDS.
161 | To accomodate passing instruments between
162 | ruby and c, bloopsaphone comes with a tiny
163 | file format for describing sounds.
164 |
165 | You can find examples of these in the sounds/
166 | folder in this distro. Possible sound types
167 | are 'square', 'sawtooth', 'sine' and 'noise'.
168 | All other settings go from 0.0 to 1.0.
169 |
170 | The 'freq' setting is only used if the sound
171 | is played without a tune.
172 |
173 |
--------------------------------------------------------------------------------
/bloopsaphone.gemspec:
--------------------------------------------------------------------------------
1 | Gem::Specification.new do |s|
2 | s.name = 'bloopsaphone'
3 | s.version = '0.4'
4 |
5 | s.authors = ["why the lucky stiff"]
6 | s.date = '2009-02-12'
7 | s.description = 'arcade sounds and chiptunes'
8 | s.email = 'why@ruby-lang.org'
9 | s.extensions = ["ext/ruby/extconf.rb"]
10 | s.extra_rdoc_files = ["README", "COPYING"]
11 | s.files = ["COPYING", "README", "c/bloopsaphone.c", "c/bloopsaphone.h", "c/notation.c",
12 | "ext/ruby/extconf.rb", "ext/ruby/rubyext.c", "ext/ruby/test.rb", "ext/ruby/test_load.rb",
13 | "sounds/dart.blu", "sounds/error.blu", "sounds/ice.blu", "sounds/jump.blu",
14 | "sounds/pogo.blu", "sounds/stun.blu"]
15 | s.has_rdoc = false
16 | s.homepage = 'http://github.com/why/bloopsaphone'
17 | s.summary = 'arcade sounds and chiptunes'
18 | end
19 |
--------------------------------------------------------------------------------
/c/bloopsaphone-internal.h:
--------------------------------------------------------------------------------
1 | //
2 | // threads.h - threaded garments for the bloopsaphone
3 | //
4 | #ifndef BLOOPSAPHONE_INTERNAL_H
5 | #define BLOOPSAPHONE_INTERNAL_H
6 |
7 | #ifdef _WIN32
8 | #include
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
27 | #include
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
47 |
--------------------------------------------------------------------------------
/c/bloopsaphone.c:
--------------------------------------------------------------------------------
1 | //
2 | // bloopsaphone.c
3 | // the chiptune maker for portaudio
4 | // (with bindings for ruby)
5 | //
6 | // (c) 2009 why the lucky stiff
7 | // See COPYING for the license
8 | //
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include "bloopsaphone.h"
18 | #include "bloopsaphone-internal.h"
19 |
20 | #ifdef PaStream
21 | #error ** Looks like you're linking against PortAudio 1.8!
22 | #error ** Bloopsaphone needs PortAudio 1.9 or greater.
23 | #error ** On Ubuntu, try: aptitude install portaudio19-dev.
24 | #endif
25 |
26 | #define SAMPLE_RATE 44100
27 | #define rnd(n) (rand() % (n + 1))
28 | #define tempo2frames(tempo) ((float)SAMPLE_RATE / (tempo / 60.0f))
29 | #define PI 3.14159265f
30 |
31 | #define FX(F, V) ({ \
32 | if (F->mod == '+') V += F->val; \
33 | else if (F->mod == '-') V -= F->val; \
34 | else V = F->val; \
35 | if (V > 1.0f) \
36 | V = 1.0f; \
37 | else if (V < 0.0f) \
38 | V = 0.0f; \
39 | })
40 |
41 | static bloopsalock LOCK;
42 | static bloopsmix *MIXER = NULL;
43 |
44 | static void bloops_synth(int, float *);
45 | static int bloops_port_callback(const void *, void *,
46 | unsigned long, const PaStreamCallbackTimeInfo *,
47 | PaStreamCallbackFlags, void *);
48 | static void bloops_set_track_at(bloops *B, bloopsatrack *track, int num);
49 |
50 | float
51 | frnd(float range)
52 | {
53 | return (float)rnd(10000) / 10000 * range;
54 | }
55 |
56 | static void
57 | bloops_remove(bloops *B)
58 | {
59 | int i;
60 | if (MIXER == NULL) return;
61 | for (i = 0; i < BLOOPS_MAX_CHANNELS; i++) {
62 | if (MIXER->B[i] == B) {
63 | MIXER->B[i] = NULL;
64 | bloops_destroy(B);
65 | }
66 | }
67 | }
68 |
69 | static void
70 | bloops_reset_voice(bloopsavoice *A)
71 | {
72 | A->period = 100.0 / (A->params.freq * A->params.freq + 0.001);
73 | A->maxperiod = 100.0 / (A->params.limit * A->params.limit + 0.001);
74 | A->slide = 1.0 - pow((double)A->params.slide, 3.0) * 0.01;
75 | A->dslide = -pow((double)A->params.dslide, 3.0) * 0.000001;
76 | A->square = 0.5f - A->params.square * 0.5f;
77 | A->sweep = -A->params.sweep * 0.00005f;
78 | if (A->params.arp >= 0.0f)
79 | A->arp = 1.0 - pow((double)A->params.arp, 2.0) * 0.9;
80 | else
81 | A->arp = 1.0 + pow((double)A->params.arp, 2.0) * 10.0;
82 | A->atime = 0;
83 | A->alimit = (int)(pow(1.0f - A->params.aspeed, 2.0f) * 20000 + 32);
84 | if (A->params.aspeed == 1.0f)
85 | A->alimit = 0;
86 | }
87 |
88 | static void
89 | bloops_start_voice(bloopsavoice *A) {
90 | int i = 0;
91 | A->phase = 0;
92 | A->filter[0] = 0.0f;
93 | A->filter[1] = 0.0f;
94 | A->filter[2] = pow(A->params.lpf, 3.0f) * 0.1f;
95 | A->filter[3] = 1.0f + A->params.lsweep * 0.0001f;
96 | A->filter[4] = 5.0f / (1.0f + pow(A->params.resonance, 2.0f) * 20.0f) * (0.01f + A->filter[2]);
97 | if (A->filter[4] > 0.8f) A->filter[4] = 0.8f;
98 | A->filter[5] = 0.0f;
99 | A->filter[6] = pow(A->params.hpf, 2.0f) * 0.1f;
100 | A->filter[7] = 1.0 + A->params.hsweep * 0.0003f;
101 |
102 | A->vibe = 0.0f;
103 | A->vspeed = pow(A->params.vspeed, 2.0f) * 0.01f;
104 | A->vdelay = A->params.vibe * 0.5f;
105 |
106 | A->volume = 0.0f;
107 | A->stage = 0;
108 | A->time = 0;
109 | A->length[0] = (int)(A->params.attack * A->params.attack * 100000.0f);
110 | A->length[1] = (int)(A->params.sustain * A->params.sustain * 100000.0f);
111 | A->length[2] = (int)(A->params.decay * A->params.decay * 100000.0f);
112 |
113 | A->fphase = pow(A->params.phase, 2.0f) * 1020.0f;
114 | if (A->params.phase < 0.0f) A->fphase = -A->fphase;
115 | A->dphase = pow(A->params.psweep, 2.0f) * 1.0f;
116 | if (A->params.psweep < 0.0f) A->dphase = -A->dphase;
117 | A->iphase = abs((int)A->fphase);
118 | A->phasex = 0;
119 |
120 | memset(A->phaser, 0, 1024 * sizeof(float));
121 | for (i = 0; i < 32; i++)
122 | A->noise[i] = frnd(2.0f) - 1.0f;
123 |
124 | A->repeat = 0;
125 | A->limit = (int)(pow(1.0f - A->params.repeat, 2.0f) * 20000 + 32);
126 | if (A->params.repeat == 0.0f)
127 | A->limit = 0;
128 | A->state = BLOOPS_PLAY;
129 | }
130 |
131 | void
132 | bloops_clear(bloops *B)
133 | {
134 | int i;
135 | for (i = 0; i < BLOOPS_MAX_TRACKS; i++) {
136 | bloops_set_track_at(B, NULL, i);
137 | }
138 | }
139 |
140 | void
141 | bloops_tempo(bloops *B, int tempo)
142 | {
143 | B->tempo = tempo;
144 | }
145 |
146 | void
147 | bloops_set_track_at(bloops *B, bloopsatrack *track, int num)
148 | {
149 | bloopsavoice *voice;
150 | bloopsatrack *old_track;
151 | voice = &B->voices[num];
152 | old_track = voice->track;
153 | voice->track = track;
154 | if (track != NULL) {
155 | bloops_track_ref(track);
156 | }
157 | if (old_track != NULL) {
158 | bloops_track_destroy(old_track);
159 | }
160 | voice->state = BLOOPS_STOP;
161 | if (track != NULL) {
162 | memcpy(&voice->params, &track->params, sizeof(bloopsaparams));
163 | }
164 | voice->frames = 0;
165 | voice->nextnote[0] = 0;
166 | voice->nextnote[1] = 0;
167 | }
168 |
169 | void
170 | _bloops_track_add(bloops *B, bloopsatrack *track) {
171 | int i;
172 | for (i = 0; i < BLOOPS_MAX_TRACKS; i++) {
173 | if (B->voices[i].track == NULL) {
174 | bloops_set_track_at(B, track, i);
175 | break;
176 | }
177 | }
178 | }
179 |
180 | int
181 | bloops_is_done(bloops *B)
182 | {
183 | return B->state == BLOOPS_STOP;
184 | }
185 |
186 | static void
187 | bloops_synth(int length, float* buffer)
188 | {
189 | int bi, t, i, si;
190 |
191 | while (length--)
192 | {
193 | int samplecount = 0;
194 | float allsample = 0.0f;
195 |
196 | for (bi = 0; bi < BLOOPS_MAX_CHANNELS; bi++)
197 | {
198 | int moreframes = 0;
199 | bloops *B = MIXER->B[bi];
200 | if (B == NULL)
201 | continue;
202 | for (t = 0; t < BLOOPS_MAX_TRACKS; t++)
203 | {
204 | bloopsavoice *A = &B->voices[t];
205 | bloopsatrack *track = A->track;
206 | if (track == NULL)
207 | continue;
208 |
209 | if (track->notes)
210 | {
211 | if (A->frames == A->nextnote[0])
212 | {
213 | if (A->nextnote[1] < track->nlen)
214 | {
215 | bloopsanote *note = &track->notes[A->nextnote[1]];
216 | float freq = A->params.freq;
217 | if (note->tone != 'n')
218 | freq = bloops_note_freq(note->tone, (int)note->octave);
219 | if (freq == 0.0f) {
220 | A->period = 0.0f;
221 | A->state = BLOOPS_STOP;
222 | } else {
223 | bloopsanote *note = &track->notes[A->nextnote[1]];
224 | bloopsafx *fx = note->FX;
225 | while (fx) {
226 | switch (fx->cmd) {
227 | case BLOOPS_FX_VOLUME: FX(fx, A->params.volume); break;
228 | case BLOOPS_FX_PUNCH: FX(fx, A->params.punch); break;
229 | case BLOOPS_FX_ATTACK: FX(fx, A->params.attack); break;
230 | case BLOOPS_FX_SUSTAIN: FX(fx, A->params.sustain); break;
231 | case BLOOPS_FX_DECAY: FX(fx, A->params.decay); break;
232 | case BLOOPS_FX_SQUARE: FX(fx, A->params.square); break;
233 | case BLOOPS_FX_SWEEP: FX(fx, A->params.sweep); break;
234 | case BLOOPS_FX_VIBE: FX(fx, A->params.vibe); break;
235 | case BLOOPS_FX_VSPEED: FX(fx, A->params.vspeed); break;
236 | case BLOOPS_FX_VDELAY: FX(fx, A->params.vdelay); break;
237 | case BLOOPS_FX_LPF: FX(fx, A->params.lpf); break;
238 | case BLOOPS_FX_LSWEEP: FX(fx, A->params.lsweep); break;
239 | case BLOOPS_FX_RESONANCE: FX(fx, A->params.resonance); break;
240 | case BLOOPS_FX_HPF: FX(fx, A->params.hpf); break;
241 | case BLOOPS_FX_HSWEEP: FX(fx, A->params.hsweep); break;
242 | case BLOOPS_FX_ARP: FX(fx, A->params.arp); break;
243 | case BLOOPS_FX_ASPEED: FX(fx, A->params.aspeed); break;
244 | case BLOOPS_FX_PHASE: FX(fx, A->params.phase); break;
245 | case BLOOPS_FX_PSWEEP: FX(fx, A->params.psweep); break;
246 | case BLOOPS_FX_REPEAT: FX(fx, A->params.repeat); break;
247 | }
248 | fx = fx->next;
249 | }
250 |
251 | bloops_reset_voice(A);
252 | bloops_start_voice(A);
253 | A->period = 100.0 / (freq * freq + 0.001);
254 | }
255 |
256 | A->nextnote[0] += (int)(tempo2frames(B->tempo) * (4.0f / note->duration));
257 | }
258 | A->nextnote[1]++;
259 | }
260 |
261 | if (A->nextnote[1] <= track->nlen)
262 | moreframes++;
263 | }
264 | else
265 | {
266 | moreframes++;
267 | }
268 |
269 | A->frames++;
270 |
271 | if (A->state == BLOOPS_STOP)
272 | continue;
273 |
274 | samplecount++;
275 | A->repeat++;
276 | if (A->limit != 0 && A->repeat >= A->limit)
277 | {
278 | A->repeat = 0;
279 | bloops_reset_voice(A);
280 | }
281 |
282 | A->atime++;
283 | if (A->alimit != 0 && A->atime >= A->alimit)
284 | {
285 | A->alimit = 0;
286 | A->period *= A->arp;
287 | }
288 |
289 | A->slide += A->dslide;
290 | A->period *= A->slide;
291 | if (A->period > A->maxperiod)
292 | {
293 | A->period = A->maxperiod;
294 | if (A->params.limit > 0.0f)
295 | A->state = BLOOPS_STOP;
296 | }
297 |
298 | float rfperiod = A->period;
299 | if (A->vdelay > 0.0f)
300 | {
301 | A->vibe += A->vspeed;
302 | rfperiod = A->period * (1.0 + sin(A->vibe) * A->vdelay);
303 | }
304 |
305 | int period = (int)rfperiod;
306 | if (period < 8) period = 8;
307 | A->square += A->sweep;
308 | if(A->square < 0.0f) A->square = 0.0f;
309 | if(A->square > 0.5f) A->square = 0.5f;
310 |
311 | A->time++;
312 | while (A->time >= A->length[A->stage])
313 | {
314 | A->time = 0;
315 | A->stage++;
316 | if (A->stage == 3)
317 | A->state = BLOOPS_STOP;
318 | }
319 |
320 | switch (A->stage) {
321 | case 0:
322 | A->volume = (float)A->time / A->length[0];
323 | break;
324 | case 1:
325 | A->volume = 1.0f + (1.0f - (float)A->time / A->length[1]) * 2.0f * A->params.punch;
326 | break;
327 | case 2:
328 | A->volume = 1.0f - (float)A->time / A->length[2];
329 | break;
330 | }
331 |
332 | A->fphase += A->dphase;
333 | A->iphase = abs((int)A->fphase);
334 | if (A->iphase > 1023) A->iphase = 1023;
335 |
336 | if (A->filter[7] != 0.0f)
337 | {
338 | A->filter[6] *= A->filter[7];
339 | if (A->filter[6] < 0.00001f) A->filter[6] = 0.00001f;
340 | if (A->filter[6] > 0.1f) A->filter[6] = 0.1f;
341 | }
342 |
343 | float ssample = 0.0f;
344 | for (si = 0; si < 8; si++)
345 | {
346 | float sample = 0.0f;
347 | A->phase++;
348 | if (A->phase >= period)
349 | {
350 | A->phase %= period;
351 | if (A->params.type == BLOOPS_NOISE)
352 | for (i = 0; i < 32; i++)
353 | A->noise[i] = frnd(2.0f) - 1.0f;
354 | }
355 |
356 | float fp = (float)A->phase / period;
357 | switch (A->params.type)
358 | {
359 | case BLOOPS_SQUARE:
360 | if (fp < A->square)
361 | sample = 0.5f;
362 | else
363 | sample = -0.5f;
364 | break;
365 | case BLOOPS_SAWTOOTH:
366 | sample = 1.0f - fp * 2;
367 | break;
368 | case BLOOPS_SINE:
369 | sample = (float)sin(fp * 2 * PI);
370 | break;
371 | case BLOOPS_NOISE:
372 | sample = A->noise[A->phase * 32 / period];
373 | break;
374 | }
375 |
376 | float pp = A->filter[0];
377 | A->filter[2] *= A->filter[3];
378 | if (A->filter[2] < 0.0f) A->filter[2] = 0.0f;
379 | if (A->filter[2] > 0.1f) A->filter[2] = 0.1f;
380 | if (A->params.lpf != 1.0f)
381 | {
382 | A->filter[1] += (sample - A->filter[0]) * A->filter[2];
383 | A->filter[1] -= A->filter[1] * A->filter[4];
384 | }
385 | else
386 | {
387 | A->filter[0] = sample;
388 | A->filter[1] = 0.0f;
389 | }
390 | A->filter[0] += A->filter[1];
391 |
392 | A->filter[5] += A->filter[0] - pp;
393 | A->filter[5] -= A->filter[5] * A->filter[6];
394 | sample = A->filter[5];
395 |
396 | A->phaser[A->phasex & 1023] = sample;
397 | sample += A->phaser[(A->phasex - A->iphase + 1024) & 1023];
398 | A->phasex = (A->phasex + 1) & 1023;
399 |
400 | ssample += sample * A->volume;
401 | }
402 | ssample = ssample / 8 * B->volume;
403 | ssample *= 2.0f * A->params.volume;
404 |
405 | if (ssample > 1.0f) ssample = 1.0f;
406 | if (ssample < -1.0f) ssample = -1.0f;
407 | allsample += ssample;
408 | }
409 | if (moreframes == 0)
410 | B->state = BLOOPS_STOP;
411 | }
412 |
413 | *buffer++ = allsample;
414 | }
415 | }
416 |
417 | static int bloops_port_callback(const void *inputBuffer, void *outputBuffer,
418 | unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo,
419 | PaStreamCallbackFlags statusFlags, void *data)
420 | {
421 | float *out = (float*)outputBuffer;
422 | bloops_synth(framesPerBuffer, out);
423 | return paContinue;
424 | }
425 |
426 | void
427 | bloops_play(bloops *B)
428 | {
429 | int i;
430 |
431 | for (i = 0; i < BLOOPS_MAX_TRACKS; i++) {
432 | bloopsavoice *A;
433 | A = &B->voices[i];
434 | if (A->track != NULL) {
435 | memcpy(&A->params, &A->track->params, sizeof(bloopsaparams));
436 | bloops_reset_voice(A);
437 | bloops_start_voice(A);
438 | A->frames = 0;
439 | A->nextnote[0] = 0;
440 | A->nextnote[1] = 0;
441 | }
442 | }
443 |
444 | bloops_remove(B);
445 | for (i = 0; i < BLOOPS_MAX_CHANNELS; i++) {
446 | if (MIXER->B[i] == NULL || MIXER->B[i]->state == BLOOPS_STOP) {
447 | bloops_ref(B);
448 | if (MIXER->B[i] != NULL) {
449 | bloops_destroy(MIXER->B[i]);
450 | }
451 | MIXER->B[i] = B;
452 | break;
453 | }
454 | }
455 |
456 | B->state = BLOOPS_PLAY;
457 | if (MIXER->stream == NULL) {
458 | Pa_OpenDefaultStream(&MIXER->stream, 0, 1, paFloat32,
459 | SAMPLE_RATE, 512, bloops_port_callback, B);
460 | Pa_StartStream(MIXER->stream);
461 | }
462 | }
463 |
464 | void
465 | bloops_stop(bloops *B)
466 | {
467 | int i, stopall = 1;
468 | B->state = BLOOPS_STOP;
469 | for (i = 0; i < BLOOPS_MAX_CHANNELS; i++)
470 | if (MIXER->B[i] != NULL && MIXER->B[i]->state != BLOOPS_STOP)
471 | stopall = 0;
472 |
473 | if (stopall)
474 | {
475 | Pa_StopStream(MIXER->stream);
476 | Pa_CloseStream(MIXER->stream);
477 | MIXER->stream = NULL;
478 | }
479 | }
480 |
481 | bloopsaphone *
482 | bloops_square()
483 | {
484 | bloopsaphone *P = (bloopsaphone *)calloc(sizeof(bloopsaphone), 1);
485 | P->refcount = 1;
486 | P->params.type = BLOOPS_SQUARE;
487 | P->params.volume = 0.5f;
488 | P->params.sustain = 0.3f;
489 | P->params.decay = 0.4f;
490 | P->params.freq = 0.3f;
491 | P->params.lpf = 1.0f;
492 | return P;
493 | }
494 |
495 | static int bloops_open = 0;
496 |
497 | bloops *
498 | bloops_new()
499 | {
500 | int i;
501 | bloops *B = (bloops *)malloc(sizeof(bloops));
502 | B->refcount = 1;
503 | B->volume = 0.10f;
504 | B->tempo = 120;
505 | B->state = BLOOPS_STOP;
506 | for (i = 0; i < BLOOPS_MAX_TRACKS; i++) {
507 | B->voices[i].track = NULL;
508 | }
509 |
510 | if (MIXER == NULL)
511 | MIXER = (bloopsmix *)calloc(sizeof(bloopsmix), 1);
512 |
513 | if (!bloops_open++)
514 | {
515 | srand(time(NULL));
516 | bloops_lock_init(&LOCK);
517 | Pa_Initialize();
518 | }
519 |
520 | return B;
521 | }
522 |
523 | void
524 | bloops_ref(bloops *B)
525 | {
526 | B->refcount++;
527 | }
528 |
529 | void
530 | bloops_destroy(bloops *B)
531 | {
532 | if (--B->refcount) {
533 | return;
534 | }
535 |
536 | bloops_remove(B);
537 | free((void *)B);
538 |
539 | if (!--bloops_open)
540 | {
541 | Pa_Terminate();
542 | bloops_lock_finalize(&LOCK);
543 | if (MIXER != NULL)
544 | free(MIXER);
545 | MIXER = NULL;
546 | }
547 | }
548 |
549 | static void bloops_notes_destroy(bloopsanote *notes, int nlen)
550 | {
551 | bloopsafx *fx, *n;
552 | int i;
553 |
554 | for (i = 0; i < nlen; i++) {
555 | n = fx = notes[i].FX;
556 | while ((fx = n)) {
557 | n = fx->next;
558 | free(fx);
559 | }
560 | }
561 |
562 | free(notes);
563 | }
564 |
565 | void
566 | bloops_track_ref(bloopsatrack *track)
567 | {
568 | track->refcount++;
569 | }
570 |
571 | void
572 | bloops_track_destroy(bloopsatrack *track)
573 | {
574 | if (--track->refcount) {
575 | return;
576 | }
577 | if (track->notes != NULL) {
578 | bloops_notes_destroy(track->notes, track->nlen);
579 | }
580 | free(track);
581 | }
582 |
583 | void bloops_sound_copy(bloopsaphone *dest, bloopsaphone const *src) {
584 | memcpy(&dest->params, &src->params, sizeof(bloopsaparams));
585 | }
586 |
587 | void bloops_sound_ref(bloopsaphone *sound) {
588 | sound->refcount++;
589 | }
590 |
591 | void bloops_sound_destroy(bloopsaphone *sound) {
592 | if (--sound->refcount) {
593 | return;
594 | }
595 | free(sound);
596 | }
597 |
--------------------------------------------------------------------------------
/c/bloopsaphone.h:
--------------------------------------------------------------------------------
1 | //
2 | // bloopsaphone.h
3 | // the chiptune maker for portaudio
4 | //
5 | #ifndef BLOOPSAPHONE_H
6 | #define BLOOPSAPHONE_H
7 |
8 | #define BLOOPSAPHONE_VERSION "1.0"
9 |
10 | typedef enum {
11 | BLOOPS_STOP = 0,
12 | BLOOPS_PLAY = 1
13 | } bloopsastate;
14 |
15 | typedef enum {
16 | BLOOPS_SQUARE = 0,
17 | BLOOPS_SAWTOOTH = 1,
18 | BLOOPS_SINE = 2,
19 | BLOOPS_NOISE = 3
20 | } bloopswaveform;
21 |
22 | typedef enum {
23 | BLOOPS_FX_VOLUME = 0,
24 | BLOOPS_FX_PUNCH = 1,
25 | BLOOPS_FX_ATTACK = 2,
26 | BLOOPS_FX_SUSTAIN = 3,
27 | BLOOPS_FX_DECAY = 4,
28 | BLOOPS_FX_SWEEP = 5,
29 | BLOOPS_FX_SQUARE = 6,
30 | BLOOPS_FX_VIBE = 7,
31 | BLOOPS_FX_VSPEED = 8,
32 | BLOOPS_FX_VDELAY = 9,
33 | BLOOPS_FX_LPF = 10,
34 | BLOOPS_FX_LSWEEP = 11,
35 | BLOOPS_FX_RESONANCE = 12,
36 | BLOOPS_FX_HPF = 13,
37 | BLOOPS_FX_HSWEEP = 14,
38 | BLOOPS_FX_ARP = 15,
39 | BLOOPS_FX_ASPEED = 16,
40 | BLOOPS_FX_PHASE = 17,
41 | BLOOPS_FX_PSWEEP = 18,
42 | BLOOPS_FX_REPEAT = 19
43 | } bloopsafxcmd;
44 |
45 | typedef struct {
46 | bloopswaveform type;
47 | unsigned char pan;
48 | float volume;
49 | float punch;
50 | float attack;
51 | float sustain;
52 | float decay;
53 | float freq, limit, slide, dslide; // pitch
54 | float square, sweep; // square wave
55 | float vibe, vspeed, vdelay; // vibrato
56 | float lpf, lsweep, resonance, hpf, hsweep;
57 | // hi-pass, lo-pass
58 | float arp, aspeed; // arpeggiator
59 | float phase, psweep; // phaser
60 | float repeat; // repeats?
61 | } bloopsaparams;
62 |
63 | typedef struct {
64 | unsigned refcount;
65 | bloopsaparams params;
66 | } bloopsaphone;
67 |
68 | #define BLOOPS_HI_OCTAVE 8
69 |
70 | typedef struct bloopsafx_tag {
71 | bloopsafxcmd cmd;
72 | float val;
73 | char mod;
74 | struct bloopsafx_tag *next;
75 | } bloopsafx;
76 |
77 | typedef struct {
78 | char tone, octave, duration;
79 | bloopsafx *FX;
80 | } bloopsanote;
81 |
82 | typedef struct {
83 | unsigned refcount;
84 | int nlen, capa;
85 | bloopsanote *notes;
86 | bloopsaparams params;
87 | } bloopsatrack;
88 |
89 | typedef struct {
90 | bloopsatrack *track;
91 | bloopsaparams params;
92 | int frames, nextnote[2];
93 | float volume, freq;
94 | bloopsastate state;
95 | int stage, time, length[3];
96 | double period, maxperiod, slide, dslide;
97 | float square, sweep;
98 | int phase, iphase, phasex;
99 | float fphase, dphase;
100 | float phaser[1024];
101 | float noise[32];
102 | float filter[8];
103 | float vibe, vspeed, vdelay;
104 | int repeat, limit;
105 | double arp;
106 | int atime, alimit;
107 | } bloopsavoice;
108 |
109 | #define BLOOPS_MAX_TRACKS 64
110 | #define BLOOPS_MAX_CHANNELS 64
111 |
112 | typedef struct {
113 | unsigned refcount;
114 | int tempo;
115 | float volume;
116 | bloopsavoice voices[BLOOPS_MAX_TRACKS];
117 | bloopsastate state;
118 | } bloops;
119 |
120 | typedef struct {
121 | bloops *B[BLOOPS_MAX_CHANNELS];
122 | void *stream;
123 | } bloopsmix;
124 |
125 | //
126 | // the api
127 | //
128 | bloops *bloops_new();
129 | void bloops_ref(bloops *);
130 | void bloops_destroy(bloops *);
131 |
132 | void bloops_clear(bloops *);
133 | void bloops_tempo(bloops *, int tempo);
134 | void bloops_play(bloops *);
135 | void bloops_stop(bloops *);
136 | int bloops_is_done(bloops *);
137 |
138 | bloopsatrack *bloops_track(bloops *, bloopsaphone *, char *, int);
139 | bloopsatrack *bloops_track2(bloops *, bloopsaphone *, char *);
140 | void bloops_track_ref(bloopsatrack *);
141 | void bloops_track_destroy(bloopsatrack *);
142 |
143 | bloopsaphone *bloops_square();
144 | bloopsaphone *bloops_sound_file(bloops *, char *);
145 | void bloops_sound_copy(bloopsaphone *, bloopsaphone const *);
146 | void bloops_sound_ref(bloopsaphone *);
147 | void bloops_sound_destroy(bloopsaphone *);
148 |
149 | char *bloops_track_str(bloopsatrack *);
150 | char *bloops_fxcmd_name(bloopsafxcmd fxcmd);
151 | float bloops_note_freq(char, int);
152 | char *bloops_sound_str(bloopsaphone *);
153 |
154 | #endif
155 |
--------------------------------------------------------------------------------
/c/bloopsawhat.c:
--------------------------------------------------------------------------------
1 | //
2 | // bloopsawhat.c
3 | // a simple commandline player
4 | //
5 | #include
6 | #include
7 | #include
8 | #include "bloopsaphone.h"
9 |
10 | static void
11 | usage()
12 | {
13 | printf("usage: bloopsawhat notes\n"
14 | " (ex.: bloopsawhat \"a b c d e f g + a b c\"\n");
15 | }
16 |
17 | int
18 | main(int argc, char *argv[])
19 | {
20 | char *str;
21 | if (argc > 1) {
22 | bloops *B = bloops_new();
23 | bloopsaphone *P = bloops_square();
24 | bloopsatrack *track = bloops_track2(B, P, argv[1]);
25 | bloops_sound_destroy(P);
26 | printf("%s\n", str = bloops_track_str(track));
27 | bloops_play(B);
28 | while (!bloops_is_done(B))
29 | sleep(1);
30 | free(str);
31 | bloops_track_destroy(track);
32 | bloops_destroy(B);
33 | return 0;
34 | }
35 |
36 | usage();
37 | return 0;
38 | }
39 |
--------------------------------------------------------------------------------
/c/notation.c:
--------------------------------------------------------------------------------
1 | #line 1 "c/notation.rl"
2 | //
3 | // notation.rl
4 | // the musical notation parser
5 | //
6 | // (c) 2009 why the lucky stiff
7 | // See COPYING for the license
8 | //
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include "bloopsaphone.h"
15 |
16 | #define ATOI(X,N) ({ \
17 | char *Ap = X; \
18 | int Ai = 0; \
19 | size_t Al = N; \
20 | while (Al--) { \
21 | if ((*Ap >= '0') && (*Ap <= '9')) { \
22 | Ai = (Ai * 10) + (*Ap - '0'); \
23 | Ap++; \
24 | } \
25 | else break; \
26 | } \
27 | Ai; \
28 | })
29 |
30 | #define NOTE S->notes[S->nlen]
31 |
32 | #define NEXT() \
33 | NOTE.duration = len; \
34 | NOTE.octave = oct; \
35 | mod = 0; \
36 | tone = 0; \
37 | len = 4; \
38 | fxval = 0; \
39 | fxmod = 0; \
40 | S->nlen++
41 |
42 |
43 | #line 44 "c/notation.c"
44 | static const char _bloopnotes_actions[] = {
45 | 0, 1, 1, 1, 3, 1, 4, 1,
46 | 6, 1, 8, 1, 9, 1, 10, 1,
47 | 11, 1, 12, 1, 13, 1, 14, 1,
48 | 15, 1, 16, 1, 17, 1, 18, 1,
49 | 19, 1, 20, 1, 21, 1, 22, 1,
50 | 23, 1, 24, 1, 25, 1, 26, 1,
51 | 27, 1, 28, 1, 29, 1, 30, 1,
52 | 31, 1, 32, 1, 33, 1, 34, 1,
53 | 35, 1, 36, 1, 41, 2, 0, 37,
54 | 2, 0, 39, 2, 0, 40, 2, 28,
55 | 39, 2, 29, 40, 2, 35, 0, 2,
56 | 35, 5, 2, 35, 30, 2, 35, 32,
57 | 3, 1, 2, 38, 3, 3, 2, 38,
58 | 3, 30, 2, 38, 3, 32, 2, 38,
59 | 3, 35, 4, 5, 3, 35, 5, 7,
60 | 4, 35, 4, 5, 7
61 | };
62 |
63 | static const short _bloopnotes_key_offsets[] = {
64 | 0, 0, 8, 11, 12, 20, 27, 31,
65 | 37, 39, 43, 45, 48, 52, 54, 57,
66 | 60, 66, 70, 71, 72, 73, 74, 82,
67 | 83, 84, 85, 86, 94, 95, 96, 97,
68 | 98, 106, 108, 109, 117, 118, 119, 120,
69 | 121, 129, 131, 132, 140, 141, 142, 143,
70 | 144, 152, 155, 156, 157, 158, 166, 167,
71 | 168, 169, 170, 178, 179, 180, 181, 189,
72 | 190, 192, 193, 194, 195, 203, 204, 205,
73 | 206, 207, 208, 209, 217, 220, 221, 222,
74 | 223, 224, 232, 233, 234, 235, 236, 237,
75 | 245, 246, 247, 248, 256, 260, 261, 262,
76 | 263, 264, 272, 273, 274, 282, 283, 284,
77 | 285, 286, 294, 295, 296, 297, 298, 306,
78 | 317, 319, 322, 323, 323, 325, 328, 329,
79 | 329, 336, 341, 345, 350, 353, 354
80 | };
81 |
82 | static const char _bloopnotes_trans_keys[] = {
83 | 97, 100, 104, 108, 112, 114, 115, 118,
84 | 114, 115, 116, 112, 32, 43, 45, 58,
85 | 9, 13, 48, 57, 32, 43, 45, 9,
86 | 13, 48, 57, 32, 58, 9, 13, 32,
87 | 45, 9, 13, 48, 57, 48, 57, 46,
88 | 93, 48, 57, 48, 57, 93, 48, 57,
89 | 46, 93, 48, 57, 48, 57, 93, 48,
90 | 57, 45, 48, 57, 32, 58, 9, 13,
91 | 48, 57, 43, 45, 48, 57, 112, 101,
92 | 101, 100, 32, 43, 45, 58, 9, 13,
93 | 48, 57, 116, 97, 99, 107, 32, 43,
94 | 45, 58, 9, 13, 48, 57, 101, 99,
95 | 97, 121, 32, 43, 45, 58, 9, 13,
96 | 48, 57, 112, 115, 102, 32, 43, 45,
97 | 58, 9, 13, 48, 57, 119, 101, 101,
98 | 112, 32, 43, 45, 58, 9, 13, 48,
99 | 57, 112, 115, 102, 32, 43, 45, 58,
100 | 9, 13, 48, 57, 119, 101, 101, 112,
101 | 32, 43, 45, 58, 9, 13, 48, 57,
102 | 104, 115, 117, 97, 115, 101, 32, 43,
103 | 45, 58, 9, 13, 48, 57, 119, 101,
104 | 101, 112, 32, 43, 45, 58, 9, 13,
105 | 48, 57, 110, 99, 104, 32, 43, 45,
106 | 58, 9, 13, 48, 57, 101, 112, 115,
107 | 101, 97, 116, 32, 43, 45, 58, 9,
108 | 13, 48, 57, 111, 110, 97, 110, 99,
109 | 101, 32, 43, 45, 58, 9, 13, 48,
110 | 57, 113, 117, 119, 117, 97, 114, 101,
111 | 32, 43, 45, 58, 9, 13, 48, 57,
112 | 115, 116, 97, 105, 110, 32, 43, 45,
113 | 58, 9, 13, 48, 57, 101, 101, 112,
114 | 32, 43, 45, 58, 9, 13, 48, 57,
115 | 100, 105, 111, 115, 101, 108, 97, 121,
116 | 32, 43, 45, 58, 9, 13, 48, 57,
117 | 98, 101, 32, 43, 45, 58, 9, 13,
118 | 48, 57, 108, 117, 109, 101, 32, 43,
119 | 45, 58, 9, 13, 48, 57, 112, 101,
120 | 101, 100, 32, 43, 45, 58, 9, 13,
121 | 48, 57, 32, 43, 45, 9, 13, 49,
122 | 57, 65, 71, 97, 103, 49, 57, 58,
123 | 48, 57, 58, 49, 57, 58, 48, 57,
124 | 58, 58, 48, 57, 65, 71, 97, 103,
125 | 58, 65, 71, 97, 103, 65, 71, 97,
126 | 103, 35, 91, 98, 49, 56, 91, 49,
127 | 56, 91, 91, 0
128 | };
129 |
130 | static const char _bloopnotes_single_lengths[] = {
131 | 0, 8, 3, 1, 4, 3, 2, 2,
132 | 0, 2, 0, 1, 2, 0, 1, 1,
133 | 2, 2, 1, 1, 1, 1, 4, 1,
134 | 1, 1, 1, 4, 1, 1, 1, 1,
135 | 4, 2, 1, 4, 1, 1, 1, 1,
136 | 4, 2, 1, 4, 1, 1, 1, 1,
137 | 4, 3, 1, 1, 1, 4, 1, 1,
138 | 1, 1, 4, 1, 1, 1, 4, 1,
139 | 2, 1, 1, 1, 4, 1, 1, 1,
140 | 1, 1, 1, 4, 3, 1, 1, 1,
141 | 1, 4, 1, 1, 1, 1, 1, 4,
142 | 1, 1, 1, 4, 4, 1, 1, 1,
143 | 1, 4, 1, 1, 4, 1, 1, 1,
144 | 1, 4, 1, 1, 1, 1, 4, 3,
145 | 0, 1, 1, 0, 0, 1, 1, 0,
146 | 1, 1, 0, 3, 1, 1, 1
147 | };
148 |
149 | static const char _bloopnotes_range_lengths[] = {
150 | 0, 0, 0, 0, 2, 2, 1, 2,
151 | 1, 1, 1, 1, 1, 1, 1, 1,
152 | 2, 1, 0, 0, 0, 0, 2, 0,
153 | 0, 0, 0, 2, 0, 0, 0, 0,
154 | 2, 0, 0, 2, 0, 0, 0, 0,
155 | 2, 0, 0, 2, 0, 0, 0, 0,
156 | 2, 0, 0, 0, 0, 2, 0, 0,
157 | 0, 0, 2, 0, 0, 0, 2, 0,
158 | 0, 0, 0, 0, 2, 0, 0, 0,
159 | 0, 0, 0, 2, 0, 0, 0, 0,
160 | 0, 2, 0, 0, 0, 0, 0, 2,
161 | 0, 0, 0, 2, 0, 0, 0, 0,
162 | 0, 2, 0, 0, 2, 0, 0, 0,
163 | 0, 2, 0, 0, 0, 0, 2, 4,
164 | 1, 1, 0, 0, 1, 1, 0, 0,
165 | 3, 2, 2, 1, 1, 0, 0
166 | };
167 |
168 | static const short _bloopnotes_index_offsets[] = {
169 | 0, 0, 9, 13, 15, 22, 28, 32,
170 | 37, 39, 43, 45, 48, 52, 54, 57,
171 | 60, 65, 69, 71, 73, 75, 77, 84,
172 | 86, 88, 90, 92, 99, 101, 103, 105,
173 | 107, 114, 117, 119, 126, 128, 130, 132,
174 | 134, 141, 144, 146, 153, 155, 157, 159,
175 | 161, 168, 172, 174, 176, 178, 185, 187,
176 | 189, 191, 193, 200, 202, 204, 206, 213,
177 | 215, 218, 220, 222, 224, 231, 233, 235,
178 | 237, 239, 241, 243, 250, 254, 256, 258,
179 | 260, 262, 269, 271, 273, 275, 277, 279,
180 | 286, 288, 290, 292, 299, 304, 306, 308,
181 | 310, 312, 319, 321, 323, 330, 332, 334,
182 | 336, 338, 345, 347, 349, 351, 353, 360,
183 | 368, 370, 373, 375, 376, 378, 381, 383,
184 | 384, 389, 393, 396, 401, 404, 406
185 | };
186 |
187 | static const char _bloopnotes_trans_targs[] = {
188 | 2, 28, 33, 41, 49, 63, 76, 92,
189 | 111, 3, 18, 23, 111, 4, 111, 5,
190 | 6, 16, 17, 5, 12, 111, 5, 6,
191 | 16, 5, 12, 111, 7, 15, 7, 111,
192 | 7, 8, 7, 12, 111, 9, 111, 10,
193 | 126, 9, 111, 11, 111, 126, 11, 111,
194 | 13, 126, 12, 111, 14, 111, 126, 14,
195 | 111, 8, 12, 111, 7, 15, 7, 9,
196 | 111, 6, 16, 12, 111, 19, 111, 20,
197 | 111, 21, 111, 22, 111, 5, 6, 16,
198 | 17, 5, 12, 111, 24, 111, 25, 111,
199 | 26, 111, 27, 111, 5, 6, 16, 17,
200 | 5, 12, 111, 29, 111, 30, 111, 31,
201 | 111, 32, 111, 5, 6, 16, 17, 5,
202 | 12, 111, 34, 36, 111, 35, 111, 5,
203 | 6, 16, 17, 5, 12, 111, 37, 111,
204 | 38, 111, 39, 111, 40, 111, 5, 6,
205 | 16, 17, 5, 12, 111, 42, 44, 111,
206 | 43, 111, 5, 6, 16, 17, 5, 12,
207 | 111, 45, 111, 46, 111, 47, 111, 48,
208 | 111, 5, 6, 16, 17, 5, 12, 111,
209 | 50, 54, 59, 111, 51, 111, 52, 111,
210 | 53, 111, 5, 6, 16, 17, 5, 12,
211 | 111, 55, 111, 56, 111, 57, 111, 58,
212 | 111, 5, 6, 16, 17, 5, 12, 111,
213 | 60, 111, 61, 111, 62, 111, 5, 6,
214 | 16, 17, 5, 12, 111, 64, 111, 65,
215 | 69, 111, 66, 111, 67, 111, 68, 111,
216 | 5, 6, 16, 17, 5, 12, 111, 70,
217 | 111, 71, 111, 72, 111, 73, 111, 74,
218 | 111, 75, 111, 5, 6, 16, 17, 5,
219 | 12, 111, 77, 82, 88, 111, 78, 111,
220 | 79, 111, 80, 111, 81, 111, 5, 6,
221 | 16, 17, 5, 12, 111, 83, 111, 84,
222 | 111, 85, 111, 86, 111, 87, 111, 5,
223 | 6, 16, 17, 5, 12, 111, 89, 111,
224 | 90, 111, 91, 111, 5, 6, 16, 17,
225 | 5, 12, 111, 93, 98, 101, 106, 111,
226 | 94, 111, 95, 111, 96, 111, 97, 111,
227 | 5, 6, 16, 17, 5, 12, 111, 99,
228 | 111, 100, 111, 5, 6, 16, 17, 5,
229 | 12, 111, 102, 111, 103, 111, 104, 111,
230 | 105, 111, 5, 6, 16, 17, 5, 12,
231 | 111, 107, 111, 108, 111, 109, 111, 110,
232 | 111, 5, 6, 16, 17, 5, 12, 111,
233 | 111, 112, 116, 111, 120, 123, 123, 0,
234 | 113, 111, 115, 114, 111, 115, 111, 111,
235 | 117, 111, 119, 118, 111, 119, 111, 111,
236 | 122, 121, 123, 123, 111, 122, 123, 123,
237 | 111, 123, 123, 111, 124, 1, 124, 125,
238 | 111, 1, 125, 111, 1, 111, 1, 111,
239 | 111, 111, 111, 111, 111, 111, 111, 111,
240 | 111, 111, 111, 111, 111, 111, 111, 111,
241 | 111, 111, 111, 111, 111, 111, 111, 111,
242 | 111, 111, 111, 111, 111, 111, 111, 111,
243 | 111, 111, 111, 111, 111, 111, 111, 111,
244 | 111, 111, 111, 111, 111, 111, 111, 111,
245 | 111, 111, 111, 111, 111, 111, 111, 111,
246 | 111, 111, 111, 111, 111, 111, 111, 111,
247 | 111, 111, 111, 111, 111, 111, 111, 111,
248 | 111, 111, 111, 111, 111, 111, 111, 111,
249 | 111, 111, 111, 111, 111, 111, 111, 111,
250 | 111, 111, 111, 111, 111, 111, 111, 111,
251 | 111, 111, 111, 111, 111, 111, 111, 111,
252 | 111, 111, 111, 111, 111, 111, 111, 111,
253 | 111, 111, 111, 111, 111, 111, 111, 111,
254 | 111, 111, 111, 111, 111, 0
255 | };
256 |
257 | static const char _bloopnotes_trans_actions[] = {
258 | 0, 0, 0, 0, 0, 0, 0, 0,
259 | 67, 0, 0, 0, 67, 0, 67, 39,
260 | 39, 39, 39, 39, 39, 67, 0, 0,
261 | 0, 0, 0, 67, 55, 55, 55, 67,
262 | 0, 0, 0, 0, 67, 0, 67, 5,
263 | 120, 0, 67, 7, 67, 116, 0, 67,
264 | 5, 112, 0, 67, 7, 67, 87, 0,
265 | 67, 0, 0, 67, 55, 55, 55, 0,
266 | 67, 0, 0, 0, 67, 0, 67, 0,
267 | 67, 0, 67, 0, 67, 41, 41, 41,
268 | 41, 41, 41, 67, 0, 67, 0, 67,
269 | 0, 67, 0, 67, 13, 13, 13, 13,
270 | 13, 13, 67, 0, 67, 0, 67, 0,
271 | 67, 0, 67, 17, 17, 17, 17, 17,
272 | 17, 67, 0, 0, 67, 0, 67, 35,
273 | 35, 35, 35, 35, 35, 67, 0, 67,
274 | 0, 67, 0, 67, 0, 67, 37, 37,
275 | 37, 37, 37, 37, 67, 0, 0, 67,
276 | 0, 67, 29, 29, 29, 29, 29, 29,
277 | 67, 0, 67, 0, 67, 0, 67, 0,
278 | 67, 31, 31, 31, 31, 31, 31, 67,
279 | 0, 0, 0, 67, 0, 67, 0, 67,
280 | 0, 67, 43, 43, 43, 43, 43, 43,
281 | 67, 0, 67, 0, 67, 0, 67, 0,
282 | 67, 45, 45, 45, 45, 45, 45, 67,
283 | 0, 67, 0, 67, 0, 67, 11, 11,
284 | 11, 11, 11, 11, 67, 0, 67, 0,
285 | 0, 67, 0, 67, 0, 67, 0, 67,
286 | 47, 47, 47, 47, 47, 47, 67, 0,
287 | 67, 0, 67, 0, 67, 0, 67, 0,
288 | 67, 0, 67, 33, 33, 33, 33, 33,
289 | 33, 67, 0, 0, 0, 67, 0, 67,
290 | 0, 67, 0, 67, 0, 67, 19, 19,
291 | 19, 19, 19, 19, 67, 0, 67, 0,
292 | 67, 0, 67, 0, 67, 0, 67, 15,
293 | 15, 15, 15, 15, 15, 67, 0, 67,
294 | 0, 67, 0, 67, 21, 21, 21, 21,
295 | 21, 21, 67, 0, 0, 0, 0, 67,
296 | 0, 67, 0, 67, 0, 67, 0, 67,
297 | 27, 27, 27, 27, 27, 27, 67, 0,
298 | 67, 0, 67, 23, 23, 23, 23, 23,
299 | 23, 67, 0, 67, 0, 67, 0, 67,
300 | 0, 67, 9, 9, 9, 9, 9, 9,
301 | 67, 0, 67, 0, 67, 0, 67, 0,
302 | 67, 25, 25, 25, 25, 25, 25, 67,
303 | 65, 0, 0, 65, 0, 63, 63, 0,
304 | 49, 78, 0, 0, 72, 0, 72, 72,
305 | 51, 81, 0, 0, 75, 0, 75, 75,
306 | 0, 0, 84, 84, 69, 0, 84, 84,
307 | 69, 84, 84, 69, 93, 57, 93, 93,
308 | 108, 53, 90, 104, 1, 96, 3, 100,
309 | 67, 67, 67, 67, 67, 67, 67, 67,
310 | 67, 67, 67, 67, 67, 67, 67, 67,
311 | 67, 67, 67, 67, 67, 67, 67, 67,
312 | 67, 67, 67, 67, 67, 67, 67, 67,
313 | 67, 67, 67, 67, 67, 67, 67, 67,
314 | 67, 67, 67, 67, 67, 67, 67, 67,
315 | 67, 67, 67, 67, 67, 67, 67, 67,
316 | 67, 67, 67, 67, 67, 67, 67, 67,
317 | 67, 67, 67, 67, 67, 67, 67, 67,
318 | 67, 67, 67, 67, 67, 67, 67, 67,
319 | 67, 67, 67, 67, 67, 67, 67, 67,
320 | 67, 67, 67, 67, 67, 67, 67, 67,
321 | 67, 67, 67, 67, 67, 67, 67, 67,
322 | 67, 67, 67, 67, 67, 67, 78, 72,
323 | 72, 72, 81, 75, 75, 75, 69, 69,
324 | 69, 108, 104, 96, 100, 0
325 | };
326 |
327 | static const char _bloopnotes_to_state_actions[] = {
328 | 0, 0, 0, 0, 0, 0, 0, 0,
329 | 0, 0, 0, 0, 0, 0, 0, 0,
330 | 0, 0, 0, 0, 0, 0, 0, 0,
331 | 0, 0, 0, 0, 0, 0, 0, 0,
332 | 0, 0, 0, 0, 0, 0, 0, 0,
333 | 0, 0, 0, 0, 0, 0, 0, 0,
334 | 0, 0, 0, 0, 0, 0, 0, 0,
335 | 0, 0, 0, 0, 0, 0, 0, 0,
336 | 0, 0, 0, 0, 0, 0, 0, 0,
337 | 0, 0, 0, 0, 0, 0, 0, 0,
338 | 0, 0, 0, 0, 0, 0, 0, 0,
339 | 0, 0, 0, 0, 0, 0, 0, 0,
340 | 0, 0, 0, 0, 0, 0, 0, 0,
341 | 0, 0, 0, 0, 0, 0, 0, 59,
342 | 0, 0, 0, 0, 0, 0, 0, 0,
343 | 0, 0, 0, 0, 0, 0, 0
344 | };
345 |
346 | static const char _bloopnotes_from_state_actions[] = {
347 | 0, 0, 0, 0, 0, 0, 0, 0,
348 | 0, 0, 0, 0, 0, 0, 0, 0,
349 | 0, 0, 0, 0, 0, 0, 0, 0,
350 | 0, 0, 0, 0, 0, 0, 0, 0,
351 | 0, 0, 0, 0, 0, 0, 0, 0,
352 | 0, 0, 0, 0, 0, 0, 0, 0,
353 | 0, 0, 0, 0, 0, 0, 0, 0,
354 | 0, 0, 0, 0, 0, 0, 0, 0,
355 | 0, 0, 0, 0, 0, 0, 0, 0,
356 | 0, 0, 0, 0, 0, 0, 0, 0,
357 | 0, 0, 0, 0, 0, 0, 0, 0,
358 | 0, 0, 0, 0, 0, 0, 0, 0,
359 | 0, 0, 0, 0, 0, 0, 0, 0,
360 | 0, 0, 0, 0, 0, 0, 0, 61,
361 | 0, 0, 0, 0, 0, 0, 0, 0,
362 | 0, 0, 0, 0, 0, 0, 0
363 | };
364 |
365 | static const short _bloopnotes_eof_trans[] = {
366 | 0, 518, 518, 518, 518, 518, 518, 518,
367 | 518, 518, 518, 518, 518, 518, 518, 518,
368 | 518, 518, 518, 518, 518, 518, 518, 518,
369 | 518, 518, 518, 518, 518, 518, 518, 518,
370 | 518, 518, 518, 518, 518, 518, 518, 518,
371 | 518, 518, 518, 518, 518, 518, 518, 518,
372 | 518, 518, 518, 518, 518, 518, 518, 518,
373 | 518, 518, 518, 518, 518, 518, 518, 518,
374 | 518, 518, 518, 518, 518, 518, 518, 518,
375 | 518, 518, 518, 518, 518, 518, 518, 518,
376 | 518, 518, 518, 518, 518, 518, 518, 518,
377 | 518, 518, 518, 518, 518, 518, 518, 518,
378 | 518, 518, 518, 518, 518, 518, 518, 518,
379 | 518, 518, 518, 518, 518, 518, 518, 0,
380 | 519, 522, 522, 522, 523, 526, 526, 526,
381 | 529, 529, 529, 530, 531, 532, 533
382 | };
383 |
384 | static const int bloopnotes_start = 111;
385 | static const int bloopnotes_error = 0;
386 |
387 | static const int bloopnotes_en_main = 111;
388 |
389 | #line 154 "c/notation.rl"
390 |
391 |
392 | extern void _bloops_track_add(bloops *B, bloopsatrack *track);
393 |
394 | bloopsatrack *
395 | bloops_track(bloops *B, bloopsaphone *P, char *track, int tracklen)
396 | {
397 | int cs, act, oct = 4, len = 4;
398 | bloopsatrack *S = (bloopsatrack *)malloc(sizeof(bloopsatrack));
399 | char tone, mod, fxmod, *p, *pe, *pf, *ts, *te, *eof = 0;
400 | bloopsafxcmd fxcmd = (bloopsafxcmd)0;
401 | float fxval = 0;
402 |
403 | S->refcount = 1;
404 | S->nlen = 0;
405 | S->capa = 1024;
406 | S->notes = (bloopsanote *)calloc(sizeof(bloopsanote), 1024);
407 |
408 | p = track;
409 | pe = track + tracklen + 1;
410 |
411 |
412 | #line 413 "c/notation.c"
413 | {
414 | cs = bloopnotes_start;
415 | ts = 0;
416 | te = 0;
417 | act = 0;
418 | }
419 | #line 176 "c/notation.rl"
420 |
421 | #line 422 "c/notation.c"
422 | {
423 | int _klen;
424 | unsigned int _trans;
425 | const char *_acts;
426 | unsigned int _nacts;
427 | const char *_keys;
428 |
429 | if ( p == pe )
430 | goto _test_eof;
431 | if ( cs == 0 )
432 | goto _out;
433 | _resume:
434 | _acts = _bloopnotes_actions + _bloopnotes_from_state_actions[cs];
435 | _nacts = (unsigned int) *_acts++;
436 | while ( _nacts-- > 0 ) {
437 | switch ( *_acts++ ) {
438 | case 34:
439 | #line 1 "c/notation.rl"
440 | {ts = p;}
441 | break;
442 | #line 443 "c/notation.c"
443 | }
444 | }
445 |
446 | _keys = _bloopnotes_trans_keys + _bloopnotes_key_offsets[cs];
447 | _trans = _bloopnotes_index_offsets[cs];
448 |
449 | _klen = _bloopnotes_single_lengths[cs];
450 | if ( _klen > 0 ) {
451 | const char *_lower = _keys;
452 | const char *_mid;
453 | const char *_upper = _keys + _klen - 1;
454 | while (1) {
455 | if ( _upper < _lower )
456 | break;
457 |
458 | _mid = _lower + ((_upper-_lower) >> 1);
459 | if ( (*p) < *_mid )
460 | _upper = _mid - 1;
461 | else if ( (*p) > *_mid )
462 | _lower = _mid + 1;
463 | else {
464 | _trans += (_mid - _keys);
465 | goto _match;
466 | }
467 | }
468 | _keys += _klen;
469 | _trans += _klen;
470 | }
471 |
472 | _klen = _bloopnotes_range_lengths[cs];
473 | if ( _klen > 0 ) {
474 | const char *_lower = _keys;
475 | const char *_mid;
476 | const char *_upper = _keys + (_klen<<1) - 2;
477 | while (1) {
478 | if ( _upper < _lower )
479 | break;
480 |
481 | _mid = _lower + (((_upper-_lower) >> 1) & ~1);
482 | if ( (*p) < _mid[0] )
483 | _upper = _mid - 2;
484 | else if ( (*p) > _mid[1] )
485 | _lower = _mid + 2;
486 | else {
487 | _trans += ((_mid - _keys)>>1);
488 | goto _match;
489 | }
490 | }
491 | _trans += _klen;
492 | }
493 |
494 | _match:
495 | _eof_trans:
496 | cs = _bloopnotes_trans_targs[_trans];
497 |
498 | if ( _bloopnotes_trans_actions[_trans] == 0 )
499 | goto _again;
500 |
501 | _acts = _bloopnotes_actions + _bloopnotes_trans_actions[_trans];
502 | _nacts = (unsigned int) *_acts++;
503 | while ( _nacts-- > 0 )
504 | {
505 | switch ( *_acts++ )
506 | {
507 | case 0:
508 | #line 44 "c/notation.rl"
509 | {
510 | len = ATOI(ts, p - ts);
511 | }
512 | break;
513 | case 1:
514 | #line 48 "c/notation.rl"
515 | {
516 | oct = ATOI(p - 1, 1);
517 | }
518 | break;
519 | case 2:
520 | #line 52 "c/notation.rl"
521 | {
522 | switch (tone) {
523 | case 'a': case 'A':
524 | if (mod == 'b') NOTE.tone = 'a';
525 | else if (mod == '#') NOTE.tone = 'b';
526 | else NOTE.tone = 'A';
527 | break;
528 | case 'b': case 'B':
529 | if (mod == 'b') NOTE.tone = 'b';
530 | else if (mod == '#') NOTE.tone = 'C';
531 | else NOTE.tone = 'B';
532 | break;
533 | case 'c': case 'C':
534 | if (mod == 'b') NOTE.tone = 'B';
535 | else if (mod == '#') NOTE.tone = 'd';
536 | else NOTE.tone = 'C';
537 | break;
538 | case 'd': case 'D':
539 | if (mod == 'b') NOTE.tone = 'd';
540 | else if (mod == '#') NOTE.tone = 'e';
541 | else NOTE.tone = 'D';
542 | break;
543 | case 'e': case 'E':
544 | if (mod == 'b') NOTE.tone = 'e';
545 | else if (mod == '#') NOTE.tone = 'F';
546 | else NOTE.tone = 'E';
547 | break;
548 | case 'f': case 'F':
549 | if (mod == 'b') NOTE.tone = 'E';
550 | else if (mod == '#') NOTE.tone = 'g';
551 | else NOTE.tone = 'F';
552 | break;
553 | case 'g': case 'G':
554 | if (mod == 'b') NOTE.tone = 'g';
555 | else if (mod == '#') NOTE.tone = 'a';
556 | else NOTE.tone = 'G';
557 | break;
558 | }
559 | }
560 | break;
561 | case 3:
562 | #line 92 "c/notation.rl"
563 | {
564 | bloopsafx *fx = (bloopsafx *)malloc(sizeof(bloopsafx));
565 | fx->next = NOTE.FX;
566 | fx->cmd = fxcmd;
567 | fx->val = fxval;
568 | fx->mod = fxmod;
569 | fxval = fxmod = 0;
570 | NOTE.FX = fx;
571 | }
572 | break;
573 | case 4:
574 | #line 102 "c/notation.rl"
575 | {
576 | fxval = atoi(p-1) * 1.0f;
577 | }
578 | break;
579 | case 5:
580 | #line 106 "c/notation.rl"
581 | {
582 | fxval += ATOI(pf, p - pf) * pow(0.1f, p - pf);
583 | }
584 | break;
585 | case 6:
586 | #line 110 "c/notation.rl"
587 | { pf = p; }
588 | break;
589 | case 7:
590 | #line 111 "c/notation.rl"
591 | { fxval *= -1.0f; }
592 | break;
593 | case 8:
594 | #line 112 "c/notation.rl"
595 | { fxcmd = BLOOPS_FX_VOLUME; }
596 | break;
597 | case 9:
598 | #line 113 "c/notation.rl"
599 | { fxcmd = BLOOPS_FX_PUNCH; }
600 | break;
601 | case 10:
602 | #line 114 "c/notation.rl"
603 | { fxcmd = BLOOPS_FX_ATTACK; }
604 | break;
605 | case 11:
606 | #line 115 "c/notation.rl"
607 | { fxcmd = BLOOPS_FX_SUSTAIN; }
608 | break;
609 | case 12:
610 | #line 116 "c/notation.rl"
611 | { fxcmd = BLOOPS_FX_DECAY; }
612 | break;
613 | case 13:
614 | #line 117 "c/notation.rl"
615 | { fxcmd = BLOOPS_FX_SQUARE; }
616 | break;
617 | case 14:
618 | #line 118 "c/notation.rl"
619 | { fxcmd = BLOOPS_FX_SWEEP; }
620 | break;
621 | case 15:
622 | #line 119 "c/notation.rl"
623 | { fxcmd = BLOOPS_FX_VIBE; }
624 | break;
625 | case 16:
626 | #line 120 "c/notation.rl"
627 | { fxcmd = BLOOPS_FX_VSPEED; }
628 | break;
629 | case 17:
630 | #line 121 "c/notation.rl"
631 | { fxcmd = BLOOPS_FX_VDELAY; }
632 | break;
633 | case 18:
634 | #line 122 "c/notation.rl"
635 | { fxcmd = BLOOPS_FX_LPF; }
636 | break;
637 | case 19:
638 | #line 123 "c/notation.rl"
639 | { fxcmd = BLOOPS_FX_LSWEEP; }
640 | break;
641 | case 20:
642 | #line 124 "c/notation.rl"
643 | { fxcmd = BLOOPS_FX_RESONANCE; }
644 | break;
645 | case 21:
646 | #line 125 "c/notation.rl"
647 | { fxcmd = BLOOPS_FX_HPF; }
648 | break;
649 | case 22:
650 | #line 126 "c/notation.rl"
651 | { fxcmd = BLOOPS_FX_HSWEEP; }
652 | break;
653 | case 23:
654 | #line 127 "c/notation.rl"
655 | { fxcmd = BLOOPS_FX_ARP; }
656 | break;
657 | case 24:
658 | #line 128 "c/notation.rl"
659 | { fxcmd = BLOOPS_FX_ASPEED; }
660 | break;
661 | case 25:
662 | #line 129 "c/notation.rl"
663 | { fxcmd = BLOOPS_FX_PHASE; }
664 | break;
665 | case 26:
666 | #line 130 "c/notation.rl"
667 | { fxcmd = BLOOPS_FX_PSWEEP; }
668 | break;
669 | case 27:
670 | #line 131 "c/notation.rl"
671 | { fxcmd = BLOOPS_FX_REPEAT; }
672 | break;
673 | case 28:
674 | #line 134 "c/notation.rl"
675 | { len = 1; }
676 | break;
677 | case 29:
678 | #line 135 "c/notation.rl"
679 | { len = 1; }
680 | break;
681 | case 30:
682 | #line 136 "c/notation.rl"
683 | { mod = p[-1]; }
684 | break;
685 | case 31:
686 | #line 138 "c/notation.rl"
687 | { fxmod = p[-1]; }
688 | break;
689 | case 32:
690 | #line 140 "c/notation.rl"
691 | { tone = p[-1]; }
692 | break;
693 | case 35:
694 | #line 1 "c/notation.rl"
695 | {te = p+1;}
696 | break;
697 | case 36:
698 | #line 150 "c/notation.rl"
699 | {te = p+1;}
700 | break;
701 | case 37:
702 | #line 143 "c/notation.rl"
703 | {te = p;p--;{
704 | NOTE.tone = 0;
705 | NEXT();
706 | }}
707 | break;
708 | case 38:
709 | #line 147 "c/notation.rl"
710 | {te = p;p--;{ NEXT(); }}
711 | break;
712 | case 39:
713 | #line 148 "c/notation.rl"
714 | {te = p;p--;{ oct++; len = 4; }}
715 | break;
716 | case 40:
717 | #line 149 "c/notation.rl"
718 | {te = p;p--;{ oct--; len = 4; }}
719 | break;
720 | case 41:
721 | #line 147 "c/notation.rl"
722 | {{p = ((te))-1;}{ NEXT(); }}
723 | break;
724 | #line 725 "c/notation.c"
725 | }
726 | }
727 |
728 | _again:
729 | _acts = _bloopnotes_actions + _bloopnotes_to_state_actions[cs];
730 | _nacts = (unsigned int) *_acts++;
731 | while ( _nacts-- > 0 ) {
732 | switch ( *_acts++ ) {
733 | case 33:
734 | #line 1 "c/notation.rl"
735 | {ts = 0;}
736 | break;
737 | #line 738 "c/notation.c"
738 | }
739 | }
740 |
741 | if ( cs == 0 )
742 | goto _out;
743 | if ( ++p != pe )
744 | goto _resume;
745 | _test_eof: {}
746 | if ( p == eof )
747 | {
748 | if ( _bloopnotes_eof_trans[cs] > 0 ) {
749 | _trans = _bloopnotes_eof_trans[cs] - 1;
750 | goto _eof_trans;
751 | }
752 | }
753 |
754 | _out: {}
755 | }
756 | #line 177 "c/notation.rl"
757 |
758 | memcpy(&S->params, &P->params, sizeof(bloopsaparams));
759 |
760 | _bloops_track_add(B, S);
761 |
762 | return S;
763 | }
764 |
765 | bloopsatrack *
766 | bloops_track2(bloops *B, bloopsaphone *P, char *track)
767 | {
768 | return bloops_track(B, P, track, strlen(track));
769 | }
770 |
771 | char *
772 | bloops_track_str(bloopsatrack *track)
773 | {
774 | int bufsize = sizeof(char) * (track->nlen * 6 + 1024);
775 | char *str = (char *)malloc(bufsize), *ptr = str;
776 | int i, adv = 0;
777 |
778 | for (i = 0; i < track->nlen; i++)
779 | {
780 | if (ptr - str + adv + sizeof(char) * 256 > bufsize) {
781 | char *new_str;
782 | bufsize += sizeof(char) * 1024;
783 | new_str = realloc(str, bufsize);
784 | if (new_str == NULL) {
785 | free(str);
786 | return NULL;
787 | }
788 | }
789 |
790 | if (ptr > str)
791 | strcat(ptr++, " ");
792 |
793 | if (track->notes[i].duration != 4)
794 | {
795 | adv = sprintf(ptr, "%d:", (int)track->notes[i].duration);
796 | ptr += adv;
797 | }
798 |
799 | if (track->notes[i].tone)
800 | {
801 | char tone[3] = "\0\0\0";
802 | tone[0] = track->notes[i].tone;
803 | switch (tone[0]) {
804 | case 'a': tone[0] = 'A'; tone[1] = 'b'; break;
805 | case 'b': tone[0] = 'B'; tone[1] = 'b'; break;
806 | case 'd': tone[0] = 'C'; tone[1] = '#'; break;
807 | case 'e': tone[0] = 'E'; tone[1] = 'b'; break;
808 | case 'g': tone[0] = 'F'; tone[1] = '#'; break;
809 | }
810 | adv = sprintf(ptr, "%s", tone);
811 | ptr += adv;
812 |
813 | adv = sprintf(ptr, "%d", (int)track->notes[i].octave);
814 | ptr += adv;
815 | bloopsafx *fx = (bloopsafx *)track->notes[i].FX;
816 | while (fx) {
817 | if (fx->mod == 0)
818 | adv = sprintf(ptr, "[%s %0.3f]", bloops_fxcmd_name(fx->cmd), fx->val);
819 | else
820 | adv = sprintf(ptr, "[%s %c %0.3f]", bloops_fxcmd_name(fx->cmd), fx->mod, fx->val);
821 | ptr += adv;
822 | fx = (bloopsafx *)fx->next;
823 | }
824 | }
825 | }
826 |
827 | return str;
828 | }
829 |
830 | char *
831 | bloops_fxcmd_name(bloopsafxcmd fxcmd) {
832 | char *fxname = "\0";
833 | switch (fxcmd) {
834 | case BLOOPS_FX_VOLUME: fxname = "volume"; break;
835 | case BLOOPS_FX_PUNCH: fxname = "punch"; break;
836 | case BLOOPS_FX_ATTACK: fxname = "attack"; break;
837 | case BLOOPS_FX_SUSTAIN: fxname = "sustain"; break;
838 | case BLOOPS_FX_DECAY: fxname = "decay"; break;
839 | case BLOOPS_FX_SQUARE: fxname = "square"; break;
840 | case BLOOPS_FX_SWEEP: fxname = "sweep"; break;
841 | case BLOOPS_FX_VIBE: fxname = "vibe"; break;
842 | case BLOOPS_FX_VSPEED: fxname = "vspeed"; break;
843 | case BLOOPS_FX_VDELAY: fxname = "vdelay"; break;
844 | case BLOOPS_FX_LPF: fxname = "lpf"; break;
845 | case BLOOPS_FX_LSWEEP: fxname = "lsweep"; break;
846 | case BLOOPS_FX_RESONANCE: fxname = "resonance"; break;
847 | case BLOOPS_FX_HPF: fxname = "hpf"; break;
848 | case BLOOPS_FX_HSWEEP: fxname = "hsweep"; break;
849 | case BLOOPS_FX_ARP: fxname = "arp"; break;
850 | case BLOOPS_FX_ASPEED: fxname = "aspeed"; break;
851 | case BLOOPS_FX_PHASE: fxname = "phase"; break;
852 | case BLOOPS_FX_PSWEEP: fxname = "psweep"; break;
853 | case BLOOPS_FX_REPEAT: fxname = "repeat"; break;
854 | }
855 | return fxname;
856 | }
857 |
858 | float
859 | bloops_note_freq(char note, int octave)
860 | {
861 | switch (note)
862 | {
863 | case 'A': // A
864 | if (octave <= 0) return 0.0;
865 | else if (octave == 1) return 0.121;
866 | else if (octave == 2) return 0.175;
867 | else if (octave == 3) return 0.248;
868 | else if (octave == 4) return 0.353;
869 | else if (octave == 5) return 0.500;
870 | break;
871 |
872 | case 'b': // A# or Bb
873 | if (octave <= 0) return 0.0;
874 | else if (octave == 1) return 0.125;
875 | else if (octave == 2) return 0.181;
876 | else if (octave == 3) return 0.255;
877 | else if (octave == 4) return 0.364;
878 | else if (octave == 5) return 0.515;
879 | break;
880 |
881 | case 'B': // B
882 | if (octave <= 0) return 0.0;
883 | else if (octave == 1) return 0.129;
884 | else if (octave == 2) return 0.187;
885 | else if (octave == 3) return 0.263;
886 | else if (octave == 4) return 0.374;
887 | else if (octave == 5) return 0.528;
888 | break;
889 |
890 | case 'C': // C
891 | if (octave <= 1) return 0.0;
892 | else if (octave == 2) return 0.133;
893 | else if (octave == 3) return 0.192;
894 | else if (octave == 4) return 0.271;
895 | else if (octave == 5) return 0.385;
896 | else if (octave == 6) return 0.544;
897 | break;
898 |
899 | case 'd': // C# or Db
900 | if (octave <= 1) return 0.0;
901 | else if (octave == 2) return 0.138;
902 | else if (octave == 3) return 0.198;
903 | else if (octave == 4) return 0.279;
904 | else if (octave == 5) return 0.395;
905 | else if (octave == 6) return 0.559;
906 | break;
907 |
908 | case 'D': // D
909 | if (octave <= 1) return 0.0;
910 | else if (octave == 2) return 0.143;
911 | else if (octave == 3) return 0.202;
912 | else if (octave == 4) return 0.287;
913 | else if (octave == 5) return 0.406;
914 | else if (octave == 6) return 0.575;
915 | break;
916 |
917 | case 'e': // D# or Eb
918 | if (octave <= 1) return 0.0;
919 | else if (octave == 2) return 0.148;
920 | else if (octave == 3) return 0.208;
921 | else if (octave == 4) return 0.296;
922 | else if (octave == 5) return 0.418;
923 | else if (octave == 6) return 0.593;
924 | break;
925 |
926 | case 'E': // E
927 | if (octave <= 1) return 0.0;
928 | else if (octave == 2) return 0.152;
929 | else if (octave == 3) return 0.214;
930 | else if (octave == 4) return 0.305;
931 | else if (octave == 5) return 0.429;
932 | else if (octave == 6) return 0.608;
933 | break;
934 |
935 | case 'F': // F
936 | if (octave <= 1) return 0.0;
937 | else if (octave == 2) return 0.155;
938 | else if (octave == 3) return 0.220;
939 | else if (octave == 4) return 0.314;
940 | else if (octave == 5) return 0.441;
941 | break;
942 |
943 | case 'g': // F# or Gb
944 | if (octave <= 1) return 0.0;
945 | else if (octave == 2) return 0.160;
946 | else if (octave == 3) return 0.227;
947 | else if (octave == 4) return 0.323;
948 | else if (octave == 5) return 0.454;
949 | break;
950 |
951 | case 'G': // G
952 | if (octave <= 1) return 0.0;
953 | else if (octave == 2) return 0.164;
954 | else if (octave == 3) return 0.234;
955 | else if (octave == 4) return 0.332;
956 | else if (octave == 5) return 0.468;
957 | break;
958 |
959 | case 'a': // G# or Ab
960 | if (octave <= 1) return 0.117;
961 | else if (octave == 2) return 0.170;
962 | else if (octave == 3) return 0.242;
963 | else if (octave == 4) return 0.343;
964 | else if (octave == 5) return 0.485;
965 | break;
966 | }
967 |
968 | return 0.0;
969 | }
970 |
971 | #define KEY(name) key = (void *)&P->params.name
972 |
973 |
974 | #line 975 "c/notation.c"
975 | static const char _bloopserial_actions[] = {
976 | 0, 1, 0, 1, 1, 1, 2, 1,
977 | 5, 1, 6, 1, 7, 1, 8, 1,
978 | 9, 1, 10, 1, 11, 1, 12, 1,
979 | 13, 1, 14, 1, 15, 1, 16, 1,
980 | 17, 1, 18, 1, 19, 1, 20, 1,
981 | 21, 1, 22, 1, 23, 1, 24, 1,
982 | 25, 1, 26, 1, 27, 1, 29, 1,
983 | 30, 1, 31, 1, 32, 1, 33, 1,
984 | 34, 1, 35, 1, 36, 2, 1, 3,
985 | 2, 1, 35, 2, 4, 28, 3, 1,
986 | 3, 35
987 | };
988 |
989 | static const unsigned char _bloopserial_key_offsets[] = {
990 | 0, 0, 3, 4, 7, 13, 15, 18,
991 | 20, 23, 25, 26, 27, 28, 29, 32,
992 | 33, 34, 35, 36, 39, 41, 42, 43,
993 | 44, 47, 48, 49, 50, 51, 54, 55,
994 | 56, 57, 60, 62, 63, 66, 67, 68,
995 | 69, 70, 73, 76, 77, 78, 79, 82,
996 | 83, 86, 87, 88, 89, 90, 93, 96,
997 | 97, 98, 99, 102, 103, 104, 105, 106,
998 | 109, 110, 111, 112, 115, 116, 118, 119,
999 | 120, 121, 124, 125, 126, 127, 128, 129,
1000 | 130, 133, 137, 138, 139, 140, 143, 144,
1001 | 145, 146, 147, 150, 151, 152, 153, 154,
1002 | 155, 158, 159, 160, 161, 164, 165, 166,
1003 | 167, 170, 175, 176, 177, 178, 179, 182,
1004 | 183, 184, 185, 186, 187, 188, 189, 190,
1005 | 191, 192, 193, 194, 198, 199, 200, 201,
1006 | 202, 205, 206, 207, 210, 211, 212, 213,
1007 | 214, 217, 218, 219, 220, 221, 224, 237,
1008 | 240, 245, 248
1009 | };
1010 |
1011 | static const char _bloopserial_trans_keys[] = {
1012 | 114, 115, 116, 112, 32, 9, 13, 32,
1013 | 45, 9, 13, 48, 57, 48, 57, 46,
1014 | 48, 57, 48, 57, 46, 48, 57, 48,
1015 | 57, 112, 101, 101, 100, 32, 9, 13,
1016 | 116, 97, 99, 107, 32, 9, 13, 101,
1017 | 115, 99, 97, 121, 32, 9, 13, 108,
1018 | 105, 100, 101, 32, 9, 13, 114, 101,
1019 | 113, 32, 9, 13, 112, 115, 102, 32,
1020 | 9, 13, 119, 101, 101, 112, 32, 9,
1021 | 13, 105, 112, 115, 109, 105, 116, 32,
1022 | 9, 13, 102, 32, 9, 13, 119, 101,
1023 | 101, 112, 32, 9, 13, 104, 115, 117,
1024 | 97, 115, 101, 32, 9, 13, 119, 101,
1025 | 101, 112, 32, 9, 13, 110, 99, 104,
1026 | 32, 9, 13, 101, 112, 115, 101, 97,
1027 | 116, 32, 9, 13, 111, 110, 97, 110,
1028 | 99, 101, 32, 9, 13, 108, 113, 117,
1029 | 119, 105, 100, 101, 32, 9, 13, 117,
1030 | 97, 114, 101, 32, 9, 13, 115, 116,
1031 | 97, 105, 110, 32, 9, 13, 101, 101,
1032 | 112, 32, 9, 13, 121, 112, 101, 32,
1033 | 9, 13, 32, 110, 115, 9, 13, 111,
1034 | 105, 115, 101, 97, 105, 113, 119, 116,
1035 | 111, 111, 116, 104, 110, 101, 117, 97,
1036 | 114, 101, 100, 105, 111, 115, 101, 108,
1037 | 97, 121, 32, 9, 13, 98, 101, 32,
1038 | 9, 13, 108, 117, 109, 101, 32, 9,
1039 | 13, 112, 101, 101, 100, 32, 9, 13,
1040 | 32, 97, 100, 102, 104, 108, 112, 114,
1041 | 115, 116, 118, 9, 13, 32, 9, 13,
1042 | 32, 9, 13, 48, 57, 32, 9, 13,
1043 | 32, 9, 13, 48, 57, 0
1044 | };
1045 |
1046 | static const char _bloopserial_single_lengths[] = {
1047 | 0, 3, 1, 1, 2, 0, 1, 0,
1048 | 1, 0, 1, 1, 1, 1, 1, 1,
1049 | 1, 1, 1, 1, 2, 1, 1, 1,
1050 | 1, 1, 1, 1, 1, 1, 1, 1,
1051 | 1, 1, 2, 1, 1, 1, 1, 1,
1052 | 1, 1, 3, 1, 1, 1, 1, 1,
1053 | 1, 1, 1, 1, 1, 1, 3, 1,
1054 | 1, 1, 1, 1, 1, 1, 1, 1,
1055 | 1, 1, 1, 1, 1, 2, 1, 1,
1056 | 1, 1, 1, 1, 1, 1, 1, 1,
1057 | 1, 4, 1, 1, 1, 1, 1, 1,
1058 | 1, 1, 1, 1, 1, 1, 1, 1,
1059 | 1, 1, 1, 1, 1, 1, 1, 1,
1060 | 1, 3, 1, 1, 1, 1, 3, 1,
1061 | 1, 1, 1, 1, 1, 1, 1, 1,
1062 | 1, 1, 1, 4, 1, 1, 1, 1,
1063 | 1, 1, 1, 1, 1, 1, 1, 1,
1064 | 1, 1, 1, 1, 1, 1, 11, 1,
1065 | 1, 1, 1
1066 | };
1067 |
1068 | static const char _bloopserial_range_lengths[] = {
1069 | 0, 0, 0, 1, 2, 1, 1, 1,
1070 | 1, 1, 0, 0, 0, 0, 1, 0,
1071 | 0, 0, 0, 1, 0, 0, 0, 0,
1072 | 1, 0, 0, 0, 0, 1, 0, 0,
1073 | 0, 1, 0, 0, 1, 0, 0, 0,
1074 | 0, 1, 0, 0, 0, 0, 1, 0,
1075 | 1, 0, 0, 0, 0, 1, 0, 0,
1076 | 0, 0, 1, 0, 0, 0, 0, 1,
1077 | 0, 0, 0, 1, 0, 0, 0, 0,
1078 | 0, 1, 0, 0, 0, 0, 0, 0,
1079 | 1, 0, 0, 0, 0, 1, 0, 0,
1080 | 0, 0, 1, 0, 0, 0, 0, 0,
1081 | 1, 0, 0, 0, 1, 0, 0, 0,
1082 | 1, 1, 0, 0, 0, 0, 0, 0,
1083 | 0, 0, 0, 0, 0, 0, 0, 0,
1084 | 0, 0, 0, 0, 0, 0, 0, 0,
1085 | 1, 0, 0, 1, 0, 0, 0, 0,
1086 | 1, 0, 0, 0, 0, 1, 1, 1,
1087 | 2, 1, 2
1088 | };
1089 |
1090 | static const short _bloopserial_index_offsets[] = {
1091 | 0, 0, 4, 6, 9, 14, 16, 19,
1092 | 21, 24, 26, 28, 30, 32, 34, 37,
1093 | 39, 41, 43, 45, 48, 51, 53, 55,
1094 | 57, 60, 62, 64, 66, 68, 71, 73,
1095 | 75, 77, 80, 83, 85, 88, 90, 92,
1096 | 94, 96, 99, 103, 105, 107, 109, 112,
1097 | 114, 117, 119, 121, 123, 125, 128, 132,
1098 | 134, 136, 138, 141, 143, 145, 147, 149,
1099 | 152, 154, 156, 158, 161, 163, 166, 168,
1100 | 170, 172, 175, 177, 179, 181, 183, 185,
1101 | 187, 190, 195, 197, 199, 201, 204, 206,
1102 | 208, 210, 212, 215, 217, 219, 221, 223,
1103 | 225, 228, 230, 232, 234, 237, 239, 241,
1104 | 243, 246, 251, 253, 255, 257, 259, 263,
1105 | 265, 267, 269, 271, 273, 275, 277, 279,
1106 | 281, 283, 285, 287, 292, 294, 296, 298,
1107 | 300, 303, 305, 307, 310, 312, 314, 316,
1108 | 318, 321, 323, 325, 327, 329, 332, 345,
1109 | 348, 352, 355
1110 | };
1111 |
1112 | static const unsigned char _bloopserial_trans_targs[] = {
1113 | 2, 10, 15, 0, 3, 0, 4, 4,
1114 | 0, 4, 5, 4, 8, 0, 6, 0,
1115 | 7, 6, 0, 144, 0, 9, 8, 0,
1116 | 146, 0, 11, 0, 12, 0, 13, 0,
1117 | 14, 0, 4, 4, 0, 16, 0, 17,
1118 | 0, 18, 0, 19, 0, 4, 4, 0,
1119 | 21, 25, 0, 22, 0, 23, 0, 24,
1120 | 0, 4, 4, 0, 26, 0, 27, 0,
1121 | 28, 0, 29, 0, 4, 4, 0, 31,
1122 | 0, 32, 0, 33, 0, 4, 4, 0,
1123 | 35, 37, 0, 36, 0, 4, 4, 0,
1124 | 38, 0, 39, 0, 40, 0, 41, 0,
1125 | 4, 4, 0, 43, 47, 49, 0, 44,
1126 | 0, 45, 0, 46, 0, 4, 4, 0,
1127 | 48, 0, 4, 4, 0, 50, 0, 51,
1128 | 0, 52, 0, 53, 0, 4, 4, 0,
1129 | 55, 59, 64, 0, 56, 0, 57, 0,
1130 | 58, 0, 4, 4, 0, 60, 0, 61,
1131 | 0, 62, 0, 63, 0, 4, 4, 0,
1132 | 65, 0, 66, 0, 67, 0, 4, 4,
1133 | 0, 69, 0, 70, 74, 0, 71, 0,
1134 | 72, 0, 73, 0, 4, 4, 0, 75,
1135 | 0, 76, 0, 77, 0, 78, 0, 79,
1136 | 0, 80, 0, 4, 4, 0, 82, 86,
1137 | 91, 97, 0, 83, 0, 84, 0, 85,
1138 | 0, 4, 4, 0, 87, 0, 88, 0,
1139 | 89, 0, 90, 0, 4, 4, 0, 92,
1140 | 0, 93, 0, 94, 0, 95, 0, 96,
1141 | 0, 4, 4, 0, 98, 0, 99, 0,
1142 | 100, 0, 4, 4, 0, 102, 0, 103,
1143 | 0, 104, 0, 105, 105, 0, 105, 106,
1144 | 110, 105, 0, 107, 0, 108, 0, 109,
1145 | 0, 142, 0, 111, 117, 119, 0, 112,
1146 | 0, 113, 0, 114, 0, 115, 0, 116,
1147 | 0, 142, 0, 118, 0, 142, 0, 120,
1148 | 0, 121, 0, 122, 0, 142, 0, 124,
1149 | 129, 132, 137, 0, 125, 0, 126, 0,
1150 | 127, 0, 128, 0, 4, 4, 0, 130,
1151 | 0, 131, 0, 4, 4, 0, 133, 0,
1152 | 134, 0, 135, 0, 136, 0, 4, 4,
1153 | 0, 138, 0, 139, 0, 140, 0, 141,
1154 | 0, 4, 4, 0, 143, 1, 20, 30,
1155 | 34, 42, 54, 68, 81, 101, 123, 143,
1156 | 0, 143, 143, 142, 145, 145, 144, 142,
1157 | 145, 145, 142, 145, 145, 146, 142, 142,
1158 | 142, 142, 142, 0
1159 | };
1160 |
1161 | static const char _bloopserial_trans_actions[] = {
1162 | 0, 0, 0, 0, 0, 0, 7, 7,
1163 | 0, 0, 0, 0, 0, 0, 0, 0,
1164 | 1, 0, 0, 5, 0, 1, 0, 0,
1165 | 5, 0, 0, 0, 0, 0, 0, 0,
1166 | 0, 0, 9, 9, 0, 0, 0, 0,
1167 | 0, 0, 0, 0, 0, 11, 11, 0,
1168 | 0, 0, 0, 0, 0, 0, 0, 0,
1169 | 0, 13, 13, 0, 0, 0, 0, 0,
1170 | 0, 0, 0, 0, 15, 15, 0, 0,
1171 | 0, 0, 0, 0, 0, 17, 17, 0,
1172 | 0, 0, 0, 0, 0, 19, 19, 0,
1173 | 0, 0, 0, 0, 0, 0, 0, 0,
1174 | 21, 21, 0, 0, 0, 0, 0, 0,
1175 | 0, 0, 0, 0, 0, 23, 23, 0,
1176 | 0, 0, 25, 25, 0, 0, 0, 0,
1177 | 0, 0, 0, 0, 0, 27, 27, 0,
1178 | 0, 0, 0, 0, 0, 0, 0, 0,
1179 | 0, 0, 29, 29, 0, 0, 0, 0,
1180 | 0, 0, 0, 0, 0, 31, 31, 0,
1181 | 0, 0, 0, 0, 0, 0, 45, 45,
1182 | 0, 0, 0, 0, 0, 0, 0, 0,
1183 | 0, 0, 0, 0, 33, 33, 0, 0,
1184 | 0, 0, 0, 0, 0, 0, 0, 0,
1185 | 0, 0, 0, 35, 35, 0, 0, 0,
1186 | 0, 0, 0, 0, 0, 0, 0, 0,
1187 | 0, 37, 37, 0, 0, 0, 0, 0,
1188 | 0, 0, 0, 0, 39, 39, 0, 0,
1189 | 0, 0, 0, 0, 0, 0, 0, 0,
1190 | 0, 41, 41, 0, 0, 0, 0, 0,
1191 | 0, 0, 43, 43, 0, 0, 0, 0,
1192 | 0, 0, 0, 0, 0, 0, 0, 0,
1193 | 0, 0, 0, 0, 0, 0, 0, 0,
1194 | 0, 63, 0, 0, 0, 0, 0, 0,
1195 | 0, 0, 0, 0, 0, 0, 0, 0,
1196 | 0, 59, 0, 0, 0, 61, 0, 0,
1197 | 0, 0, 0, 0, 0, 57, 0, 0,
1198 | 0, 0, 0, 0, 0, 0, 0, 0,
1199 | 0, 0, 0, 0, 51, 51, 0, 0,
1200 | 0, 0, 0, 47, 47, 0, 0, 0,
1201 | 0, 0, 0, 0, 0, 0, 75, 75,
1202 | 0, 0, 0, 0, 0, 0, 0, 0,
1203 | 0, 49, 49, 0, 0, 0, 0, 0,
1204 | 0, 0, 0, 0, 0, 0, 0, 0,
1205 | 0, 0, 0, 67, 69, 69, 0, 78,
1206 | 0, 0, 65, 3, 3, 0, 72, 67,
1207 | 78, 65, 72, 0
1208 | };
1209 |
1210 | static const char _bloopserial_to_state_actions[] = {
1211 | 0, 0, 0, 0, 0, 0, 0, 0,
1212 | 0, 0, 0, 0, 0, 0, 0, 0,
1213 | 0, 0, 0, 0, 0, 0, 0, 0,
1214 | 0, 0, 0, 0, 0, 0, 0, 0,
1215 | 0, 0, 0, 0, 0, 0, 0, 0,
1216 | 0, 0, 0, 0, 0, 0, 0, 0,
1217 | 0, 0, 0, 0, 0, 0, 0, 0,
1218 | 0, 0, 0, 0, 0, 0, 0, 0,
1219 | 0, 0, 0, 0, 0, 0, 0, 0,
1220 | 0, 0, 0, 0, 0, 0, 0, 0,
1221 | 0, 0, 0, 0, 0, 0, 0, 0,
1222 | 0, 0, 0, 0, 0, 0, 0, 0,
1223 | 0, 0, 0, 0, 0, 0, 0, 0,
1224 | 0, 0, 0, 0, 0, 0, 0, 0,
1225 | 0, 0, 0, 0, 0, 0, 0, 0,
1226 | 0, 0, 0, 0, 0, 0, 0, 0,
1227 | 0, 0, 0, 0, 0, 0, 0, 0,
1228 | 0, 0, 0, 0, 0, 0, 53, 0,
1229 | 0, 0, 0
1230 | };
1231 |
1232 | static const char _bloopserial_from_state_actions[] = {
1233 | 0, 0, 0, 0, 0, 0, 0, 0,
1234 | 0, 0, 0, 0, 0, 0, 0, 0,
1235 | 0, 0, 0, 0, 0, 0, 0, 0,
1236 | 0, 0, 0, 0, 0, 0, 0, 0,
1237 | 0, 0, 0, 0, 0, 0, 0, 0,
1238 | 0, 0, 0, 0, 0, 0, 0, 0,
1239 | 0, 0, 0, 0, 0, 0, 0, 0,
1240 | 0, 0, 0, 0, 0, 0, 0, 0,
1241 | 0, 0, 0, 0, 0, 0, 0, 0,
1242 | 0, 0, 0, 0, 0, 0, 0, 0,
1243 | 0, 0, 0, 0, 0, 0, 0, 0,
1244 | 0, 0, 0, 0, 0, 0, 0, 0,
1245 | 0, 0, 0, 0, 0, 0, 0, 0,
1246 | 0, 0, 0, 0, 0, 0, 0, 0,
1247 | 0, 0, 0, 0, 0, 0, 0, 0,
1248 | 0, 0, 0, 0, 0, 0, 0, 0,
1249 | 0, 0, 0, 0, 0, 0, 0, 0,
1250 | 0, 0, 0, 0, 0, 0, 55, 0,
1251 | 0, 0, 0
1252 | };
1253 |
1254 | static const short _bloopserial_eof_trans[] = {
1255 | 0, 0, 0, 0, 0, 0, 0, 0,
1256 | 0, 0, 0, 0, 0, 0, 0, 0,
1257 | 0, 0, 0, 0, 0, 0, 0, 0,
1258 | 0, 0, 0, 0, 0, 0, 0, 0,
1259 | 0, 0, 0, 0, 0, 0, 0, 0,
1260 | 0, 0, 0, 0, 0, 0, 0, 0,
1261 | 0, 0, 0, 0, 0, 0, 0, 0,
1262 | 0, 0, 0, 0, 0, 0, 0, 0,
1263 | 0, 0, 0, 0, 0, 0, 0, 0,
1264 | 0, 0, 0, 0, 0, 0, 0, 0,
1265 | 0, 0, 0, 0, 0, 0, 0, 0,
1266 | 0, 0, 0, 0, 0, 0, 0, 0,
1267 | 0, 0, 0, 0, 0, 0, 0, 0,
1268 | 0, 0, 0, 0, 0, 0, 0, 0,
1269 | 0, 0, 0, 0, 0, 0, 0, 0,
1270 | 0, 0, 0, 0, 0, 0, 0, 0,
1271 | 0, 0, 0, 0, 0, 0, 0, 0,
1272 | 0, 0, 0, 0, 0, 0, 0, 360,
1273 | 361, 362, 363
1274 | };
1275 |
1276 | static const int bloopserial_start = 142;
1277 | static const int bloopserial_error = 0;
1278 |
1279 | static const int bloopserial_en_main = 142;
1280 |
1281 | #line 446 "c/notation.rl"
1282 |
1283 |
1284 | bloopsaphone *
1285 | bloops_sound_file(bloops *B, char *fname)
1286 | {
1287 | FILE *fp;
1288 | struct stat stats;
1289 | int cs, act, len;
1290 | float fval;
1291 | void *key;
1292 | char *str, *p, *pe, *pf, *ts, *te, *eof = 0;
1293 | bloopsaphone *P;
1294 |
1295 | if (stat(fname, &stats) == -1)
1296 | return NULL;
1297 |
1298 | fp = fopen(fname, "rb");
1299 | if (!fp)
1300 | return NULL;
1301 |
1302 | len = stats.st_size;
1303 | str = (char *)malloc(stats.st_size + 1);
1304 | if (fread(str, 1, stats.st_size, fp) != stats.st_size)
1305 | goto done;
1306 |
1307 | p = str;
1308 | pe = str + len + 1;
1309 | p[len] = '\0';
1310 |
1311 | P = bloops_square();
1312 |
1313 | #line 1314 "c/notation.c"
1314 | {
1315 | cs = bloopserial_start;
1316 | ts = 0;
1317 | te = 0;
1318 | act = 0;
1319 | }
1320 | #line 477 "c/notation.rl"
1321 |
1322 | #line 1323 "c/notation.c"
1323 | {
1324 | int _klen;
1325 | unsigned int _trans;
1326 | const char *_acts;
1327 | unsigned int _nacts;
1328 | const char *_keys;
1329 |
1330 | if ( p == pe )
1331 | goto _test_eof;
1332 | if ( cs == 0 )
1333 | goto _out;
1334 | _resume:
1335 | _acts = _bloopserial_actions + _bloopserial_from_state_actions[cs];
1336 | _nacts = (unsigned int) *_acts++;
1337 | while ( _nacts-- > 0 ) {
1338 | switch ( *_acts++ ) {
1339 | case 30:
1340 | #line 1 "c/notation.rl"
1341 | {ts = p;}
1342 | break;
1343 | #line 1344 "c/notation.c"
1344 | }
1345 | }
1346 |
1347 | _keys = _bloopserial_trans_keys + _bloopserial_key_offsets[cs];
1348 | _trans = _bloopserial_index_offsets[cs];
1349 |
1350 | _klen = _bloopserial_single_lengths[cs];
1351 | if ( _klen > 0 ) {
1352 | const char *_lower = _keys;
1353 | const char *_mid;
1354 | const char *_upper = _keys + _klen - 1;
1355 | while (1) {
1356 | if ( _upper < _lower )
1357 | break;
1358 |
1359 | _mid = _lower + ((_upper-_lower) >> 1);
1360 | if ( (*p) < *_mid )
1361 | _upper = _mid - 1;
1362 | else if ( (*p) > *_mid )
1363 | _lower = _mid + 1;
1364 | else {
1365 | _trans += (_mid - _keys);
1366 | goto _match;
1367 | }
1368 | }
1369 | _keys += _klen;
1370 | _trans += _klen;
1371 | }
1372 |
1373 | _klen = _bloopserial_range_lengths[cs];
1374 | if ( _klen > 0 ) {
1375 | const char *_lower = _keys;
1376 | const char *_mid;
1377 | const char *_upper = _keys + (_klen<<1) - 2;
1378 | while (1) {
1379 | if ( _upper < _lower )
1380 | break;
1381 |
1382 | _mid = _lower + (((_upper-_lower) >> 1) & ~1);
1383 | if ( (*p) < _mid[0] )
1384 | _upper = _mid - 2;
1385 | else if ( (*p) > _mid[1] )
1386 | _lower = _mid + 2;
1387 | else {
1388 | _trans += ((_mid - _keys)>>1);
1389 | goto _match;
1390 | }
1391 | }
1392 | _trans += _klen;
1393 | }
1394 |
1395 | _match:
1396 | _eof_trans:
1397 | cs = _bloopserial_trans_targs[_trans];
1398 |
1399 | if ( _bloopserial_trans_actions[_trans] == 0 )
1400 | goto _again;
1401 |
1402 | _acts = _bloopserial_actions + _bloopserial_trans_actions[_trans];
1403 | _nacts = (unsigned int) *_acts++;
1404 | while ( _nacts-- > 0 )
1405 | {
1406 | switch ( *_acts++ )
1407 | {
1408 | case 0:
1409 | #line 400 "c/notation.rl"
1410 | {
1411 | fval = ATOI(ts, p - ts) * 1.0f;
1412 | }
1413 | break;
1414 | case 1:
1415 | #line 404 "c/notation.rl"
1416 | {
1417 | fval = ATOI(pf, p - pf) * pow(0.1f, p - pf);
1418 | }
1419 | break;
1420 | case 2:
1421 | #line 408 "c/notation.rl"
1422 | { pf = p; }
1423 | break;
1424 | case 3:
1425 | #line 409 "c/notation.rl"
1426 | { fval *= -1.0f; }
1427 | break;
1428 | case 4:
1429 | #line 410 "c/notation.rl"
1430 | { KEY(volume); }
1431 | break;
1432 | case 5:
1433 | #line 411 "c/notation.rl"
1434 | { KEY(arp); }
1435 | break;
1436 | case 6:
1437 | #line 412 "c/notation.rl"
1438 | { KEY(aspeed); }
1439 | break;
1440 | case 7:
1441 | #line 413 "c/notation.rl"
1442 | { KEY(attack); }
1443 | break;
1444 | case 8:
1445 | #line 414 "c/notation.rl"
1446 | { KEY(decay); }
1447 | break;
1448 | case 9:
1449 | #line 415 "c/notation.rl"
1450 | { KEY(dslide); }
1451 | break;
1452 | case 10:
1453 | #line 416 "c/notation.rl"
1454 | { KEY(freq); }
1455 | break;
1456 | case 11:
1457 | #line 417 "c/notation.rl"
1458 | { KEY(hpf); }
1459 | break;
1460 | case 12:
1461 | #line 418 "c/notation.rl"
1462 | { KEY(hsweep); }
1463 | break;
1464 | case 13:
1465 | #line 419 "c/notation.rl"
1466 | { KEY(limit); }
1467 | break;
1468 | case 14:
1469 | #line 420 "c/notation.rl"
1470 | { KEY(lpf); }
1471 | break;
1472 | case 15:
1473 | #line 421 "c/notation.rl"
1474 | { KEY(lsweep); }
1475 | break;
1476 | case 16:
1477 | #line 422 "c/notation.rl"
1478 | { KEY(phase); }
1479 | break;
1480 | case 17:
1481 | #line 423 "c/notation.rl"
1482 | { KEY(psweep); }
1483 | break;
1484 | case 18:
1485 | #line 424 "c/notation.rl"
1486 | { KEY(repeat); }
1487 | break;
1488 | case 19:
1489 | #line 425 "c/notation.rl"
1490 | { KEY(resonance); }
1491 | break;
1492 | case 20:
1493 | #line 426 "c/notation.rl"
1494 | { KEY(slide); }
1495 | break;
1496 | case 21:
1497 | #line 427 "c/notation.rl"
1498 | { KEY(square); }
1499 | break;
1500 | case 22:
1501 | #line 428 "c/notation.rl"
1502 | { KEY(sustain); }
1503 | break;
1504 | case 23:
1505 | #line 429 "c/notation.rl"
1506 | { KEY(sweep); }
1507 | break;
1508 | case 24:
1509 | #line 430 "c/notation.rl"
1510 | { KEY(punch); }
1511 | break;
1512 | case 25:
1513 | #line 431 "c/notation.rl"
1514 | { KEY(vibe); }
1515 | break;
1516 | case 26:
1517 | #line 432 "c/notation.rl"
1518 | { KEY(vspeed); }
1519 | break;
1520 | case 27:
1521 | #line 433 "c/notation.rl"
1522 | { KEY(vdelay); }
1523 | break;
1524 | case 28:
1525 | #line 434 "c/notation.rl"
1526 | { KEY(volume); }
1527 | break;
1528 | case 31:
1529 | #line 438 "c/notation.rl"
1530 | {te = p+1;{ P->params.type = BLOOPS_SQUARE; }}
1531 | break;
1532 | case 32:
1533 | #line 439 "c/notation.rl"
1534 | {te = p+1;{ P->params.type = BLOOPS_SAWTOOTH; }}
1535 | break;
1536 | case 33:
1537 | #line 440 "c/notation.rl"
1538 | {te = p+1;{ P->params.type = BLOOPS_SINE; }}
1539 | break;
1540 | case 34:
1541 | #line 441 "c/notation.rl"
1542 | {te = p+1;{ P->params.type = BLOOPS_NOISE; }}
1543 | break;
1544 | case 35:
1545 | #line 437 "c/notation.rl"
1546 | {te = p;p--;{ *((float *)key) = fval; }}
1547 | break;
1548 | case 36:
1549 | #line 442 "c/notation.rl"
1550 | {te = p;p--;}
1551 | break;
1552 | #line 1553 "c/notation.c"
1553 | }
1554 | }
1555 |
1556 | _again:
1557 | _acts = _bloopserial_actions + _bloopserial_to_state_actions[cs];
1558 | _nacts = (unsigned int) *_acts++;
1559 | while ( _nacts-- > 0 ) {
1560 | switch ( *_acts++ ) {
1561 | case 29:
1562 | #line 1 "c/notation.rl"
1563 | {ts = 0;}
1564 | break;
1565 | #line 1566 "c/notation.c"
1566 | }
1567 | }
1568 |
1569 | if ( cs == 0 )
1570 | goto _out;
1571 | if ( ++p != pe )
1572 | goto _resume;
1573 | _test_eof: {}
1574 | if ( p == eof )
1575 | {
1576 | if ( _bloopserial_eof_trans[cs] > 0 ) {
1577 | _trans = _bloopserial_eof_trans[cs] - 1;
1578 | goto _eof_trans;
1579 | }
1580 | }
1581 |
1582 | _out: {}
1583 | }
1584 | #line 478 "c/notation.rl"
1585 |
1586 | done:
1587 | fclose(fp);
1588 | return P;
1589 | }
1590 |
1591 | char *
1592 | bloops_sound_str(bloopsaphone *P)
1593 | {
1594 | char *lines = (char *)malloc(4096), *str = lines;
1595 | bloopsaphone *sq = bloops_square();
1596 | if (P->params.type == BLOOPS_SQUARE)
1597 | str += sprintf(str, "type square\n");
1598 | else if (P->params.type == BLOOPS_SAWTOOTH)
1599 | str += sprintf(str, "type sawtooth\n");
1600 | else if (P->params.type == BLOOPS_SINE)
1601 | str += sprintf(str, "type sine\n");
1602 | else if (P->params.type == BLOOPS_NOISE)
1603 | str += sprintf(str, "type noise\n");
1604 |
1605 | if (P->params.volume != sq->params.volume)
1606 | str += sprintf(str, "volume %0.3f\n", P->params.volume);
1607 | if (P->params.punch != sq->params.punch)
1608 | str += sprintf(str, "punch %0.3f\n", P->params.punch);
1609 | if (P->params.attack != sq->params.attack)
1610 | str += sprintf(str, "attack %0.3f\n", P->params.attack);
1611 | if (P->params.sustain != sq->params.sustain)
1612 | str += sprintf(str, "sustain %0.3f\n", P->params.sustain);
1613 | if (P->params.decay != sq->params.decay)
1614 | str += sprintf(str, "decay %0.3f\n", P->params.decay);
1615 | if (P->params.freq != sq->params.freq)
1616 | str += sprintf(str, "freq %0.3f\n", P->params.freq);
1617 | if (P->params.limit != sq->params.limit)
1618 | str += sprintf(str, "limit %0.3f\n", P->params.limit);
1619 | if (P->params.slide != sq->params.slide)
1620 | str += sprintf(str, "slide %0.3f\n", P->params.slide);
1621 | if (P->params.dslide != sq->params.dslide)
1622 | str += sprintf(str, "dslide %0.3f\n", P->params.dslide);
1623 | if (P->params.square != sq->params.square)
1624 | str += sprintf(str, "square %0.3f\n", P->params.square);
1625 | if (P->params.sweep != sq->params.sweep)
1626 | str += sprintf(str, "sweep %0.3f\n", P->params.sweep);
1627 | if (P->params.vibe != sq->params.vibe)
1628 | str += sprintf(str, "vibe %0.3f\n", P->params.vibe);
1629 | if (P->params.vspeed != sq->params.vspeed)
1630 | str += sprintf(str, "vspeed %0.3f\n", P->params.vspeed);
1631 | if (P->params.vdelay != sq->params.vdelay)
1632 | str += sprintf(str, "vdelay %0.3f\n", P->params.vdelay);
1633 | if (P->params.lpf != sq->params.lpf)
1634 | str += sprintf(str, "lpf %0.3f\n", P->params.lpf);
1635 | if (P->params.lsweep != sq->params.lsweep)
1636 | str += sprintf(str, "lsweep %0.3f\n", P->params.lsweep);
1637 | if (P->params.resonance != sq->params.resonance)
1638 | str += sprintf(str, "resonance %0.3f\n", P->params.resonance);
1639 | if (P->params.hpf != sq->params.hpf)
1640 | str += sprintf(str, "hpf %0.3f\n", P->params.hpf);
1641 | if (P->params.hsweep != sq->params.hsweep)
1642 | str += sprintf(str, "hsweep %0.3f\n", P->params.hsweep);
1643 | if (P->params.arp != sq->params.arp)
1644 | str += sprintf(str, "arp %0.3f\n", P->params.arp);
1645 | if (P->params.aspeed != sq->params.aspeed)
1646 | str += sprintf(str, "aspeed %0.3f\n", P->params.aspeed);
1647 | if (P->params.phase != sq->params.phase)
1648 | str += sprintf(str, "phase %0.3f\n", P->params.phase);
1649 | if (P->params.psweep != sq->params.psweep)
1650 | str += sprintf(str, "psweep %0.3f\n", P->params.psweep);
1651 | if (P->params.repeat != sq->params.repeat)
1652 | str += sprintf(str, "repeat %0.3f\n", P->params.repeat);
1653 |
1654 | bloops_sound_destroy(sq);
1655 | return lines;
1656 | }
1657 |
--------------------------------------------------------------------------------
/c/notation.rl:
--------------------------------------------------------------------------------
1 | //
2 | // notation.rl
3 | // the musical notation parser
4 | //
5 | // (c) 2009 why the lucky stiff
6 | // See COPYING for the license
7 | //
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include "bloopsaphone.h"
14 |
15 | #define ATOI(X,N) ({ \
16 | char *Ap = X; \
17 | int Ai = 0; \
18 | size_t Al = N; \
19 | while (Al--) { \
20 | if ((*Ap >= '0') && (*Ap <= '9')) { \
21 | Ai = (Ai * 10) + (*Ap - '0'); \
22 | Ap++; \
23 | } \
24 | else break; \
25 | } \
26 | Ai; \
27 | })
28 |
29 | #define NOTE S->notes[S->nlen]
30 |
31 | #define NEXT() \
32 | NOTE.duration = len; \
33 | NOTE.octave = oct; \
34 | mod = 0; \
35 | tone = 0; \
36 | len = 4; \
37 | fxval = 0; \
38 | fxmod = 0; \
39 | S->nlen++
40 |
41 | %%{
42 | machine bloopnotes;
43 |
44 | action Alen {
45 | len = ATOI(ts, p - ts);
46 | }
47 |
48 | action Aoct {
49 | oct = ATOI(p - 1, 1);
50 | }
51 |
52 | action Anote {
53 | switch (tone) {
54 | case 'a': case 'A':
55 | if (mod == 'b') NOTE.tone = 'a';
56 | else if (mod == '#') NOTE.tone = 'b';
57 | else NOTE.tone = 'A';
58 | break;
59 | case 'b': case 'B':
60 | if (mod == 'b') NOTE.tone = 'b';
61 | else if (mod == '#') NOTE.tone = 'C';
62 | else NOTE.tone = 'B';
63 | break;
64 | case 'c': case 'C':
65 | if (mod == 'b') NOTE.tone = 'B';
66 | else if (mod == '#') NOTE.tone = 'd';
67 | else NOTE.tone = 'C';
68 | break;
69 | case 'd': case 'D':
70 | if (mod == 'b') NOTE.tone = 'd';
71 | else if (mod == '#') NOTE.tone = 'e';
72 | else NOTE.tone = 'D';
73 | break;
74 | case 'e': case 'E':
75 | if (mod == 'b') NOTE.tone = 'e';
76 | else if (mod == '#') NOTE.tone = 'F';
77 | else NOTE.tone = 'E';
78 | break;
79 | case 'f': case 'F':
80 | if (mod == 'b') NOTE.tone = 'E';
81 | else if (mod == '#') NOTE.tone = 'g';
82 | else NOTE.tone = 'F';
83 | break;
84 | case 'g': case 'G':
85 | if (mod == 'b') NOTE.tone = 'g';
86 | else if (mod == '#') NOTE.tone = 'a';
87 | else NOTE.tone = 'G';
88 | break;
89 | }
90 | }
91 |
92 | action Afx {
93 | bloopsafx *fx = (bloopsafx *)malloc(sizeof(bloopsafx));
94 | fx->next = NOTE.FX;
95 | fx->cmd = fxcmd;
96 | fx->val = fxval;
97 | fx->mod = fxmod;
98 | fxval = fxmod = 0;
99 | NOTE.FX = fx;
100 | }
101 |
102 | action fxval1 {
103 | fxval = atoi(p-1) * 1.0f;
104 | }
105 |
106 | action fxval2 {
107 | fxval += ATOI(pf, p - pf) * pow(0.1f, p - pf);
108 | }
109 |
110 | dec = digit+ %fxval1 ("." %{ pf = p; } digit+ )? %fxval2;
111 | float = ("-" dec %{ fxval *= -1.0f; } | dec);
112 | fxcmd = "volume" %{ fxcmd = BLOOPS_FX_VOLUME; } |
113 | "punch" %{ fxcmd = BLOOPS_FX_PUNCH; } |
114 | "attack" %{ fxcmd = BLOOPS_FX_ATTACK; } |
115 | "sustain" %{ fxcmd = BLOOPS_FX_SUSTAIN; } |
116 | "decay" %{ fxcmd = BLOOPS_FX_DECAY; } |
117 | "square" %{ fxcmd = BLOOPS_FX_SQUARE; } |
118 | "sweep" %{ fxcmd = BLOOPS_FX_SWEEP; } |
119 | "vibe" %{ fxcmd = BLOOPS_FX_VIBE; } |
120 | "vspeed" %{ fxcmd = BLOOPS_FX_VSPEED; } |
121 | "vdelay" %{ fxcmd = BLOOPS_FX_VDELAY; } |
122 | "lpf" %{ fxcmd = BLOOPS_FX_LPF; } |
123 | "lsweep" %{ fxcmd = BLOOPS_FX_LSWEEP; } |
124 | "resonance" %{ fxcmd = BLOOPS_FX_RESONANCE; } |
125 | "hpf" %{ fxcmd = BLOOPS_FX_HPF; } |
126 | "hsweep" %{ fxcmd = BLOOPS_FX_HSWEEP; } |
127 | "arp" %{ fxcmd = BLOOPS_FX_ARP; } |
128 | "aspeed" %{ fxcmd = BLOOPS_FX_ASPEED; } |
129 | "phase" %{ fxcmd = BLOOPS_FX_PHASE; } |
130 | "psweep" %{ fxcmd = BLOOPS_FX_PSWEEP; } |
131 | "repeat" %{ fxcmd = BLOOPS_FX_REPEAT; };
132 |
133 | len = [1-9] [0-9]? ":"? %Alen;
134 | up = "+" %{ len = 1; } len?;
135 | down = "-" %{ len = 1; } len?;
136 | mod = [b#] %{ mod = p[-1]; };
137 | oct = [1-8] %Aoct;
138 | fxmod = ( ("+"|"-") %{ fxmod = p[-1]; } (":"|space+) )?;
139 | fx = ("[" fxcmd (":"|space*) fxmod float "]" %Afx );
140 | note = len? [a-gA-G] %{ tone = p[-1]; } mod? oct? fx* %Anote;
141 |
142 | main := |*
143 | len => {
144 | NOTE.tone = 0;
145 | NEXT();
146 | };
147 | note => { NEXT(); };
148 | up => { oct++; len = 4; };
149 | down => { oct--; len = 4; };
150 | space;
151 | *|;
152 |
153 | write data nofinal;
154 | }%%
155 |
156 | extern void _bloops_track_add(bloops *B, bloopsatrack *track);
157 |
158 | bloopsatrack *
159 | bloops_track(bloops *B, bloopsaphone *P, char *track, int tracklen)
160 | {
161 | int cs, act, oct = 4, len = 4;
162 | bloopsatrack *S = (bloopsatrack *)malloc(sizeof(bloopsatrack));
163 | char tone, mod, fxmod, *p, *pe, *pf, *ts, *te, *eof = 0;
164 | bloopsafxcmd fxcmd = (bloopsafxcmd)0;
165 | float fxval = 0;
166 |
167 | S->refcount = 1;
168 | S->nlen = 0;
169 | S->capa = 1024;
170 | S->notes = (bloopsanote *)calloc(sizeof(bloopsanote), 1024);
171 |
172 | p = track;
173 | pe = track + tracklen + 1;
174 |
175 | %% write init;
176 | %% write exec;
177 |
178 | memcpy(&S->params, &P->params, sizeof(bloopsaparams));
179 |
180 | _bloops_track_add(B, S);
181 |
182 | return S;
183 | }
184 |
185 | bloopsatrack *
186 | bloops_track2(bloops *B, bloopsaphone *P, char *track)
187 | {
188 | return bloops_track(B, P, track, strlen(track));
189 | }
190 |
191 | char *
192 | bloops_track_str(bloopsatrack *track)
193 | {
194 | int bufsize = sizeof(char) * (track->nlen * 6 + 1024);
195 | char *str = (char *)malloc(bufsize), *ptr = str;
196 | int i, adv = 0;
197 |
198 | for (i = 0; i < track->nlen; i++)
199 | {
200 | if (ptr - str + adv + sizeof(char) * 256 > bufsize) {
201 | char *new_str;
202 | bufsize += sizeof(char) * 1024;
203 | new_str = realloc(str, bufsize);
204 | if (new_str == NULL) {
205 | free(str);
206 | return NULL;
207 | }
208 | }
209 |
210 | if (ptr > str)
211 | strcat(ptr++, " ");
212 |
213 | if (track->notes[i].duration != 4)
214 | {
215 | adv = sprintf(ptr, "%d:", (int)track->notes[i].duration);
216 | ptr += adv;
217 | }
218 |
219 | if (track->notes[i].tone)
220 | {
221 | char tone[3] = "\0\0\0";
222 | tone[0] = track->notes[i].tone;
223 | switch (tone[0]) {
224 | case 'a': tone[0] = 'A'; tone[1] = 'b'; break;
225 | case 'b': tone[0] = 'B'; tone[1] = 'b'; break;
226 | case 'd': tone[0] = 'C'; tone[1] = '#'; break;
227 | case 'e': tone[0] = 'E'; tone[1] = 'b'; break;
228 | case 'g': tone[0] = 'F'; tone[1] = '#'; break;
229 | }
230 | adv = sprintf(ptr, "%s", tone);
231 | ptr += adv;
232 |
233 | adv = sprintf(ptr, "%d", (int)track->notes[i].octave);
234 | ptr += adv;
235 | bloopsafx *fx = (bloopsafx *)track->notes[i].FX;
236 | while (fx) {
237 | if (fx->mod == 0)
238 | adv = sprintf(ptr, "[%s %0.3f]", bloops_fxcmd_name(fx->cmd), fx->val);
239 | else
240 | adv = sprintf(ptr, "[%s %c %0.3f]", bloops_fxcmd_name(fx->cmd), fx->mod, fx->val);
241 | ptr += adv;
242 | fx = (bloopsafx *)fx->next;
243 | }
244 | }
245 | }
246 |
247 | return str;
248 | }
249 |
250 | char *
251 | bloops_fxcmd_name(bloopsafxcmd fxcmd) {
252 | char *fxname = "\0";
253 | switch (fxcmd) {
254 | case BLOOPS_FX_VOLUME: fxname = "volume"; break;
255 | case BLOOPS_FX_PUNCH: fxname = "punch"; break;
256 | case BLOOPS_FX_ATTACK: fxname = "attack"; break;
257 | case BLOOPS_FX_SUSTAIN: fxname = "sustain"; break;
258 | case BLOOPS_FX_DECAY: fxname = "decay"; break;
259 | case BLOOPS_FX_SQUARE: fxname = "square"; break;
260 | case BLOOPS_FX_SWEEP: fxname = "sweep"; break;
261 | case BLOOPS_FX_VIBE: fxname = "vibe"; break;
262 | case BLOOPS_FX_VSPEED: fxname = "vspeed"; break;
263 | case BLOOPS_FX_VDELAY: fxname = "vdelay"; break;
264 | case BLOOPS_FX_LPF: fxname = "lpf"; break;
265 | case BLOOPS_FX_LSWEEP: fxname = "lsweep"; break;
266 | case BLOOPS_FX_RESONANCE: fxname = "resonance"; break;
267 | case BLOOPS_FX_HPF: fxname = "hpf"; break;
268 | case BLOOPS_FX_HSWEEP: fxname = "hsweep"; break;
269 | case BLOOPS_FX_ARP: fxname = "arp"; break;
270 | case BLOOPS_FX_ASPEED: fxname = "aspeed"; break;
271 | case BLOOPS_FX_PHASE: fxname = "phase"; break;
272 | case BLOOPS_FX_PSWEEP: fxname = "psweep"; break;
273 | case BLOOPS_FX_REPEAT: fxname = "repeat"; break;
274 | }
275 | return fxname;
276 | }
277 |
278 | float
279 | bloops_note_freq(char note, int octave)
280 | {
281 | switch (note)
282 | {
283 | case 'A': // A
284 | if (octave <= 0) return 0.0;
285 | else if (octave == 1) return 0.121;
286 | else if (octave == 2) return 0.175;
287 | else if (octave == 3) return 0.248;
288 | else if (octave == 4) return 0.353;
289 | else if (octave == 5) return 0.500;
290 | break;
291 |
292 | case 'b': // A# or Bb
293 | if (octave <= 0) return 0.0;
294 | else if (octave == 1) return 0.125;
295 | else if (octave == 2) return 0.181;
296 | else if (octave == 3) return 0.255;
297 | else if (octave == 4) return 0.364;
298 | else if (octave == 5) return 0.515;
299 | break;
300 |
301 | case 'B': // B
302 | if (octave <= 0) return 0.0;
303 | else if (octave == 1) return 0.129;
304 | else if (octave == 2) return 0.187;
305 | else if (octave == 3) return 0.263;
306 | else if (octave == 4) return 0.374;
307 | else if (octave == 5) return 0.528;
308 | break;
309 |
310 | case 'C': // C
311 | if (octave <= 1) return 0.0;
312 | else if (octave == 2) return 0.133;
313 | else if (octave == 3) return 0.192;
314 | else if (octave == 4) return 0.271;
315 | else if (octave == 5) return 0.385;
316 | else if (octave == 6) return 0.544;
317 | break;
318 |
319 | case 'd': // C# or Db
320 | if (octave <= 1) return 0.0;
321 | else if (octave == 2) return 0.138;
322 | else if (octave == 3) return 0.198;
323 | else if (octave == 4) return 0.279;
324 | else if (octave == 5) return 0.395;
325 | else if (octave == 6) return 0.559;
326 | break;
327 |
328 | case 'D': // D
329 | if (octave <= 1) return 0.0;
330 | else if (octave == 2) return 0.143;
331 | else if (octave == 3) return 0.202;
332 | else if (octave == 4) return 0.287;
333 | else if (octave == 5) return 0.406;
334 | else if (octave == 6) return 0.575;
335 | break;
336 |
337 | case 'e': // D# or Eb
338 | if (octave <= 1) return 0.0;
339 | else if (octave == 2) return 0.148;
340 | else if (octave == 3) return 0.208;
341 | else if (octave == 4) return 0.296;
342 | else if (octave == 5) return 0.418;
343 | else if (octave == 6) return 0.593;
344 | break;
345 |
346 | case 'E': // E
347 | if (octave <= 1) return 0.0;
348 | else if (octave == 2) return 0.152;
349 | else if (octave == 3) return 0.214;
350 | else if (octave == 4) return 0.305;
351 | else if (octave == 5) return 0.429;
352 | else if (octave == 6) return 0.608;
353 | break;
354 |
355 | case 'F': // F
356 | if (octave <= 1) return 0.0;
357 | else if (octave == 2) return 0.155;
358 | else if (octave == 3) return 0.220;
359 | else if (octave == 4) return 0.314;
360 | else if (octave == 5) return 0.441;
361 | break;
362 |
363 | case 'g': // F# or Gb
364 | if (octave <= 1) return 0.0;
365 | else if (octave == 2) return 0.160;
366 | else if (octave == 3) return 0.227;
367 | else if (octave == 4) return 0.323;
368 | else if (octave == 5) return 0.454;
369 | break;
370 |
371 | case 'G': // G
372 | if (octave <= 1) return 0.0;
373 | else if (octave == 2) return 0.164;
374 | else if (octave == 3) return 0.234;
375 | else if (octave == 4) return 0.332;
376 | else if (octave == 5) return 0.468;
377 | break;
378 |
379 | case 'a': // G# or Ab
380 | if (octave <= 1) return 0.117;
381 | else if (octave == 2) return 0.170;
382 | else if (octave == 3) return 0.242;
383 | else if (octave == 4) return 0.343;
384 | else if (octave == 5) return 0.485;
385 | break;
386 | }
387 |
388 | return 0.0;
389 | }
390 |
391 | #define KEY(name) key = (void *)&P->params.name
392 |
393 | %%{
394 | machine bloopserial;
395 |
396 | action ival {
397 | ival = ATOI(ts, p - ts);
398 | }
399 |
400 | action fval1 {
401 | fval = ATOI(ts, p - ts) * 1.0f;
402 | }
403 |
404 | action fval2 {
405 | fval = ATOI(pf, p - pf) * pow(0.1f, p - pf);
406 | }
407 |
408 | dec = [0-9]+ %fval1 "." %{ pf = p; } [0-9]+ %fval2;
409 | float = ("-" dec %{ fval *= -1.0f; } | dec);
410 | key = "volume" %{ KEY(volume); } |
411 | "arp" %{ KEY(arp); } |
412 | "aspeed" %{ KEY(aspeed); } |
413 | "attack" %{ KEY(attack); } |
414 | "decay" %{ KEY(decay); } |
415 | "dslide" %{ KEY(dslide); } |
416 | "freq" %{ KEY(freq); } |
417 | "hpf" %{ KEY(hpf); } |
418 | "hsweep" %{ KEY(hsweep); } |
419 | "limit" %{ KEY(limit); } |
420 | "lpf" %{ KEY(lpf); } |
421 | "lsweep" %{ KEY(lsweep); } |
422 | "phase" %{ KEY(phase); } |
423 | "psweep" %{ KEY(psweep); } |
424 | "repeat" %{ KEY(repeat); } |
425 | "resonance" %{ KEY(resonance); } |
426 | "slide" %{ KEY(slide); } |
427 | "square" %{ KEY(square); } |
428 | "sustain" %{ KEY(sustain); } |
429 | "sweep" %{ KEY(sweep); } |
430 | "punch" %{ KEY(punch); } |
431 | "vibe" %{ KEY(vibe); } |
432 | "vspeed" %{ KEY(vspeed); } |
433 | "vdelay" %{ KEY(vdelay); } |
434 | "volume" %{ KEY(volume); };
435 |
436 | main := |*
437 | key space+ float space* => { *((float *)key) = fval; };
438 | "type" space+ "square" => { P->params.type = BLOOPS_SQUARE; };
439 | "type" space+ "sawtooth" => { P->params.type = BLOOPS_SAWTOOTH; };
440 | "type" space+ "sine" => { P->params.type = BLOOPS_SINE; };
441 | "type" space+ "noise" => { P->params.type = BLOOPS_NOISE; };
442 | space+;
443 | *|;
444 |
445 | write data nofinal;
446 | }%%
447 |
448 | bloopsaphone *
449 | bloops_sound_file(bloops *B, char *fname)
450 | {
451 | FILE *fp;
452 | struct stat stats;
453 | int cs, act, len;
454 | float fval;
455 | void *key;
456 | char *str, *p, *pe, *pf, *ts, *te, *eof = 0;
457 | bloopsaphone *P;
458 |
459 | if (stat(fname, &stats) == -1)
460 | return NULL;
461 |
462 | fp = fopen(fname, "rb");
463 | if (!fp)
464 | return NULL;
465 |
466 | len = stats.st_size;
467 | str = (char *)malloc(stats.st_size + 1);
468 | if (fread(str, 1, stats.st_size, fp) != stats.st_size)
469 | goto done;
470 |
471 | p = str;
472 | pe = str + len + 1;
473 | p[len] = '\0';
474 |
475 | P = bloops_square();
476 | %% write init;
477 | %% write exec;
478 |
479 | done:
480 | fclose(fp);
481 | return P;
482 | }
483 |
484 | char *
485 | bloops_sound_str(bloopsaphone *P)
486 | {
487 | char *lines = (char *)malloc(4096), *str = lines;
488 | bloopsaphone *sq = bloops_square();
489 | if (P->params.type == BLOOPS_SQUARE)
490 | str += sprintf(str, "type square\n");
491 | else if (P->params.type == BLOOPS_SAWTOOTH)
492 | str += sprintf(str, "type sawtooth\n");
493 | else if (P->params.type == BLOOPS_SINE)
494 | str += sprintf(str, "type sine\n");
495 | else if (P->params.type == BLOOPS_NOISE)
496 | str += sprintf(str, "type noise\n");
497 |
498 | if (P->params.volume != sq->params.volume)
499 | str += sprintf(str, "volume %0.3f\n", P->params.volume);
500 | if (P->params.punch != sq->params.punch)
501 | str += sprintf(str, "punch %0.3f\n", P->params.punch);
502 | if (P->params.attack != sq->params.attack)
503 | str += sprintf(str, "attack %0.3f\n", P->params.attack);
504 | if (P->params.sustain != sq->params.sustain)
505 | str += sprintf(str, "sustain %0.3f\n", P->params.sustain);
506 | if (P->params.decay != sq->params.decay)
507 | str += sprintf(str, "decay %0.3f\n", P->params.decay);
508 | if (P->params.freq != sq->params.freq)
509 | str += sprintf(str, "freq %0.3f\n", P->params.freq);
510 | if (P->params.limit != sq->params.limit)
511 | str += sprintf(str, "limit %0.3f\n", P->params.limit);
512 | if (P->params.slide != sq->params.slide)
513 | str += sprintf(str, "slide %0.3f\n", P->params.slide);
514 | if (P->params.dslide != sq->params.dslide)
515 | str += sprintf(str, "dslide %0.3f\n", P->params.dslide);
516 | if (P->params.square != sq->params.square)
517 | str += sprintf(str, "square %0.3f\n", P->params.square);
518 | if (P->params.sweep != sq->params.sweep)
519 | str += sprintf(str, "sweep %0.3f\n", P->params.sweep);
520 | if (P->params.vibe != sq->params.vibe)
521 | str += sprintf(str, "vibe %0.3f\n", P->params.vibe);
522 | if (P->params.vspeed != sq->params.vspeed)
523 | str += sprintf(str, "vspeed %0.3f\n", P->params.vspeed);
524 | if (P->params.vdelay != sq->params.vdelay)
525 | str += sprintf(str, "vdelay %0.3f\n", P->params.vdelay);
526 | if (P->params.lpf != sq->params.lpf)
527 | str += sprintf(str, "lpf %0.3f\n", P->params.lpf);
528 | if (P->params.lsweep != sq->params.lsweep)
529 | str += sprintf(str, "lsweep %0.3f\n", P->params.lsweep);
530 | if (P->params.resonance != sq->params.resonance)
531 | str += sprintf(str, "resonance %0.3f\n", P->params.resonance);
532 | if (P->params.hpf != sq->params.hpf)
533 | str += sprintf(str, "hpf %0.3f\n", P->params.hpf);
534 | if (P->params.hsweep != sq->params.hsweep)
535 | str += sprintf(str, "hsweep %0.3f\n", P->params.hsweep);
536 | if (P->params.arp != sq->params.arp)
537 | str += sprintf(str, "arp %0.3f\n", P->params.arp);
538 | if (P->params.aspeed != sq->params.aspeed)
539 | str += sprintf(str, "aspeed %0.3f\n", P->params.aspeed);
540 | if (P->params.phase != sq->params.phase)
541 | str += sprintf(str, "phase %0.3f\n", P->params.phase);
542 | if (P->params.psweep != sq->params.psweep)
543 | str += sprintf(str, "psweep %0.3f\n", P->params.psweep);
544 | if (P->params.repeat != sq->params.repeat)
545 | str += sprintf(str, "repeat %0.3f\n", P->params.repeat);
546 |
547 | bloops_sound_destroy(sq);
548 | return lines;
549 | }
550 |
--------------------------------------------------------------------------------
/ext/ruby/extconf.rb:
--------------------------------------------------------------------------------
1 | require 'mkmf'
2 | require 'fileutils'
3 |
4 | $CFLAGS << " -I../../c #{ENV['CFLAGS']}"
5 | $LIBS << " -lm -lportaudio #{ENV['LDFLAGS']}"
6 |
7 | %w[notation.c bloopsaphone-internal.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")
16 |
--------------------------------------------------------------------------------
/ext/ruby/rubyext.c:
--------------------------------------------------------------------------------
1 | //
2 | // rubyext.c
3 | // the ruby binding to bloopsaphone
4 | //
5 | // (c) 2009 why the lucky stiff
6 | //
7 | #include
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 | }
333 |
--------------------------------------------------------------------------------
/ext/ruby/test.rb:
--------------------------------------------------------------------------------
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
42 |
--------------------------------------------------------------------------------
/ext/ruby/test_load.rb:
--------------------------------------------------------------------------------
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?
26 |
--------------------------------------------------------------------------------
/ext/ruby/tune_cheeky_drat.rb:
--------------------------------------------------------------------------------
1 | #
2 | # -)= Cheeky Drat (=-
3 | # composed by freQvibez
4 | # [within TextMate]
5 | # exclusively for _why's BloopSaphone
6 | #
7 | # from Farbrausch with ♥
8 | #
9 |
10 | require './bloops'
11 |
12 | b = Bloops.new
13 | b.tempo = 172
14 |
15 | bass = b.sound Bloops::SQUARE
16 | bass.volume = 0.4
17 | bass.sustain = 0.1
18 | bass.attack = 0.1
19 | bass.decay = 0.3
20 |
21 | base = b.sound Bloops::SQUARE
22 | base.volume = 0.35
23 | base.punch = 0.3
24 | base.sustain = 0.1
25 | base.decay = 0.3
26 | base.phase = 0.2
27 | base.lpf = 0.115
28 | base.resonance = 0.55
29 | base.slide = -0.4
30 |
31 | snare = b.sound Bloops::NOISE
32 | snare.attack = 0.075
33 | snare.sustain = 0.01
34 | snare.decay = 0.33
35 | snare.hpf = 0.55
36 | snare.resonance = 0.44
37 | snare.dslide = -0.452
38 |
39 | chord = b.sound Bloops::SQUARE
40 | chord.volume = 0.275
41 | chord.attack = 0.05
42 | chord.sustain = 0.6
43 | chord.decay = 0.9
44 | chord.phase = 0.35
45 | chord.psweep = -0.25
46 | chord.vibe = 0.0455
47 | chord.vspeed = 0.255
48 |
49 | lead = b.sound Bloops::SINE
50 | lead.volume = 0.45
51 | lead.attack = 0.3
52 | lead.sustain = 0.15
53 | lead.decay = 0.8
54 | lead.vibe = 0.035
55 | lead.vspeed = 0.345
56 | lead.vdelay = -0.5
57 | lead.hpf = 0.2
58 | lead.hsweep = -0.05
59 | lead.resonance = 0.55
60 | lead.phase = 0.4
61 | lead.psweep = -0.05
62 |
63 | b.tune bass, %q^
64 | 8 4a1 8a 8a 4a 4a 4c2 9c 7c 4c 8e
65 | 8 4g2 8g 8 4g 4g 4d2 8 8c3 4b2 8e
66 | 8 4d2 8c 8c 4c 4 4a2 9a 7a 4a 8a
67 | 8 4g2 8g 8 4g 4d 4d2 9e3 7c2 8 4b1
68 |
69 | 8 4a2 8a 8d 4 4d 4a1 8a 8a 4d 8d
70 | 8 4g2 8g 8 4g 4g 4c2 8c 8c2 4g 8c
71 | 8 4d2 8d 8d 4d 4d 4a1 8a 8a 4a 8a
72 | 8 4g2 8g 8 4g 4g 4c2 8c 8c 4c 8b1
73 |
74 | 8 4a1 8a 8a 4a 4a 4c2 9c 7c 4c 8e
75 | 8 4g2 8g 8 4g 4g 4d2 8 8c3 4b2 8e
76 | 8 4d2 8c 8c 4c 4 4a2 9a 7a 4a 8a
77 | 8 4g2 8g 8 4g 4d 4d2 9e3 7c2 8 4b1
78 |
79 | 8 4a2 8a 8d 4 4d 4a1 8a 8a 4d 8d
80 | 8 4g2 8g 8 4g 4g 4c2 8c 8c2 4g 8c
81 | 8 4d2 8d 8d 4d 4d 4a1 8a 8a 4a 8a
82 | 8 4g2 8g 8 4g 4g 4c2 8c 8c 4c 8b1
83 | ^
84 |
85 | b.tune base, %q^
86 | 4a2 4 8a 8a 4 4a 4 8a 8a 4
87 | 4a 4 8a 8a 4 4a 4 4a 8 8a
88 | 4a 4 8a 8a 4 4a 4 8a 8a 4
89 | 4a 4 8a 4 8a 4a 4 8a 4 8a
90 |
91 | 4a2 4 8a 8a 4 4a 4 8a 8a 4
92 | 4a 4 8a 8a 4 4a 4 4a 8 8a
93 | 4a 4 8a 8a 4 4a 4 8a 8a 4
94 | 4a 4 8a 4 8a 4a 4 8a 4 8a
95 |
96 | 4a2 4 8a 8a 4 4a 4 8a 8a 4
97 | 4a 4 8a 8a 4 4a 4 4a 8 8a
98 | 4a 4 8a 8a 4 4a 4 8a 8a 4
99 | 4a 4 8a 4 8a 4a 4 8a 4 8a
100 |
101 | 4a2 4 8a 8a 4 4a 4 8a 8a 4
102 | 4a 4 8a 8a 4 4a 4 4a 8 8a
103 | 4a 4 8a 8a 4 4a 4 8a 8a 4
104 | 4a 4 8a 4 8a 4a 4 8a 4 8a
105 | ^
106 |
107 | b.tune snare, %q^
108 | 4 4a2 4 4a2 4 4a2 4 4a2
109 | 4 4a2 4 4a2 4 4a2 4 4a2
110 | 4 4a2 4 4a2 4 4a2 4 4a2
111 | 4 4a2 4 4a2 4 4a2 4 8a2 8a2
112 |
113 | 4 4a2 4 4a2 4 4a2 4 4a2
114 | 4 4a2 4 4a2 4 4a2 4 4a2
115 | 4 4a2 4 4a2 4 4a2 4 4a2
116 | 4 4a2 4 4a2 4 4a2 4 8a2 8a2
117 |
118 | 4 4a2 4 4a2 4 4a2 4 4a2
119 | 4 4a2 4 4a2 4 4a2 4 4a2
120 | 4 4a2 4 4a2 4 4a2 4 4a2
121 | 4 4a2 4 4a2 4 4a2 4 8a2 8a2
122 |
123 | 4 4a2 4 4a2 4 4a2 4 4a2
124 | 4 4a2 4 4a2 4 4a2 4 4a2
125 | 4 4a2 4 4a2 4 4a2 4 4a2
126 | 4 4a2 4 4a2 4 4a2 4 8a2 8a2
127 | ^
128 |
129 | b.tune chord, %q^
130 | 1
131 | 1 1
132 | 1 1 1
133 | 1 1
134 |
135 | 1a2 2a3 2 1g2 2d3 2
136 | 1a2 2a3 2 1d2 4g3 4g2 2e3
137 |
138 | 1a2 2a3 2 1g2 2d3 2
139 | 1a2 2a3 2 1d2 2g3 2
140 |
141 | 1a2 2a3 2 1g2 2d3 2
142 | 1a2 2a3 2 1d2 2g3 2
143 |
144 | 1a2 2a3 2 1g2 2d3 2
145 | 1a2 2a3 2 1d2 2g3 2
146 | ^
147 |
148 | b.tune chord, %q^
149 | 1
150 | 1 1
151 | 1 1 1
152 | 1 1
153 |
154 | 2 2c4 2 1 2b4 2
155 | 1 2c4 4 2g3 2b4 1
156 |
157 | 2 2c4 2 1 2b4 2
158 | 1 2c4 2 1 2b4 1
159 |
160 | 2 2c4 2 1 2b4 2
161 | 1 2c4 2 1 2b4 1
162 |
163 | 2 2c4 2 1 2b4 2
164 | 1 2c4 2 1 2b4 1
165 | ^
166 |
167 | b.tune chord, %q^
168 | 1
169 | 1 1
170 | 1 1 1
171 | 1 1
172 |
173 | 2 1 2e4 2 1 2d4
174 | 2 1 2e4 2 1 2d4
175 |
176 | 2 1 2e4 2 1 2d4
177 | 2 1 2e4 2 1 2d4
178 |
179 | 2 1 2e4 2 1 2d4
180 | 2 1 2e4 2 1 2d4
181 |
182 | 2 1 2e4 2 1 2d4
183 | 2 1 2e4 2 1 2d4
184 | ^
185 |
186 | b.tune lead, %q^
187 | 1 4
188 | 1 1 1 1
189 | 1 1 1 1 1 1
190 | 1 1 1 1
191 |
192 | 2g3 1a4 2
193 | 2c5 1e4 2 1
194 | 1a4 2 4 2e4 1d4 2
195 |
196 | 2a3 1b4 2
197 | 2d5 2g4 1c5
198 | 1a4 1e5
199 | 1b4 2 4 8 8d4
200 |
201 | 2g3 1a4 2
202 | 2c5 1e4 3d4 5g4
203 | 1a4 1e4
204 | 1d4 1
205 | ^
206 |
207 | while true do
208 | b.play
209 | sleep 0.5 while not b.stopped?
210 | end
211 |
--------------------------------------------------------------------------------
/ext/ruby/tune_warp.rb:
--------------------------------------------------------------------------------
1 | #
2 | # -=) warp-o-mat (=-
3 | # tune coded/composed by freQvibez
4 | # (c) 2009 Alex Brem
5 | #
6 | # exclusively for why's BloopSaphone
7 | #
8 | # from Farbrausch with ♥
9 | #
10 |
11 | module LousyBloopMachine
12 |
13 | class Tune
14 |
15 | BPM = 67
16 |
17 | ###
18 | ### sequences
19 | ###
20 |
21 | SEQUENCES = {
22 | :bass => %w^
23 | 01 02 01 02 01 02 01 02
24 | 01 02 01 02 01 02 01 02
25 |
26 | 01 02 01 02 01 02 01 02
27 | 01 02 01 02 01 02 01 02
28 | ^,
29 | :base => %w^
30 | 00 01 01 01 01 01 01 01
31 | 01 01 01 01 01 01 01 01
32 |
33 | 01 01 01 01 01 01 01 01
34 | 01 01 01 01 01 01 01 01
35 | ^,
36 | :snare => %w^
37 | 00 00 00 00 01 01 01 02
38 | 01 01 01 02 01 01 01 02
39 |
40 | 01 01 01 02 01 01 01 02
41 | 01 01 01 02 01 01 01 02
42 | ^,
43 | :hihat => %w^
44 | 00 00 01 01 01 01 01 01
45 | 01 01 01 01 01 01 01 01
46 |
47 | 01 01 01 01 01 01 01 01
48 | 01 01 01 01 01 01 01 01
49 | ^,
50 | :rhodes_1 => %w^
51 | 00 00 00 00
52 | 01 02 03 04
53 |
54 | 01 02 03 04
55 | 01 02 03 04
56 | ^,
57 | :rhodes_2 => %w^
58 | 00 00 00 00
59 | 01 02 03 04
60 |
61 | 01 02 03 04
62 | 01 02 03 04
63 | ^,
64 | :rhodes_3 => %w^
65 | 00 00 00 00
66 | 01 02 03 04
67 |
68 | 01 02 03 04
69 | 01 02 03 04
70 | ^,
71 | :rhodes_4 => %w^
72 | 00 00 00 00
73 | 01 02 03 04
74 |
75 | 01 02 03 04
76 | 01 02 03 04
77 | ^,
78 | :silent => %w^
79 | 00
80 | 00
81 |
82 | 01
83 | 01
84 | ^,
85 | :naughty => %w^
86 | 00
87 | 00
88 |
89 | 00
90 | 01
91 | ^
92 | }
93 |
94 | ###
95 | ### patterns
96 | ###
97 |
98 | PATTERNS = {
99 |
100 | :bass => {
101 | 01 => %q^
102 | 32a1[attack 0.1][sustain 0.05] 32a
103 | 32a 32a
104 | 32a 32a2
105 | 32a1 32a
106 |
107 | 32a[sustain 0.1] 32a
108 | 32a 32a
109 | 32a[sustain 0.15] 32a
110 | 32a2[sustain 0.1] 32a1
111 | ^,
112 | 02 => %q^
113 | 8 16a[attack 0.2][psweep 0.5][square 0.2] 16a[attack 0.1]
114 | 8 16a 16
115 |
116 | 16a 8 16a
117 | 16 16a 16 16a
118 |
119 | 8 16a 32a 16a 32a
120 | 32a 32 16a 32
121 | ^
122 | },
123 |
124 | :base => {
125 | 00 => %q^
126 | 1
127 | ^,
128 | 01 => %q^
129 | 8d2 8d 8d 8d
130 | 8d 8d 8d 8d
131 | ^
132 | },
133 |
134 | :snare => {
135 | 00 => %q^
136 | 1
137 | ^,
138 | 01 => %q^
139 | 8 8a 8 8a
140 | 8 8a 8 8a
141 | ^,
142 | 02 => %q^
143 | 8 8a 8 8a
144 | 16 16 8a 32 32a[volume 0.05] 16 8a[volume 0.25]
145 | ^
146 | },
147 |
148 | :hihat => {
149 | 00 => %q^
150 | 1
151 | ^,
152 | 01 => %q^
153 | 16 16a 16 16a 16 16a 16 16a
154 | 16 16a 16 16a 16 16a 16 16a
155 | ^
156 | },
157 |
158 | :rhodes_1 => {
159 | 00 => %q^
160 | 1 1
161 | ^,
162 | 01 => %q^
163 | 1c4 1e4
164 | ^,
165 | 02 => %q^
166 | 1c4 1e4
167 | ^,
168 | 03 => %q^
169 | 1d4 1c4
170 | ^,
171 | 04 => %q^
172 | 1e4 1eb4
173 | ^
174 | },
175 |
176 | :rhodes_2 => {
177 | 00 => %q^
178 | 1 1
179 | ^,
180 | 01 => %q^
181 | 1e4 1g4
182 | ^,
183 | 02 => %q^
184 | 1e4 1g4
185 | ^,
186 | 03 => %q^
187 | 1g4 1d4
188 | ^,
189 | 04 => %q^
190 | 1gb4 1gb4
191 | ^
192 | },
193 |
194 | :rhodes_3 => {
195 | 00 => %q^
196 | 1 1
197 | ^,
198 | 01 => %q^
199 | 1g4 1b4
200 | ^,
201 | 02 => %q^
202 | 1g4 1b4
203 | ^,
204 | 03 => %q^
205 | 1a4 1g4
206 | ^,
207 | 04 => %q^
208 | 1g4 1g4
209 | ^
210 | },
211 |
212 | :rhodes_4 => {
213 | 00 => %q^
214 | 1 1
215 | ^,
216 | 01 => %q^
217 | 1b4 1d4
218 | ^,
219 | 02 => %q^
220 | 1b4 1d4
221 | ^,
222 | 03 => %q^
223 | 1c4 1b4
224 | ^,
225 | 04 => %q^
226 | 1c4 1b4
227 | ^
228 | },
229 |
230 | :silent => {
231 | 00 => %q^
232 | 1 1 1 1
233 | 1 1 1 1
234 | ^,
235 | 01 => %q^
236 | 1b4 1d5
237 | 2b4 2g4 1e4
238 |
239 | 1c4 2gb5 2b4
240 | 1c4 1b3
241 | ^
242 | },
243 |
244 | :naughty => {
245 | 00 => %q^
246 | 1 1 1 1
247 | 1 1 1 1
248 | ^,
249 | 01 => %q^
250 | 2
251 |
252 | 1b4 1e4
253 | 2b3 2d4 2b4
254 |
255 | 1a4 2gb4 2a3
256 | 1eb4 1gb4
257 | ^
258 | }
259 |
260 | }
261 |
262 | end
263 |
264 | ###
265 | ### playroutine
266 | ###
267 |
268 | require 'yaml'
269 | require './bloops'
270 |
271 | extend self
272 |
273 | def init
274 | @bloops ||= Bloops.new
275 | @bloops.tempo = Tune::BPM
276 |
277 | return if @sounds
278 |
279 | @sounds = {}
280 | YAML.load(DATA.read).each do |track,instrument|
281 | @sounds[track] = @bloops.sound instrument['sound'].split("::").inject(Object) { |c1,c2| c1.const_get(c2) }
282 | instrument.reject{|k,v| k == 'sound'}.each do |sound,value|
283 | @sounds[track].send "#{sound}=", value
284 | end
285 | end
286 |
287 | Tune::SEQUENCES.each do |track,sequences|
288 | instr = track.to_s.split('_')[0]
289 | next unless @sounds[instr]
290 | next unless Tune::PATTERNS[track]
291 |
292 | notes = ''
293 | sequences.each do |seq|
294 | seq = seq.to_i
295 | next unless Tune::PATTERNS[track][seq]
296 | notes << Tune::PATTERNS[track][seq]
297 | end
298 | @bloops.tune @sounds[instr], notes
299 | end
300 | end
301 |
302 | def play
303 | init unless @bloops
304 | @bloops.play
305 | sleep 0.05 while !@bloops.stopped?
306 | end
307 |
308 | def play_endless
309 | while true do play; end
310 | end
311 |
312 | end
313 |
314 | LousyBloopMachine.play_endless if $0 == __FILE__
315 |
316 | ###
317 | ### instruments
318 | ###
319 |
320 | __END__
321 |
322 | bass:
323 | sound: Bloops::SQUARE
324 | volume: 0.9
325 | attack: 0.1
326 | decay: 0.15
327 | sustain: 0.05
328 | square: 0.05
329 | phase: 0.5
330 | psweep: -0.255
331 |
332 | base:
333 | sound: Bloops::SINE
334 | volume: 0.6
335 | attack: 0.0
336 | decay: 0.25
337 | sustain: 0.15
338 | lpf: 0.45
339 | resonance: 0.4
340 | dslide: -0.3
341 |
342 | snare:
343 | sound: Bloops::NOISE
344 | volume: 0.25
345 | attack: 0.01
346 | decay: 0.305
347 | sustain: 0
348 | hpf: 0.65
349 | resonance: 0.24
350 | dslide: -0.452
351 |
352 | hihat:
353 | sound: Bloops::NOISE
354 | volume: 0.25
355 | attack: 0.150
356 | decay: 0.105
357 | sustain: 0.205
358 | hpf: 0.95
359 |
360 | rhodes:
361 | sound: Bloops::SAWTOOTH
362 | volume: 0.09
363 | attack: 0.55
364 | decay: 1.0
365 | sustain: 0.45
366 | lpf: 0.55
367 | lsweep: -0.005
368 | resonance: 0.35
369 | vibe: 0.035
370 | vspeed: 0.292
371 | phase: 0.305
372 | psweep: -0.025
373 | vdelay: 0.9
374 |
375 | silent:
376 | sound: Bloops::SINE
377 | volume: 0.45
378 | attack: 0.35
379 | decay: 0.95
380 | sustain: 0.85
381 | lpf: 0.25
382 | lsweep: -0.025
383 | hpf: 0.25
384 | hsweep: -0.025
385 | resonance: 0.75
386 | vibe: 0.055
387 | vspeed: -0.325
388 | phase: 0.505
389 | psweep: -0.025
390 |
391 | naughty:
392 | sound: Bloops::SQUARE
393 | volume: 0.15
394 | attack: 0.45
395 | decay: 0.95
396 | sustain: 0.85
397 | lpf: 0.25
398 | lsweep: -0.025
399 | hpf: 0.25
400 | hsweep: -0.025
401 | resonance: 0.65
402 | vibe: 0.065
403 | vspeed: -0.325
404 | phase: 0.305
405 | psweep: -0.025
406 | square: 0.75
407 | phase: 0.0
408 | psweep: 0.555
409 |
--------------------------------------------------------------------------------
/misc/Makefile-dll:
--------------------------------------------------------------------------------
1 | # Project: portaudio-dll
2 | # Makefile created by Dev-C++ 4.9.8.2
3 | # modified 2009-01-25 by Mateusz Czaplinski for MinGW and PortAudio V19.
4 | # http://www.musescore.org/en/handbook/compile-instructions-windows-mingw
5 |
6 | TMPOBJ = ./pa_asio.o ./iasiothiscallresolver.o ./pa_win_ds.o ./dsound_wrapper.o
7 | TMPLINKOBJ = ./pa_asio.o ./iasiothiscallresolver.o ./pa_win_ds.o ./dsound_wrapper.o
8 |
9 | CPP = g++.exe
10 | CC = gcc.exe
11 | WINDRES = windres.exe
12 | RES =
13 | OBJ = ./pa_skeleton.o ./pa_stream.o ./pa_trace.o ./pa_allocation.o ./pa_converters.o ./pa_cpuload.o ./pa_dither.o ./pa_front.o ./pa_process.o ./pa_win_util.o ./pa_win_hostapis.o ./pa_win_wmme.o ./pa_win_waveformat.o $(RES)
14 | LINKOBJ = ./pa_skeleton.o ./pa_stream.o ./pa_trace.o ./pa_allocation.o ./pa_converters.o ./pa_cpuload.o ./pa_dither.o ./pa_front.o ./pa_process.o ./pa_win_util.o ./pa_win_hostapis.o ./pa_win_wmme.o ./pa_win_waveformat.o $(RES)
15 | LIBS = -fmessage-length=0 -export-all-symbols --add-stdcall-alias -O3 -s -lwinmm
16 | INCS = -I"../../src/common" -I"../../include"
17 | CXXINCS = -I"../../src/common" -I"../../include"
18 | BIN = portaudio.dll
19 | CXXFLAGS = $(CXXINCS) -DBUILDING_DLL=1 -O3 -fmessage-length=0 -Wall -DPA_NO_DS -DPA_NO_ASIO
20 | CFLAGS = $(CXXFLAGS)
21 |
22 | .PHONY: all all-before all-after clean clean-custom
23 |
24 | all: all-before $(BIN) all-after
25 |
26 |
27 | clean: clean-custom
28 | rm -f $(OBJ) $(BIN)
29 |
30 | DLLWRAP=dllwrap.exe
31 | DEFFILE=libportaudio.def
32 | STATICLIB=libportaudio.a
33 |
34 | $(BIN): $(LINKOBJ)
35 | $(DLLWRAP) --output-def $(DEFFILE) --driver-name c++ --implib $(STATICLIB) $(LINKOBJ) $(LIBS) -o $(BIN)
36 |
37 | ./pa_skeleton.o: ../../src/common/pa_skeleton.c
38 | $(CPP) -c ../../src/common/pa_skeleton.c -o ./pa_skeleton.o $(CXXFLAGS)
39 |
40 | ./pa_stream.o: ../../src/common/pa_stream.c
41 | $(CPP) -c ../../src/common/pa_stream.c -o ./pa_stream.o $(CXXFLAGS)
42 |
43 | ./pa_trace.o: ../../src/common/pa_trace.c
44 | $(CPP) -c ../../src/common/pa_trace.c -o ./pa_trace.o $(CXXFLAGS)
45 |
46 | ./pa_allocation.o: ../../src/common/pa_allocation.c
47 | $(CPP) -c ../../src/common/pa_allocation.c -o ./pa_allocation.o $(CXXFLAGS)
48 |
49 | ./pa_converters.o: ../../src/common/pa_converters.c
50 | $(CPP) -c ../../src/common/pa_converters.c -o ./pa_converters.o $(CXXFLAGS)
51 |
52 | ./pa_cpuload.o: ../../src/common/pa_cpuload.c
53 | $(CPP) -c ../../src/common/pa_cpuload.c -o ./pa_cpuload.o $(CXXFLAGS)
54 |
55 | ./pa_dither.o: ../../src/common/pa_dither.c
56 | $(CPP) -c ../../src/common/pa_dither.c -o ./pa_dither.o $(CXXFLAGS)
57 |
58 | ./pa_front.o: ../../src/common/pa_front.c
59 | $(CPP) -c ../../src/common/pa_front.c -o ./pa_front.o $(CXXFLAGS)
60 |
61 | ./pa_process.o: ../../src/common/pa_process.c
62 | $(CPP) -c ../../src/common/pa_process.c -o ./pa_process.o $(CXXFLAGS)
63 |
64 | #./pa_asio.o: ../../pa_asio/pa_asio.cpp
65 | # $(CPP) -c ../../pa_asio/pa_asio.cpp -o ./pa_asio.o $(CXXFLAGS)
66 |
67 | ./pa_win_util.o: ../../src/os/win/pa_win_util.c
68 | $(CPP) -c ../../src/os/win/pa_win_util.c -o ./pa_win_util.o $(CXXFLAGS)
69 |
70 | ./pa_win_hostapis.o: ../../src/os/win/pa_win_hostapis.c
71 | $(CPP) -c ../../src/os/win/pa_win_hostapis.c -o ./pa_win_hostapis.o $(CXXFLAGS)
72 |
73 | #./pa_win_ds.o: ../../pa_win_ds/pa_win_ds.c
74 | # $(CPP) -c ../../pa_win_ds/pa_win_ds.c -o ./pa_win_ds.o $(CXXFLAGS)
75 | #./pa_win_ds.o: ../../src/hostapi/dsound/pa_win_ds.c
76 | # $(CPP) -c ../../src/hostapi/dsound/pa_win_ds.c -o ./pa_win_ds.o $(CXXFLAGS)
77 |
78 | #./dsound_wrapper.o: ../../pa_win_ds/dsound_wrapper.c
79 | # $(CPP) -c ../../pa_win_ds/dsound_wrapper.c -o ./dsound_wrapper.o $(CXXFLAGS)
80 | #./dsound_wrapper.o: ../../src/hostapi/dsound/pa_win_ds_dynlink.c
81 | # $(CPP) -c ../../src/hostapi/dsound/pa_win_ds_dynlink.c -o ./dsound_wrapper.o $(CXXFLAGS)
82 |
83 | ./pa_win_wmme.o: ../../src/hostapi/wmme/pa_win_wmme.c
84 | $(CPP) -c ../../src/hostapi/wmme/pa_win_wmme.c -o ./pa_win_wmme.o $(CXXFLAGS)
85 |
86 | #./iasiothiscallresolver.o: ../../pa_asio/iasiothiscallresolver.cpp
87 | # $(CPP) -c ../../pa_asio/iasiothiscallresolver.cpp -o ./iasiothiscallresolver.o $(CXXFLAGS)
88 |
89 | ./pa_win_waveformat.o: ../../src/os/win/pa_win_waveformat.c
90 | $(CPP) -c ../../src/os/win/pa_win_waveformat.c -o ./pa_win_waveformat.o $(CXXFLAGS)
91 |
92 |
--------------------------------------------------------------------------------
/sounds/dart.blu:
--------------------------------------------------------------------------------
1 | type noise
2 | punch 0.524
3 | sustain 0.160
4 | decay 0.367
5 | freq 0.296
6 | slide -0.373
7 | vibe 0.665
8 | vspeed 0.103
9 | phase 0.141
10 | psweep -0.005
11 |
--------------------------------------------------------------------------------
/sounds/error.blu:
--------------------------------------------------------------------------------
1 | type square
2 | sustain 0.333
3 | decay 0.380
4 | freq 0.336
5 | slide 0.292
6 | square 0.289
7 | sweep 0.020
8 | vibe 0.002
9 | lpf 0.220
10 | lsweep 0.015
11 | resonance 0.875
12 | aspeed 0.035
13 | repeat 0.551
14 |
--------------------------------------------------------------------------------
/sounds/ice.blu:
--------------------------------------------------------------------------------
1 | type square
2 | punch 0.441
3 | sustain 0.067
4 | decay 0.197
5 | freq 0.499
6 |
--------------------------------------------------------------------------------
/sounds/jump.blu:
--------------------------------------------------------------------------------
1 | type square
2 | sustain 0.266
3 | decay 0.187
4 | freq 0.268
5 | slide 0.179
6 | square 0.326
7 | vibe 0.227
8 | vspeed 0.231
9 |
--------------------------------------------------------------------------------
/sounds/pogo.blu:
--------------------------------------------------------------------------------
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
20 |
--------------------------------------------------------------------------------
/sounds/stun.blu:
--------------------------------------------------------------------------------
1 | type sawtooth
2 | sustain 0.306
3 | decay 0.477
4 | freq 0.429
5 | slide 0.217
6 | repeat 0.677
7 |
--------------------------------------------------------------------------------