Skip to content

Commit

Permalink
Put back the fact logic
Browse files Browse the repository at this point in the history
  • Loading branch information
linkyndy committed Jul 1, 2024
1 parent 806f65d commit 5fcf230
Showing 1 changed file with 15 additions and 9 deletions.
24 changes: 15 additions & 9 deletions lib/parsers/wav_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,28 @@ def call(io)
# The specification does not require the Format chunk to be the first chunk
# after the RIFF header.
# https://www.mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html
fmt_processed = false
fmt_data = {}
loop do
chunk_type, chunk_size = safe_read(io, 8).unpack('a4l')
case chunk_type
when 'fmt ' # watch out: the chunk ID of the format chunk ends with a space
fmt_data = unpack_fmt_chunk(io, chunk_size)
fmt_processed = true
fmt_data.merge!(unpack_fmt_chunk(io, chunk_size))
when 'data'
return unless fmt_processed # the 'data' chunk cannot preceed the 'fmt ' chunk
return file_info(fmt_data, chunk_size)
fmt_data[:data_size] = chunk_size
when 'fact'
fmt_data[:sample_frames] = safe_read(io, 4).unpack('l').first
safe_skip(io, chunk_size - 4)
else
# Skip this chunk until a known chunk is encountered
safe_skip(io, chunk_size)
end
rescue FormatParser::IOUtils::InvalidRead
# We've reached EOF, so it's time to make the most out of the metadata we
# manage to parse
break
end

file_info(fmt_data)
end

def unpack_fmt_chunk(io, chunk_size)
Expand Down Expand Up @@ -64,15 +70,15 @@ def unpack_fmt_chunk(io, chunk_size)
}
end

def file_info(fmt_data, data_size)
def file_info(fmt_data)
# NOTE: Each sample includes information for each channel
sample_frames = data_size / (fmt_data[:channels] * fmt_data[:bits_per_sample] / 8) if fmt_data[:channels] > 0 && fmt_data[:bits_per_sample] > 0
duration_in_seconds = data_size / fmt_data[:byte_rate].to_f if fmt_data[:byte_rate] > 0
fmt_data[:sample_frames] ||= fmt_data[:data_size] / (fmt_data[:channels] * fmt_data[:bits_per_sample] / 8) if fmt_data[:channels] > 0 && fmt_data[:bits_per_sample] > 0
duration_in_seconds = fmt_data[:sample_frames] / fmt_data[:sample_rate].to_f if fmt_data[:sample_rate] > 0
FormatParser::Audio.new(
format: :wav,
num_audio_channels: fmt_data[:channels],
audio_sample_rate_hz: fmt_data[:sample_rate],
media_duration_frames: sample_frames,
media_duration_frames: fmt_data[:sample_frames],
media_duration_seconds: duration_in_seconds,
content_type: WAV_MIME_TYPE,
)
Expand Down

0 comments on commit 5fcf230

Please sign in to comment.