tsunami 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. data/.gitignore +2 -0
  2. data/Rakefile +1 -1
  3. data/VERSION +1 -1
  4. data/lib/tsunami.rb +31 -70
  5. data/tsunami.gemspec +5 -5
  6. metadata +3 -3
data/.gitignore CHANGED
@@ -20,5 +20,7 @@ pkg
20
20
 
21
21
  ## PROJECT::SPECIFIC
22
22
  lib/*.mp3
23
+ lib/*.wav
24
+ lib/*.ogg
23
25
  lib/*.png
24
26
  lib/test.rb
data/Rakefile CHANGED
@@ -11,7 +11,7 @@ begin
11
11
  gem.homepage = "http://github.com/zmack/tsunami"
12
12
  gem.authors = ["Andrei Bocan"]
13
13
  gem.add_dependency "rmagick", ">= 0"
14
- gem.add_dependency "narray", ">= 0"
14
+ gem.add_dependency "ruby-audio", ">= 0"
15
15
  gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
16
16
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
17
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.2
1
+ 0.1.0
data/lib/tsunami.rb CHANGED
@@ -1,103 +1,64 @@
1
1
  #this class was inspired by rjp's awesome http://github.com/rjp/cdcover
2
2
  require 'rubygems'
3
3
  require 'RMagick'
4
- require 'narray'
4
+ require 'audio/sndfile'
5
5
 
6
6
  class Tsunami
7
7
 
8
8
  def initialize audio_file
9
- # graph parameters
10
- @bitrate = '500'
11
- @offset = 5
12
- @audio_file = audio_file
9
+ @audio_file = Audio::Soundfile.new audio_file
13
10
  end
14
11
 
15
- def create_waveform(image_file, options)
16
- @width = options[:width].to_i || 100
17
- @height = options[:height].to_i || 50
12
+ def create_waveform(image_file, options = {})
13
+ @width = options[:width] || 100
14
+ @height = options[:height] || 50
18
15
 
19
16
  buckets = fill_buckets
20
17
 
21
18
  gc = build_graph buckets
22
19
 
23
- #create new image canvas
24
- canvas = Magick::Image.new(@width + 2*@offset, @height) { self.background_color = 'transparent' }
20
+ canvas = Magick::Image.new(@width, @height) { self.background_color = 'transparent' }
25
21
 
26
- # canvas = Magick::ImageList.new('images/waveform.png')
27
22
  gc.draw(canvas)
28
23
 
29
24
  canvas.write(image_file)
30
25
  end
31
26
 
32
- #fill the buckets
33
27
  def fill_buckets
34
- buckets = NArray.int(@width,2)
35
-
36
- #let sox fetch the byte array
37
- bytes = wave_bytes
38
-
39
- bucket_size = (((bytes.size-1).to_f / @width)+0.5).to_i + 1
40
-
41
- (0..bytes.total-1).each do |i|
42
- value = bytes[i]
43
- index = i/bucket_size
44
- #minimum
45
- buckets[index,0] = value if value < buckets[index,0]
46
- #maximum
47
- buckets[index,1] = value if value > buckets[index,1]
48
- #total value
49
- #buckets[index,2] += value
50
- #count
51
- #buckets[index,3] += 1
52
- #negative total
53
- #buckets[index,4] += value if value < 0
54
- #positive total
55
- #buckets[index,5] += value if value > 0
56
- end
28
+ frames = @audio_file.read_float(@audio_file.frames).channel(0)
29
+ buckets = []
30
+ frame_index = 0
31
+ frames_per_pixel = frames.length / @width
57
32
 
58
- return buckets
59
- end
33
+ frames.each do |frame|
34
+ index = frame_index / frames_per_pixel
35
+ buckets[index] ||= { :max => -1, :min => 1 }
60
36
 
61
- def wave_bytes
62
- @wave_bytes ||= sox_get_bytes
63
- end
37
+ buckets[index][:min] = frame if frame < buckets[index][:min]
38
+
39
+ buckets[index][:max] = frame if frame > buckets[index][:max]
64
40
 
65
- #open file with sox and return a byte array with sweet waveform information in it
66
- def sox_get_bytes channels = 1
67
- x=nil
68
- # read a 16 bit linear raw PCM file
69
- sox_command = [ 'sox', @audio_file, '-t', 'raw', '-r', @bitrate, '-c', channels.to_s, '-s', '-L', '-' ]
70
- # we have to fork/exec to get a clean commandline
71
- IO.popen('-') { |p|
72
- if p.nil? then
73
- $stderr.close
74
- # raw 16 bit linear PCM one channel
75
- exec *sox_command
76
- end
77
- x = p.read
78
- }
79
- if x.size == 0 then
80
- puts "sox returned no data, command was\n> #{sox_command.join(' ')}"
81
- exit 1
41
+ frame_index += 1
82
42
  end
83
- return NArray.to_na(x.unpack("s*"))
43
+
44
+ return buckets
84
45
  end
85
46
 
86
- #build the waveform graph
87
47
  def build_graph buckets
88
48
  gc = Magick::Draw.new
49
+ gc.stroke('red')
50
+ gc.stroke_width(1)
51
+
52
+ mid = @height/2
53
+
54
+ buckets.each_with_index do |bucket, i|
55
+ low = bucket[:min]
56
+ high = bucket[:max]
57
+
58
+ low_point = mid * ( 1 - low )
59
+ high_point = mid * ( 1 - high )
89
60
 
90
- scale = 32768/@height*2.75
91
- midpoint = @height/2
92
-
93
- (0..(buckets.size/2)-1).each do |i|
94
- low = buckets[i,0]
95
- high = buckets[i,1]
96
- gc.stroke('red')
97
- gc.stroke_width(1)
98
- low_point = midpoint+low/scale
99
- high_point = midpoint+high/scale
100
- gc.line(i+@offset, low_point.to_i, i+@offset, high_point.to_i)
61
+ gc.line(i, low_point.to_i, i, high_point.to_i)
101
62
  end
102
63
 
103
64
  return gc
data/tsunami.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{tsunami}
8
- s.version = "0.0.2"
8
+ s.version = "0.1.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Andrei Bocan"]
12
- s.date = %q{2010-03-09}
12
+ s.date = %q{2010-03-10}
13
13
  s.description = %q{For reals, it draws waveforms, man}
14
14
  s.email = %q{zmaxor@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -44,16 +44,16 @@ Gem::Specification.new do |s|
44
44
 
45
45
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
46
46
  s.add_runtime_dependency(%q<rmagick>, [">= 0"])
47
- s.add_runtime_dependency(%q<narray>, [">= 0"])
47
+ s.add_runtime_dependency(%q<ruby-audio>, [">= 0"])
48
48
  s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
49
49
  else
50
50
  s.add_dependency(%q<rmagick>, [">= 0"])
51
- s.add_dependency(%q<narray>, [">= 0"])
51
+ s.add_dependency(%q<ruby-audio>, [">= 0"])
52
52
  s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
53
53
  end
54
54
  else
55
55
  s.add_dependency(%q<rmagick>, [">= 0"])
56
- s.add_dependency(%q<narray>, [">= 0"])
56
+ s.add_dependency(%q<ruby-audio>, [">= 0"])
57
57
  s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
58
58
  end
59
59
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tsunami
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrei Bocan
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-03-09 00:00:00 +02:00
12
+ date: 2010-03-10 00:00:00 +02:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -23,7 +23,7 @@ dependencies:
23
23
  version: "0"
24
24
  version:
25
25
  - !ruby/object:Gem::Dependency
26
- name: narray
26
+ name: ruby-audio
27
27
  type: :runtime
28
28
  version_requirement:
29
29
  version_requirements: !ruby/object:Gem::Requirement