On Mon, 30 Nov 2009, Thomas Girod wrote:

> That's what I call a good teaser !
>
> Can you elaborate on how you achieved that ?

What details do you like to know?

The final data structure is a lazy storable vector that I write chunk by 
chunk to ALSA output. However I try to put as much as possible into a loop 
that fills the storable vector. This way I do not need to generate many 
temporary storable vectors. I extensively use a structure 
(synthesizer-core:Synthesizer.State.Signal), that is essentially a (exists 
s. (StateT s Maybe a, s)). It maintains an internal state and generates 
one new value per call. It is isomorphic to lists but does not have a 
storage. It is like stream-fusion:Data.Stream without the Skip constructor 
(because I have no 'filter' functions). I also use arrows 
(Synthesizer.Process.Causal) for getting sharing on a per sample basis.
  E.g. in
    StateSig.zip (StateSig.map f a) (StateSig.map g a)
   'a' is also a generator. When writing it this way, then the generator 
'a' is run twice, because it does not store anything. I have to write it 
this way:
    f &&& g :: Causal.T a (b,c)

I think the biggest bottleneck today is, that GHC decides to specialise 
functions that are used more than once and then does not inline them, 
although I have told it to do so. It's a pity, I can use an oscillator and 
it is rendered really fast. When I use the oscillator twice to get an 
phaser effect, then the program may become three times slower.
_______________________________________________
haskell-art mailing list
[email protected]
http://lists.lurk.org/mailman/listinfo/haskell-art

Reply via email to