File: format_chunk_reader.rb

package info (click to toggle)
ruby-wavefile 1.1.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,708 kB
  • sloc: ruby: 4,171; makefile: 2
file content (55 lines) | stat: -rw-r--r-- 2,386 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
module WaveFile
  module ChunkReaders
    # Internal
    class FormatChunkReader < BaseChunkReader    # :nodoc:
      def initialize(io, chunk_size)
        @io = io
        @chunk_size = chunk_size
      end

      def read
        if @chunk_size < MINIMUM_CHUNK_SIZE
          raise_error InvalidFormatError, "The format chunk is incomplete; it contains fewer than the required number of fields."
        end

        raw_bytes = read_entire_chunk_body(CHUNK_IDS[:format])

        format_chunk = {}
        format_chunk[:audio_format],
        format_chunk[:channels],
        format_chunk[:sample_rate],
        format_chunk[:byte_rate],
        format_chunk[:block_align],
        format_chunk[:bits_per_sample] = raw_bytes.slice!(0...MINIMUM_CHUNK_SIZE).unpack("vvVVvv")

        if format_chunk[:audio_format] == FORMAT_CODES[:extensible] || (format_chunk[:audio_format] != FORMAT_CODES[:pcm] && @chunk_size > MINIMUM_CHUNK_SIZE)
          if raw_bytes.length < 2
            raise_error InvalidFormatError, "The format chunk is missing an expected extension."
          end

          format_chunk[:extension_size] = raw_bytes.slice!(0...2).unpack(UNSIGNED_INT_16).first

          if format_chunk[:extension_size] > raw_bytes.length
            raise_error InvalidFormatError, "The format chunk extension size of #{format_chunk[:extension_size]} bytes is too large to fit in the format chunk. The format chunk has a stated size of #{@chunk_size} bytes, with #{raw_bytes.length} bytes available for the extension."
          end

          if format_chunk[:audio_format] == FORMAT_CODES[:extensible]
            if format_chunk[:extension_size] < 22
              raise_error InvalidFormatError, "The format chunk extension size of #{format_chunk[:extension_size]} bytes is too small. Since the format chunk has a format code of #{FORMAT_CODES[:extensible]} (i.e. WAVE_FORMAT_EXTENSIBLE), the extension size must be at least 22 bytes."
            end

            format_chunk[:valid_bits_per_sample] = raw_bytes.slice!(0...2).unpack(UNSIGNED_INT_16).first
            format_chunk[:speaker_mapping] = raw_bytes.slice!(0...4).unpack(UNSIGNED_INT_32).first
            format_chunk[:sub_audio_format_guid] = raw_bytes.slice!(0...16)
          end
        end

        UnvalidatedFormat.new(format_chunk)
      end

      private

      MINIMUM_CHUNK_SIZE = 16
    end
  end
end