module Discorb::Voice # # Represents a Ogg stream. # class OggStream # # Creates a new Ogg stream. # # @param [IO] io The audio ogg stream. # def initialize(io) @io = io end # # Enumerates the packets of the Ogg stream. # # @return [Enumerator] The packets of the Ogg stream. # def packets Enumerator.new do |enum| part = +"" raw_packets.each do |packet| part << packet.data unless packet.partial enum << part part = +"" end end end end # # Enumerates the raw packets of the Ogg stream. # This may include partial packets. # # @return [Enumerator] The raw packets of the Ogg stream. # def raw_packets Enumerator.new do |enum| loop do # p c += 1 if @io.read(4) != "OggS" break end pg = Page.new(@io) pg.packets.each do |packet| enum << packet end # enum << pg.packets.next end end end # # Represents a page of the Ogg stream. # class Page # @return [Struct] The struct of the packet Packet = Struct.new(:data, :partial, :page) # @return [Integer] The version of the page. attr_reader :version # @return [Integer] The header type of the page. attr_reader :header_type # @return [Integer] The granule position of the page. attr_reader :granule_position # @return [Integer] The bitstream serial number of the page. attr_reader :bitstream_serial_number # @return [Integer] The page sequence number of the page. attr_reader :page_sequence_number # @return [Integer] The CRC checksum of the page. attr_reader :crc_checksum # @return [Integer] The length of the page segment table. attr_reader :page_segments # @return [String] The body of the page. attr_reader :body # # Creates a new page. # # @param [IO] io The audio ogg stream. # @note This method will seek the io. # def initialize(io) @version, @header_type, @granule_position, @bitstream_serial_number, @page_sequence_number, @crc_checksum, @page_segments = io.read(23).unpack("CCQ] The packets of the page. # def packets Enumerator.new do |enum| offset = 0 length = 0 partial = true @segtable.bytes.each do |seg| if seg == 255 length += 255 partial = true else length += seg partial = false enum << Packet.new(@body[offset, length], partial, self) offset += length length = 0 end end enum << Packet.new(@body[offset, length], partial, self) if partial end end end end end