tsunami 0.0.2 → 0.1.0

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 (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