Lisp HUG Maillist Archive

Multiple calls to draw-line

I have a display-callback that draws a grayscale sonogram from fft data. To do 
this I'm making a lot of calls to draw-line, since (obviously) I need to draw 
each line, representing a frequency bin, with a different grayscale value 
(hence I can't use draw-lines or draw-polygon). This seems to slow the code up 
considerably. Here is the core loop within the function:

(let ((fft/2 (/ *fft-size* 2))
      (bin-width (round (/ %scroll-height% (/ *sample-rate* *fft-size*))))
      (delta (round (/ %scroll-width% *n-frames*))))
  (loop for k of-type fixnum being the hash-key of *spectrum*
        for fr of-type (simple-array double-float (*)) = (gethash k *spectrum*)
	for time of-type fixnum = (* delta k)
        do		  
	(loop for i of-type fixnum from 0 below fft/2
	      for freq = (the fixnum (rescale (* i bin-width) 
                                              (* bin-width fft/2) 
                                              %scroll-height%)) 
              for mag = (the double-float (aref fr (- fft/2 1 i)))
	      when (>= mag *cut-off*)
	      do
	      (gp:draw-line pixmap 
			    time freq (+ time delta) freq
		            :thickness bin-width
			    :foreground (make-gray (rescale (float mag 0.0s0)
                                                            *cut-off* 
                                                            1))))))

I have of course profiled, and whilst draw-line didn't seem to be on top of the 
stack a lot I still feel it's the culprit. I can't see a way to optimize this 
any more, so is there a different way I could do this, without having to make 
so many calls to draw-line?

Help/suggestions greatly appreciated,
Chris


Re: Multiple calls to draw-line

Hello Christopher,

The biggest speedup comes from avoiding I/O to the screen. So draw  
into an off-screen pixmap first, and then render all at once as an  
image copy operation from that pixmap to the screen.

Dr. David McClain
dbm@refined-audiometrics.com



On Jul 22, 2009, at 16:14 PM, Christopher Melen wrote:

>
> I have a display-callback that draws a grayscale sonogram from fft  
> data. To do
> this I'm making a lot of calls to draw-line, since (obviously) I  
> need to draw
> each line, representing a frequency bin, with a different grayscale  
> value
> (hence I can't use draw-lines or draw-polygon). This seems to slow  
> the code up
> considerably. Here is the core loop within the function:
>
> (let ((fft/2 (/ *fft-size* 2))
>      (bin-width (round (/ %scroll-height% (/ *sample-rate* *fft- 
> size*))))
>      (delta (round (/ %scroll-width% *n-frames*))))
>  (loop for k of-type fixnum being the hash-key of *spectrum*
>        for fr of-type (simple-array double-float (*)) = (gethash k  
> *spectrum*)
> 	for time of-type fixnum = (* delta k)
>        do		
> 	(loop for i of-type fixnum from 0 below fft/2
> 	      for freq = (the fixnum (rescale (* i bin-width)
>                                              (* bin-width fft/2)
>                                              %scroll-height%))
>              for mag = (the double-float (aref fr (- fft/2 1 i)))
> 	      when (>= mag *cut-off*)
> 	      do
> 	      (gp:draw-line pixmap
> 			    time freq (+ time delta) freq
> 		            :thickness bin-width
> 			    :foreground (make-gray (rescale (float mag 0.0s0)
>                                                            *cut-off*
>                                                            1))))))
>
> I have of course profiled, and whilst draw-line didn't seem to be on  
> top of the
> stack a lot I still feel it's the culprit. I can't see a way to  
> optimize this
> any more, so is there a different way I could do this, without  
> having to make
> so many calls to draw-line?
>
> Help/suggestions greatly appreciated,
> Chris
>
>



Re: Multiple calls to draw-line


On Jul 23, 2009, at 1:14 AM, Christopher Melen wrote:

>
> I have a display-callback that draws a grayscale sonogram from fft  
> data. To do
> this I'm making a lot of calls to draw-line, since (obviously) I  
> need to draw
> each line, representing a frequency bin, with a different grayscale  
> value
> (hence I can't use draw-lines or draw-polygon). This seems to slow  
> the code up
> considerably. Here is the core loop within the function:
>
> (let ((fft/2 (/ *fft-size* 2))
>      (bin-width (round (/ %scroll-height% (/ *sample-rate* *fft- 
> size*))))
>      (delta (round (/ %scroll-width% *n-frames*))))
>  (loop for k of-type fixnum being the hash-key of *spectrum*
>        for fr of-type (simple-array double-float (*)) = (gethash k  
> *spectrum*)
> 	for time of-type fixnum = (* delta k)
>        do		
> 	(loop for i of-type fixnum from 0 below fft/2
> 	      for freq = (the fixnum (rescale (* i bin-width)
>                                              (* bin-width fft/2)
>                                              %scroll-height%))
>              for mag = (the double-float (aref fr (- fft/2 1 i)))
> 	      when (>= mag *cut-off*)
> 	      do
> 	      (gp:draw-line pixmap
> 			    time freq (+ time delta) freq
> 		            :thickness bin-width
> 			    :foreground (make-gray (rescale (float mag 0.0s0)
>                                                            *cut-off*
>                                                            1))))))
>
> I have of course profiled, and whilst draw-line didn't seem to be on  
> top of the
> stack a lot I still feel it's the culprit. I can't see a way to  
> optimize this
> any more, so is there a different way I could do this, without  
> having to make
> so many calls to draw-line?
>
> Help/suggestions greatly appreciated,
> Chris
>


I don't know if it's possible with the API you use, but with X or  
other drawing systems, we could  speed this up by filling a polyline  
with a pattern (pixmap) having the wanted grayscale shades.

Or even easier, using that grayscale shade as a background and fill  
the complement polyline in black.

In either case, things could be cached in the window server and only  
one polyline drawing instruction would have to be issued.


-- 
__Pascal Bourguignon__
http://www.informatimago.com




Updated at: 2020-12-10 08:40 UTC