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.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/picotune.rb +49 -20
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 420d900e79e43c6c4707fdf1475659527d486713959829ba8919016643727e49
4
- data.tar.gz: 5d4ddd69133f82d076bc7b74110a2d1c6b3a346e9155eae17c094506bbb24794
3
+ metadata.gz: 0ecca785ebf3408cba41634a5b8fcaf831f4c2fd0491ca9b1a44490e874a7d5b
4
+ data.tar.gz: 9b1dce6e5835dbcc4c15cf5f35093305745ffdad355b9e5bc29f1cc79081fbec
5
5
  SHA512:
6
- metadata.gz: 6c1e615d6ee4d1d35cfdefb97badb5c2c27a99ff35684db59c0a3c959177d3f74e29e359c0839ab13ab95f76134d847b5ae0faf97402a9531561b27051e28695
7
- data.tar.gz: b0c17d66fe3841a45a871cdafbc5a4d1f8a542827c0af72fcd83e59da1d061881f5ff37a53cf96201c01a379c573aaebbd4a4e185af68c22ae76fb97f7b911cd
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
- # "foldback" instead of hard clipping, sounds cool
52
+ # hard clip
53
+
53
54
  if @left > 1.0
54
- @left = 1.0 - (@left - 1.0) # ex: 1.0 - (1.2 - 1.0) => 1.0 - 0.2 => 0.8
55
+ @left = 1.0
55
56
  elsif @left < -1.0
56
- @left = -1.0 - (@left + 1.0) # ex: -1.0 - (-1.2 + 1.0) => -1.0 - -0.2 => -0.8
57
+ @left = -1.0
57
58
  end
58
59
 
59
60
  if @right > 1.0
60
- @right = 1.0 - (@right - 1.0)
61
+ @right = 1.0
61
62
  elsif @right < -1.0
62
- @right = -1.0 - (@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, multiplier = nil
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))) * (@multiplier || 0.5)
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) * (@multiplier || 0.5)
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) * (@multiplier || 0.25)
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 * (@multiplier || 0.5)
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 * m
131
+ index * ramp
133
132
  else
134
- (half - index) * ramp * m
133
+ (half - index) * ramp
135
134
  end
136
135
  else
137
136
  if index <= half + quarter
138
- -((index - half) * ramp) * m
137
+ -((index - half) * ramp)
139
138
  else
140
- -((@samples_per_wave - index) * ramp) * m
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 = (buffer_size.to_f / (@beats * @subbeats)).ceil
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).ceil
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).ceil end
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.5
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-13 00:00:00.000000000 Z
11
+ date: 2021-10-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: wavefile