ASIO driver failing to load when calling from Java

View: New views
6 Messages — Rating Filter:   Alert me  

ASIO driver failing to load when calling from Java

by Phil Burk :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I have an odd problem where I can load and use an ASIO driver when I
call PortAudio from various 'C' programs. But when I call PortAudio from
my JNI code from Java the driver fails to load. The failure is consistent.

The error occurs when ASIO calls
        CoCreateInstance() called by
        AsioDriverList::asioOpenDriver() in asiolist.cpp called by
        AsioDrivers::loadDriver() in asiodrivers.cpp called by
        LoadAsioDriver() in pa_asio.cpp called by
        OpenStream() in pa_asio.cpp called by
        Pa_OpenStream()

Both programs just
        Initialize PA
        List the available devices, number of channels etc
        Open a 44100 Hz stereo stream for output only <==Fails here!


Both programs use the same DLL.

If I open a WMME device then both Java and the 'C' program work fine.

I have checked the parameters to Pa_OpenStream() in both cases and they
are identical.

   inputParameters = NULL
   outputParameters.sampleFormat = 1 (float)
   outputParameters.suggestedLatency = 0.02
   framesPerBuffer = 0x40


I find this quite puzzling. Any ideas why an ASIO driver would show up
in a query but then fail to load?

I am running with current Win XP on a Dual Core Athlon 64.
The ASIO device is "ASIO4ALL v2".
The audio HW is a "SoundMAX HD Audio" card.

Thanks,
Phil Burk
_______________________________________________
Portaudio mailing list
Portaudio@...
http://techweb.rfa.org/mailman/listinfo/portaudio

Re: ASIO driver failing to load when calling from Java

by Ross Bencina-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Phil

You might want to have a look at the other CoCreateInstance() calls in the
PA code -- I seem to remember I patched something a while back to ignore
errors if CoCreateInstance was called with a different threading model
parameter than what the current thread is already initialized with (and in
the case of Java, possibly the thread has already had COM initialized). You
might need to apply a similar patch to the ASIO SDK to ignore the thread
model mismatch -- not sure, just a guess.

Cheers

Ross.



----- Original Message -----
From: "Phil Burk" <nospam@...>
To: "portaudio" <portaudio@...>
Sent: Friday, June 27, 2008 2:17 PM
Subject: [Portaudio] ASIO driver failing to load when calling from Java


>I have an odd problem where I can load and use an ASIO driver when I
> call PortAudio from various 'C' programs. But when I call PortAudio from
> my JNI code from Java the driver fails to load. The failure is consistent.
>
> The error occurs when ASIO calls
> CoCreateInstance() called by
> AsioDriverList::asioOpenDriver() in asiolist.cpp called by
> AsioDrivers::loadDriver() in asiodrivers.cpp called by
> LoadAsioDriver() in pa_asio.cpp called by
> OpenStream() in pa_asio.cpp called by
> Pa_OpenStream()
>
> Both programs just
> Initialize PA
> List the available devices, number of channels etc
> Open a 44100 Hz stereo stream for output only <==Fails here!
>
>
> Both programs use the same DLL.
>
> If I open a WMME device then both Java and the 'C' program work fine.
>
> I have checked the parameters to Pa_OpenStream() in both cases and they
> are identical.
>
>   inputParameters = NULL
>   outputParameters.sampleFormat = 1 (float)
>   outputParameters.suggestedLatency = 0.02
>   framesPerBuffer = 0x40
>
>
> I find this quite puzzling. Any ideas why an ASIO driver would show up
> in a query but then fail to load?
>
> I am running with current Win XP on a Dual Core Athlon 64.
> The ASIO device is "ASIO4ALL v2".
> The audio HW is a "SoundMAX HD Audio" card.
>
> Thanks,
> Phil Burk
> _______________________________________________
> Portaudio mailing list
> Portaudio@...
> http://techweb.rfa.org/mailman/listinfo/portaudio
>

_______________________________________________
Portaudio mailing list
Portaudio@...
http://techweb.rfa.org/mailman/listinfo/portaudio

Re: ASIO driver failing to load when calling from Java

by Phil Burk :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Ross,

You were right. Thanks for the tip. It was a thread issue but I don't
think ignoring the return code from CoCreateInstance is the best
solution. That would require a patch to ASIO and also does not address
to core issue.

I was googling and found that I had reported the exact same problem back
in 2002.

http://techweb.rfa.org/pipermail/portaudio/2002-February/000464.html

The crux of the problem is that I initialized ASIO from one thread. Then
tried to open the stream from another thread. There was no timing
problem. The problem is that CoInitialize(0) needs to be called in both
threads.

There was a note from Stephane Letz on Feb 19 2002 in pa_asio.cpp saying
that he added some calls to CoInitialize(0) "on each thread on Windows".
This was probably a fix for the problem I reported.

Then I found a comment in Pa_ASIO_LoadDriver() in pa_asio.cpp saying
that CoInitialize(0) had been removed from the code. When I added back a
call to CoInitialize(0) then ASIO worked fine from my multi-threaded
Java application. The comment says we should have applications call
CoInitialize(0) for each thread. But I feel an App using PA should not
have to worry about what goes on under the hood. If PA needs to call
CoCreateInstance() and that requires a call to CoInitialize(0) then PA
should call CoInitialize(0), not the app.

I did some research and found that CoInitialize(0) must be balanced by a
call to CoUnitialize(). I notice that we are calling
Pa_ASIO_LoadDriver() and that it is balanced by a call to ASIOExit().

I propose:

1) Adding a call to CoInitialize(0) in Pa_ASIO_LoadDriver().

2) Adding a new function called Pa_UnloadDriver() that calls
CoUninitialize() and ASIOExit.

3) Replace calls to ASIOExit() with calls to Pa_UnloadDriver() where
appropriate.

4) Add comments explaining the problem and the fix.

Objections?

Phil Burk


_______________________________________________
Portaudio mailing list
Portaudio@...
http://techweb.rfa.org/mailman/listinfo/portaudio

Re: ASIO driver failing to load when calling from Java

by Phil Burk :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Correction to function name.

Phil Burk wrote:
> I propose:
> 1) Adding a call to CoInitialize(0) in Pa_ASIO_LoadDriver().

At some point Pa_ASIO_LoadDriver() got changed to LoadAsioDriver(). So I
will add CoInitialize to that and create a new function UnloadAsioDriver().

I've made all the changes and they seem fine.

Phil Burk
_______________________________________________
Portaudio mailing list
Portaudio@...
http://techweb.rfa.org/mailman/listinfo/portaudio

Re: ASIO driver failing to load when calling from Java

by Ross Bencina-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Phil

I'm afraid I'm not 100% sure I understand how your proposal resolves the
problem, but I have couple of comments/questions:

- You seem to be implying that you are calling Pa_Initialize() in one
thread, and then Pa_OpenStream() in a different thread. This is already a
bit outside the specifications of how PortAudio works. If I understand you
correctly -- you fix is to ensure that CoInitialize is always called before
calling CoCreateInstance -- given that CoCreateInstance is called so rarely
this seems like a reasonable improvement.

I am concerned about is that this setup seems to ensure some small degree of
thread agility, but that your overal usage is not really within-spec in the
first place.


Cheers

Ross.


----- Original Message -----
From: "Phil Burk" <nospam@...>
To: "portaudio" <portaudio@...>
Sent: Saturday, June 28, 2008 6:25 AM
Subject: Re: [Portaudio] ASIO driver failing to load when calling from Java


> Correction to function name.
>
> Phil Burk wrote:
>> I propose:
>> 1) Adding a call to CoInitialize(0) in Pa_ASIO_LoadDriver().
>
> At some point Pa_ASIO_LoadDriver() got changed to LoadAsioDriver(). So I
> will add CoInitialize to that and create a new function
> UnloadAsioDriver().
>
> I've made all the changes and they seem fine.
>
> Phil Burk
> _______________________________________________
> Portaudio mailing list
> Portaudio@...
> http://techweb.rfa.org/mailman/listinfo/portaudio
>

_______________________________________________
Portaudio mailing list
Portaudio@...
http://techweb.rfa.org/mailman/listinfo/portaudio

Re: ASIO driver failing to load when calling from Java

by Phil Burk :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Ross Bencina wrote:
> - You seem to be implying that you are calling Pa_Initialize() in one
> thread, and then Pa_OpenStream() in a different thread. This is already a
> bit outside the specifications of how PortAudio works.

I have a Java program that indirectly calls Pa_Initialize() in the
start() method. It also sets up a GUI that lets the user select a device
and the number of channels.

The Pa_OpenStream() call is made in response to a button press so it is
in a special GUI thread.  This worked with PortAudio V18. It also worked
with V19 for WMME but not for ASIO until I made the change.

I know that PortAudio is not "thread safe". To me that implies that if
calls are made to PortAudio simultaneously from two or more threads then
  internal data may get munged. That is different than requiring that
all calls be made from the same thread.

What is the PortAudio policy regarding non-overlapping calls from more
than one thread?

Phil Burk

_______________________________________________
Portaudio mailing list
Portaudio@...
http://techweb.rfa.org/mailman/listinfo/portaudio
LightInTheBox - Buy quality products at wholesale price