Bringing my development in line with CVS now that the repository is set up.
authorMonty <xiphmont@xiph.org>
Mon, 19 Jul 1999 05:02:03 +0000 (05:02 +0000)
committerMonty <xiphmont@xiph.org>
Mon, 19 Jul 1999 05:02:03 +0000 (05:02 +0000)
Added beginning of HTML docs, and a semi-complete framing.c

Monty 19990719

svn path=/trunk/vorbis/; revision=8

15 files changed:
doc/framing.html [new file with mode: 0644]
doc/framing.txt [deleted file]
doc/oggstream.html [new file with mode: 0644]
doc/stream.gif [new file with mode: 0644]
doc/vorbis.html [new file with mode: 0644]
doc/vorbisword2.gif [new file with mode: 0644]
doc/wait.gif [new file with mode: 0644]
doc/white-ogg.gif [new file with mode: 0644]
doc/white-xifish.gif [new file with mode: 0644]
lib/analysis.c
lib/codec.h
lib/envelope.c
lib/framing.c
lib/mdct.c
lib/mdct.h

diff --git a/doc/framing.html b/doc/framing.html
new file mode 100644 (file)
index 0000000..d5707c2
--- /dev/null
@@ -0,0 +1,385 @@
+<HTML><HEAD><TITLE>xiph.org: OggSquish Vorbis documentation</TITLE>
+<BODY bgcolor="#ffffff" text="#202020" link="#006666" vlink="#000000">
+<nobr><a href="vorbis.html"><img src="white-ogg.gif" border=0><img 
+src="vorbisword2.gif" border=0></a></nobr><p>
+
+<h1><font color=#000070>
+OggSquish logical bitstream framing
+</font></h1>
+
+<em>Last update to this document: July 15, 1999</em><br> 
+
+<h2>OggSquish bitstreams</h2>
+
+Vorbis encodes short-time blocks of PCM data into raw packets of
+bit-packed data.  These raw packets may be used directly by transport
+mechanisms that provide their own framing and packet-seperation
+mechanisms (such as UDP datagrams).  For stream based storage (such as
+files) and transport (such as TCP streams or pipes), Vorbis uses the
+OggSquish bitstream format to provide framing/sync, sync recapture
+after error, landmarks during seeking, and enough information to
+properly seperate data back into packets at the original packet
+boundaries without relying on decoding to find packet boundaries.<p>
+
+<h2>Design constraints for OggSquish bitstreams</h2>
+
+<ol><li>True streaming; we must not need to seek to build a 100%
+   complete bitstream.
+
+<li> Use no more than approximately 1-2% of bitstream bandwidth for
+   packet boundary marking, high-level framing, sync and seeking.
+
+<li> Specification of absolute position within the original sample
+   stream.
+
+<li> Simple mechanism to ease limited editing, such as a simplified
+   concatenation mechanism.
+
+<li> Detection of corruption, recapture after error and direct, random
+   access to data at arbitrary positions in the bitstream.
+</ol>
+
+<h2>Logical and Physical Bitstreams</h2>
+
+A <em>logical</em> OggSquish bitstream is a contiguous stream of
+sequential pages belonging only to the logical bitstream.  A
+<em>physical</em> OggSquish bitstream is constructed from one or more
+than one logical OggSquish bitstream (the simplest physical bitstream
+is simply a single logical bitstream).  We describe below the exact
+formatting of an OggSquish logical bitstream.  Combining logical
+bitstreams into more complex physical bitstreams is described in the
+<a href="oggstream.html">OggSquish bitstream overview</a>.  The exact
+mapping of raw Vorbis packets into a valid Ogg Vorbis physical
+bitstream is described in <a href="vorbis-stream.html">Vorbis
+bitstream mapping</a>.
+
+<h2>Bitstream structure</h2>
+
+An OggSquish stream is structured by dividing incoming packets into
+segments of up to 255 bytes and then wrapping a group of contiguous
+packet segments into a variable length page preceeded by a page
+header.  Both the header size and page size are variable; the page
+header contains sizing information and checksum data to determine
+header/page size and data integrity.<p>
+
+The bitstream is captured (or recaptured) by looking for the beginning
+of a page, specifically the capture pattern.  Once the capture pattern
+is found, the decoder verifies page sync and integrity by computing
+and comparing the checksum. At that point, the decoder can extract the
+packets themselves.<p>
+
+<h3>Packet segmentation</h3>
+
+Packets are logically divided into multiple segments before encoding
+into a page. Note that the segmentation and fragmentation process is a
+logical one; it's used to compute page header values and the original
+page data need not be disturbed, even when a packet spans page
+boundaries.<p>
+
+The raw packet is logically divided into [n] 255 byte segments and a
+last fractional segment of < 255 bytes.  A packet size may well
+consist only of the trailing fractional segment, and a fractional
+segment may be zero length.  These values, called "lacing values" are
+then saved and placed into the header segment table.<p>
+
+An example should make the basic concept clear:<p>
+
+<pre>
+<tt>
+raw packet:
+  ___________________________________________
+ |______________packet data__________________| 753 bytes
+
+lacing values for page header segment table: 255,255,243
+</tt>
+</pre>
+
+We simply add the lacing values for the total size; the last lacing
+value for a packet is always the value that is less than 255. Note
+that this encoding both avoids imposing a maximum packet size as well
+as imposing minimum overhead on small packets (as opposed to, eg,
+simply using two bytes at the head of every packet and having a max
+packet size of 32k.  Small packets (<255, the typical case) are
+penalized with twice the segmentation overhead). Using the lacing
+values as suggested, small packets see the minimum possible
+byte-aligned overheade (1 byte) and large packets, over 512 bytes or
+so, see a fairly constant ~.5% overhead on encoding space.<p>
+
+Note that a lacing value of 255 implies that a second lacing value
+follows in the packet, and a value of < 255 marks the end of the
+packet after that many additional bytes.  A packet of 255 bytes (or a
+multiple of 255 bytes) is terminated by a lacing value of 0:<p>
+
+<pre><tt>
+raw packet:
+  _______________________________
+ |________packet data____________|          255 bytes
+
+lacing values: 255, 0
+</tt></pre>
+
+Note also that a 'nil' (zero length) packet is not an error; it
+consists of nothing more than a lacing value of zero in the header.<p>
+
+<h3>Packets spanning pages</h3>
+
+Packets are not resticted to beginning and ending within a page,
+although individual segments are, by definition, required to do so.
+Packets are not restricted to a maximum size, although excessively
+large packets in the data stream are discouraged; the OggSquish
+bitstream specification strongly recommends nominal page size of
+approximately 4-8kB (large packets are forseen as being useful for
+initialization data at the beginning of a logical bitstream).<p>
+
+After segmenting a packet, the encoder may decide not to place all the
+resulting segments into the current page; to do so, the encoder places
+the lacing values of the segments it wishes to belong to the current
+page into the current segment table, then finishes the page.  The next
+page is begun with the first value in the segment table belonging to
+the next packet segment, thus continuing the packet (data in the
+packet body must also correspond properly to the lacing values in the
+spanned pages. The segment data in the first packet corresponding to
+the lacing values of the first page belong in that page; packet
+segments listed in the segment table of the following page must begin
+the page body of the subsequent page).<p>
+
+The last mechanic to spanning a page boundary is to set the header
+flag in the new page to indicate that the first lacing value in the
+segment table continues rather than begins a packet; a header flag of
+0x01 is set to indicate a continued packet.  Although mandatory, it
+is not actually algorithmically necessary; one could inspect the
+preceeding segment table to determine if the packet is new or
+continued.  Adding the information to the packet_header flag allows a
+simpler design (with no overhead) that needs only inspect the current
+page header after frame capture.  This also allows faster error
+recovery in the event that the packet originates in a corrupt
+preceeding page, implying that the previous page's segment table
+cannot be trusted.<p>
+
+Note that a packet can span an arbitrary number of pages; the above
+spanning process is repeated for each spanned page boundary.  Also a
+'zero termination' on a packet size that is an even multiple of 255
+must appear even if the lacing value appears in the next page as a
+zero-length continuation of the current packet.  The header flag
+should be set to 0x01 to indicate that the packet spanned, even though
+the span is a nil case as far as data is concerned.<p>
+
+The encoding looks odd, but is properly optimized for speed and the
+expected case of the majority of packets being between 50 and 200
+bytes (note that it is designed such that packets of wildly different
+sizes can be handled within the model; placing packet size
+restrictions on the encoder would have only slightly simplified design
+in page generation and increased overall encoder complexity).<p>
+
+The main point behind tracking individual packets (and packet
+segments) is to allow more flexible encoding tricks that requiring
+explicit knowledge of packet size. An example is simple bandwidth
+limiting, implemented by simply truncating packets in the nominal case
+if the packet is arranged so that the least sensitive portion of the
+data comes last.<p>
+
+<h3>Page header</h3>
+
+The headering mechanism is designed to avoid copying and re-assembly
+of the packet data (ie, making the packet segmentation process a
+logical one); the header can be generated directly from incoming
+packet data.  The encoder buffers packet data until it finishes a
+complete page at which point it writes the header followed by the
+buffered packet segments.<p>
+
+<h4>capture_pattern</h4>
+
+ A header begins with a capture pattern that simplifies identifying
+ pages; once the decoder has found the capture pattern it can do a more
+ intensive job of verifying that it has in fact found a page boundary
+ (as opposed to an inadvertant coincidence in the byte stream).<p>
+
+<pre><tt>
+ byte value
+
+  0  0x4f 'O'
+  1  0x67 'g'
+  2  0x67 'g'
+  3  0x53 'S'  
+</tt></pre>
+
+<h4>stream_structure_version</h4>
+
+ The capture pattern is followed by the stream structure revision:
+
+<pre><tt>
+ byte value
+
+  4  0x00
+</tt></pre>
+<h4>header_type_flag</h4>
+  
+ The header type flag identifies this page's context in the bitstream:
+
+<pre><tt>
+ byte value
+
+  5  bitflags: 0x01: unset = fresh packet
+                      set = continued packet
+              0x02: unset = not first page of logical bitstream
+                       set = first page of logical bitstream (bos)
+              0x04: unset = not last page of logical bitstream
+                       set = last page of logical bitstream (eos)
+</tt></pre>
+
+<h4>PCM absolute position</h4>
+
+ (This is packed in the same way the rest of OggSquish data is packed;
+ LSb of LSB first.  Note that the 'position' data specifies a 'sample'
+ number (eg, in a CD quality sample is four octets, 16 bits for left
+ and 16 bits for right; in video it would be the frame number).  The
+ position specified is the total samples encoded after including all
+ packets finished on this page (packets begun on this page but
+ continuing on to thenext page do not count).  The rationale here is
+ that the position specified in the frame header of the last page
+ tells how long the PCM data coded by the bitstream is.  A truncated
+ stream will still return the proper number of samples that can be
+ decoded fully.
+
+<pre><tt>
+ byte value
+
+  6  0xXX LSB
+  7  0xXX
+  8  0xXX
+  9  0xXX
+ 10  0xXX
+ 11  0xXX
+ 12  0xXX
+ 13  0xXX MSB
+</tt></pre>
+
+<h4>stream serial number</h4>
+ OggSquish allows for seperate logical bitstreams to be mixed at page
+ granularity in a physical bitstream.  The most common case would be
+ sequential arrangement, but it is possible to interleave pages for
+ two seperate bitstreams to be decoded concurrently.  The serial
+ number is the means by which pages physical pages are associated with
+ a particular logical stream.  Each logical stream must have a unique
+ serial number within a physical stream:
+
+<pre><tt>
+ byte value
+
+ 14  0xXX LSB
+ 15  0xXX
+ 16  0xXX
+ 17  0xXX MSB
+</tt></pre>
+
+<h4>page sequence no</h4>
+
+ Page counter; lets us know if a page is lost (useful where packets
+ span page boundaries).
+
+<pre><tt>
+ byte value
+
+ 18  0xXX LSB
+ 19  0xXX
+ 20  0xXX
+ 21  0xXX MSB
+</tt></pre>
+
+<h4>page checksum</h4>
+     
+ 32 bit CRC value (direct algorithm, initial val and final XOR = 0,
+ generator polynomial=0x04c11db7).  The value is computed over the
+ entire header (with the CRC field in the header set to zero) and then
+ continued over the page.  The CRC field is then filled with the
+ computed value.<p>
+
+ (A thorough discussion of CRC algorithms can be found in <a
+ href="ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt">"A
+ Painless Guide to CRC Error Detection Algorithms"</a> by Ross
+ Williams <a
+ href="mailto:ross@guest.adelaide.edu.au">ross@guest.adelaide.edu.au</a>.)
+
+<pre><tt>
+ byte value
+
+ 22  0xXX LSB
+ 23  0xXX
+ 24  0xXX
+ 25  0xXX MSB
+</tt></pre>
+
+<h4>page_segments</h4>
+
+ The number of segment entries to appear in the segment table. The
+ maximum number of 255 segments (255 bytes each) sets the maximum
+ possible physical page size at 65307 bytes or just under 64kB (thus
+ we know that a header corrupted so as destroy sizing/alignment
+ information will not cause a runaway bitstream.  We'll read in the
+ page according to the corrupted size information that's guaranteed to
+ be a reasonable size regardless, notice the checksum mismatch, drop
+ sync and then look for recapture).<p>
+
+<pre><tt>
+ byte value
+
+ 26 0x00-0xff (0-255)
+</tt></pre>
+
+<h4>segment_table (containing packet lacing values)</h4>
+
+ The lacing values for each packet segment physically appearing in
+ this page are listed in contiguous order.
+
+<pre><tt>
+ byte value
+
+ 27 0x00-0xff (0-255)
+ [...]
+ n  0x00-0xff (0-255, n=page_segments+26)
+</tt></pre>
+
+Total page size is calculated directly from the known header size and
+lacing values in the segment table. Packet data segments follow
+immediately after the header.<p>
+
+Page headers typically impose a flat .25-.5% space overhead assuming
+nominal ~8k page sizes.  The segmentation table needed for exact
+packet recovery in the streaming layer adds approximately .5-1%
+nominal assuming expected encoder behavior in the 44.1kHz, 128kbps
+stereo encodings.<p>
+
+<hr>
+<a href="http://www.xiph.org/">
+<img src="white-xifish.gif" align=left border=0>
+</a>
+<font size=-2 color=#505050>
+
+OggSquish is a <a href="http://www.xiph.org">Xiphophorus</a> effort to
+protect essential tenets of Internet multimedia from corporate
+hostage-taking; Open Source is the net's greatest tool to keep
+everyone honest. See <a href="http://www.xiph.org/about.html">About
+Xiphophorus</a> for details.
+<p>
+
+Ogg Vorbis is the first OggSquish audio CODEC.  Anyone may
+freely use and distribute the OggSquish and Vorbis specification,
+whether in a private, public or corporate capacity.  However,
+Xiphophorus and the Ogg project (xiph.org) reserve the right to set
+the Ogg/Vorbis specification and certify specification compliance.<p>
+
+Xiphophorus's Vorbis software CODEC implementation (libvorbis and the
+vorbis encode/decode/playback utility) are distributed under the GNU
+Public License.  This does not restrict third parties from
+distributing independent implementations of Vorbis software under
+other licenses.<p>
+
+OggSquish, Vorbis, Xiphophorus and their logos are trademarks (tm) of
+<a href="http://www.xiph.org/">Xiphophorus</a>.  These pages are
+copyright (C) 1994-1999 Xiphophorus. All rights reserved.<p>
+
+</body>
+
+
diff --git a/doc/framing.txt b/doc/framing.txt
deleted file mode 100644 (file)
index 9872a03..0000000
+++ /dev/null
@@ -1,293 +0,0 @@
-********************************************************************
-*                                                                  *
-* THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE.  *
-* USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
-* THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE.    *
-* PLEASE READ THESE TERMS DISTRIBUTING.                            *
-*                                                                  *
-* THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-1999             *
-* by 1999 Monty <monty@xiph.org> and The XIPHOPHORUS Company       *
-* http://www.xiph.org/                                             *
-*                                                                  *
-********************************************************************
-
- function: discussion of Vorbis framing
- author: Monty <xiphmont@mit.edu>, <monty@xiph.org>
- modifications by: Monty
- last modification date: Jun 30 1999
-
-********************************************************************
-
-Vorbis encodes short-time blocks of PCM data into raw packets of
-bit-packed data.  These raw packets may be used directly by transport
-mechanisms that provide their own framing and packet-seperation
-mechanisms (such as UDP datagrams).  For stream based storage (such as
-files) and transport (such as TCP streams or pipes), Vorbis also
-specifies an additional layer of bitstream structure to provide
-framing/sync, sync recapture after error, landmarks during seeking,
-and enough information to properly seperate data back into packets at
-the original packet boundaries without relying on decoding to find
-packet boundaries.
-
-Design constraints:
-
-1) True streaming; we must not need to seek to build a 100% complete
-   bitstream.
-
-2) Use no more than approximately 1-2% of bitstream bandwidth for packet
-   boundary marking, high-level framing, sync and seeking.
-
-3) Specification of absolute position within the original sample stream.
-
-4) Simple mechanism to ease limited editing, such as a simplified
-   concatenation mechanism.
-
-5) Detection of corruption and recapture after error.
-
-A vorbis stream is structured by dividing packets into segments of up
-to 255 bytes and then wrapping a group of contiguous packet segments
-into a variable length page preceeded by a page header.  Both the
-header size and page size are variable; the page header contains
-sizing information and checksum data to determine header/page size and
-data integrity. 
-
-The bitstream is captured (or recaptured) by looking for the beginning
-of a page, specifically the capture pattern.  Once the capture pattern
-is found, the decoder verifies page sync and integrity by computing
-and comparing the checksum. At that point, the decoder can extract the
-packetss themselves.
-
-**** Packet segmentation
-
-Packets are logically divided into multiple segments before encoding
-into a page. Note that the segmentation and fragmentation process is a
-logical one; it's used to compute page header values and the original
-page data need not be disturbed, even when a packet spans page
-boundaries.
-
-The raw packet is logically divided into [n] 255 byte segments and a
-last fractional segment of < 255 bytes.  A packet size may well
-consist only of the trailing fractional segment, and a fractional
-segment may be zero length.  These values, called "lacing values" are
-then saved and placed into the header segment table.
-
-An example should make the basic concept clear:
-
-raw packet:
-  ___________________________________________
- |______________packet data__________________| 753 bytes
-
-lacing values for page header segment table: 255,255,243
-
-We simply add the lacing values for the total size; the last lacing
-value for a packet is always the value that is less than 255. Note
-that this encoding both avoids imposing a maximum packet size as well
-as imposing minimum overhead on small packets (as opposed to, eg,
-simply using two bytes at the head of every packet and having a max
-packet size of 32k.  Small packets (<255, the typical case) are
-penalized with twice the segmentation overhead). Using the lacing
-values as suggested, small packets see the minimum possible
-byte-aligned overheade (1 byte) and large packets, over 512 bytes or
-so, see a fairly constant ~.5% overhead on encoding space.
-
-Clarification of boundary cases:
-
-Note that a lacing value of 255 implies that a second lacing value
-follows in the packet, and a value of < 255 marks the end of the
-packet after that many additional bytes.  A packet of 255 bytes (or a
-multiple of 255 bytes) is terminated by a lacing value of 0:
-
-raw packet:
-  _______________________________
- |________packet data____________|          255 bytes
-
-lacing values: 255, 0
-
-Note also that a 'nil' (zero length) packet is not an error; it
-consists of nothing more than a lacing value of zero in the header.
-
-**** Packets spanning pages:
-
-Packets are not resticted to beginning and ending within a page,
-although individual segments are, by definition, required to do so.
-Packets are not restricted to a maximum size, although excessively
-large packets in the data stream are discouraged; the Vorbis
-specification strongly recommend nominal page size of approximately
-4-8kB (large packets are forseen as being useful for initialization
-data at the beginning of a logical bitstream).
-
-After segmenting a packet, the encoder may decide not to place all the
-resulting segments into the current page; to do so, the encoder places
-the lacing values of the segments it wishes to belong to the current
-page into the current segment table, then finishes the page.  The next
-page is begun with the first value in the segment table belonging to
-the next packet segment, thus continuing the packet (data in the
-packet body must also correspond properly to the lacing values in the
-spanned pages. The segment data in the first packet corresponding to the
-lacing values of the first page belong in that page; packet segments listed in the segment table of the following page must begin the page body of the subsequent page).
-
-The last mechanic to spanning a page boundary is to set the header
-flag in the new page to indicate that the first lacing value in the
-segment table continues rather than begins a packet; a header flag of
-0x02 is used to indicate a continued packet.  Although mandatory, it
-is not actually algorithmically necessary; one could inspect the
-preceeding segment table to determine if the packet is new or
-continued.  Adding the information to the packet_header flag allows a
-simpler design (with no overhead) that needs only inspect the current
-page header after frame capture.  This also allows faster error
-recovery in the event that the packet originates in a corrupt
-preceeding page, implying that the previous page's segment table
-cannot be trusted.
-
-Note that a packet can span an arbitrary number of pages; the above
-spanning process is repeated for each spanned page boundary.  Also a
-'zero termination' on a packet size that is an even multiple of 255
-must appear even if the lacing value appears in the next page as a
-zero-length continuation of the current packet.  The header flag
-should be set to 0x02 to indicate that the packet spanned, even though
-the span is a nil case as far as data is concerned.
-
-The encoding looks odd, but is properly optimized for speed and the
-expected case of the majority of packets being between 50 and 200
-bytes (note that it is designed such that packets of wildly different
-sizes can be handled within the model; placing packet size
-restrictions on the encoder would have only slightly simplified design
-in page generation and increased overall encoder complexity).
-
-The main point behind tracking individual packets (and packet
-segments) is to allow more flexible encoding tricks that requiring
-explicit knowledge of packet size. An example is simple bandwidth
-limiting, implemented by simply truncating packets in the nominal case
-(the packet is arranged so that the least sensitive portion of the
-data comes last).
-
-**** Page header
-
-The headering mechanism is designed to avoid copying and re-assembly
-of the packet data; the header can be generated directly from incoming
-packet data.  The encoder buffers packet data until it finishes a
-complete page at which point it writes the header followed by the
-buffered packet segments.
-
-capture_pattern:
-
- A header begins with a capture pattern that simplifies identifying
- pages; once the decoder has found the capture pattern it can do a more
- intensive job of verifying that it has in fact found a page boundary
- (as opposed to an inadvertant coincidence in the byte stream).
-
- byte value
-  0  0x4f 'O'
-  1  0x67 'g'
-  2  0x67 'g'
-  3  0x53 'S'  
-
-stream_structure_version:
-
- The capture pattern is followed by the stream structure revision:
-
-  4  0x00
-
-header_type_flag:
-  
- The header type flag identifies this page's context in the bitstream:
-
-  5  0x00 (beginning of bitstream)
-     0x01 (bitstream continued, fresh packet)
-     0x02 (bitstream continued, continued packet)
-
-PCM absolute position
-
- (This is packed in the same way the rest of Vorbis packet data is
- packed; LSb of LSB first.  Note that the 'position' data specifies a
- sample number (eg, in a CD quality sample is four octets, 16 bits for
- left and 16 bits for right).  The position specified is the total
- samples encoded after including all packets begun in this page.  The
- rationale here is that the position specified in the frame header of
- the last page tells how long the PCM data coded by the bitstream is.
-
-  6  0xXX LSB
-  7  0xXX
-  8  0xXX
-  9  0xXX
- 10  0xXX
- 11  0xXX
- 12  0xXX
- 13  0xXX MSB
-
-stream serial number:
- Vorbis allows for seperate logical bitstreams to be mixed at page
- granularity in a physical bitstream.  The most common case would be
- sequential arrangement, but it is possible to interleave pages for
- two seperate bitstreams to be decoded concurrently.  Right now, the
- standard code doesn't use the serial number (sets it to zero), but it
- will eventually.  Each logical stream must have a unique serial
- number within a physical stream:
-
- 14  0xXX LSB
- 15  0xXX
- 16  0xXX
- 17  0xXX MSB
-
-page sequence no
-
- Page counter; lets us know if a page is lost (useful where packets
- span page boundaries).
-
- 18  0xXX LSB
- 19  0xXX
- 20  0xXX
- 21  0xXX MSB
-
-page checksum
-     
- 32 bit CRC value (direct algorithm, initial val and final XOR = 0,
- generator polynomial=0x04c11db7).  The value is computed over the
- entire header (with the CRC field in the header set to zero) and then
- continued over the page.  The CRC field is then filled with the
- computed value.
-
- (A thorough discussion of CRC algorithms can be found in "A Painless
- Guide to CRC Error Detection Algorithms" by Ross Williams
- (ross@guest.adelaide.edu.au).  The document is available from
- ftp://ftp.adelaide.edu.au/pub/rocksoft)
-
- 22  0xXX LSB
- 23  0xXX
- 24  0xXX
- 25  0xXX MSB
-
-page_segments
-
- The number of segment entries to appear in the segment table. The
- maximum number of 255 segments (255 bytes each) sets the maximum
- possible physical page size at 65307 bytes or just under 64kB (thus
- we know that a header corrupted so as destroy sizing/alignment
- information will not cause a runaway bitstream.  We'll read in the
- page according to the corrupted size information that's guaranteed to
- be a reasonable size regardless, notice the checksum mismatch, drop
- sync and then look for recapture).
-
- 26 0x00-0xff (0-255)
-
-segment_table (containing packet lacing values)
-
- The lacing values for each packet segment physically appearing in
- this page are listed in contiguous order.
-
- 27 0x00-0xff (0-255)
- [...]
- n  0x00-0xff (0-255, n=page_segments+26)
-
-Total page size is calculated directly from the known header size and
-lacing values in the segment table. Packet data segments follow
-immediately after the header.
-
-Page headers typically impose a flat .25-.5% space overhead assuming
-nominal ~8k page sizes.  The segmentation table needed for exact
-packet recovery in the streaming layer adds approximately .5-1%
-nominal assuming expected encoder behavior in the 44.1kHz, 128kbps
-stereo encodings.
-
diff --git a/doc/oggstream.html b/doc/oggstream.html
new file mode 100644 (file)
index 0000000..2980c6d
--- /dev/null
@@ -0,0 +1,193 @@
+<HTML><HEAD><TITLE>xiph.org: OggSquish Vorbis documentation</TITLE>
+<BODY bgcolor="#ffffff" text="#202020" link="#006666" vlink="#000000">
+<nobr><a href="vorbis.html"><img src="white-ogg.gif" border=0><img 
+src="vorbisword2.gif" border=0></a></nobr><p>
+
+
+<h1><font color=#000070>
+OggSquish logical and physical bitstream overview
+</font></h1>
+
+<em>Last update to this document: July 18, 1999</em><br> 
+
+<h2>OggSquish bitstreams</h2>
+
+OggSquish codecs use octet vectors of raw, compressed data
+(<em>packets</em>). These compressed packets do not have any
+high-level structure or boundary information; strung together, they
+appear to be streams of random bytes with no landmarks.<p>
+
+Raw packets may be used directly by transport mechanisms that provide
+their own framing and packet-seperation mechanisms (such as UDP
+datagrams).  For stream based storage (such as files) and transport
+(such as TCP streams or pipes), Vorbis and other future Ogg codecs use
+the OggSquish bitstream format to provide framing/sync, sync recapture
+after error, landmarks during seeking, and enough information to
+properly seperate data back into packets at the original packet
+boundaries without relying on decoding to find packet boundaries.<p>
+
+<h2>Logical and physical bitstreams</h2>
+
+Raw packets are grouped and encoded into contiguous pages of
+structured bitstream data called <em>logical bitstreams</em>.  A
+logical bitstream consists of pages, in order, belonging to a single
+codec instance.  Each page is a self contained entity (although it is
+possible that a packet may be split and encoded across one or more
+pages); that is, the page decode mechanism is designed to recognize,
+verify and handle single pages at a time from the overall bitstream.<p>
+
+Multiple logical bitstreams can be combined (with restricctions) into
+a single <em>physical bitstream</em>.  A physical bitstream consists
+of multiple logical bitstreams multiplexed at the page level. Whole
+pages are taken in order from multiple logical bitstreams and combined
+into a single physical stream of pages. The decoder reconstructs the
+original logical bitstreams from the physical bitstream by taking the
+pages in order fromt he physical bitstream and redirecting them into
+the appropriate logical decoding entitiy. The simplest physical
+bitstream is a single, unmultiplexed logical bitstream.  <p>
+
+<a href=framing.html>OggSquish Logical Bitstream Framing</a> discusses
+the page format of an OggSquish bitstream, the packet coding process
+and logical bitstreams in detail.  The remainder of this document
+specifies requirements for constructing finished, physical OggSquish
+bitstreams.<p>
+
+<h2>Mapping Restrictions</h2>
+
+Logical bitstreams may not be mapped/multiplexed into physical
+bitstreams without restriction.  Here we discuss design restrictions
+on OggSquish physical bitstreams in general, mostly to introduce
+design rationale. Each 'media' format defines its own (generally more
+restrictive) mapping.  An '<a href="vorbis-stream.html">Ogg Vorbis
+Audio Bitstream</a>', for example, has a <a
+href="vorbis-stream.html">specific physical bitstream structure</a>.
+An 'Ogg A/V' bitstream (not currently specified) will also mandate a
+specific, restricted physical bitstream format.<p>
+
+<h3>additional end-to-end structure</h3>
+
+The <a href="framing.html">framing specification</a> defines
+'beginning of stream' and 'end of stream' page markers via a header
+flag (it is possible for a stream to consist of a single page).  A
+stream always consists of an integer number of pages, an easy
+requirement given the variable size nature of pages.<p>
+
+In addition to the header flag marking the first and last pages of a
+logical bitstream, the first page of an OggSquish bitstream obeys
+additional restrictions.  Each individual media mapping specifies its
+own implementation details regarding these restrictions.<p>
+
+The first page of a logical OggSquish bitstream consists of a single,
+small 'initial header' packet that includes sufficient information to
+identify the exact CODEC type and media requirements of the logical
+bitstream.  The intent of this restriction is to simplify identifying
+the bitstream type and content; for a given media type (or across all
+OggSquish media types) we can know that we only need a small, fixed
+amount of data to uniquely identify the bitstream type.<p>
+
+As an example, Ogg Vorbis places the name and revision of the Vorbis
+CODEC, the audio rate and the audio quality into this initial header,
+thus simplifying vastly the certain identification of an Ogg Vorbis
+audio bitstream.<p>
+
+<h3>sequential multiplexing (chaining)</h3>
+
+The simplest form of logical bitstream multiplexing is concatenation
+(<em>chaining</em>).  Complete logical bitstreams are strung
+one-after-another in order.  The bitstreams do not overlap; the final
+page of a given logical bitstream is immediately followed by the
+initial page of the next.  Chaining is the only logical->physical
+mapping allowed by Ogg Vorbis.<p>
+
+Each chained logical bitstream must have a unique serial number within
+the scope of the physical bitstream.<p>
+
+<h3>concurrent multiplexing (grouping)</h3>
+
+Logical bitstreams may also be multiplexed 'in parallel'
+(<em>grouped</em>).  An example of grouping would be to allow
+streaming of seperate audio and video streams, using differnt codecs
+and different logical bitstreams, in the same physical bitstream.
+Whole pages from multiple logical bitstreams are mixed together.<p>
+
+The initial pages of each logical bitstream must appear first; the
+media mapping specifies the order of the initial pages.  For example,
+Ogg A/V will eventually specify an OggSquish video bitstream with
+audio.  The mapping may specify that the physical bitstream must begin
+with the initial page of a logical video bitstream, followed by the
+initial page of an audio stream.  Unlike initial pages, terminal pages
+for the logical bitstreams need not all occur contiguously (although a
+specific media mapping may require this; it is not mandated by the
+generic OggSquish stream spec).  Terminal pages may be 'nil' pages,
+that is, pages containing no content but simply a page header with
+position information and the 'last page of bitstream' flag set in the
+page header.<p>
+
+Each grouped bitstream must have a unique serial number within the
+scope of the physical bitstream.<p>
+
+<h3>sequential and concurrent multiplexing</h3>
+
+Groups of concurrently multiplexed bitstreams may be chained
+consecutively.  Such a physical bitstream obeys all the rules of both
+grouped and chained multiplexed streams; the groups, when unchained ,
+must stand on their own as a valid concurrently multiplexed
+bitstream.<p>
+
+<h3>multiplexing example</h3>
+
+Below, we present an example of a grouped and chained bitstream:<p>
+
+<img src=stream.gif><p>
+
+In this example, we see pages from five total logical bitstreams
+multiplexed into a physical bitstream.  Note the following
+characteristics:
+
+<ol><li>Grouped bitstreams begin together; all of the initial pages
+must appear before any data pages.  When concurrently multiplexed
+groups are chained, the new group does not begin until all the
+bitstreams in the previous group have terminated.<p>
+
+<li>The pages of concurrently multiplexed bitstreams need not conform
+to a regular order; the only requirement is that page <tt>n</tt> of a
+logical bitstream follow page <tt>n-1</tt> in the physical bitstream.
+There are no restrictions on intervening pages belonging to other
+logical bitstreams.  (Tying page appearence to bitrate demands is one
+logical strategy, ie, the page appears at the chronological point
+where decode requires more information).
+
+</ol>
+
+<hr>
+<a href="http://www.xiph.org/">
+<img src="white-xifish.gif" align=left border=0>
+</a>
+<font size=-2 color=#505050>
+
+OggSquish is a <a href="http://www.xiph.org">Xiphophorus</a> effort to
+protect essential tenets of Internet multimedia from corporate
+hostage-taking; Open Source is the net's greatest tool to keep
+everyone honest. See <a href="http://www.xiph.org/about.html">About
+Xiphophorus</a> for details.
+<p>
+
+Ogg Vorbis is the first OggSquish audio CODEC.  Anyone may
+freely use and distribute the OggSquish and Vorbis specification,
+whether in a private, public or corporate capacity.  However,
+Xiphophorus and the Ogg project (xiph.org) reserve the right to set
+the Ogg/Vorbis specification and certify specification compliance.<p>
+
+Xiphophorus's Vorbis software CODEC implementation (libvorbis and the
+vorbis encode/decode/playback utility) are distributed under the GNU
+Public License.  This does not restrict third parties from
+distributing independent implementations of Vorbis software under
+other licenses.<p>
+
+OggSquish, Vorbis, Xiphophorus and their logos are trademarks (tm) of
+<a href="http://www.xiph.org/">Xiphophorus</a>.  These pages are
+copyright (C) 1994-1999 Xiphophorus. All rights reserved.<p>
+
+</body>
+
+
diff --git a/doc/stream.gif b/doc/stream.gif
new file mode 100644 (file)
index 0000000..6cb7cae
Binary files /dev/null and b/doc/stream.gif differ
diff --git a/doc/vorbis.html b/doc/vorbis.html
new file mode 100644 (file)
index 0000000..9e7e8a7
--- /dev/null
@@ -0,0 +1,197 @@
+<HTML><HEAD><TITLE>xiph.org: OggSquish Vorbis documentation</TITLE>
+<BODY bgcolor="#ffffff" text="#202020" link="#006666" vlink="#000000">
+<nobr><img src="white-ogg.gif"><img src="vorbisword2.gif"></nobr><p>
+
+
+<h1><font color=#000070>
+OggSquish Vorbis encoding format documentation
+</font></h1>
+
+<em>Last update to this document: July 15, 1999</em><br> 
+<em>Last update to Vorbis documentation: July 15, 1999</em><p> 
+
+<table><tr><td>
+<img src=wait.gif>
+</td><td valign=center>
+As of writing, not all the below document
+links are live.  They will be populated as we complete the
+documents.
+</td></tr></table>
+
+<p>
+<h2>Documents</h2>
+<ul>
+<li><a href="programming.html">Programming with libvorbis</a><p>
+<li><a href="packet.html">Vorbis packet structure</a>
+<li><a href="envelope.html">Temporal envelope shaping and blocksize</a>
+<li><a href="mdct.html">Time domain segmentation and MDCT transform</a>
+<li><a href="resolution.html">The resolution floor</a>
+<li><a href="residuals.html">MDCT-domain fine structure</a><p>
+
+<li><a href="probmodel.html">The Vorbis probability model</a>
+
+<li><a href="bitpack.html">The Vorbis bitpacker</a><p>
+
+<li><a href="oggstream.html">OggSquish bitstream overview</a>
+<li><a href="framing.html">OggSquish logical bitstream and framing spec</a>
+<li><a href="vorbis-stream.html">Vorbis packet->OggSquish bitstream 
+       mapping</a><p>
+
+</ul>
+
+<h2>Description</h2>
+Ogg Vorbis is a general purpose compressed audio format
+for high quality (44.1-48.0kHz, 16+ bit, polyphonic) audio and music
+at moderate fixed and variable bitrates (40-80 kb/s/channel).  This
+places Vorbis in the same class as audio representations including
+MPEG-1 audio layer 3, MPEG-4 audio (AAC and TwinVQ), and PAC.<p>
+
+Vorbis is the first of a planned family of OggSquish multimedia coding
+formats being developed as part of Xiphophorus's OggSquish multimedia
+project.  See <a href="http://www.xiph.org/">http://www.xiph.org/</a>
+for more information.
+
+<h2>Vorbis technical documents</h2>
+
+A Vorbis encoder takes in overlapping (but contiguous) short-time
+segments of audio data. The encoder analyzes the content of the audio
+to determine an optimal compact representation; this phase of encoding
+is known as <em>analysis</em>.  For each short-time block of sound,
+the encoder then packs an efficient representation of the signal, as
+determined by analysis, into a raw packet much smaller than the size
+required by the original signal; this phase is <em>coding</em>.
+Lastly, in a streaming environment, the raw packets are then
+structured into a continuous stream of octets; this last phase is
+<em>streaming</em>. Note that the stream of octets is referred to both
+as a 'byte-' and 'bit-'stream; the latter usage is acceptible as the
+stream of octets is a physical representation of a true logical
+bit-by-bit stream.<p>
+
+A Vorbis decoder performs a mirror image process of extracting the
+original sequence of raw packets from an Ogg stream (<em>stream
+decomposition</em>), reconstructing the signal representation from the
+raw data in the packet (<em>decoding</em>) and them reconstituting an
+audio signal from the decoded representation (<em>synthesis</em>).<p>
+
+The <a href="programming.html">Programming with libvorbis</a>
+documents discuss use of the reference Vorbis codec library
+(libvorbis) produced by Xiphophorus.<p>
+
+The data representations and algorithms necessary at each step to
+encode and decode Ogg Vorbis bitstreams are described by the below
+documents in sufficient detail to construct a complete Vorbis codec.
+Note that at the time of writing, Vorbis is still in a 'Request For
+Comments' stage of development; despite being in advanced stages of
+development, input from the multimedia community is welcome.<p>
+
+<h3>Vorbis analysis and synthesis</h3>
+
+Analysis begins by seperating an input audio stream into individual,
+overlapping short-time segments of audio data.  These segments are
+then transformed into an alternate representation, seeking to
+represent the original signal in a more efficient form that codes into
+a smaller number of bytes.  The analysis and transformation stage is
+the most complex element of producing a Vorbis bitstream.<p>
+
+The corresponding synthesis step in the decoder is simpler; there is
+no analysis to perform, merely a mechanical, deterministic
+reconstruction of the original audio data from the transform-domain
+representation.<p>
+
+<ul>
+<li><a href="packet.html">Vorbis packet structure</a>: Describes the basic analysis components necessary to produce Vorbis packets and the structure of the packet itself.
+<li><a href="envelope.html">Temporal envelope shaping and blocksize</a>: Use of temporal envelope shaping and variable blocksize to minimize time-domain energy leakage during wide dynamic range and spectral energy swings.  Also discusses time-related principles of psychoacoustics.
+<li><a href="mdct.html">Time domain segmentation and MDCT transform</a>: Division of time domain data into individual overlapped, windowed short-time vectors and transformation using the MDCT
+<li><a href="resolution.html">The resolution floor</a>: Use of frequency doamin psychoacoustics, and the MDCT-domain noise, masking and resolution floors
+<li><a href="residuals.html">MDCT-domain fine structure</a>: Production, quantization and massaging of MDCT-spectrum fine structure
+</ul>
+
+<h3>Vorbis coding and decoding</h3>
+
+Coding and decoding converts the transform-domain representation of
+the original audio produced by analysis to and from a bitwise packed
+raw data packet.  Coding and decoding consist of two logically
+orthogonal concepts, <em>back-end coding</em> and <em>bitpacking</em>.<p>
+
+<em>Back-end coding</em> uses a probability model to represent the raw numbers
+of the audio representation in as few physical bits as possible;
+familiar examples of back-end coding include Huffman coding and Vector
+Quantization.<p>
+
+<em>Bitpacking</em> arranges the variable sized words of the back-end
+coding into a vector of octets without wasting space.  The octets
+produced by coding a single short-time audio segment is one raw Vorbis
+packet.<p>
+
+<ul>
+
+<li><a href="probmodel.html">The Vorbis probability model</a>
+
+<li><a href="bitpack.html">The Vorbis bitpacker</a>: Arrangement of 
+variable bit-length words into an octet-aligned packet.
+
+</ul>
+
+<h3>Vorbis streaming and stream decomposition</h3>
+
+Vorbis packets contain the raw, bitwise-compressed representation of a
+snippet of audio.  These packets contain no structure and cannot be
+strung together directly into a stream; for streamed transmission and
+storage, Vorbis packets are encoded into an Ogg bitstream.<p>
+
+<ul>
+
+<li><a href="oggstream.html">OggSquish bitstream overview</a>: High-level
+description of OggSquish logical bitstreams, how logical bitstreams
+(of mixed media types) can be combined into physical bitstreams, and
+restrictions on logical-to-physical mapping.  Note that this document is
+not specific only to Ogg Vorbis.
+
+<li><a href="framing.html">OggSquish logical bitstream and framing
+spec</a>: Low level, complete specification of OggSquish logical
+bitstream pages.  Note that this document is not specific only to Ogg
+Vorbis.
+
+<li><a href="vorbis-stream.html">Vorbis bitstream mapping</a>:
+Specifically describes mapping Vorbis data into an
+OggSquish physical bitstream.  
+
+</ul>
+
+
+<hr>
+<a href="http://www.xiph.org/">
+<img src="white-xifish.gif" align=left border=0>
+</a>
+<font size=-2 color=#505050>
+
+OggSquish is a <a href="http://www.xiph.org">Xiphophorus</a> effort to
+protect essential tenets of Internet multimedia from corporate
+hostage-taking; Open Source is the net's greatest tool to keep
+everyone honest. See <a href="http://www.xiph.org/about.html">About
+Xiphophorus</a> for details.
+<p>
+
+Ogg Vorbis is the first OggSquish audio CODEC.  Anyone may
+freely use and distribute the OggSquish and Vorbis specification,
+whether in a private, public or corporate capacity.  However,
+Xiphophorus and the Ogg project (xiph.org) reserve the right to set
+the Ogg/Vorbis specification and certify specification compliance.<p>
+
+Xiphophorus's Vorbis software CODEC implementation (libvorbis and the
+vorbis encode/decode/playback utility) are distributed under the GNU
+Public License.  This does not restrict third parties from
+distributing independent implementations of Vorbis software under
+other licenses.<p>
+
+OggSquish, Vorbis, Xiphophorus and their logos are trademarks (tm) of
+<a href="http://www.xiph.org/">Xiphophorus</a>.  These pages are
+copyright (C) 1994-1999 Xiphophorus. All rights reserved.<p>
+
+</body>
+
+
+
+
+
+
diff --git a/doc/vorbisword2.gif b/doc/vorbisword2.gif
new file mode 100644 (file)
index 0000000..204a7de
Binary files /dev/null and b/doc/vorbisword2.gif differ
diff --git a/doc/wait.gif b/doc/wait.gif
new file mode 100644 (file)
index 0000000..a0da80f
Binary files /dev/null and b/doc/wait.gif differ
diff --git a/doc/white-ogg.gif b/doc/white-ogg.gif
new file mode 100644 (file)
index 0000000..9bd5306
Binary files /dev/null and b/doc/white-ogg.gif differ
diff --git a/doc/white-xifish.gif b/doc/white-xifish.gif
new file mode 100644 (file)
index 0000000..e76d036
Binary files /dev/null and b/doc/white-xifish.gif differ
index 9bc4fcd..dc31653 100644 (file)
@@ -26,8 +26,6 @@
 
  ********************************************************************/
 
-static const char rcsid[] = "$Id";
-
 #include <stdlib.h>
 
 /* pcm accumulator and multipliers 
@@ -307,3 +305,7 @@ int vorbis_analysis(vorbis_state *v, double **pcm, int vals){
   /* done */
   return(1);
 }
+
+
+
+
index acfca40..a4c8f35 100644 (file)
  function: PCM data vector blocking, windowing and dis/reassembly
  author: Monty <xiphmont@mit.edu>
  modifications by: Monty
- last modification date: Jun 26 1999
+ last modification date: Jul 13 1999
 
  ********************************************************************/
 
-/* $Id: codec.h,v 1.2 1999/07/13 08:00:15 mwhitson Exp $ */
-
 #ifndef _vorbis_codec_h_
 #define _vorbis_codec_h_
 
@@ -76,12 +74,22 @@ typedef struct {
 } vorbis_page;
 
 typedef struct {
-  unsigned size32 crc_lookup[256];
+  /*             _________________________________________________
+     body_data: |_________________________________________________|
+     body_returned ----^       ^                          ^       ^
+     body_processed------------'                          |       |
+     body_fill     ---------------------------------------'       |     
+     body_storage  _______________________________________________' 
+
+     the header is labelled the same way.  Not all the pointers are 
+     used by both encode and decode */
 
   unsigned char   *body_data;    /* bytes from packet bodies */
-  long    body_storage;
-  long    body_fill;
-  long    body_processed;
+  long    body_storage;          /* storage elements allocated */
+  long    body_fill;             /* elements stored; fill mark */
+  long    body_returned;         /* elements of fill returned */
+
 
   int    *lacing_vals;    /* The values that will go to the segment table */
   size64 *pcm_vals;       /* pcm_pos values for headers. Not compact
@@ -89,9 +97,11 @@ typedef struct {
                             lacing fifo */
   long    lacing_storage;
   long    lacing_fill;
+  long    lacing_packet;
+  long    lacing_returned;
 
-  unsigned char    header[282];    /* working space for header */
-  int              headerbytes;    
+  unsigned char    header[282];      /* working space for header encode */
+  int              header_fill;
 
   int     e_o_s;          /* set when we have buffered the last packet in the
                             logical bitstream */
@@ -99,17 +109,31 @@ typedef struct {
                             of a logical bitstream */
   long    serialno;
   long    pageno;
+  size64  pcmpos;
+
 } vorbis_stream_state;
 
 typedef struct {
   unsigned char *packet;
   long  bytes;
+  long  b_o_s;
   long  e_o_s;
 
   size64 pcm_pos;
 
 } vorbis_packet;
 
+typedef struct {
+  char *data;
+  int storage;
+  int fill;
+  int returned;
+
+  int unsynced;
+  int headerbytes;
+  int bodybytes;
+} vorbis_sync_state;
+
 /* libvorbis encodes in two abstraction layers; first we perform DSP
    and produce a packet (see docs/analysis.txt).  The packet is then
    coded into a framed bitstream by the second layer (see
@@ -136,6 +160,14 @@ extern int vorbis_stream_clear(vorbis_stream_state *vs);
 extern int vorbis_stream_destroy(vorbis_stream_state *vs);
 extern int vorbis_stream_eof(vorbis_stream_state *vs);
 
+extern int vorbis_page_version(vorbis_page *vg);
+extern int vorbis_page_continued(vorbis_page *vg);
+extern int vorbis_page_bos(vorbis_page *vg);
+extern int vorbis_page_eos(vorbis_page *vg);
+extern size64 vorbis_page_pcmpos(vorbis_page *vg);
+extern int vorbis_page_serialno(vorbis_page *vg);
+extern int vorbis_page_pageno(vorbis_page *vg);
+
 /* ENCODING PRIMITIVES: packet streaming layer **********************/
 
 extern int vorbis_stream_encode(vorbis_stream_state *vs,vorbis_packet *vp);
@@ -143,22 +175,19 @@ extern int vorbis_stream_page(vorbis_stream_state *vs, vorbis_page *vg);
 
 /* DECODING PRIMITIVES: packet streaming layer **********************/
 
-/* returns nonzero when it has a complete vorbis packet synced and
-   framed for decoding. Generally, it wants to see two page headers at
-   proper spacing before returning 'yea'. An exception is the initial
-   header to make IDing the vorbis stream easier: it will return sync
-   on the page header + beginning-of-stream marker.
+extern int vorbis_sync_init(vorbis_sync_state *vs);
+extern int vorbis_sync_clear(vorbis_sync_state *vs);
+extern int vorbis_sync_destroy(vorbis_sync_state *vs);
 
-   _sync will also abort framing if is sees a problem in the packet
-   boundary lacing.  */
-
-extern int vorbis_stream_decode(vorbis_stream_state *vs,char *stream,int size);
-extern int vorbis_stream_sync(vorbis_stream_state *vs);
-extern int vorbis_stream_verify(vorbis_stream_state *vs);
-extern size64 vorbis_stream_position(vorbis_stream_state *vs);
-extern int vorbis_stream_skippage(vorbis_stream_state *vs);
+extern char *vorbis_decode_buffer(vorbis_sync_state *vs, long size);
+extern int vorbis_decode_wrote(vorbis_sync_state *vs, long bytes);
+extern int vorbis_decode_stream(vorbis_sync_state *vs, vorbis_page *vg);
+extern int vorbis_decode_page(vorbis_stream_state *vs, vorbis_page *vg);
 extern int vorbis_stream_packet(vorbis_stream_state *vs,vorbis_packet *vp);
 
+extern int vorbis_sync_reset(vorbis_sync_state *vs);
+extern int vorbis_stream_reset(vorbis_stream_state *vs);
+
 /* DECODING PRIMITIVES: synthesis layer *****************************/
 
 extern int vorbis_synthesis_info(vorbis_dsp_state *vd,vorbis_info *vi);
index 601f6cf..71efd4b 100644 (file)
@@ -22,8 +22,6 @@
 
  ********************************************************************/
 
-static const char rcsid[] = "$Id";
-
 #include <stdlib.h>
 #include <stdio.h>
 #include <math.h>
index 3f35a77..1a9fdb1 100644 (file)
@@ -6,7 +6,7 @@
  * PLEASE READ THESE TERMS DISTRIBUTING.                            *
  *                                                                  *
  * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-1999             *
- * by 1999 Monty <monty@xiph.org> and The XIPHOPHORUS Company       *
+ * by 1999 Monty <monty@xiph.org> and the XIPHOPHORUS Company       *
  * http://www.xiph.org/                                             *
  *                                                                  *
  ********************************************************************
@@ -15,7 +15,7 @@
            decode vorbis streams back into raw packets
  author: Monty <xiphmont@mit.edu>
  modifications by: Monty
- last modification date: Jul 10 1999
+ last modification date: Jul 13 1999
 
  note: The CRC code is directly derived from public domain code by
  Ross Williams (ross@guest.adelaide.edu.au).  See framing.txt for
 
  ********************************************************************/
 
-static const char rcsid[] = "$Id";
-
 #include <stdlib.h>
 #include <string.h>
 #include "codec.h"
 
 /* A complete description of Vorbis framing exists in docs/framing.txt */
 
+int vorbis_page_version(vorbis_page *vg){
+  return((int)(vg->header[4]));
+}
+
+int vorbis_page_continued(vorbis_page *vg){
+  return((int)(vg->header[5]&0x01));
+}
+
+int vorbis_page_bos(vorbis_page *vg){
+  return((int)(vg->header[5]&0x02));
+}
+
+int vorbis_page_eos(vorbis_page *vg){
+  return((int)(vg->header[5]&0x04));
+}
+
+size64 vorbis_page_pcmpos(vorbis_page *vg){
+  char *page=vg->header;
+  size64 pcmpos=page[13];
+  pcmpos= (pcmpos<<8)|page[12];
+  pcmpos= (pcmpos<<8)|page[11];
+  pcmpos= (pcmpos<<8)|page[10];
+  pcmpos= (pcmpos<<8)|page[9];
+  pcmpos= (pcmpos<<8)|page[8];
+  pcmpos= (pcmpos<<8)|page[7];
+  pcmpos= (pcmpos<<8)|page[6];
+  return(pcmpos);
+}
+
+int vorbis_page_serialno(vorbis_page *vg){
+  return(vg->header[14] |
+        (vg->header[15]<<8) |
+        (vg->header[16]<<16) |
+        (vg->header[17]<<24));
+}
+int vorbis_page_pageno(vorbis_page *vg){
+  return(vg->header[18] |
+        (vg->header[19]<<8) |
+        (vg->header[20]<<16) |
+        (vg->header[21]<<24));
+}
+
 /* helper to initialize lookup for direct-table CRC */
+
+static unsigned size32 crc_lookup[256];
+static int crc_ready=0;
+
 static unsigned size32 _vorbis_crc_entry(unsigned long index){
   int           i;
   unsigned long r;
@@ -48,8 +93,22 @@ static unsigned size32 _vorbis_crc_entry(unsigned long index){
  return (r & 0xffffffffUL);
 }
 
+/* mind this in threaded code; sync_init and stream_init call it.
+   It's thread safe only after the first time it returns */
+
+static void _vorbis_crc_init(void){
+  if(!crc_ready){
+    /* initialize the crc_lookup table */
+    int i;
+    for (i=0;i<256;i++)
+      crc_lookup[i]=_vorbis_crc_entry((unsigned long)i);
+    crc_ready=0;
+  }
+}
+
+/* init the encode/decode logical stream state */
+
 int vorbis_stream_init(vorbis_stream_state *vs,int serialno){
-  int i;
   if(vs){
     memset(vs,0,sizeof(vorbis_stream_state));
     vs->body_storage=16*1024;
@@ -59,9 +118,8 @@ int vorbis_stream_init(vorbis_stream_state *vs,int serialno){
     vs->lacing_vals=malloc(vs->lacing_storage*sizeof(int));
     vs->pcm_vals=malloc(vs->lacing_storage*sizeof(size64));
 
-    /* initialize the crc_lookup table */
-    for (i=0;i<256;i++)
-      vs->crc_lookup[i]=_vorbis_crc_entry((unsigned long)i);
+    /* initialize the crc_lookup table if not done */
+    _vorbis_crc_init();
 
     vs->serialno=serialno;
 
@@ -93,19 +151,33 @@ int vorbis_stream_destroy(vorbis_stream_state *vs){
 /* Helpers for vorbis_stream_encode; this keeps the structure and
    what's happening fairly clear */
 
+static void _vs_body_expand(vorbis_stream_state *vs,int needed){
+  if(vs->body_storage<=vs->body_fill+needed){
+    vs->body_storage+=(needed+1024);
+    vs->body_data=realloc(vs->body_data,vs->body_storage);
+  }
+}
+
+static void _vs_lacing_expand(vorbis_stream_state *vs,int needed){
+  if(vs->lacing_storage<=vs->lacing_fill+needed){
+    vs->lacing_storage+=(needed+32);
+    vs->lacing_vals=realloc(vs->lacing_vals,vs->lacing_storage*sizeof(int));
+    vs->pcm_vals=realloc(vs->pcm_vals,vs->lacing_storage*sizeof(size64));
+  }
+}
+
 /* checksum the page */
 /* Direct table CRC; note that this will be faster in the future if we
    perform the checksum silmultaneously with other copies */
 
-static void _vs_checksum(vorbis_stream_state *vs,vorbis_page *vg){
+static void _vs_checksum(vorbis_page *vg){
   unsigned size32 crc_reg=0;
-  unsigned size32 *lookup=vs->crc_lookup;
   int i;
 
   for(i=0;i<vg->header_len;i++)
-    crc_reg=(crc_reg<<8)^lookup[((crc_reg >> 24)&0xff)^vg->header[i]];
+    crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^vg->header[i]];
   for(i=0;i<vg->body_len;i++)
-    crc_reg=(crc_reg<<8)^lookup[((crc_reg >> 24)&0xff)^vg->body[i]];
+    crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^vg->body[i]];
   
   vg->header[22]=crc_reg&0xff;
   vg->header[23]=(crc_reg>>8)&0xff;
@@ -118,15 +190,8 @@ int vorbis_stream_encode(vorbis_stream_state *vs,vorbis_packet *vp){
   int lacing_vals=vp->bytes/255+1,i;
 
   /* make sure we have the buffer storage */
-  if(vs->body_storage<=vs->body_fill+vp->bytes){
-    vs->body_storage+=(vp->bytes+1024);
-    vs->body_data=realloc(vs->body_data,vs->body_storage);
-  }
-  if(vs->lacing_storage<=vs->lacing_fill+lacing_vals){
-    vs->lacing_storage+=(lacing_vals+32);
-    vs->lacing_vals=realloc(vs->lacing_vals,vs->lacing_storage*sizeof(int));
-    vs->pcm_vals=realloc(vs->pcm_vals,vs->lacing_storage*sizeof(size64));
-  }
+  _vs_body_expand(vs,vp->bytes);
+  _vs_lacing_expand(vs,lacing_vals);
 
   /* Copy in the submitted packet.  Yes, the copy is a waste; this is
      the liability of overly clean abstraction for the time being.  It
@@ -168,7 +233,7 @@ int vorbis_stream_page(vorbis_stream_state *vs, vorbis_page *vg){
 
     vs->body_fill-=vs->body_returned;
     memmove(vs->body_data,vs->body_data+vs->body_returned,
-           vs->body_fill*sizeof(char));
+           (vs->body_fill-vs->body_returned)*sizeof(char));
     vs->body_returned=0;
   }
 
@@ -178,12 +243,14 @@ int vorbis_stream_page(vorbis_stream_state *vs, vorbis_page *vg){
     int vals=0,bytes=0;
     int maxvals=(vs->lacing_fill>255?255:vs->lacing_fill);
     long acc=0;
+    size64 pcm_pos=vs->pcm_vals[0];
 
     /* construct a page */
     /* decide how many segments to include */
     for(vals=0;vals<maxvals;vals++){
       if(acc>4096)break;
       acc+=vs->lacing_vals[vals]&0x0ff;
+      if((vs->lacing_vals[vals]&0x0ff)<255)pcm_pos=vs->pcm_vals[vals];
     }
 
     /* construct the header in temp storage */
@@ -192,27 +259,20 @@ int vorbis_stream_page(vorbis_stream_state *vs, vorbis_page *vg){
     /* stream structure version */
     vs->header[4]=0x00;
 
-    if(vs->b_o_s==0){ 
-      /* Ah, this is the first page */
-      vs->header[5]=0x00;
-    }else{
-      if(vs->lacing_vals[0]&0x100){
-       /* The first packet segment is the beginning of a packet */
-       vs->header[5]=0x01;
-      }else{
-       vs->header[5]=0x02;
-      }
-    }
+    
+    vs->header[5]=0x00;
+    /* continued packet flag? */
+    if((vs->lacing_vals[0]&0x100)==0)vs->header[5]|=0x01;
+    /* first page flag? */
+    if(vs->b_o_s==0)vs->header[5]|=0x02;
+    /* last page flag? */
+    if(vs->e_o_s && vs->lacing_fill==vals)vs->header[5]|=0x04;
     vs->b_o_s=1;
 
     /* 64 bits of PCM position */
-    {
-      size64 pcm_pos=vs->pcm_vals[vals-1];
-
-      for(i=6;i<14;i++){
-       vs->header[i]=(pcm_pos&0xff);
-       pcm_pos>>=8;
-      }
+    for(i=6;i<14;i++){
+      vs->header[i]=(pcm_pos&0xff);
+      pcm_pos>>=8;
     }
 
     /* 32 bits of stream serial number */
@@ -254,13 +314,13 @@ int vorbis_stream_page(vorbis_stream_state *vs, vorbis_page *vg){
 
     /* set pointers in the vorbis_page struct */
     vg->header=vs->header;
-    vg->header_len=vs->headerbytes=vals+27;
+    vg->header_len=vs->header_fill=vals+27;
     vg->body=vs->body_data;
     vg->body_len=bytes;
 
     /* calculate the checksum */
 
-    _vs_checksum(vs,vg);
+    _vs_checksum(vg);
 
     return(1);
   }
@@ -275,36 +335,343 @@ int vorbis_stream_eof(vorbis_stream_state *vs){
 
 /* DECODING PRIMITIVES: packet streaming layer **********************/
 
-/* Accepts data for decoding; syncs and frames the bitstream, then
-   decodes pages into packets.  Works through errors and dropouts,
-   reporting holes/errors in the bitstream when the missing/corrupt
-   packet is requested by vorbis_stream_packet(). Call with size=-1
-   for EOS */
+/* This has two layers to place more of the multi-serialno and paging
+   control in the application's hands.  First, we expose a data buffer
+   using vorbis_decode_buffer().  The app either copies into the
+   buffer, or passes it directly to read(), etc.  We then call
+   vorbis_decode_wrote() to tell how many bytes we just added.
+
+   Pages are returned (pointers into the buffer in vorbis_sync_state)
+   by vorbis_decode_stream().  The page is then submitted to
+   vorbis_decode_page() along with the appropriate
+   vorbis_stream_state* (ie, matching serialno).  We then get raw
+   packets out calling vorbis_stream_packet() with a
+   vorbis_stream_state.  See the 'frame-prog.txt' docs for details and
+   example code. */
+
+/* initialize the struct to a known state */
+int vorbis_sync_init(vorbis_sync_state *vs){
+  if(vs){
+    memset(vs,0,sizeof(vorbis_sync_state));
+    _vorbis_crc_init();
+  }
+  return(0);
+}
+
+/* clear non-flat storage within */
+int vorbis_sync_clear(vorbis_sync_state *vs){
+  if(vs){
+    if(vs->data)free(vs->data);
+    vorbis_sync_init(vs);
+  }
+  return(0);
+}
+
+char *vorbis_decode_buffer(vorbis_sync_state *vs, long size){
 
-/* all below:  <0 error, 0 not enough data, >0 success */
+  /* first, clear out any space that has been previously returned */
+  if(vs->returned){
+    vs->fill-=vs->returned;
+    if(vs->fill-vs->returned>0)
+      memmove(vs->data,vs->data+vs->returned,
+             (vs->fill-vs->returned)*sizeof(char));
+    vs->returned=0;
+  }
 
-int vorbis_stream_decode(vorbis_stream_state *vs,char *stream,int size){
-  /* beginning a page? ie, no header started yet?*/
-  if vs->
-  
-  
+  if(size>vs->storage-vs->fill){
+    /* We need to extend the internal buffer */
+    long newsize=size+vs->fill+4096; /* an extra page to be nice */
 
+    if(vs->data)
+      vs->data=realloc(vs->data,newsize);
+    else
+      vs->data=malloc(newsize);
+    vs->storage=newsize;
+  }
 
+  /* expose a segment at least as large as requested at the fill mark */
+  return(vs->data+vs->fill);
 }
 
-size64 vorbis_stream_pcmpos(vorbis_stream_state *vs){
+int vorbis_decode_wrote(vorbis_sync_state *vs, long bytes){
+  if(vs->fill+bytes>vs->storage)return(-1);
+  vs->fill+=bytes;
+  return(0);
+}
+
+/* sync the stream.  If we had to recapture, return -1.  If we
+   couldn't capture at all, return 0.  If a page was already framed
+   and ready to go, return 1 and fill in the page struct.
+
+   Returns pointers into buffered data; invalidated by next call to
+   _stream, _clear, _init, or _buffer */
+
+int vorbis_decode_stream(vorbis_sync_state *vs, vorbis_page *vg){
+
+  /* all we need to do is verify a page at the head of the stream
+     buffer.  If it doesn't verify, we look for the next potential
+     frame */
+
+  while(1){
+    char *page=vs->data+vs->returned;
+    long bytes=vs->fill-vs->returned;
+      
+    if(vs->headerbytes==0){
+      int headerbytes,i;
+      if(bytes<27)return(0); /* not enough for a header */
+
+      /* verify capture pattern */
+      if(memcmp(page,"OggS",4))goto sync_fail;
+      
+      headerbytes=page[26]+27;
+      if(bytes<headerbytes)return(0); /* not enough for header + seg table */
+
+      /* count up body length in the segment table */
+
+      for(i=0;i<page[26];i++)
+       vs->bodybytes+=page[27+i];
+      vs->headerbytes=headerbytes;
+    }
+    
+    if(vs->bodybytes+vs->headerbytes>bytes)return(0);
+
+    /* The whole test page is buffered.  Verify the checksum */
+    {
+      /* Grab the checksum bytes, set the header field to zero */
+      char chksum[4];
+      vorbis_page lvg;
+      
+      memcpy(chksum,page+22,4);
+      memset(page+22,0,4);
+      
+      /* set up a temp page struct and recompute the checksum */
+      lvg.header=page;
+      lvg.header_len=vs->headerbytes;
+      lvg.body=page+vs->headerbytes;
+      lvg.body_len=vs->bodybytes;
+      _vs_checksum(&lvg);
+       
+      /* Compare */
+      if(memcmp(chksum,page+22,4)){
+       /* D'oh.  Mismatch! Corrupt page (or miscapture and not a page
+          at all) */
+       /* replace the computed checksum with the one actually read in */
+       memcpy(page+22,chksum,4);
+         
+       /* Bad checksum. Lose sync */
+       goto sync_fail;
+      }
+    }
+       
+    vg->header=page;
+    vg->header_len=vs->headerbytes;
+    vg->body=page+vs->headerbytes;
+    vg->body_len=vs->bodybytes;
+    
+    vs->unsynced=0;
+    vs->returned+=vs->headerbytes+vs->bodybytes;
+    vs->headerbytes=0;
+    vs->bodybytes=0;
+
+    return(1);
+
+  sync_fail:
+    
+    vs->headerbytes=0;
+    vs->bodybytes=0;
+
+    /* search for possible capture */
+    
+    page=memchr(page+1,'O',bytes-1);
+    if(page)
+      vs->returned=page-vs->data;
+    else
+      vs->returned=vs->fill;
+
+    if(!vs->unsynced){
+      vs->unsynced=1;
+      return(-1);
+    }
+
+    /* loop; verifier above will take care of determining capture or not */
+
+  }
 }
 
-size64 vorbis_stream_pageno(vorbis_stream_state *vs){
+/* add the incoming page to the stream state; we decompose the page
+   into packet segments here as well. */
+
+int vorbis_decode_page(vorbis_stream_state *vs, vorbis_page *vg){
+  unsigned char *header=vg->header;
+  unsigned char *body=vg->body;
+  long            bodysize=vg->body_len;
+  int segptr=0;
+
+  int version=vorbis_page_version(vg);
+  int continued=vorbis_page_continued(vg);
+  int bos=vorbis_page_bos(vg);
+  int eos=vorbis_page_eos(vg);
+  size64 pcmpos=vorbis_page_pcmpos(vg);
+  int serialno=vorbis_page_serialno(vg);
+  int pageno=vorbis_page_pageno(vg);
+  int segments=header[26];
+  
+  /* clean up 'returned data' */
+  {
+    long lr=vs->lacing_returned;
+    long br=vs->body_returned;
+
+    /* body data */
+    if(vs->body_fill-br)
+      memmove(vs->body_data,vs->body_data+br,vs->body_fill-br);
+    vs->body_fill-=br;
+    vs->body_returned=0;
+
+    /* segment table */
+    if(vs->lacing_fill-lr){
+      memmove(vs->lacing_vals,vs->lacing_vals+lr,
+             (vs->lacing_fill-lr)*sizeof(int));
+      memmove(vs->pcm_vals,vs->pcm_vals+lr,
+             (vs->lacing_fill-lr)*sizeof(size64));
+    }
+    vs->lacing_fill-=lr;
+    vs->lacing_packet-=lr;
+    vs->lacing_returned=0;
+  }
+
+  /* check the serial number */
+  if(serialno!=vs->serialno)return(-1);
+  if(version>0)return(-1);
+
+  _vs_lacing_expand(vs,segments+1);
+
+  /* are we in sequence? */
+  if(pageno!=vs->pageno){
+    int i;
+
+    /* unroll previous partial packet (if any) */
+    for(i=vs->lacing_packet;i<vs->lacing_fill;i++)
+      vs->body_fill-=vs->lacing_vals[i]&0xff;
+    vs->lacing_fill=vs->lacing_packet;
+
+    /* make a note of dropped data in segment table */
+    vs->lacing_vals[vs->lacing_fill++]=0x400;
+    vs->lacing_packet++;
+
+    /* are we a 'continued packet' page?  If so, we'll need to skip
+       some segments */
+    if(continued){
+      bos=0;
+      for(;segptr<segments;segptr++){
+       int val=header[27+segptr];
+       body+=val;
+       bodysize-=val;
+       if(val<255){
+         segptr++;
+         break;
+       }
+      }
+    }
+  }
+  
+  if(bodysize){
+    _vs_body_expand(vs,bodysize);
+    memcpy(vs->body_data+vs->body_fill,body,bodysize);
+    vs->body_fill+=bodysize;
+  }
+
+  while(segptr<segments){
+    int val=header[27+segptr];
+    vs->lacing_vals[vs->lacing_fill]=val;
+    vs->pcm_vals[vs->lacing_fill]=pcmpos;
+
+    if(bos){
+      vs->lacing_vals[vs->lacing_fill]|=0x100;
+      bos=0;
+    }
+
+    vs->lacing_fill++;
+    segptr++;
+
+    if(val<255)vs->lacing_packet=vs->lacing_fill;
+  }
+  if(eos){
+    vs->e_o_s=1;
+    if(vs->lacing_fill>0)
+      vs->lacing_vals[vs->lacing_fill-1]|=0x200;
+  }
+
+  vs->pageno=pageno;
+
+  return(0);
 }
 
-int vorbis_stream_skippage(vorbis_stream_state *vs){
+/* clear things to an initial state.  Good to call, eg, before seeking */
+int vorbis_sync_reset(vorbis_sync_state *vs){
+  vs->fill=0;
+  vs->returned=0;
+  vs->unsynced=0;
+  vs->headerbytes=0;
+  vs->bodybytes=0;
+  return(0);
 }
 
-int vorbis_stream_clearbuf(vorbis_stream_state *vs){
+int vorbis_stream_reset(vorbis_stream_state *vs){
+  vs->body_fill=0;
+  vs->body_returned=0;
+
+  vs->lacing_fill=0;
+  vs->lacing_packet=0;
+  vs->lacing_returned=0;
+
+  vs->header_fill=0;
+
+  vs->e_o_s=0;
+  vs->b_o_s=0;
+  vs->pageno=0;
+  vs->pcmpos=0;
+
+  return(0);
 }
 
 int vorbis_stream_packet(vorbis_stream_state *vs,vorbis_packet *vp){
+
+  /* The last part of decode. We have the stream broken into packet
+     segments.  Now we need to group them into packets (or return the
+     out of sync markers) */
+
+  int ptr=vs->lacing_returned;
+
+  if(vs->lacing_packet<=ptr)return(0);
+  if(vs->lacing_vals[ptr]&=0x400){
+    /* We lost sync here; let the app know */
+    vs->lacing_returned++;
+    return(-1);
+  }
+
+  /* Gather the whole packet. We'll have no holes or a partial packet */
+  {
+    int size=vs->lacing_vals[ptr]&0xff;
+    int bytes=0;
+
+    vp->packet=vs->body_data+vs->body_returned;
+    vp->e_o_s=vs->lacing_vals[ptr]&0x200; /* last packet of the stream? */
+    vp->b_o_s=vs->lacing_vals[ptr]&0x100; /* first packet of the stream? */
+    bytes+=size;
+
+    while(size==255){
+      int val=vs->lacing_vals[++ptr];
+      size=val&0xff;
+      if(val&0x200)vp->e_o_s=0x200;
+      bytes+=size;
+    }
+    vp->pcm_pos=vs->pcm_vals[ptr];
+    vp->bytes=bytes;
+
+    vs->body_returned+=bytes;
+    vs->lacing_returned=ptr+1;
+  }
+  return(1);
 }
 
 #ifdef _V_SELFTEST
@@ -642,3 +1009,7 @@ int main(void){
 }
 
 #endif
+
+
+
+
index f6fd63b..f28fb4e 100644 (file)
@@ -36,8 +36,6 @@
 
  ********************************************************************/
 
-static const char rcsid[] = "$Id";
-
 #include <stdlib.h>
 #include <stdio.h>
 #include <math.h>
@@ -338,3 +336,16 @@ void iMDCT(double *in, double *out, MDCT_lookup *init, double *window){
     }
   }
 }
+
+
+
+
+
+
+
+
+
+
+
+
+
index 526187b..f7d3dbd 100644 (file)
@@ -15,8 +15,6 @@
 
  ********************************************************************/
 
-/* $Id: mdct.h,v 1.2 1999/07/13 08:00:19 mwhitson Exp $ */
-
 #ifndef _OGG_MDCT_H_
 #define _OGG_MDCT_H_