viking-bloopsaphone 0.4 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -17,6 +17,9 @@
17
17
  a rather light cross-platform audio lib.
18
18
  <http://www.portaudio.com/>
19
19
 
20
+ it also records to a wav file using
21
+ libsndfile.
22
+
20
23
  right now i'm only including ruby
21
24
  bindings. you are welcome to contribute
22
25
  code to hook up to other languages,
@@ -82,20 +85,12 @@
82
85
 
83
86
  aptitude install portaudio19-dev
84
87
 
85
- To build from source isn't too bad.
86
- Download PortAudio 1.9 and build it.
87
- <http://www.portaudio.com/archives/pa_stable_v19_20071207.tar.gz>
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
88
+ Under MacPorts, you may need to add
89
+ /opt/local to your make settings:
96
90
 
97
- Then go back to Bloopsaphone and do
98
- a `make ruby`.
91
+ make CFLAGS="-I/opt/local/include" \
92
+ LDFLAGS="-L/opt/local/lib" \
93
+ ruby
99
94
 
100
95
  ~
101
96
 
data/c/bloopsaphone.c CHANGED
@@ -2,50 +2,27 @@
2
2
  // bloopsaphone.c
3
3
  // the chiptune maker for portaudio
4
4
  // (with bindings for ruby)
5
- //
5
+ //
6
6
  // (c) 2009 why the lucky stiff
7
7
  // See COPYING for the license
8
8
  //
9
9
  #include <stdio.h>
10
10
  #include <stdlib.h>
11
- #include <stddef.h>
12
11
  #include <string.h>
13
12
  #include <time.h>
14
13
  #include <math.h>
15
14
  #include <portaudio.h>
15
+ #include <sndfile.h>
16
16
  #include <unistd.h>
17
17
  #include "bloopsaphone.h"
18
- #include "threads.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
18
 
26
19
  #define SAMPLE_RATE 44100
20
+ #define FRAMES_PER_BUFFER 512
27
21
  #define rnd(n) (rand() % (n + 1))
28
22
  #define tempo2frames(tempo) ((float)SAMPLE_RATE / (tempo / 60.0f))
29
23
  #define PI 3.14159265f
30
24
 
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);
25
+ static int bloops_open = 0;
49
26
 
50
27
  float
51
28
  frnd(float range)
@@ -53,88 +30,74 @@ frnd(float range)
53
30
  return (float)rnd(10000) / 10000 * range;
54
31
  }
55
32
 
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)
33
+ void
34
+ bloops_ready(bloops *B, bloopsatrack *A, unsigned char init)
71
35
  {
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;
36
+ A->period = 100.0 / (A->P->freq * A->P->freq + 0.001);
37
+ A->maxperiod = 100.0 / (A->P->limit * A->P->limit + 0.001);
38
+ A->slide = 1.0 - pow((double)A->P->slide, 3.0) * 0.01;
39
+ A->dslide = -pow((double)A->P->dslide, 3.0) * 0.000001;
40
+ A->square = 0.5f - A->P->square * 0.5f;
41
+ A->sweep = -A->P->sweep * 0.00005f;
42
+ if (A->P->arp >= 0.0f)
43
+ A->arp = 1.0 - pow((double)A->P->arp, 2.0) * 0.9;
80
44
  else
81
- A->arp = 1.0 + pow((double)A->params.arp, 2.0) * 10.0;
45
+ A->arp = 1.0 + pow((double)A->P->arp, 2.0) * 10.0;
82
46
  A->atime = 0;
83
- A->alimit = (int)(pow(1.0f - A->params.aspeed, 2.0f) * 20000 + 32);
84
- if (A->params.aspeed == 1.0f)
47
+ A->alimit = (int)(pow(1.0f - A->P->aspeed, 2.0f) * 20000 + 32);
48
+ if (A->P->aspeed == 1.0f)
85
49
  A->alimit = 0;
86
- }
87
50
 
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;
51
+ if (init)
52
+ {
53
+ int i = 0;
54
+ A->phase = 0;
55
+ A->filter[0] = 0.0f;
56
+ A->filter[1] = 0.0f;
57
+ A->filter[2] = pow(A->P->lpf, 3.0f) * 0.1f;
58
+ A->filter[3] = 1.0f + A->P->lsweep * 0.0001f;
59
+ A->filter[4] = 5.0f / (1.0f + pow(A->P->resonance, 2.0f) * 20.0f) * (0.01f + A->filter[2]);
60
+ if (A->filter[4] > 0.8f) A->filter[4] = 0.8f;
61
+ A->filter[5] = 0.0f;
62
+ A->filter[6] = pow(A->P->hpf, 2.0f) * 0.1f;
63
+ A->filter[7] = 1.0 + A->P->hsweep * 0.0003f;
64
+
65
+ A->vibe = 0.0f;
66
+ A->vspeed = pow(A->P->vspeed, 2.0f) * 0.01f;
67
+ A->vdelay = A->P->vibe * 0.5f;
68
+
69
+ A->volume = 0.0f;
70
+ A->stage = 0;
71
+ A->time = 0;
72
+ A->length[0] = (int)(A->P->attack * A->P->attack * 100000.0f);
73
+ A->length[1] = (int)(A->P->sustain * A->P->sustain * 100000.0f);
74
+ A->length[2] = (int)(A->P->decay * A->P->decay * 100000.0f);
75
+
76
+ A->fphase = pow(A->P->phase, 2.0f) * 1020.0f;
77
+ if (A->P->phase < 0.0f) A->fphase = -A->fphase;
78
+ A->dphase = pow(A->P->psweep, 2.0f) * 1.0f;
79
+ if (A->P->psweep < 0.0f) A->dphase = -A->dphase;
80
+ A->iphase = abs((int)A->fphase);
81
+ A->phasex = 0;
82
+
83
+ memset(A->phaser, 0, 1024 * sizeof(float));
84
+ for (i = 0; i < 32; i++)
85
+ A->noise[i] = frnd(2.0f) - 1.0f;
86
+
87
+ A->repeat = 0;
88
+ A->limit = (int)(pow(1.0f - A->P->repeat, 2.0f) * 20000 + 32);
89
+ if (A->P->repeat == 0.0f)
90
+ A->limit = 0;
91
+ A->playing = BLOOPS_PLAY;
92
+ }
129
93
  }
130
94
 
131
95
  void
132
96
  bloops_clear(bloops *B)
133
97
  {
134
98
  int i;
135
- for (i = 0; i < BLOOPS_MAX_TRACKS; i++) {
136
- bloops_set_track_at(B, NULL, i);
137
- }
99
+ for (i = 0; i < BLOOPS_MAX_TRACKS; i++)
100
+ B->tracks[i] = NULL;
138
101
  }
139
102
 
140
103
  void
@@ -144,272 +107,207 @@ bloops_tempo(bloops *B, int tempo)
144
107
  }
145
108
 
146
109
  void
147
- bloops_set_track_at(bloops *B, bloopsatrack *track, int num)
110
+ bloops_track_at(bloops *B, bloopsatrack *track, int num)
148
111
  {
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
- }
112
+ B->tracks[num] = track;
178
113
  }
179
114
 
180
115
  int
181
116
  bloops_is_done(bloops *B)
182
117
  {
183
- return B->state == BLOOPS_STOP;
118
+ return B->play == BLOOPS_STOP;
184
119
  }
185
120
 
186
121
  static void
187
- bloops_synth(int length, float* buffer)
122
+ bloops_synth(bloops *B, int length, float* buffer)
188
123
  {
189
- int bi, t, i, si;
124
+ int t, i, si;
190
125
 
191
126
  while (length--)
192
127
  {
193
128
  int samplecount = 0;
129
+ int moreframes = 0;
194
130
  float allsample = 0.0f;
195
131
 
196
- for (bi = 0; bi < BLOOPS_MAX_CHANNELS; bi++)
132
+ for (t = 0; t < BLOOPS_MAX_TRACKS; t++)
197
133
  {
198
- int moreframes = 0;
199
- bloops *B = MIXER->B[bi];
200
- if (B == NULL)
134
+ bloopsatrack *A = B->tracks[t];
135
+ if (A == NULL)
201
136
  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
137
 
209
- if (track->notes)
138
+ if (A->notes)
139
+ {
140
+ int frames = 0;
141
+ for (i = 0; i < A->nlen; i++)
210
142
  {
211
- if (A->frames == A->nextnote[0])
143
+ bloopsanote *note = &A->notes[i];
144
+ if (A->frames == frames)
212
145
  {
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));
146
+ float freq = bloops_note_freq(note->tone, (int)note->octave);
147
+ if (freq == 0.0f) {
148
+ A->period = 0.0f;
149
+ A->playing = BLOOPS_STOP;
150
+ } else {
151
+ bloops_ready(B, A, 1);
152
+ A->period = 100.0 / (freq * freq + 0.001);
257
153
  }
258
- A->nextnote[1]++;
259
154
  }
260
-
261
- if (A->nextnote[1] <= track->nlen)
262
- moreframes++;
155
+ else if (A->frames < frames)
156
+ break;
157
+ frames += (int)(tempo2frames(B->tempo) * (4.0f / note->duration));
263
158
  }
264
- else
265
- {
159
+
160
+ if (A->frames <= frames)
266
161
  moreframes++;
267
- }
162
+ }
163
+ else
164
+ {
165
+ moreframes++;
166
+ }
268
167
 
269
- A->frames++;
168
+ A->frames++;
270
169
 
271
- if (A->state == BLOOPS_STOP)
272
- continue;
170
+ if (A->playing == BLOOPS_STOP)
171
+ continue;
273
172
 
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
- }
173
+ samplecount++;
174
+ A->repeat++;
175
+ if (A->limit != 0 && A->repeat >= A->limit)
176
+ {
177
+ A->repeat = 0;
178
+ bloops_ready(B, A, 0);
179
+ }
281
180
 
282
- A->atime++;
283
- if (A->alimit != 0 && A->atime >= A->alimit)
284
- {
285
- A->alimit = 0;
286
- A->period *= A->arp;
287
- }
181
+ A->atime++;
182
+ if (A->alimit != 0 && A->atime >= A->alimit)
183
+ {
184
+ A->alimit = 0;
185
+ A->period *= A->arp;
186
+ }
288
187
 
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
- }
188
+ A->slide += A->dslide;
189
+ A->period *= A->slide;
190
+ if (A->period > A->maxperiod)
191
+ {
192
+ A->period = A->maxperiod;
193
+ if (A->P->limit > 0.0f)
194
+ A->playing = BLOOPS_STOP;
195
+ }
297
196
 
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
- }
197
+ float rfperiod = A->period;
198
+ if (A->vdelay > 0.0f)
199
+ {
200
+ A->vibe += A->vspeed;
201
+ rfperiod = A->period * (1.0 + sin(A->vibe) * A->vdelay);
202
+ }
203
+
204
+ int period = (int)rfperiod;
205
+ if (period < 8) period = 8;
206
+ A->square += A->sweep;
207
+ if(A->square < 0.0f) A->square = 0.0f;
208
+ if(A->square > 0.5f) A->square = 0.5f;
304
209
 
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;
210
+ A->time++;
211
+ if (A->time > A->length[A->stage])
212
+ {
213
+ A->time = 0;
214
+ A->stage++;
215
+ if (A->stage == 3)
216
+ A->playing = BLOOPS_STOP;
217
+ }
218
+
219
+ switch (A->stage) {
220
+ case 0:
221
+ A->volume = (float)A->time / A->length[0];
222
+ break;
223
+ case 1:
224
+ A->volume = 1.0f + pow(1.0f - (float)A->time / A->length[1], 1.0f) * 2.0f * A->P->punch;
225
+ break;
226
+ case 2:
227
+ A->volume = 1.0f - (float)A->time / A->length[2];
228
+ break;
229
+ }
230
+
231
+ A->fphase += A->dphase;
232
+ A->iphase = abs((int)A->fphase);
233
+ if (A->iphase > 1023) A->iphase = 1023;
310
234
 
311
- A->time++;
312
- while (A->time >= A->length[A->stage])
235
+ if (A->filter[7] != 0.0f)
236
+ {
237
+ A->filter[6] *= A->filter[7];
238
+ if (A->filter[6] < 0.00001f) A->filter[6] = 0.00001f;
239
+ if (A->filter[6] > 0.1f) A->filter[6] = 0.1f;
240
+ }
241
+
242
+ float ssample = 0.0f;
243
+ for (si = 0; si < 8; si++)
244
+ {
245
+ float sample = 0.0f;
246
+ A->phase++;
247
+ if (A->phase >= period)
313
248
  {
314
- A->time = 0;
315
- A->stage++;
316
- if (A->stage == 3)
317
- A->state = BLOOPS_STOP;
249
+ A->phase %= period;
250
+ if (A->P->type == BLOOPS_NOISE)
251
+ for (i = 0; i < 32; i++)
252
+ A->noise[i] = frnd(2.0f) - 1.0f;
318
253
  }
319
254
 
320
- switch (A->stage) {
321
- case 0:
322
- A->volume = (float)A->time / A->length[0];
255
+ float fp = (float)A->phase / period;
256
+ switch (A->P->type)
257
+ {
258
+ case BLOOPS_SQUARE:
259
+ if (fp < A->square)
260
+ sample = 0.5f;
261
+ else
262
+ sample = -0.5f;
263
+ break;
264
+ case BLOOPS_SAWTOOTH:
265
+ sample = 1.0f - fp * 2;
323
266
  break;
324
- case 1:
325
- A->volume = 1.0f + (1.0f - (float)A->time / A->length[1]) * 2.0f * A->params.punch;
267
+ case BLOOPS_SINE:
268
+ sample = (float)sin(fp * 2 * PI);
326
269
  break;
327
- case 2:
328
- A->volume = 1.0f - (float)A->time / A->length[2];
270
+ case BLOOPS_NOISE:
271
+ sample = A->noise[A->phase * 32 / period];
329
272
  break;
330
273
  }
331
274
 
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)
275
+ float pp = A->filter[0];
276
+ A->filter[2] *= A->filter[3];
277
+ if (A->filter[2] < 0.0f) A->filter[2] = 0.0f;
278
+ if (A->filter[2] > 0.1f) A->filter[2] = 0.1f;
279
+ if (A->P->lpf != 1.0f)
337
280
  {
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;
281
+ A->filter[1] += (sample - A->filter[0]) * A->filter[2];
282
+ A->filter[1] -= A->filter[1] * A->filter[4];
341
283
  }
342
-
343
- float ssample = 0.0f;
344
- for (si = 0; si < 8; si++)
284
+ else
345
285
  {
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];
286
+ A->filter[0] = sample;
287
+ A->filter[1] = 0.0f;
288
+ }
289
+ A->filter[0] += A->filter[1];
395
290
 
396
- A->phaser[A->phasex & 1023] = sample;
397
- sample += A->phaser[(A->phasex - A->iphase + 1024) & 1023];
398
- A->phasex = (A->phasex + 1) & 1023;
291
+ A->filter[5] += A->filter[0] - pp;
292
+ A->filter[5] -= A->filter[5] * A->filter[6];
293
+ sample = A->filter[5];
399
294
 
400
- ssample += sample * A->volume;
401
- }
402
- ssample = ssample / 8 * B->volume;
403
- ssample *= 2.0f * A->params.volume;
295
+ A->phaser[A->phasex & 1023] = sample;
296
+ sample += A->phaser[(A->phasex - A->iphase + 1024) & 1023];
297
+ A->phasex = (A->phasex + 1) & 1023;
404
298
 
405
- if (ssample > 1.0f) ssample = 1.0f;
406
- if (ssample < -1.0f) ssample = -1.0f;
407
- allsample += ssample;
299
+ ssample += sample * A->volume;
408
300
  }
409
- if (moreframes == 0)
410
- B->state = BLOOPS_STOP;
301
+ ssample = ssample / 8 * B->volume;
302
+ ssample *= 2.0f * A->P->volume;
303
+
304
+ if (ssample > 1.0f) ssample = 1.0f;
305
+ if (ssample < -1.0f) ssample = -1.0f;
306
+ allsample += ssample;
411
307
  }
412
308
 
309
+ if (moreframes == 0)
310
+ B->play = BLOOPS_STOP;
413
311
  *buffer++ = allsample;
414
312
  }
415
313
  }
@@ -418,179 +316,168 @@ static int bloops_port_callback(const void *inputBuffer, void *outputBuffer,
418
316
  unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo,
419
317
  PaStreamCallbackFlags statusFlags, void *data)
420
318
  {
319
+ int i;
421
320
  float *out = (float*)outputBuffer;
422
- bloops_synth(framesPerBuffer, out);
423
- return paContinue;
321
+ bloops *B = (bloops *)data;
322
+
323
+ if (B->play == BLOOPS_PLAY) {
324
+ bloops_synth(B, framesPerBuffer, out);
325
+ }
326
+ else
327
+ for(i = 0; i < framesPerBuffer; i++)
328
+ *out++ = 0.0f;
329
+
330
+ return 0;
424
331
  }
425
332
 
426
333
  void
427
- bloops_play(bloops *B)
334
+ bloops_prep(bloops *B)
428
335
  {
429
336
  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;
337
+ for (i = 0; i < BLOOPS_MAX_TRACKS; i++)
338
+ if (B->tracks[i] != NULL) {
339
+ bloops_ready(B, B->tracks[i], 1);
340
+ B->tracks[i]->frames = 0;
441
341
  }
442
- }
342
+ B->play = BLOOPS_PLAY;
343
+ }
443
344
 
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;
345
+ void
346
+ bloops_play(bloops *B)
347
+ {
348
+ bloops_prep(B);
349
+
350
+ if (B->stream == NULL) {
351
+ if (!bloops_open++)
352
+ {
353
+ srand(time(NULL));
354
+ Pa_Initialize();
453
355
  }
454
- }
455
356
 
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);
357
+ Pa_OpenDefaultStream(&B->stream, 0, 1, paFloat32,
358
+ SAMPLE_RATE, FRAMES_PER_BUFFER, bloops_port_callback, B);
359
+ Pa_StartStream(B->stream);
461
360
  }
462
361
  }
463
362
 
464
- void
465
- bloops_stop(bloops *B)
363
+ int
364
+ bloops_record(bloops *B, char *path)
466
365
  {
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;
366
+ // setup sndfile
367
+ SF_INFO info;
368
+ info.samplerate = SAMPLE_RATE;
369
+ info.channels = 1;
370
+ info.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT;
371
+
372
+ SNDFILE *sndfile = sf_open(path, SFM_WRITE, &info);
373
+ if (sndfile) {
374
+ bloops_prep(B);
375
+
376
+ float *buffer = (float *)malloc(sizeof(float)*FRAMES_PER_BUFFER);
377
+ while(!bloops_is_done(B)) {
378
+ bloops_synth(B, FRAMES_PER_BUFFER, buffer);
379
+ sf_write_float(sndfile, buffer, FRAMES_PER_BUFFER);
380
+ }
381
+ sf_close(sndfile);
382
+ free(buffer);
383
+ return 0;
478
384
  }
385
+ return 1;
479
386
  }
480
387
 
481
388
  bloopsaphone *
482
389
  bloops_square()
483
390
  {
484
391
  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;
392
+ P->type = BLOOPS_SQUARE;
393
+ P->volume = 0.5f;
394
+ P->sustain = 0.3f;
395
+ P->decay = 0.4f;
396
+ P->freq = 0.3f;
397
+ P->lpf = 1.0f;
492
398
  return P;
493
399
  }
494
400
 
495
- static int bloops_open = 0;
401
+ bloopsaphone *
402
+ bloops_load(char* filename)
403
+ {
404
+ bloopsaphone *P = NULL;
405
+ FILE* file = fopen(filename, "rb");
406
+ if (!file) return NULL;
407
+
408
+ int version = 0;
409
+ fread(&version, 1, sizeof(int), file);
410
+ if (version != 102)
411
+ return NULL;
412
+
413
+ P = (bloopsaphone *)malloc(sizeof(bloopsaphone));
414
+ fread(&P->type, 1, sizeof(int), file);
415
+
416
+ P->volume = 0.5f;
417
+ fread(&P->volume, 1, sizeof(float), file);
418
+ fread(&P->freq, 1, sizeof(float), file);
419
+ fread(&P->limit, 1, sizeof(float), file);
420
+ fread(&P->slide, 1, sizeof(float), file);
421
+ fread(&P->dslide, 1, sizeof(float), file);
422
+ fread(&P->square, 1, sizeof(float), file);
423
+ fread(&P->sweep, 1, sizeof(float), file);
424
+
425
+ fread(&P->vibe, 1, sizeof(float), file);
426
+ fread(&P->vspeed, 1, sizeof(float), file);
427
+ fread(&P->vdelay, 1, sizeof(float), file);
428
+
429
+ fread(&P->attack, 1, sizeof(float), file);
430
+ fread(&P->sustain, 1, sizeof(float), file);
431
+ fread(&P->decay, 1, sizeof(float), file);
432
+ fread(&P->punch, 1, sizeof(float), file);
433
+
434
+ fread(&P->resonance, 1, sizeof(float), file);
435
+ fread(&P->lpf, 1, sizeof(float), file);
436
+ fread(&P->lsweep, 1, sizeof(float), file);
437
+ fread(&P->hpf, 1, sizeof(float), file);
438
+ fread(&P->hsweep, 1, sizeof(float), file);
439
+
440
+ fread(&P->phase, 1, sizeof(float), file);
441
+ fread(&P->psweep, 1, sizeof(float), file);
442
+
443
+ fread(&P->repeat, 1, sizeof(float), file);
444
+ fread(&P->arp, 1, sizeof(float), file);
445
+ fread(&P->aspeed, 1, sizeof(float), file);
446
+
447
+ fclose(file);
448
+ return P;
449
+ }
496
450
 
497
451
  bloops *
498
- bloops_new()
452
+ bloops_new(char *path)
499
453
  {
500
- int i;
501
454
  bloops *B = (bloops *)malloc(sizeof(bloops));
502
- B->refcount = 1;
503
455
  B->volume = 0.10f;
504
456
  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
- }
457
+ B->play = BLOOPS_STOP;
458
+ bloops_clear(B);
519
459
 
520
460
  return B;
521
461
  }
522
462
 
523
- void
524
- bloops_ref(bloops *B)
525
- {
526
- B->refcount++;
527
- }
528
-
529
463
  void
530
464
  bloops_destroy(bloops *B)
531
465
  {
532
- if (--B->refcount) {
533
- return;
466
+ if (B->stream != NULL) {
467
+ Pa_StopStream(B->stream);
468
+ Pa_CloseStream(B->stream);
534
469
  }
535
470
 
536
- bloops_remove(B);
537
471
  free((void *)B);
538
472
 
539
473
  if (!--bloops_open)
540
- {
541
474
  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
475
  }
570
476
 
571
477
  void
572
478
  bloops_track_destroy(bloopsatrack *track)
573
479
  {
574
- if (--track->refcount) {
575
- return;
576
- }
577
- if (track->notes != NULL) {
578
- bloops_notes_destroy(track->notes, track->nlen);
579
- }
480
+ if (track->notes != NULL)
481
+ free(track->notes);
580
482
  free(track);
581
483
  }
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
- }