Skip to content

Commit

Permalink
Merge pull request #43 from aidewoode/lazy
Browse files Browse the repository at this point in the history
Parse Ogg duration and bitrate lazily
  • Loading branch information
aidewoode authored Jun 6, 2024
2 parents 717c823 + 899d207 commit da99291
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 13 deletions.
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,15 @@ WahWah is so easy to use.
```ruby
require "wahwah"

# Get metadata from an audio file

# Get metadata from an audio file path
tag = WahWah.open("/files/example.wav")

# Or from IO like object
File.open("/files/example.wav") do |file|
tag = WahWah.open(file)
end

# Supported attributes
tag.title # => "song title"
tag.artist # => "artist name"
tag.album # => "album name"
Expand All @@ -62,6 +67,5 @@ tag.images # => [{ :type => :cover_front, :mime_type => 'image/jpeg', :data


# Get all support formats

WahWah.support_formats # => ["mp3", "ogg", "oga", "opus", "wav", "flac", "wma", "m4a"]
```
8 changes: 2 additions & 6 deletions lib/wahwah/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,10 @@ def self.split_with_terminator(string, terminator_size)
def self.file_format(io)
if io.respond_to?(:path) && io.path && !io.path.empty?
file_format = file_format_from_extension io.path
# Using OpenURI, the file *has* a path, but it's without an extension.
# To support that case, we fall back on signature detection.
file_format = file_format_from_signature io if file_format.empty?
else
file_format = file_format_from_signature io
return file_format unless file_format.nil? || file_format.empty?
end

file_format
file_format_from_signature io
end

def self.byte_string_to_guid(byte_string)
Expand Down
16 changes: 14 additions & 2 deletions lib/wahwah/ogg_tag.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,20 @@ class OggTag < Tag
:sample_rate,
:lyrics

# Oggs require reading to the end of the file in order to calculate their
# duration (as it's not stored in any header or metadata). Thus, if the
# IO like object supplied to WahWah is a streaming download, getting the
# duration would download the entire audio file, which may not be
# desirable. Making it lazy in this manner allows the user to avoid that.
def duration
@duration ||= parse_duration
end

# Requires duration to calculate, so lazy as well.
def bitrate
@bitrate ||= parse_bitrate
end

private

def packets
Expand All @@ -41,8 +55,6 @@ def parse
Ogg::FlacTag.new(identification_packet, comment_packet)
end

@duration = parse_duration
@bitrate = parse_bitrate
@bit_depth = parse_bit_depth
end

Expand Down
4 changes: 2 additions & 2 deletions lib/wahwah/tag.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
module WahWah
class Tag
INTEGER_ATTRIBUTES = %i[disc disc_total track track_total]
INSPECT_ATTRIBUTES = %i[title artist album albumartist composer track track_total genre year disc disc_total duration bitrate sample_rate bit_depth]
INSPECT_ATTRIBUTES = %i[title artist album albumartist composer track track_total genre year disc disc_total]

attr_reader(
:title,
Expand Down Expand Up @@ -51,7 +51,7 @@ def inspect
def images
return @images_data if @images_data.empty?

@images_data.map do |data|
@images ||= @images_data.map do |data|
parse_image_data(data)
end
end
Expand Down
22 changes: 22 additions & 0 deletions test/wahwah/ogg_tag_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,26 @@ def test_flac_tag_file
assert_equal "I'm feeling tragic like I'm Marlon Brando", tag.lyrics
end
end

def test_lazy_duration
File.open("test/files/vorbis_tag.ogg", "rb") do |file|
tag = WahWah::OggTag.new(file)
assert tag.instance_variable_get(:@file_io).pos < file.size
assert_nil tag.instance_variable_get(:@duration)

tag.duration
assert_equal 8.0, tag.instance_variable_get(:@duration)
end
end

def test_lazy_bitrate
File.open("test/files/vorbis_tag.ogg", "rb") do |file|
tag = WahWah::OggTag.new(file)
assert tag.instance_variable_get(:@file_io).pos < file.size
assert_nil tag.instance_variable_get(:@bitrate)

tag.bitrate
assert_equal 192, tag.instance_variable_get(:@bitrate)
end
end
end

0 comments on commit da99291

Please sign in to comment.