{"id":886,"date":"2009-01-18T23:01:07","date_gmt":"2009-01-19T07:01:07","guid":{"rendered":"http:\/\/multimedia.cx\/eggs\/?p=886"},"modified":"2009-01-18T23:01:07","modified_gmt":"2009-01-19T07:01:07","slug":"not-an-exact-science","status":"publish","type":"post","link":"https:\/\/multimedia.cx\/eggs\/not-an-exact-science\/","title":{"rendered":"Not An Exact Science"},"content":{"rendered":"<p>A big shortcoming of <a href=\"http:\/\/fate.multimedia.cx\/\">FATE<\/a> so far has been its inability to test perceptual audio and video codecs. This is because when FATE runs a test, it compares the output to a known value in its own database, and the output needs to match the known value precisely, i.e., &#8220;bit-exact&#8221;. The problem with codecs classed as perceptual is that they are not specified to decode in a bit-exact manner. So, for example, decoding the Ogg Vorbis audio file abc.ogg on x86_64 and on PowerPC will produce 2 waves that, though they may sound identical to most listeners, are not precisely the same down to the PCM sample level; minor variations exist (generally, +\/- 1).<\/p>\n<p>I have a plan for adapting FATE to handle this. It may seem a little (or a lot) crazy, but hear me out.<\/p>\n<p>At first, I am only thinking about perceptual <strong>audio<\/strong> codecs. This will include Vorbis, MP3, AAC, WMA, QDesign, Real-cook, Real-28_8, and a bunch of others I am forgetting at the moment.<\/p>\n<p>The big idea is to store reference decoded waves and then, for each perceptual audio decoding test, decode the file and compare the wave to its reference wave; fail the test if the difference of any of the PCM points is greater than 1.<\/p>\n<p>How to perform the comparison? I have a few ideas:<\/p>\n<ul>\n<li>Craft a default Python algorithm that painstakingly unpacks each byte from both waves, iterates along each, and calculates the absolute value at each sample.<\/li>\n<li>Allow for a FATE installation to call out to a more efficient helper program, one preferably written using SIMD instructions that could read 16 bytes at a time from each wave, and perform absolute value calculations in parallel. I&#8217;m thinking a parallel subtract, followed by a parallel absolute value, followed by a bitwise AND should reveal if any of the 16 bytes is outside of tolerance.<\/li>\n<li>Any other tricks would be appreciated, especially regarding the default algorithm. Are there any special numerical tricks for determining the information I need from 4 bytes in parallel, packed in a 32-bit integer, without SIMD?<\/li>\n<\/ul>\n<p>This has the potential to be big, sample-wise. It occurred to me to use FLAC to mitigate storage problems. My first impulse was to store the reference waves as FLAC files in a FATE installation&#8217;s sample suite. They would be decoded as needed during a build\/test cycle. Decoding FLAC is reasonably fast, after all. However, the more I think about it, I think that part is a silly solution. As a compromise, I may store the reference waves as FLAC in the <a href=\"http:\/\/samples.mplayerhq.hu\/fate-suite\/\">central MPlayerhq.hu FATE suite archive<\/a> in order to mitigate storage and transfer requirements. It will also be time to create a small, standard syncing script that performs both the samples rsync and decompresses any new FLAC wave references in the archive.<\/p>\n<p>All of this is highly speculative at this point. I don&#8217;t know how much storage these hypothetical reference waves are going to require. And I don&#8217;t know how long it&#8217;s going to take in practice to perform all the comparisons. And of course, I don&#8217;t know if the +\/- 1 tolerance idea will hold up. Although cursory tests have been positive.<\/p>\n<p>I know it&#8217;s a mathematically &#8220;impure&#8221; solution. But we need <em>something<\/em> and I wanted to get this possibly workable idea out.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I have an idea for testing inexact perceptual audio codecs<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[101],"tags":[134,108],"class_list":["post-886","post","type-post","status-publish","format-standard","hentry","category-fate-server","tag-audio","tag-fate"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/posts\/886","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/comments?post=886"}],"version-history":[{"count":9,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/posts\/886\/revisions"}],"predecessor-version":[{"id":896,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/posts\/886\/revisions\/896"}],"wp:attachment":[{"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/media?parent=886"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/categories?post=886"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/tags?post=886"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}