picotune 0.0.4 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/picotune.rb +66 -31
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: de0cea1678fa0056bb4da4e3a016166160b1e1190a13f067f38d6cf620d07a54
|
4
|
+
data.tar.gz: f18fb53c744d050f6cf6632855fbd239fb4cd3ce45fa636f18dc27d65f42355c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e745f4dd1af6767c828f711019a8c3a2c9f16027b5a7dba7647c519e2dfe06fa24ec8a00c51219b599092854f1a1e7b5918801846684d2b4ded7b1403fd50771
|
7
|
+
data.tar.gz: d532fac56aac02ad6353c3328ed2baca6a968566bbe721dbec25e7969ccb5e7f73b7b60b4869ddfa49a5e27eb17e7cc6dc5acd2fc90d186c1b7f94308a9ad189
|
data/lib/picotune.rb
CHANGED
@@ -49,17 +49,18 @@ class PicoTune::Sample
|
|
49
49
|
@left += sample.left
|
50
50
|
@right += sample.right
|
51
51
|
|
52
|
-
#
|
52
|
+
# hard clip
|
53
|
+
|
53
54
|
if @left > 1.0
|
54
|
-
@left = 1.0
|
55
|
+
@left = 1.0
|
55
56
|
elsif @left < -1.0
|
56
|
-
@left = -1.0
|
57
|
+
@left = -1.0
|
57
58
|
end
|
58
59
|
|
59
60
|
if @right > 1.0
|
60
|
-
@right = 1.0
|
61
|
+
@right = 1.0
|
61
62
|
elsif @right < -1.0
|
62
|
-
@right = -1.0
|
63
|
+
@right = -1.0
|
63
64
|
end
|
64
65
|
|
65
66
|
self # return self to chain ops EX: sample.add(sample).add(sample) etc
|
@@ -75,10 +76,9 @@ class PicoTune::Sample
|
|
75
76
|
end
|
76
77
|
|
77
78
|
class PicoTune::WaveSample
|
78
|
-
def initialize tone, samples_per_wave
|
79
|
+
def initialize tone, samples_per_wave
|
79
80
|
@tone = tone
|
80
81
|
@samples_per_wave = samples_per_wave
|
81
|
-
@multiplier = multiplier
|
82
82
|
end
|
83
83
|
|
84
84
|
def sample index
|
@@ -101,43 +101,42 @@ class PicoTune::WaveSample
|
|
101
101
|
end
|
102
102
|
|
103
103
|
def sine index
|
104
|
-
Math.sin(index / (@samples_per_wave / (Math::PI * 2)))
|
104
|
+
Math.sin(index / (@samples_per_wave / (Math::PI * 2)))
|
105
105
|
end
|
106
106
|
|
107
107
|
def saw index
|
108
108
|
interval = @samples_per_wave / 2
|
109
109
|
half_interval = interval / 2
|
110
110
|
percent = ((index + half_interval) % interval) / interval.to_f
|
111
|
-
((0.6 * percent) - 0.3)
|
111
|
+
((0.6 * percent) - 0.3)
|
112
112
|
end
|
113
113
|
|
114
114
|
def square index
|
115
|
-
(index <= @samples_per_wave / 2 ? 1.0 : -1.0)
|
115
|
+
(index <= @samples_per_wave / 2 ? 1.0 : -1.0)
|
116
116
|
end
|
117
117
|
|
118
118
|
def noise index
|
119
119
|
value = sine index
|
120
120
|
rand = Random.rand - 0.5
|
121
|
-
value * rand
|
121
|
+
value * rand
|
122
122
|
end
|
123
123
|
|
124
124
|
def triangle index
|
125
125
|
half = @samples_per_wave / 2
|
126
126
|
quarter = @samples_per_wave / 4
|
127
127
|
ramp = 1.0 / quarter
|
128
|
-
m = @multiplier || 0.5
|
129
128
|
|
130
129
|
if index <= half
|
131
130
|
if index <= quarter
|
132
|
-
index * ramp
|
131
|
+
index * ramp
|
133
132
|
else
|
134
|
-
(half - index) * ramp
|
133
|
+
(half - index) * ramp
|
135
134
|
end
|
136
135
|
else
|
137
136
|
if index <= half + quarter
|
138
|
-
-((index - half) * ramp)
|
137
|
+
-((index - half) * ramp)
|
139
138
|
else
|
140
|
-
-((@samples_per_wave - index) * ramp)
|
139
|
+
-((@samples_per_wave - index) * ramp)
|
141
140
|
end
|
142
141
|
end
|
143
142
|
end
|
@@ -150,6 +149,22 @@ class PicoTune::Tune
|
|
150
149
|
@name = name
|
151
150
|
@sequence = sequence
|
152
151
|
@phrases = phrases
|
152
|
+
|
153
|
+
@phrases.each do |p|
|
154
|
+
p.tune = self
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def volume_factor_for_simultaneous_melodies
|
159
|
+
max_melodies_in_phrases = 0
|
160
|
+
|
161
|
+
@phrases.each do |phrase|
|
162
|
+
if phrase.simultaneous_melodies > max_melodies_in_phrases
|
163
|
+
max_melodies_in_phrases = phrase.simultaneous_melodies
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
1.0 / max_melodies_in_phrases if max_melodies_in_phrases > 0
|
153
168
|
end
|
154
169
|
|
155
170
|
def buffer
|
@@ -193,7 +208,8 @@ class PicoTune::Tune
|
|
193
208
|
end
|
194
209
|
|
195
210
|
class PicoTune::Phrase
|
196
|
-
attr_reader :name, :tempo, :beats, :subbeats, :melodies
|
211
|
+
attr_reader :name, :tempo, :beats, :subbeats, :melodies, :simultaneous_melodies
|
212
|
+
attr_accessor :tune
|
197
213
|
|
198
214
|
def initialize name, tempo, beats, subbeats, melodies
|
199
215
|
@name = name
|
@@ -201,6 +217,11 @@ class PicoTune::Phrase
|
|
201
217
|
@beats = beats.to_i
|
202
218
|
@subbeats = subbeats.to_i
|
203
219
|
@melodies = melodies
|
220
|
+
@simultaneous_melodies = @melodies.count
|
221
|
+
|
222
|
+
@melodies.each do |m|
|
223
|
+
m.instrument.phrase = self
|
224
|
+
end
|
204
225
|
end
|
205
226
|
|
206
227
|
def seconds_per_beat
|
@@ -221,7 +242,7 @@ class PicoTune::Phrase
|
|
221
242
|
|
222
243
|
@melodies.each do |melody|
|
223
244
|
temp = Array.new(buffer_size) { PicoTune::Sample.new } if melody.instrument.reverb?
|
224
|
-
sub_buffer_size =
|
245
|
+
sub_buffer_size = buffer_size / (@beats * @subbeats)
|
225
246
|
last_step_number = -1
|
226
247
|
carry_over = 0
|
227
248
|
|
@@ -269,7 +290,7 @@ class PicoTune::Phrase
|
|
269
290
|
temp[i + melody.instrument.reverb_offset] = verb_sample
|
270
291
|
end
|
271
292
|
|
272
|
-
samples[i] = samples[i].add temp[i]
|
293
|
+
samples[i] = (samples[i] || PicoTune::Sample.new).add temp[i]
|
273
294
|
|
274
295
|
i += 1
|
275
296
|
end
|
@@ -285,8 +306,9 @@ end
|
|
285
306
|
|
286
307
|
class PicoTune::Instrument
|
287
308
|
attr_reader :name, :tone, :length, :volume, :pan, :reverb
|
309
|
+
attr_accessor :phrase
|
288
310
|
|
289
|
-
def initialize name, tone
|
311
|
+
def initialize name, tone, length, volume, pan, reverb
|
290
312
|
@name = name
|
291
313
|
@tone = tone
|
292
314
|
@length = length
|
@@ -307,6 +329,8 @@ class PicoTune::Instrument
|
|
307
329
|
0.75
|
308
330
|
when 'full'
|
309
331
|
1.0
|
332
|
+
else
|
333
|
+
1.0
|
310
334
|
end
|
311
335
|
end
|
312
336
|
|
@@ -322,6 +346,8 @@ class PicoTune::Instrument
|
|
322
346
|
0.75
|
323
347
|
when 'full'
|
324
348
|
1.0
|
349
|
+
else
|
350
|
+
1.0
|
325
351
|
end
|
326
352
|
end
|
327
353
|
|
@@ -337,11 +363,13 @@ class PicoTune::Instrument
|
|
337
363
|
3
|
338
364
|
when 'right'
|
339
365
|
4
|
366
|
+
else
|
367
|
+
2
|
340
368
|
end
|
341
369
|
end
|
342
370
|
|
343
371
|
def delay
|
344
|
-
@reverb == 'none' ? 0.0 : 0.
|
372
|
+
@reverb == 'none' ? 0.0 : 0.08
|
345
373
|
end
|
346
374
|
|
347
375
|
def decay
|
@@ -349,11 +377,11 @@ class PicoTune::Instrument
|
|
349
377
|
when 'none'
|
350
378
|
0.0
|
351
379
|
when 'some'
|
352
|
-
0.
|
380
|
+
0.1
|
353
381
|
when 'more'
|
354
|
-
0.
|
382
|
+
0.3
|
355
383
|
when 'lots'
|
356
|
-
0.
|
384
|
+
0.5
|
357
385
|
else
|
358
386
|
0.0
|
359
387
|
end
|
@@ -369,16 +397,23 @@ class PicoTune::Instrument
|
|
369
397
|
|
370
398
|
def wave wave_index, note
|
371
399
|
frequency = frequency_for_note note
|
372
|
-
samples_per_wave = (PicoTune::SAMPLE_RATE / frequency).
|
400
|
+
samples_per_wave = (PicoTune::SAMPLE_RATE / frequency).to_i
|
373
401
|
sample = PicoTune::WaveSample.new(@tone, samples_per_wave).sample wave_index
|
374
402
|
sample.modify_left :*, volume_value * (1 - pan_value / 4.0)
|
375
403
|
sample.modify_right :*, volume_value * (pan_value / 4.0)
|
404
|
+
|
405
|
+
if v = phrase&.tune&.volume_factor_for_simultaneous_melodies
|
406
|
+
sample.modify_left :*, v
|
407
|
+
sample.modify_right :*, v
|
408
|
+
end
|
409
|
+
|
376
410
|
sample
|
377
411
|
end
|
378
412
|
|
379
413
|
def samples_per_wave note
|
380
414
|
frequency = frequency_for_note note
|
381
|
-
(PicoTune::SAMPLE_RATE / frequency).
|
415
|
+
(PicoTune::SAMPLE_RATE / frequency).to_i
|
416
|
+
end
|
382
417
|
|
383
418
|
def frequency_for_note note
|
384
419
|
parts = note.split ''
|
@@ -434,11 +469,11 @@ class PicoTune::Assembler
|
|
434
469
|
instruments = list.select { |item| item['type'] == 'instrument' }.map do |item|
|
435
470
|
PicoTune::Instrument.new(
|
436
471
|
item['name'],
|
437
|
-
item['tone'],
|
438
|
-
item['length'],
|
439
|
-
item['volume'],
|
440
|
-
item['pan'],
|
441
|
-
item['reverb']
|
472
|
+
item['tone'] || 'sine',
|
473
|
+
item['length'] || 'full',
|
474
|
+
item['volume'] || 'full',
|
475
|
+
item['pan'] || 'center',
|
476
|
+
item['reverb'] || 'none'
|
442
477
|
)
|
443
478
|
end
|
444
479
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: picotune
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Zachary Schroeder
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-10-
|
11
|
+
date: 2021-10-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: wavefile
|
@@ -25,6 +25,7 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 1.1.1
|
27
27
|
description: Use a text file with a simple DSL to generate a musical (maybe) wav file.
|
28
|
+
See https://github.com/robobluebird/picotune for DSL documentation!
|
28
29
|
email: schroza@gmail.com
|
29
30
|
executables:
|
30
31
|
- picotune
|
@@ -33,10 +34,13 @@ extra_rdoc_files: []
|
|
33
34
|
files:
|
34
35
|
- bin/picotune
|
35
36
|
- lib/picotune.rb
|
36
|
-
homepage: https://
|
37
|
+
homepage: https://github.com/robobluebird/picotune
|
37
38
|
licenses:
|
38
39
|
- MIT
|
39
|
-
metadata:
|
40
|
+
metadata:
|
41
|
+
documentation_uri: https://github.com/robobluebird/picotune
|
42
|
+
homepage_uri: https://github.com/robobluebird/picotune
|
43
|
+
source_code_uri: https://github.com/robobluebird/picotune
|
40
44
|
post_install_message:
|
41
45
|
rdoc_options: []
|
42
46
|
require_paths:
|