ruby-ogginfo 0.4.2 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,7 @@
1
+ === 0.5 / 2011-01-13
2
+
3
+ * speex support (thanks to Grant Gardner)
4
+
1
5
  === 0.4.2 / 2010-03-13
2
6
 
3
7
  * bugfix on frame parsing
data/Manifest.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  History.txt
2
2
  Manifest.txt
3
- README.txt
3
+ README.rdoc
4
4
  Rakefile
5
5
  setup.rb
6
6
  lib/ogginfo.rb
@@ -1,6 +1,7 @@
1
1
  = ruby-ogginfo
2
2
 
3
3
  http://ruby-ogginfo.rubyforge.org/
4
+ https://github.com/moumar/ruby-ogginfo
4
5
 
5
6
  == DESCRIPTION:
6
7
 
data/Rakefile CHANGED
@@ -2,6 +2,9 @@
2
2
 
3
3
  require 'rubygems'
4
4
  require 'hoe'
5
+
6
+ Hoe.plugin :yard
7
+
5
8
  require 'lib/ogginfo.rb'
6
9
 
7
10
  Hoe.new('ruby-ogginfo', OggInfo::VERSION) do |p|
@@ -9,10 +12,11 @@ Hoe.new('ruby-ogginfo', OggInfo::VERSION) do |p|
9
12
  p.author = 'Guillaume Pierronnet'
10
13
  p.email = 'moumar@rubyforge.org'
11
14
  p.summary = 'ruby-ogginfo is a pure-ruby library that gives low level informations on ogg files'
12
- p.description = p.paragraphs_of('README.txt', 3).first
13
- p.url = p.paragraphs_of('README.txt', 1).first
15
+ p.description = p.paragraphs_of('README.rdoc', 3).first
16
+ p.url = p.paragraphs_of('README.rdoc', 1).first
14
17
  p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
15
18
  p.remote_rdoc_dir = ''
19
+ p.rdoc_locations << "rubyforge.org:/var/www/gforge-projects/ruby-ogginfo/"
16
20
  end
17
21
 
18
22
  # vim: syntax=Ruby
data/lib/ogginfo.rb CHANGED
@@ -23,7 +23,7 @@ end
23
23
  class OggInfoError < StandardError ; end
24
24
 
25
25
  class OggInfo
26
- VERSION = "0.4.2"
26
+ VERSION = "0.5"
27
27
  CHECKSUM_TABLE = [
28
28
  0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9,
29
29
  0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005,
@@ -103,7 +103,7 @@ class OggInfo
103
103
  @file = File.new(@filename, "rb")
104
104
 
105
105
  frames = (1..2).collect { |i| OggInfo.read_frame(@file) }
106
- extract_vorbis_infos(frames[0])
106
+ extract_bitstream_infos(frames[0])
107
107
  extract_tag(frames[1])
108
108
  convert_tag_charset("utf-8", @charset)
109
109
  @original_tag = @tag.dup
@@ -130,7 +130,7 @@ class OggInfo
130
130
 
131
131
  # commits any tags to file
132
132
  def close
133
- if @tag != @original_tag
133
+ if @bitstream_format == "vorbis" && @tag != @original_tag
134
134
  cmd = %w{vorbiscomment -w}
135
135
  convert_tag_charset(@charset, "utf-8")
136
136
 
@@ -202,20 +202,45 @@ class OggInfo
202
202
  end
203
203
 
204
204
  private
205
+ def extract_bitstream_infos(frame)
206
+ @file.seek(frame[:file_position] + frame[:header_size] + 1)
207
+ @bitstream_format = @file.read(6).rstrip()
208
+ case @bitstream_format
209
+ when "vorbis" : extract_vorbis_infos(frame)
210
+ when "peex" :
211
+ #Speex does not align itself to a 4 byte boundary.
212
+ @bitstream_format="Speex"
213
+ extract_speex_infos(frame)
214
+ else raise(OggInfoError,"Unknown bitstream format #{@bitstream_format}")
215
+ end
216
+ end
217
+
218
+ def extract_speex_infos(frame)
219
+ @file.seek(frame[:file_position] + frame[:header_size] )
220
+ speex_string,speex_version,speex_version_id,header_size,@samplerate,mode,mode_bitstream_version,
221
+ @channels,bitrate,framesize,vbr = @file.read(28+ 9 * 4).unpack("A8A20VVVVVVVVV")
222
+ #not sure how to make sense of the bitrate info,picard doesn't show it either...
223
+ end
224
+
205
225
  def extract_vorbis_infos(frame)
206
- @file.seek(frame[:file_position] + frame[:header_size] + 1 ) # seek after "vorbis"
226
+ @file.seek(frame[:file_position] + frame[:header_size] + 1 )
227
+
207
228
  vorbis_string, vorbis_version, @channels, @samplerate, upper_bitrate, @nominal_bitrate, lower_bitrate = @file.read(27).unpack("a6VCV4")
208
229
  if @nominal_bitrate == 0
209
230
  if upper_bitrate == 2**32 - 1 or lower_bitrate == 2**32 - 1
210
231
  @nominal_bitrate = 0
211
232
  else
212
233
  @nominal_bitrate = (upper_bitrate + lower_bitrate)/2
213
- end
234
+ end
214
235
  end
215
236
  end
216
237
 
217
238
  def extract_tag(frame)
218
- @file.seek(frame[:file_position] + frame[:header_size] + 1 + "vorbis".size)
239
+ @file.seek(frame[:file_position] + frame[:header_size] )
240
+ # GG: Vorbis includes a preamble "vorbis", which is not included in the comments,
241
+ # but is definitely in the /libvorbis/lib/info.c _vorbis_pack_comment reference implementation.
242
+ # Speex does not seem to include this preamble.
243
+ @file.read(7) if @bitstream_format=="vorbis"
219
244
  vendor_length = @file.read(4).unpack("V").first
220
245
  @vendor = @file.read(vendor_length)
221
246
 
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/ruby -w
2
+
3
+ $:.unshift("lib/")
4
+
5
+ require "test/unit"
6
+ require "ogginfo"
7
+ require "fileutils"
8
+ require "tempfile"
9
+
10
+ VALID_SPX = <<EOF
11
+ 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
55
+ uTv3X00=
56
+ EOF
57
+
58
+ class SpxInfoTest < Test::Unit::TestCase
59
+
60
+ TEMP_FILE = File.join(Dir.tmpdir, "test.spxinfo.spx")
61
+
62
+ def setup
63
+ valid_spx_file = VALID_SPX.unpack("m*").first
64
+ File.open(TEMP_FILE, "w") { |f| f.write(valid_spx_file) }
65
+ end
66
+
67
+ def teardown
68
+ FileUtils.rm_f(TEMP_FILE)
69
+ end
70
+
71
+ def test_infos
72
+ OggInfo.open(TEMP_FILE) do |spx|
73
+ assert_equal 1, spx.channels
74
+ assert_equal 32000, spx.samplerate
75
+ assert_in_delta(0.5, spx.length, 1)
76
+ end
77
+ end
78
+
79
+ def test_generated_info
80
+ generate_spx
81
+ OggInfo.open("test.spx") do |spx|
82
+ assert_equal 2, spx.channels
83
+ assert_equal 44100, spx.samplerate
84
+ end
85
+ end
86
+
87
+
88
+ def test_charset
89
+ generate_spx
90
+ OggInfo.open("test.spx", "utf-8") do |spx|
91
+ assert_equal "spxinfotest", spx.tag["author"]
92
+ end
93
+
94
+ OggInfo.open("test.spx", "iso-8859-1") do |spx|
95
+ assert_equal "hello\xe9", spx.tag["test"]
96
+ end
97
+ end
98
+
99
+ def generate_spx
100
+ unless test(?f, "test.spx")
101
+ system("dd if=/dev/urandom bs=1024 count=3000 | speexenc --rate 44100 --stereo --author spxinfotest --title SpxInfoTest --comment test=\"hello\303\251\" - test.spx") or
102
+ flunk("cannot generate \"test.spx\", tests cannot be fully performed")
103
+ end
104
+ end
105
+ end
metadata CHANGED
@@ -1,7 +1,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-ogginfo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 5
8
+ version: "0.5"
5
9
  platform: ruby
6
10
  authors:
7
11
  - Guillaume Pierronnet
@@ -9,19 +13,37 @@ autorequire:
9
13
  bindir: bin
10
14
  cert_chain: []
11
15
 
12
- date: 2010-03-13 00:00:00 +01:00
16
+ date: 2011-01-13 00:00:00 +01:00
13
17
  default_executable:
14
18
  dependencies:
15
19
  - !ruby/object:Gem::Dependency
16
- name: hoe
20
+ name: hoe-yard
21
+ prerelease: false
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ segments:
27
+ - 0
28
+ - 1
29
+ - 2
30
+ version: 0.1.2
17
31
  type: :development
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: hoe
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
20
37
  requirements:
21
38
  - - ">="
22
39
  - !ruby/object:Gem::Version
23
- version: 1.9.0
24
- version:
40
+ segments:
41
+ - 2
42
+ - 8
43
+ - 0
44
+ version: 2.8.0
45
+ type: :development
46
+ version_requirements: *id002
25
47
  description: |-
26
48
  ruby-ogginfo gives you access to low level information on ogg files
27
49
  (bitrate, length, samplerate, encoder, etc... ), as well as tag.
@@ -34,43 +56,48 @@ extensions: []
34
56
  extra_rdoc_files:
35
57
  - History.txt
36
58
  - Manifest.txt
37
- - README.txt
38
59
  files:
39
60
  - History.txt
40
61
  - Manifest.txt
41
- - README.txt
62
+ - README.rdoc
42
63
  - Rakefile
43
64
  - setup.rb
44
65
  - lib/ogginfo.rb
45
66
  - test/test_ruby-ogginfo.rb
46
- has_rdoc: true
47
- homepage: http://ruby-ogginfo.rubyforge.org/
67
+ has_rdoc: yard
68
+ homepage: |
69
+ http://ruby-ogginfo.rubyforge.org/
70
+
48
71
  licenses: []
49
72
 
50
73
  post_install_message:
51
74
  rdoc_options:
52
- - --main
53
- - README.txt
75
+ - --title
76
+ - RubyOgginfo Documentation
77
+ - --quiet
54
78
  require_paths:
55
79
  - lib
56
80
  required_ruby_version: !ruby/object:Gem::Requirement
57
81
  requirements:
58
82
  - - ">="
59
83
  - !ruby/object:Gem::Version
84
+ segments:
85
+ - 0
60
86
  version: "0"
61
- version:
62
87
  required_rubygems_version: !ruby/object:Gem::Requirement
63
88
  requirements:
64
89
  - - ">="
65
90
  - !ruby/object:Gem::Version
91
+ segments:
92
+ - 0
66
93
  version: "0"
67
- version:
68
94
  requirements: []
69
95
 
70
96
  rubyforge_project: ruby-ogginfo
71
- rubygems_version: 1.3.5
97
+ rubygems_version: 1.3.6
72
98
  signing_key:
73
99
  specification_version: 3
74
100
  summary: ruby-ogginfo is a pure-ruby library that gives low level informations on ogg files
75
101
  test_files:
76
102
  - test/test_ruby-ogginfo.rb
103
+ - test/test_ruby-spxinfo.rb