in reply to Re^3: sound and gamepad support in Perl?
in thread sound and gamepad support in Perl?

There is Audio:DSP for sound. And if you have a c application that takes commands on STDIN and simulates gamepad output, (like a keystroke interface simulator for the gamepad) you could run it thru Perl's IPC.

Is the Audio:DSP module an official or an honored-by-most module like Perl/TK? I am trying to avoid using CPAN modules as much as possible other than those taken as semi-official modules by the community like Perl/TK, Perl-to-SDL binding, etc...

For inputs, are you saying to get a C app or to creat one which takes gamepad inputs as STDINs to it and translate/pass to the perl script via a pipe or socket?

Hmm...
Whether having that kind of 'C' skill being one side of the problem, it sounds like to me that it would be very difficult to achieve cross-platform-ablility among systems... Would not I need all different C apps for each system: Win32, Win64, Linux, Mac...?

Sorry about being a bit rejective, though. No dis-respect intended:)

  • Comment on Re^4: sound and gamepad support in Perl?

Replies are listed 'Best First'.
Re^5: sound and gamepad support in Perl?
by zentara (Cardinal) on Jan 08, 2011 at 14:42 UTC
    Sorry about being a bit rejective, though. No dis-respect intended:)

    No problem, as I understood your original post to be asking for non-SDL solutions to gamepads and audio.

    You don't need the Audio::DSP module to access the /dev/dsp, BUT to properly initialize the soundcard, to accept your audio as input, you need some system calls. Audio::DSP does this in code like

    #!/usr/bin/perl use warnings; use strict; use Audio::DSP; #alsamixer must be setup right, just turn everything up :-) my ($buf, $chan, $fmt, $rate) = (4096, 1, 16, 44100); #use the formats from soundcard.h, plain 16 for $fmt might not work w +ith sblive #($buf, $chan, $fmt, $rate) = (4096, 1, 8, 8192); #crummy minimum soun +d my $dsp = new Audio::DSP( buffer => $buf, channels => $chan, format => $fmt, rate => $rate); my $seconds = 5; my $length = ($chan * $fmt * $rate * $seconds) / 8; $dsp->init() || die $dsp->errstr(); # Record 5 seconds of sound for (my $i = 0; $i < $length; $i += $buf) { $dsp->read() || die $dsp->errstr(); } print "Play Back\n"; # Play it back for (;;) { $dsp->write() || last; } $dsp->close();
    BUT, you can read Audio::DSP and see what system calls are required to init the soundcard manually, using h2ph. It is not simple, and involves various low level hex codes, using
    require 'sys/ioctl.ph';
    Once inited, you can write to the /dev/dsp directly from Perl. This involves alot of work. Initing can also be done with a c app, like alsactl. But once inited, you can write directly to the /dev/dsp
    #!/usr/bin/perl my $file = shift || 'testout.wav'; open FH, "< $file" or warn "$!\n"; open(DSP,">/dev/dsp") or warn "$!\n"; while ( 4096 == read( FH, my $buffer, 4096 ) ) { print DSP $buffer; } #1liner #perl -e 'local $/;$w=<>;open(F,">","/dev/dsp") && print F $w;' dtmf.w +av

    You can also use a "c" app like aplay, to play your sounds. Every time you want to make a sound, send the file to a forked aplay, with simple IPC.

    As far as the gamepad goes, you really need an event-loop system, to take advantage of the input. SDL gives you this, but I would also look at the gtk+ libraries for it..... google for "gtk+ gamepad" for librairies.

    That brings us back to the point of you trying to avoid SDL. First SDL gives you an eventloop system, it's audio access is way better than direct access to /dev/dsp, because it lets you access the soundcard's channels independently. See below, the cannons, explosions, and music all can be played simultaneously in different channels. ( Although aplay, probably has a command line option for which channel to play thru.)

    The code and test files are at z-sampler

    #!/usr/bin/perl use SDL; use SDL::Mixer; use SDL::Music; use SDL::App; use SDL::Event; $|++; $width=400; $height=300; my $app = new SDL::App( -title => "Sampler", -width => 400, -height =>300, -depth => 8); $mixer = SDL::Mixer->new(-frequency => MIX_DEFAULT_FREQUENCY, -format => MIX_DEFAULT_FORMAT, -channels => MIX_DEFAULT_CHANNELS, -size => 4096); # provides 8 channels of # 16 bit audio at 22050 Hz. and a single channel of music. my $music = new SDL::Music('1bb.mp3'); #background can be mp3,ogg or w +av my $sound0 = new SDL::Sound('cannon.wav'); #effects must be wav $sound0->volume(128); #max my $sound1 = new SDL::Sound('explosion.wav'); $sound1->volume(128); #max $mixer->music_volume(MIX_MAX_VOLUME); my $event = new SDL::Event; my %events = ( SDL_KEYUP() => sub { my ($e) = @_; my $key = SDL::GetKeyName($e->key_sym()); print "$key up\n"; if ($key eq 'm'){ $mixer->play_music($music,10)}; if ($key eq 'c'){ $mixer->play_channel(0,$sound0,0)}; if ($key eq 'e'){ $mixer->play_channel(1,$sound1,0)}; }, SDL_KEYDOWN() => sub { my ($e) = @_; if ($e->key_sym() == SDLK_ESCAPE){exit}; my $key = SDL::GetKeyName($e->key_sym()); print "$key down\n"; }, SDL_QUIT() => sub { exit }, ); $app->loop(\%events);

    The "c" apps I'm talking about, are the various ones laying around for playing audio or possible controlling a gamepad or soundcard. See the use of the c app amixer in ztk-v4l-video-bloger/recorder for switching mic inputs. Perl is a great GLUE language. But you are far better off using SDL OR finding a gtk+ library for the gamepad, and see if SDL's usb support see's it. Otherwise, switch to gtk+ ( which can be converted to Perl/Gtk2) thru the gtk+ to Perl pathways.

    So, you can do this all from straight Perl, but it is way more difficult than using modules. You will need an eventloop system, for the gamepad, so an alternative would be use the gtk+ gamepad libs, and a simple c app, like aplay, to make sounds.

    Or go with SDL, and google for "SDL gamepad", use that code combined with my code above for audio.

    Finally, if you want to reinvent the wheel, and not use modules, you can find the low-level ways of initing the soundcard and directly reading the gamepad input from it's usb file in /proc/input/gamepad ( or wherever )


    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
      "That brings us back to the point of you trying to avoid SDL."

      Actually, I w....as a... going to use the SDL. I just wanted to make sure that their isn't an easier or more official-like solution than using perl-to-SDL binding. And with all the state-of-art non-SDL solutions that you have shown me above, I pretty sure that I am going to stick with SDL:)


      thanks for all your reply

Re^5: sound and gamepad support in Perl?
by Anonyrnous Monk (Hermit) on Jan 08, 2011 at 12:40 UTC
    ...it sounds like to me that it would be very difficult to achieve cross-platform-ablility among systems

    The same problem essentially arises as soon as you're using any module that links against a C library or is implemented in XS (as virtually all sound/multimedia stuff is).   As soon as there's some compiled machine code involved, you have in theory at least an architecture (x86, x86_64, etc.) dependency, and in practice always also an OS dependency, because the extension makes system calls to the OS or uses one of its libraries.

    The advantage of a popular Perl XS module (as opposed to some home-grown C thingy) however is that someone else might have built it for you already, and made it available for at least some platforms (such as ppm for Windows, .deb or .rpm for Linux, etc.)...

      The same problem essentially arises as soon as you're using any module that links against a C library or is implemented in XS (as virtually all sound/multimedia stuff is).

      ??? Doesn't Perl-to-SDL bind provides cross-platformal access to the low level sound and gamepad input to a lot of OS'es? If I use Perl to SDL bind, I thought that I could create a game for both the win32 machine and the linux one. But can't I? I'm confused now:(

        The SDL Perl module is a binding to libsdl (and various other libraries, to be precise). Those are written in C and thus have to be compiled separately for every architecture and OS. The SDL Perl module also comprises compiled shared object files (such as Audio.so), which serve as glue code between the Perl interpreter and the above mentioned libraries.  When you say "use SDL::Audio;" perl dynamically loads Audio.so behind the scenes, which in turn loads libsdl.so, etc.

        In other words, to be able to run your SDL Perl code, those platform specific shared object files need to be installed on the target systems your code should run on. This means that - unlike with a pure-Perl module - you can't just bundle up your Perl code plus the required modules and expect it to run on every system where a standard Perl is installed. You'd either have to create a different bundle for each combination of architecture, OS, and major Perl-version (not recommended), or tell your potential users to install the SDL Perl module plus the dependent libs themselves on their system (e.g. using available precompiled packages). Once they are installed, your same Perl code will of course run on both Windows and Linux — in that sense it's "cross-platform".

        Hope this clears it up.