www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Anyone using Portaudio?

reply Andrej Mitrovic <andrej.mitrovich none.com> writes:
There's a .d header file in the Bindings project on dsource which I'm using
with the Portaudio DLL v19, and I'm implicitly loading the DLL. There's a  sine
playback example, and I'm comparing the usage of Portaudio from the C sine
example (patest_sine.c) compared to the D one (patest_sine_hello.d). The C and
D code are almost identical, however there seems to be a pretty big overhead
when using D.

I can safely use a buffer size of 64 frames in the C example, but in the D one
the minimum I could get was around 1800 frames.

I've tried compiling with-O -release -inline, and issuing a call to
GC.disable() before the call to Pa_StartStream(). I've also tried compiling the
portaudio DLL in Release mode. But none of this had any effect. Anything lower
than 1800 for the buffer size gives me choppy sound in D. 

There shouldn't be a problem with such a small buffer size, all the data is
preallocated and the buffers are prefilled with data, so it can't be a CPU
bottleneck issue. Since D uses C functions directly, I just don't see where the
overhead could be.

Has anyone used Portaudio with D2 (or D1 for that matter) with close-to-equal
performance as when using C?
Oct 17 2010
next sibling parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Mon, 18 Oct 2010 01:10:31 +0400, Andrej Mitrovic  
<andrej.mitrovich none.com> wrote:

 There's a .d header file in the Bindings project on dsource which I'm  
 using with the Portaudio DLL v19, and I'm implicitly loading the DLL.  
 There's a  sine playback example, and I'm comparing the usage of  
 Portaudio from the C sine example (patest_sine.c) compared to the D one  
 (patest_sine_hello.d). The C and D code are almost identical, however  
 there seems to be a pretty big overhead when using D.

 I can safely use a buffer size of 64 frames in the C example, but in the  
 D one the minimum I could get was around 1800 frames.

 I've tried compiling with-O -release -inline, and issuing a call to  
 GC.disable() before the call to Pa_StartStream(). I've also tried  
 compiling the portaudio DLL in Release mode. But none of this had any  
 effect. Anything lower than 1800 for the buffer size gives me choppy  
 sound in D.

 There shouldn't be a problem with such a small buffer size, all the data  
 is preallocated and the buffers are prefilled with data, so it can't be  
 a CPU bottleneck issue. Since D uses C functions directly, I just don't  
 see where the overhead could be.

 Has anyone used Portaudio with D2 (or D1 for that matter) with  
 close-to-equal performance as when using C?

From my experience, starting with D that purely calls C code and then slowly porting it to D (one piece of code at a time) usually helps revealing the problem. Just try to keep it the same (i.e. interchangeable). You can do that by marking functions as extern (C) and optionally having some of the variables as extern (C) __gshared.
Oct 17 2010
next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
This is interesting. It appears the callback function is not called
frequently enough. Really weird.. it must be some bug in my code.

You see, I have a sample rate of 44100hz per second, and a buffer size
of 64. This basically means that for 1 second of audio I need to fill
~680buffers per second in my callback (the callback is called ~680
times per second, and each buffer is 64 frames in size), so ~680 * 64
= ~44100. The C code gets its callback called around 680 times, but
interestingly the D code gets its callback called only 29 times. This
is why I hear the sound stuttering, its because my callback isn't
getting called frequently enough and the audio card is filling the
missing buffers with zeros.

Now I have to figure out why it's not getting called often enough.

On 10/18/10, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:
 Yeah, that's what I would usually do. The trouble is there's a library
 in DLL format, and there's only a couple of calls to it and that's it.
 But somehow the C client code performs better. I've just tried a D1
 sample, with the same result. I'll have to investigate..

 On 10/17/10, Denis Koroskin <2korden gmail.com> wrote:
 On Mon, 18 Oct 2010 01:10:31 +0400, Andrej Mitrovic
 <andrej.mitrovich none.com> wrote:

 There's a .d header file in the Bindings project on dsource which I'm
 using with the Portaudio DLL v19, and I'm implicitly loading the DLL.
 There's a  sine playback example, and I'm comparing the usage of
 Portaudio from the C sine example (patest_sine.c) compared to the D one
 (patest_sine_hello.d). The C and D code are almost identical, however
 there seems to be a pretty big overhead when using D.

 I can safely use a buffer size of 64 frames in the C example, but in the
 D one the minimum I could get was around 1800 frames.

 I've tried compiling with-O -release -inline, and issuing a call to
 GC.disable() before the call to Pa_StartStream(). I've also tried
 compiling the portaudio DLL in Release mode. But none of this had any
 effect. Anything lower than 1800 for the buffer size gives me choppy
 sound in D.

 There shouldn't be a problem with such a small buffer size, all the data
 is preallocated and the buffers are prefilled with data, so it can't be
 a CPU bottleneck issue. Since D uses C functions directly, I just don't
 see where the overhead could be.

 Has anyone used Portaudio with D2 (or D1 for that matter) with
 close-to-equal performance as when using C?

From my experience, starting with D that purely calls C code and then slowly porting it to D (one piece of code at a time) usually helps revealing the problem. Just try to keep it the same (i.e. interchangeable). You can do that by marking functions as extern (C) and optionally having some of the variables as extern (C) __gshared.


Oct 17 2010
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Problem solved!

The D header file for Portaudio was bugged, I'll update it in the
Bindings project.

On 10/18/10, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:
 This is interesting. It appears the callback function is not called
 frequently enough. Really weird.. it must be some bug in my code.

 You see, I have a sample rate of 44100hz per second, and a buffer size
 of 64. This basically means that for 1 second of audio I need to fill
 ~680buffers per second in my callback (the callback is called ~680
 times per second, and each buffer is 64 frames in size), so ~680 * 64
 = ~44100. The C code gets its callback called around 680 times, but
 interestingly the D code gets its callback called only 29 times. This
 is why I hear the sound stuttering, its because my callback isn't
 getting called frequently enough and the audio card is filling the
 missing buffers with zeros.

 Now I have to figure out why it's not getting called often enough.

 On 10/18/10, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:
 Yeah, that's what I would usually do. The trouble is there's a library
 in DLL format, and there's only a couple of calls to it and that's it.
 But somehow the C client code performs better. I've just tried a D1
 sample, with the same result. I'll have to investigate..

 On 10/17/10, Denis Koroskin <2korden gmail.com> wrote:
 On Mon, 18 Oct 2010 01:10:31 +0400, Andrej Mitrovic
 <andrej.mitrovich none.com> wrote:

 There's a .d header file in the Bindings project on dsource which I'm
 using with the Portaudio DLL v19, and I'm implicitly loading the DLL.
 There's a  sine playback example, and I'm comparing the usage of
 Portaudio from the C sine example (patest_sine.c) compared to the D one
 (patest_sine_hello.d). The C and D code are almost identical, however
 there seems to be a pretty big overhead when using D.

 I can safely use a buffer size of 64 frames in the C example, but in
 the
 D one the minimum I could get was around 1800 frames.

 I've tried compiling with-O -release -inline, and issuing a call to
 GC.disable() before the call to Pa_StartStream(). I've also tried
 compiling the portaudio DLL in Release mode. But none of this had any
 effect. Anything lower than 1800 for the buffer size gives me choppy
 sound in D.

 There shouldn't be a problem with such a small buffer size, all the
 data
 is preallocated and the buffers are prefilled with data, so it can't be
 a CPU bottleneck issue. Since D uses C functions directly, I just don't
 see where the overhead could be.

 Has anyone used Portaudio with D2 (or D1 for that matter) with
 close-to-equal performance as when using C?

From my experience, starting with D that purely calls C code and then slowly porting it to D (one piece of code at a time) usually helps revealing the problem. Just try to keep it the same (i.e. interchangeable). You can do that by marking functions as extern (C) and optionally having some of the variables as extern (C) __gshared.



Oct 17 2010
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Here's the update, I hope someone puts it in the repo:

http://www.dsource.org/forums/viewtopic.php?p=25726#25726

On 10/18/10, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:
 Problem solved!

 The D header file for Portaudio was bugged, I'll update it in the
 Bindings project.

 On 10/18/10, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:
 This is interesting. It appears the callback function is not called
 frequently enough. Really weird.. it must be some bug in my code.

 You see, I have a sample rate of 44100hz per second, and a buffer size
 of 64. This basically means that for 1 second of audio I need to fill
 ~680buffers per second in my callback (the callback is called ~680
 times per second, and each buffer is 64 frames in size), so ~680 * 64
 = ~44100. The C code gets its callback called around 680 times, but
 interestingly the D code gets its callback called only 29 times. This
 is why I hear the sound stuttering, its because my callback isn't
 getting called frequently enough and the audio card is filling the
 missing buffers with zeros.

 Now I have to figure out why it's not getting called often enough.

 On 10/18/10, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:
 Yeah, that's what I would usually do. The trouble is there's a library
 in DLL format, and there's only a couple of calls to it and that's it.
 But somehow the C client code performs better. I've just tried a D1
 sample, with the same result. I'll have to investigate..

 On 10/17/10, Denis Koroskin <2korden gmail.com> wrote:
 On Mon, 18 Oct 2010 01:10:31 +0400, Andrej Mitrovic
 <andrej.mitrovich none.com> wrote:

 There's a .d header file in the Bindings project on dsource which I'm
 using with the Portaudio DLL v19, and I'm implicitly loading the DLL.
 There's a  sine playback example, and I'm comparing the usage of
 Portaudio from the C sine example (patest_sine.c) compared to the D
 one
 (patest_sine_hello.d). The C and D code are almost identical, however
 there seems to be a pretty big overhead when using D.

 I can safely use a buffer size of 64 frames in the C example, but in
 the
 D one the minimum I could get was around 1800 frames.

 I've tried compiling with-O -release -inline, and issuing a call to
 GC.disable() before the call to Pa_StartStream(). I've also tried
 compiling the portaudio DLL in Release mode. But none of this had any
 effect. Anything lower than 1800 for the buffer size gives me choppy
 sound in D.

 There shouldn't be a problem with such a small buffer size, all the
 data
 is preallocated and the buffers are prefilled with data, so it can't
 be
 a CPU bottleneck issue. Since D uses C functions directly, I just
 don't
 see where the overhead could be.

 Has anyone used Portaudio with D2 (or D1 for that matter) with
 close-to-equal performance as when using C?

From my experience, starting with D that purely calls C code and then slowly porting it to D (one piece of code at a time) usually helps revealing the problem. Just try to keep it the same (i.e. interchangeable). You can do that by marking functions as extern (C) and optionally having some of the variables as extern (C) __gshared.




Oct 17 2010
prev sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Mon, 18 Oct 2010 04:16:10 +0400, Andrej Mitrovic  
<andrej.mitrovich gmail.com> wrote:

 Here's the update, I hope someone puts it in the repo:

 http://www.dsource.org/forums/viewtopic.php?p=25726#25726

IIRC, the repo is public, i.e. everyone has commit access. If so, you can commit the change yourself. Try it.
Oct 17 2010
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Yeah, that's what I would usually do. The trouble is there's a library
in DLL format, and there's only a couple of calls to it and that's it.
But somehow the C client code performs better. I've just tried a D1
sample, with the same result. I'll have to investigate..

On 10/17/10, Denis Koroskin <2korden gmail.com> wrote:
 On Mon, 18 Oct 2010 01:10:31 +0400, Andrej Mitrovic
 <andrej.mitrovich none.com> wrote:

 There's a .d header file in the Bindings project on dsource which I'm
 using with the Portaudio DLL v19, and I'm implicitly loading the DLL.
 There's a  sine playback example, and I'm comparing the usage of
 Portaudio from the C sine example (patest_sine.c) compared to the D one
 (patest_sine_hello.d). The C and D code are almost identical, however
 there seems to be a pretty big overhead when using D.

 I can safely use a buffer size of 64 frames in the C example, but in the
 D one the minimum I could get was around 1800 frames.

 I've tried compiling with-O -release -inline, and issuing a call to
 GC.disable() before the call to Pa_StartStream(). I've also tried
 compiling the portaudio DLL in Release mode. But none of this had any
 effect. Anything lower than 1800 for the buffer size gives me choppy
 sound in D.

 There shouldn't be a problem with such a small buffer size, all the data
 is preallocated and the buffers are prefilled with data, so it can't be
 a CPU bottleneck issue. Since D uses C functions directly, I just don't
 see where the overhead could be.

 Has anyone used Portaudio with D2 (or D1 for that matter) with
 close-to-equal performance as when using C?

From my experience, starting with D that purely calls C code and then slowly porting it to D (one piece of code at a time) usually helps revealing the problem. Just try to keep it the same (i.e. interchangeable). You can do that by marking functions as extern (C) and optionally having some of the variables as extern (C) __gshared.

Oct 17 2010
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday 17 October 2010 17:05:50 Andrej Mitrovic wrote:
 Problem solved!
 
 The D header file for Portaudio was bugged, I'll update it in the
 Bindings project.

Bugged? Who was listening in on it? ;) I think that you meant to say that it was buggy or that it had a bug (or bugs) in it. - Jonathan M Davis
Oct 17 2010
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Nooo, I'm telling you there are Russian spies in the header files!!

So is anyone else interested in DSP/Music software around here? I'm
quite excited about using D for some audio programming..

On 10/18/10, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 On Sunday 17 October 2010 17:05:50 Andrej Mitrovic wrote:
 Problem solved!

 The D header file for Portaudio was bugged, I'll update it in the
 Bindings project.

Bugged? Who was listening in on it? ;) I think that you meant to say that it was buggy or that it had a bug (or bugs) in it. - Jonathan M Davis

Oct 17 2010