Lisp HUG Maillist Archive

Problem with C callback (PortAudio)

I have written some bindings for PortAudio, a widely-used cross-platform C
audio API. It requires a callback, which is called continuously while audio is
required. It works, but I often encounter the following error -

Error: Exception C0000005 [flags 0] at 218313C 
eax    40200 ebx  262FA60 ecx   19CEF0 edx   A5BFE8
esp  262FA14 ebp        0 esi        0 edi FFFFFFFF
  1 (abort) Return to event loop.

Type :b for backtrace, :c <option number> to proceed,  or :? for other options

PORTAUDIO-TEST 1 : 1 > :b
Call to (HARLEQUIN-COMMON-LISP:SUBFUNCTION
SYSTEM::|%FOREIGN-CALLABLE/fault_handler_on_c_stack|
(FLI:DEFINE-FOREIGN-CALLABLE "fault_handler_on_c_stack"))
Call to FLI::FOREIGN-CALLABLE-ENTRY-POINT-AUX-NESTED
Call to |%cffi-foreign-function/PA-OPEN-STREAM|
Interpreted call to PA-OPEN-STREAM
Interpreted call to PLAY-SAMPLES
Call to CAPI::EXECUTE-CALLBACK
Call to CAPI:EXECUTE-WITH-INTERFACE
Call to CAPI-WIN32-LIB::PERFORM-WM-COMMAND-FOR-R-PCL-WINDOW
Call to WIN32::WND-PROC
Call to (HARLEQUIN-COMMON-LISP:SUBFUNCTION
WIN32::|%FOREIGN-CALLABLE/wnd_proc_callback| (FLI:DEFINE-FOREIGN-CALLABLE
"wnd_proc_callback"))
Call to FLI::FOREIGN-CALLABLE-ENTRY-POINT-AUX-NESTED
Call to WIN32:IS-DIALOG-MESSAGE
Call to WIN32::PROCESS-MESSAGES
Call to MP::WIN32-PROCESS-WAIT-FOR-EVENT
Call to MP:PROCESS-READ-EVENT
Call to CAPI-INTERNALS:LOOP-PROCESS-EVENTS
Call to CAPI::INTERFACE-EVENT-LOOP
Call to CAPI::INITIALIZE-AND-PROCESS-EVENTS
Call to (HARLEQUIN-COMMON-LISP:SUBFUNCTION MP::PROCESS-SG-FUNCTION
MP::INITIALIZE-PROCESS-STACK)

On my Mac I simply get this -

Bus error(10) [code F068C678] at C

The callback itself takes the following form (I'm using CFFI) -

(defcallback process-samples :int ((input :pointer) 
                                   (output :pointer) 
			           (frames-per-buffer :ulong) 
                                   (time-info pa-stream-callback-time-info) 
                                   (status-flags pa-stream-callback-flags)
	                           (user-data :pointer))
  (declare (ignore input time-info status-flags user-data))
  (loop with n-samps = (length *samples*)		 
        for i from 0 below frames-per-buffer
        for j = (+ *counter* i)		  
	if (< j n-samps)
	do (setf (mem-aref output :float i) (aref *samples* j))	  
	else do
          (setf *counter* 0)
          (return 1)
	finally 
	(setf *counter* (+ *counter* frames-per-buffer))
	(return 0)))
		
This simply writes samples from the Lisp array *samples* to the output audio
buffer in blocks of size frames-per-buffer (in this case 2048). While the 
callback returns 0 it continues to be called, returning 1 stops it. The 
variable *counter* stores the current position within the sample buffer.

I suspect the error I'm getting may be due to GC occurring during the callback 
process, thus moving objects which the foreign code is still pointing to. I've 
declared my samples buffer static to hopefully account for this, but the error 
remains. The callback lives in its own thread, so possibly it's a 
multi-threading problem... Plus I'm calling PortAudio from a menu in my main 
interface, which adds possibly another level of complication...

PortAudio also has a non-callback interface, which causes no problems, but the 
advantage of the callback approach is that it allows me to update various 
variables on a 'per sample' basis. More info on this can be found at 
http://www.portaudio.com/trac/wiki/TutorialDir/WritingACallback.

Any help/suggestions greatly appreciated.

Chris


AW: Problem with C callback (PortAudio)

Hi Chris,

this is just a rough guess. Did you compile the callback function?
Interpreted code is slow in Lispworks AFAIK. This might be a problem in
audio processing.

Andreas


> -----Ursprüngliche Nachricht-----
> Von: owner-lisp-hug@lispworks.com [mailto:owner-lisp-hug@lispworks.com]
> Im Auftrag von Chris Melen
> Gesendet: Montag, 6. April 2009 00:54
> An: lisp-hug@lispworks.com
> Betreff: Problem with C callback (PortAudio)
> 
> 
> I have written some bindings for PortAudio, a widely-used cross-
> platform C
> audio API. It requires a callback, which is called continuously while
> audio is
> required. It works, but I often encounter the following error -
> 
> Error: Exception C0000005 [flags 0] at 218313C
> eax    40200 ebx  262FA60 ecx   19CEF0 edx   A5BFE8
> esp  262FA14 ebp        0 esi        0 edi FFFFFFFF
>   1 (abort) Return to event loop.
> 
> Type :b for backtrace, :c <option number> to proceed,  or :? for other
> options
> 
> PORTAUDIO-TEST 1 : 1 > :b
> Call to (HARLEQUIN-COMMON-LISP:SUBFUNCTION
> SYSTEM::|%FOREIGN-CALLABLE/fault_handler_on_c_stack|
> (FLI:DEFINE-FOREIGN-CALLABLE "fault_handler_on_c_stack"))
> Call to FLI::FOREIGN-CALLABLE-ENTRY-POINT-AUX-NESTED
> Call to |%cffi-foreign-function/PA-OPEN-STREAM|
> Interpreted call to PA-OPEN-STREAM
> Interpreted call to PLAY-SAMPLES
> Call to CAPI::EXECUTE-CALLBACK
> Call to CAPI:EXECUTE-WITH-INTERFACE
> Call to CAPI-WIN32-LIB::PERFORM-WM-COMMAND-FOR-R-PCL-WINDOW
> Call to WIN32::WND-PROC
> Call to (HARLEQUIN-COMMON-LISP:SUBFUNCTION
> WIN32::|%FOREIGN-CALLABLE/wnd_proc_callback| (FLI:DEFINE-FOREIGN-
> CALLABLE
> "wnd_proc_callback"))
> Call to FLI::FOREIGN-CALLABLE-ENTRY-POINT-AUX-NESTED
> Call to WIN32:IS-DIALOG-MESSAGE
> Call to WIN32::PROCESS-MESSAGES
> Call to MP::WIN32-PROCESS-WAIT-FOR-EVENT
> Call to MP:PROCESS-READ-EVENT
> Call to CAPI-INTERNALS:LOOP-PROCESS-EVENTS
> Call to CAPI::INTERFACE-EVENT-LOOP
> Call to CAPI::INITIALIZE-AND-PROCESS-EVENTS
> Call to (HARLEQUIN-COMMON-LISP:SUBFUNCTION MP::PROCESS-SG-FUNCTION
> MP::INITIALIZE-PROCESS-STACK)
> 
> On my Mac I simply get this -
> 
> Bus error(10) [code F068C678] at C
> 
> The callback itself takes the following form (I'm using CFFI) -
> 
> (defcallback process-samples :int ((input :pointer)
>                                    (output :pointer)
> 			           (frames-per-buffer :ulong)
>                                    (time-info pa-stream-callback-time-
> info)
>                                    (status-flags pa-stream-callback-
> flags)
> 	                           (user-data :pointer))
>   (declare (ignore input time-info status-flags user-data))
>   (loop with n-samps = (length *samples*)
>         for i from 0 below frames-per-buffer
>         for j = (+ *counter* i)
> 	if (< j n-samps)
> 	do (setf (mem-aref output :float i) (aref *samples* j))
> 	else do
>           (setf *counter* 0)
>           (return 1)
> 	finally
> 	(setf *counter* (+ *counter* frames-per-buffer))
> 	(return 0)))
> 
> This simply writes samples from the Lisp array *samples* to the output
> audio
> buffer in blocks of size frames-per-buffer (in this case 2048). While
> the
> callback returns 0 it continues to be called, returning 1 stops it. The
> variable *counter* stores the current position within the sample
> buffer.
> 
> I suspect the error I'm getting may be due to GC occurring during the
> callback
> process, thus moving objects which the foreign code is still pointing
> to. I've
> declared my samples buffer static to hopefully account for this, but
> the error
> remains. The callback lives in its own thread, so possibly it's a
> multi-threading problem... Plus I'm calling PortAudio from a menu in my
> main
> interface, which adds possibly another level of complication...
> 
> PortAudio also has a non-callback interface, which causes no problems,
> but the
> advantage of the callback approach is that it allows me to update
> various
> variables on a 'per sample' basis. More info on this can be found at
> http://www.portaudio.com/trac/wiki/TutorialDir/WritingACallback.
> 
> Any help/suggestions greatly appreciated.
> 
> Chris


Re: Problem with C callback (PortAudio)

On Sun, 05 Apr 2009 15:53:54 -0700, Chris Melen  
<relativeflux@hotmail.co.uk> wrote:

>
> I have written some bindings for PortAudio, a widely-used cross-platform  
> C
> audio API. It requires a callback, which is called continuously while  
> audio is
> required. It works, but I often encounter the following error -
>
> Error: Exception C0000005 [flags 0] at 218313C
> eax    40200 ebx  262FA60 ecx   19CEF0 edx   A5BFE8
> esp  262FA14 ebp        0 esi        0 edi FFFFFFFF
>   1 (abort) Return to event loop.

This might happen if PortAudio creates a new thread to perfrom the  
callback.

- Luke


Re: Problem with C callback (PortAudio)

Unable to parse email body. Email id is 9122

Re: Problem with C callback (PortAudio)

>>>>> On Mon, 06 Apr 2009 10:10:46 -0700, Luke Crook said:
> 
> On Mon, 06 Apr 2009 09:33:27 -0700, Chris Melen  
> <relativeflux@hotmail.co.uk> wrote:
> 
> >
> > Eivind Midtgård <eivind <at> autosim.no> writes:
> >
> >> > >
> >> > > Error: Exception C0000005 [flags 0] at 218313C
> >> > > eax    40200 ebx  262FA60 ecx   19CEF0 edx   A5BFE8
> >> > > esp  262FA14 ebp        0 esi        0 edi FFFFFFFF
> >> > >   1 (abort) Return to event loop.
> >> >
> >> > This might happen if PortAudio creates a new thread to perfrom the
> >> > callback.
> >>
> >> If so, sys:setup-for-alien-threads should help.
> >>
> >> Eivind
> >>
> >>
> >
> > Thanks guys. I thought sys:setup-for-alien-threads wasn't necessary any  
> > more,
> > however, and had been removed.
> 
> It is no longer necessary in the latest version of Lispworks.

Correct.  In fact, the function is no longer defined in LispWorks 5.1.


>                                                               However this  
> does not apply to callbacks from unknown foreign threads. If PortAudio  
> spawns a new thread and the new thread calls back into Lispworks then you  
> will see random crashes all over the place.

That might be a bug.  New threads can call back into LispWorks, unless they
have some particularly strange environmental requirements (though I can't
think of any offhand).

-- 
Martin Simmons
LispWorks Ltd
http://www.lispworks.com/


Re: Problem with C callback (PortAudio)

Unable to parse email body. Email id is 9124

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