www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - DPortAudio

reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
This is a direct D binding of the PortAudio C library, meaning it's
not OOP but a plain D conversion of its headers. PortAudio is
MIT-licensed, and these bindings are Boost-licensed.

There are already two bindings that exist for PortAudio. One is at
http://www.dsource.org/projects/bindings/wiki/Portaudio, and the other
is Derelict which has its own binding as well.

However the dsource bindings have missing symbols, and the 1-byte
alignment of struct members crashes the tests which I've ported to D.
When using default 4-byte alignment the tests will run without issues
(the PortAudio documentation recommends 4-byte alignment, so I don't
know why 1-byte alignment was used).

Derelict also has 1-byte aligned struct members and it might suffer
from the same issues, but I haven't tested it out so I can't confirm.
In either case Derelict is a game-oriented library, and contains no
examples on how to use PortAudio, plus it's on dsource which is a
graveyard of dead projects anyway.

For the above reasons (and because I've worked on PortMidi as well),
I've started my own bindings to PortAudio. Currently it's only built
on Win32 platforms, but I'll see about getting it to work on Linux as
well.

Project link: https://github.com/AndrejMitrovic/DPortAudio

It has about 15 ported tests, with a few dozen more to do.

It also has one standalone example, in which you can play your qwerty
keyboard and the app will play a sinewave at a certain tone in the
left and right channles, and draw the sinewaves on the screen for both
channels. The visuals are updated as you "play" your keyboard. :) This
example is currently built on win32 only.

Here's a screenshot:

http://i.imgur.com/7zsdJ.png

More samples will be coming by, including how to use PortAudio with
PortMidi to make some cool realtime manipulation of audio data and
visuals via a MIDI interface.
Jul 14 2011
next sibling parent ponce <ponce spam.org> writes:
 Derelict also has 1-byte aligned struct members and it might suffer
 from the same issues, but I haven't tested it out so I can't confirm.
 In either case Derelict is a game-oriented library, and contains no
 examples on how to use PortAudio, plus it's on dsource which is a
 graveyard of dead projects anyway.

Hi, I'm the one which once made a PortAudio derelict binding based on previous work (http://www.dsource.org/projects/bindings/wiki/Portaudio). I made a derelict extension because I didn't know how to do otherwise :) Portaudio is not a library choice I would make again. I was bitten hard with sound-card dependent synchronization issues, perhaps related to this alignment problem I did not see. BASS and FMOD are the ones I would use now. I made a partial BASS derelict binding too later on. Cool project btw.
 
 For the above reasons (and because I've worked on PortMidi as well),
 I've started my own bindings to PortAudio. Currently it's only built
 on Win32 platforms, but I'll see about getting it to work on Linux as
 well.
 
 Project link: https://github.com/AndrejMitrovic/DPortAudio
 
 It has about 15 ported tests, with a few dozen more to do.
 
 It also has one standalone example, in which you can play your qwerty
 keyboard and the app will play a sinewave at a certain tone in the
 left and right channles, and draw the sinewaves on the screen for both
 channels. The visuals are updated as you "play" your keyboard. :) This
 example is currently built on win32 only.
 
 Here's a screenshot:
 
 http://i.imgur.com/7zsdJ.png
 
 More samples will be coming by, including how to use PortAudio with
 PortMidi to make some cool realtime manipulation of audio data and
 visuals via a MIDI interface.

Jul 15 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
PortAudio is really just a uniform layer over APIs which already exist
on the platform, so any synchronization problems those APIs have will
be reflected in PortAudio. I did some reading about this in the
portaudio newsgroups, and synchronization seems to be a difficult
issue to solve.

I'll research this more and add synchronization samples to the
bindings project as I figure things out.

FMOD and BASS are good libraries too! :)
Jul 15 2011
prev sibling next sibling parent Jonas Kivi <seewebsite foremail.fom> writes:
14.7.2011 22.34, Andrej Mitrovic kirjoitti:
 There are already two bindings that exist for PortAudio. One is at
 http://www.dsource.org/projects/bindings/wiki/Portaudio, and the other
 is Derelict which has its own binding as well.
 However the dsource bindings have missing symbols, and the 1-byte
 alignment of struct members crashes the tests which I've ported to D.
 When using default 4-byte alignment the tests will run without issues
 (the PortAudio documentation recommends 4-byte alignment, so I don't
 know why 1-byte alignment was used).

I made the bindings on dsource... I don't know about the alignment stuff. The decision to use 1-byte alignment was made with trial and error. I think it was propably the only way the whole thing worked on Linux at the time. (A couple of years ago.) It still works "fine" on Linux and Mac OS X with the 1-byte alignment. I should propably test 4-byte alignment again. (If I get the time...) I'm using GDC as the compiler. There were some performance issues with the D versions. It was much easier for the D versions to drop audio, than the corresponding C versions, but that might have been due to the alignment or other issues... I remember there were some issues with threads, GC and crashes. But it eventually worked. By trial and error, which isn't such a good way to write software.
 For the above reasons (and because I've worked on PortMidi as well),
 I've started my own bindings to PortAudio. Currently it's only built
 on Win32 platforms, but I'll see about getting it to work on Linux as
 well.

 Project link: https://github.com/AndrejMitrovic/DPortAudio

 It has about 15 ported tests, with a few dozen more to do.

Great stuff. I hope you get it to work on Linux as well, as I don't want to start messing with it until somebody else has gotten it working. You are obviously doing a much better job at making the bindings complete with good examples. That is great!
 More samples will be coming by, including how to use PortAudio with
 PortMidi to make some cool realtime manipulation of audio data and
 visuals via a MIDI interface.

That would be nice. I've been meaning to test PortMidi to get some midi controls for my app (the Pihlaja video viewer thing). On a related note, I've also made bindings (barely working) for Jack. http://www.dsource.org/projects/bindings/browser/trunk/jack It might not be much interest for Windows users, and it's a bit more complex system, but I found it to perform a little better than PortAudio. (But that might be due to the alignment issues in my PortAudio bindings, as discussed above.) Oh, and Jack also works on Windows nowadays. I'm still using PortAudio for my app, as it was easier to bundle into my installer, but I might change to Jack (it also has midi support) if my app ever becomes more audio oriented. I can change between the two with a compile switch (hurray, how wonderful). Jonas Kivi
Jul 19 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 7/20/11, Jonas Kivi <seewebsite foremail.fom> wrote:
 That would be nice. I've been meaning to test PortMidi to get some midi
 controls for my app (the Pihlaja video viewer thing).

There's bindings for that too (although only Windows was tested): https://github.com/AndrejMitrovic/DPortMidi You might be interested in this example: https://github.com/AndrejMitrovic/DPortMidi/blob/master/samples/win32_drawshapes.d It draws midi CC control changes as envelopes, it uses a plain C binding to Cairo to draw on a Win32 surface. Here's a screenshot: http://i.imgur.com/19vKa.png It's not my best code, I should be using a cyclic buffer to pass data from the Midi worker thread to the GUI drawing thread, but instead I've used some hackish array duplication. :)
Jul 19 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 7/20/11, Jonas Kivi <seewebsite foremail.fom> wrote:
 Great stuff. I hope you get it to work on Linux as well, as I don't want
 to start messing with it until somebody else has gotten it working.

Sure, I'll test it on Ubuntu sometime soon and see how it works there.
Jul 19 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Someone mentioned that Linux doesn't need import libs. But I'm having
linker errors when trying to compile a test file on Linux. I've built
PortAudio as a shared lib, and installed via make install, and also
exported an environment variable:

LD_LIBRARY_PATH=/usr/local/lib
export LD_LIBRARY_PATH

I've also tried manually copying the two (I don't know why there's
two) shared libraries to the local folder, the libportaudio.so and
libportaudio.so.2 files.

Command was:
andrej andrej-VirtualBox:~/Desktop/dev/DPortAudio/tests$ dmd pa_devs.d
../portaudio/portaudio.a -I..

portaudio.a is the static lib of DPortAudio which has the converted
header file that lists all extern(C) function prototypes.

Errors:
http://codepad.org/AIhYkqiZ

Any ideas?
Jul 19 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
IOW is there a utility I can use on Linux to list .so exports?
Jul 19 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Ok this does the trick: nm -D libportaudio.so

It does list all of those functions though.
Jul 19 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
The C examples compile and run fine, so I must be doing something
wrong on the D side.
Jul 19 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
I've just added a brand new GUI example!

This time it's a wave player that draws the waveforms of the left and
right channels of the wave file, and also draws the playback position
as a typical sequencer would do.

It also allows you to change the playback position, just point and click!

Here's a screenshot (poor jpeg to save bandwidth): http://i.imgur.com/Wv5Lx.jpg

The drawing routine is a little bit expensive, this is due to drawing
a lot of lines with cairo in a single call. I'll have to investigate
how to make drawing faster.
Jul 19 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Btw, I've noticed something very interesting. I've pushed a 2.2
megabyte DLL in less than 2 seconds to the repo. That's impossible
with my limited ~20Kb upload speed. I wonder if github does some kind
of caching, if it does it probably did a hash check on my file, got a
match, and just copied an existing file from its servers instead of
downloading it from me.

If that's the case that's pretty freakin cool.
Jul 19 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Before you ask, it was a new DLL. I never had it in my repo before,
not even in an earlier changeset, or in any of my other repos.
Jul 19 2011
prev sibling next sibling parent Johannes Pfau <spam example.com> writes:
Andrej Mitrovic wrote:
Someone mentioned that Linux doesn't need import libs. But I'm having
linker errors when trying to compile a test file on Linux. I've built
PortAudio as a shared lib, and installed via make install, and also
exported an environment variable:

LD_LIBRARY_PATH=/usr/local/lib
export LD_LIBRARY_PATH

I've also tried manually copying the two (I don't know why there's
two) shared libraries to the local folder, the libportaudio.so and
libportaudio.so.2 files.

Command was:
andrej andrej-VirtualBox:~/Desktop/dev/DPortAudio/tests$ dmd pa_devs.d
../portaudio/portaudio.a -I..

portaudio.a is the static lib of DPortAudio which has the converted
header file that lists all extern(C) function prototypes.

Errors:
http://codepad.org/AIhYkqiZ

Any ideas?

You have to compile like this: dmd pa_devs.d ../portaudio/portaudio.a -I.. -L-L/usr/local/lib -L-lportaudio The -L-L/usr/local/lib is maybe not necessary, depends on if /usr/local/lib is in your standard link path. If you then run the program and it complains about shared library not found or something like that, you have to run it with LD_LIBRARY_PATH set: LD_LIBRARY_PATH=/usr/local/lib ./pa_devs -- Johannes Pfau
Jul 20 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 7/20/11, Johannes Pfau <spam example.com> wrote:
 You have to compile like this:
 dmd pa_devs.d ../portaudio/portaudio.a -I.. -L-L/usr/local/lib
 -L-lportaudio

 The -L-L/usr/local/lib is maybe not necessary, depends on
 if /usr/local/lib is in your standard link path.
 If you then run the program and it complains about shared library not
 found or something like that, you have to run it with LD_LIBRARY_PATH
 set:
 LD_LIBRARY_PATH=/usr/local/lib ./pa_devs

 --
 Johannes Pfau

Now it's saying it can't find libportaudio.a. The compilation documents say that libportaudio.a should be generated in the portaudio lib/.libs/ folder, but there's not a single .a file generated after running ./configure and make.. only the shared lib, and some .la, .lai, .ver, .exp files. I'll take this to the portaudio newsgroup.
Jul 20 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
I've fixed the performance issue with the wave player example. Instead
of constantly redrawing a large amount of data (it would max out my
single core), I've employed a caching technique.

Basically, the waveform only needs to be redrawn when the window size
changes. So I hold two buffers, one for the waveform, the other for
the playback indicator. The first one is rarely updated, while for the
second one I first do a /blit/ of the cached bitmap from buffer 1 to
buffer 2, and then draw the playback indicator over buffer 2.

I can't directly draw the indicator over buffer 1 because that would
overwrite the cached image.
This is all described in the source code btw.

Now the CPU usage is a clean 0%, and the GUI is much more responsive! :)
Jul 20 2011
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Oh I completely neglected that libsndfile automatically loads any
filetype it supports. You can open FLAC's as well as wave's and other
filetypes in the waveplayer example. But it loads the file all at once
and doesn't use any buffering, so you can't load really big files
because the memory allocation will fail.
Jul 21 2011