Class: Scissor::Tape

Inherits:
Object
  • Object
show all
Defined in:
lib/scissor/tape.rb

Defined Under Namespace

Classes: EmptyFragment, Error

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(filename = nil) ⇒ Tape

Returns a new instance of Tape.



11
12
13
14
15
16
17
18
19
20
21
# File 'lib/scissor/tape.rb', line 11

def initialize(filename = nil)
  @fragments = []

  if filename
    filename = Pathname(filename).expand_path
    @fragments << Fragment.new(
      filename,
      0,
      SoundFile.new_from_filename(filename).length)
  end
end

Instance Attribute Details

#fragmentsObject (readonly)

Returns the value of attribute fragments.



9
10
11
# File 'lib/scissor/tape.rb', line 9

def fragments
  @fragments
end

Class Method Details

.new_from_url(url) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/scissor/tape.rb', line 23

def self.new_from_url(url)
  file = nil
  content_types = {
    'audio/wav' => 'wav',
    'audio/x-wav' => 'wav',
    'audio/wave' => 'wav',
    'audio/x-pn-wav' => 'wav',
    'audio/mpeg' => 'mp3',
    'audio/x-mpeg' => 'mp3',
    'audio/mp3' => 'mp3',
    'audio/x-mp3' => 'mp3',
    'audio/mpeg3' => 'mp3',
    'audio/x-mpeg3' => 'mp3',
    'audio/mpg' => 'mp3',
    'audio/x-mpg' => 'mp3',
    'audio/x-mpegaudio' => 'mp3',
  }

  open(url) do |f|
    ext = content_types[f.content_type.downcase]

    file = Tempfile.new(['audio', '.' + ext])
    file.write(f.read)
    file.flush
  end

  tape = new(file.path)

  # reference tempfile to prevent GC
  tape.instance_variable_set('@__tempfile', file)
  tape
end

Instance Method Details

#+(other) ⇒ Object



107
108
109
110
111
# File 'lib/scissor/tape.rb', line 107

def +(other)
  new_instance = Scissor()
  new_instance.add_fragments(@fragments + other.fragments)
  new_instance
end

#>>(filename) ⇒ Object



217
218
219
# File 'lib/scissor/tape.rb', line 217

def >>(filename)
  to_file(filename, :overwrite => true)
end

#add_fragment(fragment) ⇒ Object



56
57
58
# File 'lib/scissor/tape.rb', line 56

def add_fragment(fragment)
  @fragments << fragment
end

#add_fragments(fragments) ⇒ Object



60
61
62
63
64
# File 'lib/scissor/tape.rb', line 60

def add_fragments(fragments)
  fragments.each do |fragment|
    add_fragment(fragment)
  end
end

#concat(other) ⇒ Object Also known as: <<



99
100
101
102
103
# File 'lib/scissor/tape.rb', line 99

def concat(other)
  add_fragments(other.fragments)

  self
end

#durationObject



66
67
68
69
70
# File 'lib/scissor/tape.rb', line 66

def duration
  @fragments.inject(0) do |memo, fragment|
    memo += fragment.duration
  end
end

#fill(filled_duration) ⇒ Object



139
140
141
142
143
144
145
146
147
148
# File 'lib/scissor/tape.rb', line 139

def fill(filled_duration)
  if duration.zero?
    raise EmptyFragment
  end

  loop_count = (filled_duration / duration).to_i
  remain = filled_duration % duration

  loop(loop_count) + slice(0, remain)
end

#loop(count) ⇒ Object Also known as: *



113
114
115
116
117
118
119
120
121
122
# File 'lib/scissor/tape.rb', line 113

def loop(count)
  orig_fragments = @fragments.clone
  new_instance = Scissor()

  count.times do
    new_instance.add_fragments(orig_fragments)
  end

  new_instance
end

#pan(right_percent) ⇒ Object



199
200
201
202
203
204
205
206
207
208
209
# File 'lib/scissor/tape.rb', line 199

def pan(right_percent)
  new_instance = self.class.new

  @fragments.each do |fragment|
    new_instance.add_fragment(fragment.clone do |attributes|
        attributes[:pan] = right_percent
      end)
  end

  new_instance
end

#pitch(pitch, stretch = false) ⇒ Object



181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/scissor/tape.rb', line 181

def pitch(pitch, stretch = false)
  new_instance = self.class.new

  @fragments.each do |fragment|
    new_instance.add_fragment(fragment.clone do |attributes|
        attributes[:pitch]   = fragment.pitch * (pitch.to_f / 100)
        attributes[:stretch] = stretch
      end)
  end

  new_instance
end

#replace(start, length, replaced) ⇒ Object



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/scissor/tape.rb', line 150

def replace(start, length, replaced)
  new_instance = self.class.new
  offset = start + length

  new_instance += slice(0, start)

  if new_instance.duration < start
    new_instance + Scissor.silence(start - new_instance.duration)
  end

  new_instance += replaced

  if duration > offset
    new_instance += slice(offset, duration - offset)
  end

  new_instance
end

#reverseObject



169
170
171
172
173
174
175
176
177
178
179
# File 'lib/scissor/tape.rb', line 169

def reverse
  new_instance = self.class.new

  @fragments.reverse.each do |fragment|
    new_instance.add_fragment(fragment.clone do |attributes|
        attributes[:reverse] = !fragment.reversed?
      end)
  end

  new_instance
end

#silenceObject



221
222
223
# File 'lib/scissor/tape.rb', line 221

def silence
  Scissor.silence(duration)
end

#slice(start, length) ⇒ Object Also known as: []



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/scissor/tape.rb', line 72

def slice(start, length)
  if start + length > duration
    length = duration - start
  end

  new_instance = self.class.new
  remaining_start = start.to_f
  remaining_length = length.to_f

  @fragments.each do |fragment|
    new_fragment, remaining_start, remaining_length =
      fragment.create(remaining_start, remaining_length)

    if new_fragment
      new_instance.add_fragment(new_fragment)
    end

    if remaining_length == 0
      break
    end
  end

  new_instance
end

#split(count) ⇒ Object Also known as: /



126
127
128
129
130
131
132
133
134
135
# File 'lib/scissor/tape.rb', line 126

def split(count)
  splitted_duration = duration / count.to_f
  results = []

  count.times do |i|
    results << slice(i * splitted_duration, splitted_duration)
  end

  results
end

#stretch(factor) ⇒ Object



194
195
196
197
# File 'lib/scissor/tape.rb', line 194

def stretch(factor)
  factor_for_pitch = 1 / (factor.to_f / 100) * 100
  pitch(factor_for_pitch, true)
end

#to_file(filename, options = {}) ⇒ Object Also known as: >



211
212
213
# File 'lib/scissor/tape.rb', line 211

def to_file(filename, options = {})
  Scissor.mix([self], filename, options)
end