picotune 0.0.5 → 0.0.6
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 +49 -20
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0ecca785ebf3408cba41634a5b8fcaf831f4c2fd0491ca9b1a44490e874a7d5b
|
4
|
+
data.tar.gz: 9b1dce6e5835dbcc4c15cf5f35093305745ffdad355b9e5bc29f1cc79081fbec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6acaaf48a00c73696d870fe31976f49712f557b76733c093d9f10b16a1083ec80e9479298fee97736fcc1e6fcc954c0e7871e85aeb29c3d50b0867ce26aee996
|
7
|
+
data.tar.gz: 78569c71d4dacb1f8997b39de1708d807ef52f8b609aff8bac4d461c92fdf5ff95b5188b2718b143efe1b2134dfc06c25d70c7540b26ee5e3a6af0895b335b87
|
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
|
|
@@ -285,6 +306,7 @@ 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
311
|
def initialize name, tone = 0, length = 'full', volume = 'full', pan = 'center', reverb = 'none'
|
290
312
|
@name = name
|
@@ -369,16 +391,23 @@ class PicoTune::Instrument
|
|
369
391
|
|
370
392
|
def wave wave_index, note
|
371
393
|
frequency = frequency_for_note note
|
372
|
-
samples_per_wave = (PicoTune::SAMPLE_RATE / frequency).
|
394
|
+
samples_per_wave = (PicoTune::SAMPLE_RATE / frequency).to_i
|
373
395
|
sample = PicoTune::WaveSample.new(@tone, samples_per_wave).sample wave_index
|
374
396
|
sample.modify_left :*, volume_value * (1 - pan_value / 4.0)
|
375
397
|
sample.modify_right :*, volume_value * (pan_value / 4.0)
|
398
|
+
|
399
|
+
if v = phrase&.tune&.volume_factor_for_simultaneous_melodies
|
400
|
+
sample.modify_left :*, v
|
401
|
+
sample.modify_right :*, v
|
402
|
+
end
|
403
|
+
|
376
404
|
sample
|
377
405
|
end
|
378
406
|
|
379
407
|
def samples_per_wave note
|
380
408
|
frequency = frequency_for_note note
|
381
|
-
(PicoTune::SAMPLE_RATE / frequency).
|
409
|
+
(PicoTune::SAMPLE_RATE / frequency).to_i
|
410
|
+
end
|
382
411
|
|
383
412
|
def frequency_for_note note
|
384
413
|
parts = note.split ''
|
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.6
|
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-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: wavefile
|