Hello, This is the sort of thing that most people would put in a blog post, but I don't have a blog so I'm sending it to this list, since I think most readers would be interested.
I've recently been doing some tests of different sound file I/O packages in Haskell, and I would like to share the results. My test script involves reading a 66MB Wave file, a stereo recording at 44,100 / 16. The entire file is processed to determine the peak sample value. This is of particular instance to me because it involves scanning a large amount of data in its entirety, the file format is extremely common, and the process seems representative of the sort of operations often encountered doing audio work. I tested the following packages: Codecs hsndfile WAVE in addition, I tested two experimental interfaces to my library, HSoundFile. I did not test the current published interface, HSoundFile v. 2. The first interface I am experimenting with uses a "smart handle" approach, and in some ways is very similar to a Haskell implementation of libsndfile. I refer to this as HSoundFile-3. The second interface uses an enumerator streams overlaid on a Word8 enumerator, derived from Oleg's Iteratee package. I refer to this as Enumerator. All packages are haskell only, except hsndfile, which is a binding to the C libsndfile library. Test harnesses: HSoundFile-3 - a stream type is created to hold AudioBuffers. A recursive reader function uses unsafeInterleaveIO to read the entire file on demand. A strict foldl processes the Stream chunks to achieve the final value. Enumerator - An Iteratee is processes all values as received Codecs - the data list is processed by a strict foldl WAVE - the data list is processed by a strict foldl hsndfile - a recursive I/O function reads a chunk from the file (using IOCArray type) and accumulates the maximum values from each chunk. I attempted to create a framework like used for HSoundFile-3, however performance dropped dramatically; I suspect the slowdown is mostly from the process of freezing mutable arrays to immutable arrays. API type: HSoundFile-3 - strict reads/writes of buffers Enumerator - enumerator-based strict I/O Codecs - read/write entire file into data structure WAVE - lazily read file into list hsndfile - strict reads/writes of buffers Data Types: HSoundFile-3 - custom AudioBuffer class. Implementations are provided for UArr Double, List Double, and StorableVector Double Enumerator - enumerates Doubles Codecs - array of Doubles WAVE - [[Int32]] hsndfile - custom Buffer class with Array constraint. Implementations are provided for IOCArray and StorableVector. For chunked data types, all data is with chunk size 1000. All timing/memory data is the median value from multiple runs. In general different runs had very similar performance. Timing results: HSoundFile-3, StorableVector - real 16.5s HSoundFile-3, UArr - real 15.7s HSoundFile-3, List - real 17.6s Codecs - real 1m20s Enumerator - real 19s WAVE - real 29.1s hsndfile - real 2.0s Memory results (running test program with -hT) HSoundFile-3, StorableVector - 457,674,398 bytes x seconds HSoundFile-3, UArr - 531,452,404 bytes x seconds HSoundFile-3, List - 532,806,405 bytes x seconds Codecs - 5,869,214,258 bytes x seconds Enumerator - 957,845 bytes x seconds WAVE - 986,310,412 bytes x seconds hsndfile - 23,160 bytes x seconds A few notes: I did make an HSoundFile-3 implementation that used only UArrs, not the AudioBuffer class. This implementation was about 2 seconds faster for this test than the shown implementation, however I didn't think the extra efficiency was worth the more restrictive API. Anyway, that's what I've found so far. I was very hopeful that at least one of the pure haskell packages would be similar to hsndfile, but unfortunately I haven't found anything at this time. It's certainly beyond my ability. Cheers, John _______________________________________________ haskell-art mailing list haskell-art@lurk.org http://lists.lurk.org/mailman/listinfo/haskell-art