music_coder 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/api/api.rb +108 -0
- data/lib/api/dist.rb +145 -0
- data/lib/api/hit_sq.rb +108 -0
- data/lib/api/note.rb +59 -0
- data/lib/api/snd.rb +62 -0
- data/lib/audio.rb +48 -0
- data/lib/audio_output.rb +110 -0
- data/lib/composer.rb +164 -0
- data/lib/fader.rb +37 -0
- data/lib/file_list.rb +202 -0
- data/lib/logger.rb +39 -0
- data/lib/math_utils.rb +64 -0
- data/lib/mixer.rb +14 -0
- data/lib/music_coder.rb +192 -0
- data/lib/snd_dist.rb +104 -0
- data/lib/tests.rb +168 -0
- data/lib/tone.rb +136 -0
- data/lib/tone_part.rb +96 -0
- data/lib/tone_seq.rb +42 -0
- data/lib/wave.rb +77 -0
- data/lib/wave_data.rb +103 -0
- metadata +85 -0
data/lib/audio.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# All disc operations.
|
2
|
+
class App
|
3
|
+
|
4
|
+
def App.open_w_audiofile file
|
5
|
+
raise "no file name to open for writting. " if file.nil? || App.fileoptions.nil?
|
6
|
+
# puts "#{file} #{App.fileoptions}"
|
7
|
+
Sndfile::File.open(file, App.fileoptions)
|
8
|
+
end
|
9
|
+
def self.m_from_array data
|
10
|
+
write_matrix = GSLng::Matrix.from_array(data)
|
11
|
+
write_matrix.transpose
|
12
|
+
end
|
13
|
+
|
14
|
+
def App.write_to_audiofile fout, array
|
15
|
+
fout.write App.m_from_array array
|
16
|
+
GC.start
|
17
|
+
end
|
18
|
+
|
19
|
+
def App.open_write(filen)
|
20
|
+
File.open(filen, 'w')
|
21
|
+
end
|
22
|
+
|
23
|
+
def App.close_write(fi)
|
24
|
+
fi.close
|
25
|
+
end
|
26
|
+
|
27
|
+
def App.split_array(array, size)
|
28
|
+
upto=0
|
29
|
+
ammont=array.count
|
30
|
+
jump=size
|
31
|
+
out = []
|
32
|
+
while upto < ammont do
|
33
|
+
# puts "upto #{upto} amount #{ammont}"
|
34
|
+
jump = ammont - upto if upto+jump >= ammont
|
35
|
+
# puts "array range #{upto} to #{upto+jump-1}"
|
36
|
+
out << array[upto..upto+jump-1]
|
37
|
+
upto+=jump
|
38
|
+
end
|
39
|
+
out
|
40
|
+
end
|
41
|
+
def App.read_chunk_of(array, start=0, chunk_size)
|
42
|
+
array[start..start+chunk_size-1]
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
require 'sndfile'
|
data/lib/audio_output.rb
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
class AudioOutput
|
2
|
+
# add all other fls to this
|
3
|
+
attr_accessor :filelist
|
4
|
+
#this didn't need to be an array, but maybe use it for track mixing?
|
5
|
+
attr_accessor :snddists
|
6
|
+
attr_accessor :outfile
|
7
|
+
# of file write
|
8
|
+
attr_accessor :percent_complete
|
9
|
+
|
10
|
+
def initialize()
|
11
|
+
@snddists = []
|
12
|
+
@outfile = nil
|
13
|
+
@filelist= FileList.new
|
14
|
+
@percent_complete = 0
|
15
|
+
end
|
16
|
+
def render
|
17
|
+
log "phase 1 of 2: render sounds", 2
|
18
|
+
App.done=0
|
19
|
+
App.total=0
|
20
|
+
snddists.each {|snddist| App.total+=snddist.tally_frames}
|
21
|
+
# puts "App.total #{App.total}" # Only for progress bar
|
22
|
+
snddists.each {|snddist| self.filelist.addlist snddist.render }
|
23
|
+
log "phase 1 complete.", 2
|
24
|
+
end
|
25
|
+
def make_audio_file
|
26
|
+
log "phase 2 of 2: merging all tmp files into #{App::EXT} file. == #{App.time_since}", 2
|
27
|
+
frames_index = 0
|
28
|
+
len = 0
|
29
|
+
# get max len
|
30
|
+
snddists.each { |sn| len = sn.len if sn.len > len }
|
31
|
+
len = len.round
|
32
|
+
fout = App.open_w_audiofile outfile
|
33
|
+
App.checks = 0 # for performance testing
|
34
|
+
last_jump=0
|
35
|
+
while frames_index < len
|
36
|
+
|
37
|
+
if frames_index + App::CHUNK_SIZE >= len
|
38
|
+
# set jump to finish it off since it's under chunk size
|
39
|
+
rest = len - frames_index #1 min, chunk_size max.
|
40
|
+
jump = rest
|
41
|
+
log "capping chunk size at #{jump}", 4
|
42
|
+
else
|
43
|
+
jump=App::CHUNK_SIZE
|
44
|
+
end
|
45
|
+
|
46
|
+
values_for_write = []
|
47
|
+
# while values_for_write.count < jump
|
48
|
+
# if frames_index-last_jump >= jump
|
49
|
+
# puts "frames index was #{frames_index} jump was #{jump}"
|
50
|
+
# puts "jump neeeds to be > #{frames_index-last_jump}"
|
51
|
+
# jump = App::CHUNK_SIZE
|
52
|
+
# end
|
53
|
+
|
54
|
+
# jump=frames_index+10000
|
55
|
+
|
56
|
+
while frames_index-last_jump < jump
|
57
|
+
# minimize if too big
|
58
|
+
if frames_index-last_jump+jump > len
|
59
|
+
jump = len-frames_index-last_jump
|
60
|
+
log "minimizing this chunk to #{jump}", 4
|
61
|
+
end
|
62
|
+
log "CHUNK_@#{frames_index} asked for #{jump}. total: #{len}", 4
|
63
|
+
values = filelist.root_get_value(frames_index,jump)#, jump)+
|
64
|
+
# if values.count==0
|
65
|
+
# puts "VALUES RETURNED 0"
|
66
|
+
# frames_index = len # end this shit
|
67
|
+
# end
|
68
|
+
# puts "CHUNK recieved #{values.count} "
|
69
|
+
# puts "--> read #{values.join(', ')}"
|
70
|
+
values_for_write+= values
|
71
|
+
# puts "____#{found_vals}"
|
72
|
+
# values.add_e found_vals
|
73
|
+
# raise " couldn't find a value... fuck." if found_val.nil?
|
74
|
+
# print percent
|
75
|
+
frames_index += values.count
|
76
|
+
App.logger.print_loading_bar(frames_index, len, percent_complete)
|
77
|
+
self.percent_complete = ((frames_index.to_f/len)*100)
|
78
|
+
# values=nil
|
79
|
+
# GC.start
|
80
|
+
end
|
81
|
+
last_jump=frames_index
|
82
|
+
# puts "--> to write: #{values_for_write.count} #{frames_index} #{len}"
|
83
|
+
App.write_to_audiofile fout, values_for_write if values_for_write.count>0
|
84
|
+
# values_for_write=nil
|
85
|
+
# GC.start
|
86
|
+
end
|
87
|
+
App.close_write fout
|
88
|
+
log "performed #{App.checks} lookup checks.", 4
|
89
|
+
print_tail_info len
|
90
|
+
end
|
91
|
+
def write_text_files file=nil
|
92
|
+
file = App.outpath + "save.rb" if file.nil?
|
93
|
+
log "state save to file #{file}", 2
|
94
|
+
File.open(file, 'w') do |file|
|
95
|
+
# snddists.each do |snddist|
|
96
|
+
# file.puts YAML::dump(snddist)
|
97
|
+
# end
|
98
|
+
file.puts YAML::dump(self)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
def print_tail_info total_frames
|
102
|
+
time_taken = App.time_since
|
103
|
+
log 'wrote file: ' + outfile, 1
|
104
|
+
log 'seconds: ' + (total_frames.to_f / Composer.samplerate).round(2).to_s +
|
105
|
+
" (frames: #{(total_frames/1000).round},000)", 2
|
106
|
+
log 'time taken: ' + time_taken.round(2).to_s +
|
107
|
+
" seconds (fps: #{(total_frames/time_taken/1000).round()},000)", 2
|
108
|
+
end
|
109
|
+
|
110
|
+
end#class
|
data/lib/composer.rb
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
# contains the functions a music composer needs.
|
2
|
+
# all functions are related to music instead of audio.
|
3
|
+
class Composer
|
4
|
+
class << self
|
5
|
+
#beats per minute of the track. (Set this first thing in your input file)
|
6
|
+
attr_accessor :bpm
|
7
|
+
#fames per second
|
8
|
+
attr_accessor :samplerate
|
9
|
+
end
|
10
|
+
def self.chords
|
11
|
+
all = Hash.new
|
12
|
+
#Triads
|
13
|
+
all["maj"] = [4, 7] # major
|
14
|
+
all["min"] = [3, 7] # minor
|
15
|
+
all["aug"] = [4, 8] # augmented
|
16
|
+
all["dim"] = [3, 6] # diminished
|
17
|
+
|
18
|
+
#Seventh chords
|
19
|
+
all["dim7"] = [3, 6, 9] # diminished 7th
|
20
|
+
all["mm7"] = [3, 7, 11] # major minor 7th
|
21
|
+
all["min7"] = [3, 7, 10] # minor 7th
|
22
|
+
all["dom7"] = [4, 7, 10] # dominant 7th
|
23
|
+
all["maj7"] = [4, 7, 11] # major 7th
|
24
|
+
# half diminished
|
25
|
+
# augmented
|
26
|
+
# augmented major
|
27
|
+
|
28
|
+
all["sus4"] = [5, 7]
|
29
|
+
all["sus2"] = [2, 7]
|
30
|
+
all["6"] = [4, 7, 9]
|
31
|
+
all["m13"] = [2, 4, 7, 9, 11]
|
32
|
+
all["9#11"] = [2, 4, 6, 7, 10]
|
33
|
+
all["tonic"] = [6]
|
34
|
+
all
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.scales
|
38
|
+
all = Hash.new
|
39
|
+
all["major"] = [2,4,5,7,9,11] # 7 total
|
40
|
+
all["minor"] = [2,3,5,7,8,10]
|
41
|
+
all["chromatic"] = *(1..10) #splat
|
42
|
+
#all["ionian"] = [2,4,5,7,9,11]
|
43
|
+
all["dorian"] = [2,3,5,7,9,10]
|
44
|
+
all["phygian"] = [1,3,5,7,8,10]
|
45
|
+
all["lydian"] = [2,4,6,7,9,11]
|
46
|
+
all["mixolydian"] = [2,4,5,7,9,10]
|
47
|
+
#all["aeolian"] = [2,3,5,7,8,10]
|
48
|
+
all["locrian"] = [1,3,5,6,8,10]
|
49
|
+
all
|
50
|
+
end
|
51
|
+
|
52
|
+
#outputs the midi notes of the chord in an array
|
53
|
+
#note:: midi value of root note in chord. range: 0 to 11
|
54
|
+
def self.chord_notes(note, name = "dim7")
|
55
|
+
set=[]
|
56
|
+
out=[]
|
57
|
+
all=chords
|
58
|
+
# handle all selected
|
59
|
+
if name=="all"
|
60
|
+
all.keys.each { |val| out.push chord_notes(note, val) }
|
61
|
+
else #normal
|
62
|
+
set = all[name]
|
63
|
+
raise "Unknown scale name" if set.nil?
|
64
|
+
out = [note] # always root
|
65
|
+
set.each do |val|
|
66
|
+
out.push note+val
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
out
|
71
|
+
end
|
72
|
+
|
73
|
+
#outputs the scale name and midi notes in hash
|
74
|
+
#note:: midi value of root note. range: 0 to 11
|
75
|
+
def self.scale_notes(note, name = "major")
|
76
|
+
set=[]
|
77
|
+
out=[]
|
78
|
+
all=scales
|
79
|
+
# handle all selected
|
80
|
+
if name=="all"
|
81
|
+
all.keys.each { |val| out.push scale_notes(note, val) }
|
82
|
+
else #normal
|
83
|
+
set = all[name]
|
84
|
+
raise "Unknown scale name" if set.nil?
|
85
|
+
out = [note] # always root
|
86
|
+
set.each do |val|
|
87
|
+
out.push note+ val
|
88
|
+
end
|
89
|
+
end
|
90
|
+
out
|
91
|
+
end
|
92
|
+
|
93
|
+
# return set of chords that fit in the scale
|
94
|
+
def self.matching_chords(scale = "major", offset = 0)
|
95
|
+
all = chords
|
96
|
+
scale_n = [0] + scales[scale]
|
97
|
+
out = []
|
98
|
+
all.each do |chord|
|
99
|
+
name = chord[0]
|
100
|
+
notes=get_notes all[name], offset # lookup chord with name
|
101
|
+
out.push name if (scale_n¬es).sort==notes.sort # if all notes are in scale
|
102
|
+
end
|
103
|
+
out
|
104
|
+
end
|
105
|
+
|
106
|
+
# return an array of notes from a array of notes with an offset, adding the root note at the start.
|
107
|
+
# e.g. ([1,10,2],2) outputs [2,3,0,4] (root note is 2, 10 + 2 becomes 0, 1 + 2 is 3 etc)
|
108
|
+
def self.get_notes(notes_ar, offset = 0)
|
109
|
+
notes = [0] + notes_ar
|
110
|
+
#offset
|
111
|
+
notes.collect! do |val|
|
112
|
+
if offset >= 0
|
113
|
+
val+offset>11 ? val+offset-12 : val+offset
|
114
|
+
else
|
115
|
+
val+offset<0 ? val+offset+12 : val+offset
|
116
|
+
end
|
117
|
+
end
|
118
|
+
notes
|
119
|
+
end
|
120
|
+
|
121
|
+
# convert beats to seconds
|
122
|
+
# @beat: the beat denominator. ie 4 means 4 beats, .125 means 1 8th beat.
|
123
|
+
def self.beat(beats)
|
124
|
+
bps = (self.bpm/60.0)
|
125
|
+
return (beats) * (1.0/bps) * self.samplerate.to_f
|
126
|
+
end
|
127
|
+
|
128
|
+
#convert a note as a string to midi value
|
129
|
+
#note:: range: "A" to "G#". No a flats.
|
130
|
+
def self.note_m(note)
|
131
|
+
val=nil
|
132
|
+
note.upcase!
|
133
|
+
case note
|
134
|
+
when 'A'
|
135
|
+
val=0
|
136
|
+
when 'A#'
|
137
|
+
val=1
|
138
|
+
when 'B'
|
139
|
+
val=2
|
140
|
+
when 'C'
|
141
|
+
val=3
|
142
|
+
when 'C#'
|
143
|
+
val=4
|
144
|
+
when 'D'
|
145
|
+
val=5
|
146
|
+
when 'D#'
|
147
|
+
val=6
|
148
|
+
when 'E'
|
149
|
+
val=7
|
150
|
+
when 'F'
|
151
|
+
val=8
|
152
|
+
when 'F#'
|
153
|
+
val=9
|
154
|
+
when 'G'
|
155
|
+
val=10
|
156
|
+
when 'G#'
|
157
|
+
val=11
|
158
|
+
else
|
159
|
+
raise "Unknown note name recieved."
|
160
|
+
end
|
161
|
+
val
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
data/lib/fader.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# An initial value, a
|
2
|
+
class Fader
|
3
|
+
# The initial value.
|
4
|
+
attr_accessor :start
|
5
|
+
# The final value.
|
6
|
+
attr_accessor :final
|
7
|
+
# The exponential rate it fades from initial to final.
|
8
|
+
# range:: +0
|
9
|
+
# 0 is linear.
|
10
|
+
# higher than 1 means it reachs the final later than linear.
|
11
|
+
# less than 1 means it reachs the final sooner than linear.
|
12
|
+
attr_accessor :exp
|
13
|
+
def initialize(start=nil,final=nil,exp=0)
|
14
|
+
@start = start
|
15
|
+
@final = final
|
16
|
+
@exp = exp
|
17
|
+
end
|
18
|
+
# set #final to a percentage of start
|
19
|
+
def %(percent)
|
20
|
+
self.final = start.to_f*(percent/100.0)
|
21
|
+
end
|
22
|
+
# operate on both start and final
|
23
|
+
def *(mul=0.5)
|
24
|
+
self.start *= mul
|
25
|
+
self.final *= mul
|
26
|
+
end
|
27
|
+
# getter
|
28
|
+
def exp
|
29
|
+
@exp==0 ? nil : @exp
|
30
|
+
end
|
31
|
+
def exp_no_nil
|
32
|
+
@exp.nil? ? 0 : @exp
|
33
|
+
end
|
34
|
+
def is_eql(other)
|
35
|
+
vars_eql?(other)
|
36
|
+
end
|
37
|
+
end
|
data/lib/file_list.rb
ADDED
@@ -0,0 +1,202 @@
|
|
1
|
+
|
2
|
+
# tree
|
3
|
+
class FileList
|
4
|
+
# ONLY WITH NO CHILDREN
|
5
|
+
attr_accessor :files
|
6
|
+
attr_accessor :file_content_lens
|
7
|
+
attr_accessor :loaded_file_index
|
8
|
+
attr_accessor :loaded_file_data
|
9
|
+
|
10
|
+
# N CHILDREN
|
11
|
+
attr_accessor :filelists
|
12
|
+
# delays of children
|
13
|
+
attr_accessor :filelist_delays
|
14
|
+
# I want each child in the fileslist to fill len frames from my start
|
15
|
+
attr_accessor :child_len, :mark_of_death
|
16
|
+
def initialize()
|
17
|
+
@files = []
|
18
|
+
@loaded_file_index = nil
|
19
|
+
@filelists = []
|
20
|
+
@filelist_delays = []
|
21
|
+
@child_len = 0
|
22
|
+
@file_content_lens=[]
|
23
|
+
@loaded_file_data = nil
|
24
|
+
@mark_of_death = false
|
25
|
+
end
|
26
|
+
|
27
|
+
def root_get_value(index,size=1)
|
28
|
+
out=get_value(index,size)
|
29
|
+
if out.count < 1
|
30
|
+
# raise "Error looking up a value at that index. fatal. index #{index}, size #{size}."
|
31
|
+
out=Array.new(size,0)
|
32
|
+
end
|
33
|
+
out
|
34
|
+
end
|
35
|
+
# return the value, index frames into your files. recursive.
|
36
|
+
def get_value(index,size=1)
|
37
|
+
# puts "requested #{size}"
|
38
|
+
out = []
|
39
|
+
|
40
|
+
if files.empty? # has children
|
41
|
+
out=lookup_children(index,size)
|
42
|
+
# raise "Child filelist failed at index #{index}, size #{size}." if out.count < 1
|
43
|
+
else # no children, just files
|
44
|
+
# puts "looked something up"
|
45
|
+
out = get(index,size)
|
46
|
+
# puts "retrieved #{out.count} frames from object files on disk"
|
47
|
+
# puts "got #{out.count}"
|
48
|
+
# puts "=>> no children, real files found value #{out}"
|
49
|
+
end
|
50
|
+
# puts "valuse #{out}"
|
51
|
+
out
|
52
|
+
end
|
53
|
+
|
54
|
+
def lookup_child(index,size,i)
|
55
|
+
out=[]
|
56
|
+
fl=filelists[i]
|
57
|
+
App.checks+=1
|
58
|
+
delay = filelist_delays[i]
|
59
|
+
# delay = 0 if delay.nil?
|
60
|
+
# puts "deciding if we should go into filelist #{i+1} of #{filelists.count},"+
|
61
|
+
# " is #{delay} <= #{index} ? "
|
62
|
+
# puts "child len #{@child_len}"
|
63
|
+
needed_until_in = delay - index
|
64
|
+
if needed_until_in <= 0
|
65
|
+
# puts "child #{i}"# #{index-delay}"
|
66
|
+
if fl.mark_of_death
|
67
|
+
# puts "old count: #{filelists.count}"
|
68
|
+
# fl.loaded_file_data=nil
|
69
|
+
# GC.start
|
70
|
+
self.filelists.delete_at i
|
71
|
+
self.filelist_delays.delete_at i
|
72
|
+
# puts "#{i} is dead! new count: #{filelists.count}"
|
73
|
+
else
|
74
|
+
# normal result
|
75
|
+
result =fl.get_value(index-delay,size)
|
76
|
+
# puts "normal #{result.count}"
|
77
|
+
out= result
|
78
|
+
end
|
79
|
+
else
|
80
|
+
spoof_req_len = size - needed_until_in
|
81
|
+
if spoof_req_len > 0
|
82
|
+
# Read a smaller chunk in the futre that will be missed if we increment by size.
|
83
|
+
index_to_get_in = needed_until_in + index
|
84
|
+
delay_on_future_chunk = Array.new(needed_until_in, 0)
|
85
|
+
future_chunk = fl.get_value(index_to_get_in-delay, spoof_req_len)
|
86
|
+
# puts future_chunk.count
|
87
|
+
combo = [] + delay_on_future_chunk + future_chunk
|
88
|
+
# puts combo.count
|
89
|
+
out= combo # with resizing, but will be chunk len anyway.
|
90
|
+
else
|
91
|
+
# Will be handled in future chunks.
|
92
|
+
# out.add_e Array.new(2,0)
|
93
|
+
# puts "not above delay"
|
94
|
+
# puts "c #{delay-index}"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
out
|
98
|
+
end
|
99
|
+
|
100
|
+
def lookup_children(index,size)
|
101
|
+
out = []
|
102
|
+
if filelists.count==0
|
103
|
+
#no file lists, so fill with 0s to len
|
104
|
+
sil_amount = size
|
105
|
+
sil_amount = child_len if child_len < sil_amount && child_len != 0 #limit silence to my length
|
106
|
+
sil_amount
|
107
|
+
out = Array.new(sil_amount-index,0) if sil_amount-index > 0
|
108
|
+
### puts "set mark of death, returning silence #{sil_amount}, my length: #{child_len}"
|
109
|
+
self.mark_of_death = true
|
110
|
+
return []
|
111
|
+
end
|
112
|
+
filelists.each_with_index do |fl,i|
|
113
|
+
out.add_e lookup_child(index,size,i)
|
114
|
+
end
|
115
|
+
out
|
116
|
+
end
|
117
|
+
|
118
|
+
def get(index, size=1)
|
119
|
+
# out=Array.new(1,0)
|
120
|
+
out=[]
|
121
|
+
# not opened yet
|
122
|
+
if loaded_file_index.nil?
|
123
|
+
# App.logger.print_and_flush "|t|"
|
124
|
+
load_from_file(0)
|
125
|
+
end
|
126
|
+
|
127
|
+
#still got data to write in THIS file
|
128
|
+
if current_index_fits_opended_file?(index)
|
129
|
+
out = (read_data_at index, size)
|
130
|
+
# puts "fl-no-child: normal read #{out}"
|
131
|
+
|
132
|
+
#need to load next file (index is higher than current)
|
133
|
+
else
|
134
|
+
# theres more files to load
|
135
|
+
if files.count > loaded_file_index+1
|
136
|
+
load_from_file(loaded_file_index+1)
|
137
|
+
out = (read_data_at index, size)
|
138
|
+
# puts "fl-no-child: file #{loaded_file_index} is finished. load next. found val #{out}"
|
139
|
+
else # no more files, index is past
|
140
|
+
self.mark_of_death =true
|
141
|
+
# puts "fl-no-child: marking for dead!!!"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
out
|
145
|
+
end
|
146
|
+
|
147
|
+
#return:: total len of this TrackSection
|
148
|
+
#nil is error
|
149
|
+
def get_content_len
|
150
|
+
child_len.nil? ? file_content_lens.reduce(:+) : child_len
|
151
|
+
end
|
152
|
+
|
153
|
+
def current_index_fits_opended_file?(index) # all that have been opened are tallied
|
154
|
+
index < file_content_lens[0..loaded_file_index].reduce(:+)
|
155
|
+
end
|
156
|
+
|
157
|
+
# returning array of size
|
158
|
+
def read_data_at (index,size=2)
|
159
|
+
lookup=loaded_file_index==0 ? index : index-file_content_lens[0..loaded_file_index-1].reduce(:+)
|
160
|
+
#index - all other lengths, so we get a relative index.
|
161
|
+
rb = loaded_file_data.count-1 # right bound
|
162
|
+
# puts "largest possible #{rb}, lookup #{lookup}"
|
163
|
+
jump = lookup+size-1
|
164
|
+
jump = rb if jump > rb
|
165
|
+
result=loaded_file_data[lookup..jump]
|
166
|
+
# puts "#{lookup } #{jump} #{result}"
|
167
|
+
# puts "giving data size #{result.count}"
|
168
|
+
result
|
169
|
+
end
|
170
|
+
|
171
|
+
#index
|
172
|
+
def load_from_file(fi)
|
173
|
+
f=File.new(files[fi], "r")
|
174
|
+
data=f.gets(nil)
|
175
|
+
f.close
|
176
|
+
self.loaded_file_index = fi
|
177
|
+
parse_loaded data
|
178
|
+
end
|
179
|
+
|
180
|
+
def parse_loaded data
|
181
|
+
self.loaded_file_data=Marshal.load(data)
|
182
|
+
end
|
183
|
+
|
184
|
+
def addlist list, delay=0
|
185
|
+
self.filelists.push list
|
186
|
+
self.filelist_delays.push delay.to_i
|
187
|
+
end
|
188
|
+
|
189
|
+
def write(wave_data,delay=0)
|
190
|
+
full=wave_data.dps
|
191
|
+
# puts "--> values: #{full.join(', ')}"
|
192
|
+
spli=App.split_array(full, App::CHUNK_SIZE)
|
193
|
+
spli.each_with_index do |array,i|
|
194
|
+
self.files.push "../tmp/#{object_id}_#{i}"
|
195
|
+
self.file_content_lens.push array.count
|
196
|
+
File.open(self.files.last, 'w') do |fout|
|
197
|
+
fout.puts Marshal.dump(array)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
# puts "written #{spli.count} tmp files"
|
201
|
+
end
|
202
|
+
end
|