Re: [haskell-art] Haskell audio I/O packages
hi john, John Lato wrote: Using unsafeFreezeIOCArray and my stream implementation provides the fastest version yet, with an average of about 1.9s per run. This is in the hsndfile.hs test code as function test1. For the record, the stream implementation and fold I'm using are copied from Data.ByteString.Lazy. I changed the types to suit this code, but that's the source. thanks for posting the code. i'm not very convinced of lazy IO, but i'd be very interested in incorporating an iteratee based approach into hsndfile. i'm currently finalizing various api changes and extensions (mostly to do with abstracting both mutable and immutable buffers) and when i'm done i'll have a look at what you did in hsoundfile-3. obviously oleg's iteratee code is not hackaged yet, and i couldn't find it anywhere else, do you have any pointers? thanks, sk ___ haskell-art mailing list haskell-art@lurk.org http://lists.lurk.org/mailman/listinfo/haskell-art
Re: [haskell-art] Haskell audio I/O packages
On Tue, 9 Dec 2008, stefan kersten wrote: thanks for posting the code. i'm not very convinced of lazy IO, but i'd be very interested in incorporating an iteratee based approach into hsndfile. What are the reasons, you do not like lazy IO? Yes, currently it's a hack using unsafeInterleaveIO. But I hope someday one can hide this safely in a nice monad. But in general I find lazy stream processing a very elegant way of programming. Why else should we use Haskell and not, say OCaml? ___ haskell-art mailing list haskell-art@lurk.org http://lists.lurk.org/mailman/listinfo/haskell-art
Re: [haskell-art] Haskell audio I/O packages
On Tue, Dec 9, 2008 at 4:45 PM, stefan kersten [EMAIL PROTECTED] wrote: hi john, John Lato wrote: Using unsafeFreezeIOCArray and my stream implementation provides the fastest version yet, with an average of about 1.9s per run. This is in the hsndfile.hs test code as function test1. For the record, the stream implementation and fold I'm using are copied from Data.ByteString.Lazy. I changed the types to suit this code, but that's the source. thanks for posting the code. i'm not very convinced of lazy IO, but i'd be very interested in incorporating an iteratee based approach into hsndfile. i'm currently finalizing various api changes and extensions (mostly to do with abstracting both mutable and immutable buffers) and when i'm done i'll have a look at what you did in hsoundfile-3. obviously oleg's iteratee code is not hackaged yet, and i couldn't find it anywhere else, do you have any pointers? thanks, sk Hi Stefan, It's available at http://okmij.org/ftp/Haskell/Iteratee/ His DEFUN slides and notes, found at http://okmij.org/ftp/Streams.html#iteratee, are also helpful. I think it's pretty obvious how to apply this to hsndfile. However, I just noticed that Oleg has posted a TIFF library using an Iteratee approach. It supports seeking/random access and various other things that directly apply to the matter at hand. Looks like I'll have to do some studying again... http://okmij.org/ftp/Streams.html#random-bin-IO ___ haskell-art mailing list haskell-art@lurk.org http://lists.lurk.org/mailman/listinfo/haskell-art
Re: [haskell-art] Haskell audio I/O packages
On Fri, Dec 5, 2008 at 7:04 PM, stefan kersten [EMAIL PROTECTED] wrote: Henning Thielemann wrote: Thank you for this benchmark! I'm particularly interested in StorableVector because I hacked it quite a bit and use it for my own signal processing. I would also like to know how Fusion+Inlining improves the picture, but I do not know if there is anything to fuse at all in this simple example. Can you show us the actual test you run? I would then compare with my fusing signal data type from the synthesizer package. yes, thanks john, very interesting ... i'd also be interested in the benchmarking code ;) I'll try to post the code tonight after work. I'll also post the library versions I tested, which in all cases were the latest available on Hackage at the time I ran my tests. One thing to keep in mind is that, in general, the benchmarking code is pretty simple. I was trying to approach this from the point of view of an average user (e.g. me), who may not be familiar with all the Haskell optimization strategies. I doubt there's anything to fuse in this example, but I don't know much about fusion implementations. I have tried inlining certain functions, but either there was no change (which was my expectation), or a slight slowdown. 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. for CArray i've been using unsafeFreezeIOCArray, which does an O(1) conversion (simply keeping the pointer to the mutable array). Thanks, I'll try that. 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 Is this the plain Prelude [] type? Why are List and StorableVector similar in speed? Yes, it's the plain Prelude [] type. I expect they're similar in speed because of the particular implementation of AudioBuffer in HSoundFile-3. Specifically, the AudioBuffer class has a fromList function which is used to create the buffer from a Data.Binary decode operation. The UArr API is somewhat optimized for this use case, however I believe it's relatively inefficient for StorableVector. If someone more familiar with StorableVector were to write the AudioBuffer instance, I think it would perform better. Adding specialized instances for AudioBuffer UArr and AudioBuffer StorableVector would likely produce a significant gain; about 10% for UArr and probably less for StorableVector. Changing the AudioBuffer class to avoid the intermediate List is trickier. Last time I tried, I don't believe I found a successful approach. Given my results, my next approach will be an Enumerator API that uses hsndfile to actually read from the file. I think that would have nearly all the performance of hsndfile with a functional, composable interface. ___ haskell-art mailing list haskell-art@lurk.org http://lists.lurk.org/mailman/listinfo/haskell-art
Re: [haskell-art] Haskell audio I/O packages
On Mon, 8 Dec 2008, John Lato wrote: On Fri, Dec 5, 2008 at 4:36 PM, Henning Thielemann [EMAIL PROTECTED] wrote: Data Types: HSoundFile-3 - custom AudioBuffer class. Implementations are provided for UArr Double, List Double, and StorableVector Double StorableVector or StorableVector.Lazy? The latter seems appropriate here. I think that StorableVector is the correct choice. AudioBuffers are meant to be read/written strictly, in small chunks. I could certainly try StorableVector.Lazy. It may in fact be more performance. StorableVector.Lazy uses chunks. It won't be faster but will require less memory for stream operations. ___ haskell-art mailing list haskell-art@lurk.org http://lists.lurk.org/mailman/listinfo/haskell-art
Re: [haskell-art] Haskell audio I/O packages
Henning Thielemann wrote: Thank you for this benchmark! I'm particularly interested in StorableVector because I hacked it quite a bit and use it for my own signal processing. I would also like to know how Fusion+Inlining improves the picture, but I do not know if there is anything to fuse at all in this simple example. Can you show us the actual test you run? I would then compare with my fusing signal data type from the synthesizer package. yes, thanks john, very interesting ... i'd also be interested in the benchmarking code ;) 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. for CArray i've been using unsafeFreezeIOCArray, which does an O(1) conversion (simply keeping the pointer to the mutable array). 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 Is this the plain Prelude [] type? Why are List and StorableVector similar in speed? i'm curious about that one too ... sk ___ haskell-art mailing list haskell-art@lurk.org http://lists.lurk.org/mailman/listinfo/haskell-art
[haskell-art] Haskell audio I/O packages
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