Ogg CRC32 in Golang

blov · · 4375 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>The <a href="https://xiph.org/vorbis/doc/framing.html" rel="nofollow">Ogg audio framing format</a> has a 32-bit field in page headers that is supposed to store a 32-bit CRC checksum of the entire page. That is, the checksum field is set to 0, then the page is fed into CRC, and then the checksum field set to the result.</p> <p>The <a href="https://golang.org/pkg/hash/crc32/" rel="nofollow">standard library</a> has CRC support. This is what I&#39;m doing:</p> <pre><code>package main import ( &#34;hash/crc32&#34; ) func main() { // Read Opus file page into &#34;bytes&#34; // Zero checksum bytes table := crc32.MakeTable(0x04c11db7) hash := crc32.New(table) hash.Write(bytes) } </code></pre> <p>This gives me a checksum of <code>0xfa70dc13</code>. But looking at the input file in a hex editor, I can see the checksum should be <code>0x4092e33c</code>. I believe the problem is that Ogg uses a <a href="http://forum.xentax.com/viewtopic.php?f=17&amp;t=5314" rel="nofollow">slightly non-standard</a> version of CRC, where the initial value and final XOR are 0 as opposed to some other value (I think normally both are <code>0xffffffff</code>).</p> <p>I&#39;m wondering what my options are. Is there some way to use these custom values, or do I have to write my own CRC32?</p> <p>Thanks so much for any help.</p> <p>EDIT: It looks like others have decided to <a href="https://github.com/grd/ogg/blob/master/ogg.go#L246" rel="nofollow">write their own</a>, but I&#39;m still wondering if there&#39;s a better way.</p> <hr/>**评论:**<br/><br/>besna: <pre><p>If I remember right, isn&#39;t the crc calculated based on the resulting audio stream?</p></pre>will_alexander: <pre><p>The CRC is calculated for each page. Each page can be up to 255 segments long, where each segment contains 255 bytes (except the last segment, which can contain fewer). That means that each page can be at most ~64 kilobytes long, which means that most audio streams wouldn&#39;t fit in a single page. So no, the CRC isn&#39;t calculated based on the stream per se. <a href="https://xiph.org/vorbis/doc/framing.html" rel="nofollow">More info</a></p> <p>In the case of the pages I&#39;m working with, which are the metadata/Vorbis comment blocks, they&#39;re much short than 64KB, usually only one or two segments long.</p></pre>dwevlo: <pre><p>You can use Update:</p> <pre><code>x := crc32.Update(0xFFFFFFFF, table, bytes) fmt.Printf(&#34;%x\n&#34;, ^x) </code></pre> <p>But that doesn&#39;t seem to give the right answer. The algorithms look different:</p> <pre><code>func OggCRC(crc uint32, data []byte, tab *crc32.Table) uint32 { crc = ^crc for i := range data { crc = tab[byte(crc&gt;&gt;24)^data[i]] ^ (crc &lt;&lt; 8) } return ^crc } </code></pre> <p>vs:</p> <pre><code>func update(crc uint32, tab *Table, p []byte) uint32 { crc = ^crc for _, v := range p { crc = tab[byte(crc)^v] ^ (crc &gt;&gt; 8) } return ^crc } </code></pre> <p>But maybe you could modify the table in such a way that it comes out the same.</p></pre>will_alexander: <pre><p>Thanks for the info. How did you find <code>OggCRC()</code>? </p></pre>dwevlo: <pre><p>From the link you provided. I just rewrote it slightly to match the other one so I could compare them.</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

4375 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传