Topic: Sound in Open Sonic with PulseAudio

Hi! I have found in the FAQ below tip:

The game has no sound! (Linux)

Games made using the Allegro game programming library can't play sounds on some Linux distributions (like Ubuntu 9.04) due to a problem with pulseaudio (check out the full explanation). This issue can be solved by removing the pulseaudio package. In Debian-based distributions, open a terminal and type:

sudo apt-get remove pulseaudio

In my opinion, removing the package (here it's a sound server), which somebody may need, isn't a solution for the problem. For example, I'm using the PulseAudio, because it can play GNOME sounds (like ESD), mixes sounds in various applications, allows to change their volume separately and doesn't eat much CPU. When I was installing it, I also had a problem with Allegro games, for example Open Sonic, but I managed to solve it without removing PA.

This tutorial describes how to force games using Allegro library to work with PulseAudio. Let's start:

1. In the beginning we must take care of basic configuration of the PulseAudio sound server. If you're using Ubuntu 8.10 or newer you can try to do it by this command:

asoundconf set-pulseaudio

If that works for you, restart your PC and go to 2 step. If not (or you're using Debian / Ubuntu 8.04 and older) open the terminal and type (you can replace gedit with your favourite editor):

gedit .asoundrc

You'll probably see the blank document. Paste into it below code:

pcm.pulse {
    type pulse
}

ctl.pulse {
    type pulse
}

pcm.!default {
    type pulse
}

ctl.!default {
    type pulse
}

pcm.!dmix {
    type pulse
}

Now save it in your HOME directory and restart PC (I think it should also work if you'll restart only your desktop environment). If you want to check whether it works, run pavucontrol and an application, which uses ALSA to play sound, for example Flash 10. If you're able to change volume of your app with pavucontrol, that means you configured PA correctly.

More information about configuring PulseAudio you can find here:
http://www.pulseaudio.org/wiki/PerfectSetup

2. ALSA is default driver used by Allegro apps to play music. Unfortunately alsa plug-in for Allegro doesn't work with PulseAudio, even with good configuration, which we have done in first step (WINE has similar problem). But don't worry, I didn't write that first point to waste your time, we'll need it later. wink Now we must disable this broken plugin, so open the terminal and type (command for Ubuntu):

sudo gedit /usr/lib/allegro/4.4.1/modules.lst

Again you can use your own editor. Here we have two ways to achieve our purpose. I'm using and recommending 2a method.

2a. We must comment (disable) all sound plugins, so that we'll force Allegro to use OSS driver. Editing file should look like this:

alleg-vga.so
alleg-fbcon.so
alleg-svgalib.so
alleg-dga2.so
# alleg-esddigi.so
# alleg-artsdigi.so
alleg-sgialdigi.so
# alleg-alsadigi.so
alleg-alsamidi.so
# alleg-jackdigi.so

Now you can save the file and go to third step.

2b. (Alternative method, not recommended)
Use this method only as alternative, when the recommended won't work. Why? Because it describes how to use ESD driver with Allegro apps, which gives big delays in playing sounds.
Here the modules.lst file should look like this one (alleg-esddigi.so is uncommented):

alleg-vga.so
alleg-fbcon.so
alleg-svgalib.so
alleg-dga2.so
alleg-esddigi.so
# alleg-artsdigi.so
alleg-sgialdigi.so
# alleg-alsadigi.so
alleg-alsamidi.so
# alleg-jackdigi.so

Now you have to install a proper package. In Ubuntu it would be:

sudo apt-get install liballegro4.2-plugin-esd

And that's all. You don't have to do the third step in this method. Now you can run Open Sonic with working sound and with running PulseAudio in background (remember about delays).

3. In this last step you'll learn how to mix sound in OSS applications with PA (previously we forced Allegro to use OSS). By default our sound server provides "padsp" app, which works nice with a large part of programs using OSS, but not with Allegro (yeah, I know you're now thinking, that nothing works with this allegro tongue). Of course you can try by yourself, but you won't be pleased. Fortunately, there's another application that works similar to padsp and we'll used it here. It's Alsa-Oss and it was designed to play sound in OSS applications using Alsa. PulseAudio works nice with it (that's because we need to make first step). In Ubuntu type a command:

sudo apt-get install alsa-oss

Now the only thing you need to do is to remember, that you must run Open Sonic (and other allegro apps) with aoss. Example:

aoss opensonic

If you have an entry in the menu, you can edit it, so that will be easier to run it in feature.

Enjoy!

PS: I have a request to the admin. Please insert a link to this post in the FAQ, so that people would know there's another way to solve the problem smile

Last edited by SzynaW (2011-05-25 19:39:24)

Re: Sound in Open Sonic with PulseAudio

Great tutorial! Thanks for the information. Our FAQ has been updated. smile

Re: Sound in Open Sonic with PulseAudio

After this tutorial I still have one problem: sound works in only OpenSonic or only in other apps, not together.

Re: Sound in Open Sonic with PulseAudio

What system do you have? Are you sure you had done everything properly? As i wrote, check in 'pavucontrol' if Open Sonic is displayed there (you can check it in Playback card); if yes that means you have configured PA properly for the game, but maybe you haven't still configured other applications. You should follow these steps.

Re: Sound in Open Sonic with PulseAudio

I didn't want to risk removing Pulse (and the meta-package Ubuntu Desktop that goes bye-bye too). I also didn't want to reconfigure sound files.

I did some judicious googling and came up with this...

To Play the Game with Sound...
1) Open Terminal, Enter the following...

killall -9 pulseaudio

2) Close Terminal


*** INTERLUDE *** Playing Your Ass Off and Rocking Out While Doing It***


After Playing the Game...
1) [Alt+F2], Run the following...

pulseaudio

Notes...
There is a speaker pop for me when Pulse comes back on, I recommend powering off your speakers first. You could also just leave Pulse off, as sound should be working still, and Pulse will restart itself when you reboot or log off/on. Tested on Ubuntu 9.04 Jaunty.

Hope that helps,

Cheers

Last edited by hhh (2009-12-19 02:12:33)

Re: Sound in Open Sonic with PulseAudio

Maybe stopping PulseAudio is excessive too.
You may use this command to suspend it instead:

pasuspender opensonic_launcher

I have tried it with Audacity, but it will probably work with OpenSonic. The utility (pasuspender) is located (at least in openSUSE) in pasuspender-utils package. It mutes sound in all applications working with PulseAudio until the game process is exited.

Last edited by Anachron (2010-01-07 12:57:46)

Re: Sound in Open Sonic with PulseAudio

Hi,
Sorry for my english.
Does not want to troll about PulseAudio but just saying i use Linux for years (as a user not a geek) and i did never have so much sound problems.

Well, a new little joke from Ubuntu team after an upgrage from my old version to Lucid Lynx...
They removed many things (don't know why because it worked perfectly).

As i am an OpenSonic  player i was upset to see my working OS install have lost sound after ubuntu upgrade.

And your tuto can't be use as it as they remove asoundconf (why? but why? Are you crazy dudes?)

So here's my very little help...
Before Step 1 for Lucid Lynx you have a prerequisite:

Copy the following (wich is my old asoundconf) to /usr/bin folder:

#!/usr/bin/python

# (C) 2005 Canonical Ltd.
# Author: Martin Pitt <martin.pitt@ubuntu.com>
# License: GNU General Public License, version 2 or any later version
#
# Modified by: Thomas Hood, Daniel T Chen
#
# Get and set configuration parameters in ~/.asoundrc.asoundconf.

import sys, re, os.path

our_conf_file = os.path.expanduser('~/.asoundrc.asoundconf')
asoundrc_file = os.path.expanduser('~/.asoundrc')
predefs_file = '/usr/share/alsa/alsa.conf'

setting_re_template = '!?\s*%s\s*(?:=|\s)\s*([^;,]+)[;,]?$'

our_conf_header = '''# ALSA library configuration file managed by asoundconf(1).
#
# MANUAL CHANGES TO THIS FILE WILL BE OVERWRITTEN!
#
# Manual changes to the ALSA library configuration should be implemented
# by editing the ~/.asoundrc file, not by editing this file.
'''

asoundrc_header = '''# ALSA library configuration file
'''

inclusion_comment = '''# Include settings that are under the control of asoundconf(1).
# (To disable these settings, comment out this line.)'''

usage = '''Usage:
asoundconf is-active
asoundconf get|delete PARAMETER
asoundconf set PARAMETER VALUE
asoundconf list

Convenience macro functions:
asoundconf set-default-card PARAMETER
asoundconf reset-default-card
asoundconf set-pulseaudio
asoundconf unset-pulseaudio
asoundconf set-oss PARAMETER
asoundconf unset-oss
'''


needs_default_card = '''You have omitted a necessary parameter.  Please see the output from `asoundconf list`, and use one of those sound card(s) as the parameter.
'''


needs_oss_dev = '''You have omitted a necessary parameter.  Please specify an OSS device (e.g., /dev/dsp).
'''


superuser_warn = '''Please note that you are attempting to run asoundconf as a privileged superuser, which may have unintended consequences.
'''


def get_default_predefs():
    try:
    if not os.path.exists(predefs_file):
        return
    predefs_file_entire = open(predefs_file).readlines()
    r = re.compile('^defaults')
    ## Between these hashes, add additional unique regexps that
    ## must exist at the end of the user's custom asoundrc.
    s = re.compile('^defaults.namehint')
    ##
    predefs_list = []
    must_append_predefs_list = []
    for i in predefs_file_entire:
        if r.match(i) and not s.match(i):
        predefs_list.append(str(i).strip())
        elif s.match(i):
        must_append_predefs_list.append(str(i).strip())
    for i in must_append_predefs_list:
        predefs_list.append(str(i).strip())
    return predefs_list
    except IOError:
    pass


def ensure_our_conf_exists():
    '''If it does not exist then generate a default configuration
    file with no settings.

    Return: True on success, False if the file could not be created.
    '''

    if os.path.exists(our_conf_file):
        return True

    try:
        open(our_conf_file, 'w').write(our_conf_header)
        return True
    except IOError:
        print >> sys.stderr, 'Error: could not create', our_conf_file
        return False


def ensure_asound_rc_exists():
    '''Generate a default user configuration file with only the
    inclusion line.

    Return: True on success, False if the file could not be created.
    '''

    if os.path.exists(asoundrc_file):
        return True

    try:
        open(asoundrc_file, 'w').write('%s\n%s\n<%s>\n\n' % (asoundrc_header, inclusion_comment, our_conf_file))
        return True
    except IOError:
        print >> sys.stderr, 'Error: could not create', asoundrc_file
        return False


def sds_transition():
    '''Replace the magic comments added to the user configuration file
    by the obsolete set-default-soundcard program with the standard
    inclusion statement for our configuration file.
    '''

    if not os.path.exists(asoundrc_file):
        return

    lines = open(asoundrc_file).readlines()

    start_marker_re = re.compile('### BEGIN set-default-soundcard')
    end_marker_re = re.compile('### END set-default-soundcard')

    userconf_lines = []
    our_conf_lines = []

    # read up to start comment
    lineno = 0
    found = 0
    for l in lines:
        lineno = lineno+1
        if start_marker_re.match(l):
            found = 1
            break
        userconf_lines.append(l)

    if found:
        # replace magic comment section with include
        userconf_lines.append('%s\n<%s>\n\n' % (inclusion_comment, our_conf_file))
    else:
        # no magic comment
        return

    # read magic comment section until end marker and add it to asoundconf
    found = 0
    for l in lines[lineno:]:
        lineno = lineno+1
        if end_marker_re.match(l):
            found = 1
            break
        if not l.startswith('#'):
            our_conf_lines.append(l)

    if not found:
        # no complete magic comment
        return

    # add the rest to user conf
    userconf_lines = userconf_lines + lines[lineno:]

    # write our configuration file
    if not ensure_our_conf_exists():
        return
    try:
        open(our_conf_file, 'a').writelines(our_conf_lines)
    except IOError:
        return # panic out

    # write user configuration file
    try:
        open(asoundrc_file, 'w').writelines(userconf_lines)
    except IOError:
        pass


def is_active():
    '''Check that the user configuration file is either absent, or,
    if present, that it includifies the asoundconf configuration file;
    in those cases asoundconf can be used to change the user's ALSA
    library configuration.

    Also transition from the legacy set-default-soundcard program.

    Return True if the above condition is met, False if not.
    '''

    if not os.path.exists(asoundrc_file):
        return True

    sds_transition()

    # check whether or not the file has the inclusion line
    include_re = re.compile('\s*<\s*%s\s*>' % our_conf_file)
    for l in open(asoundrc_file):
        if include_re.match(l):
            return True

    return False

def get(prmtr):
    '''Print the value of the given parameter on stdout

    Also transition from the legacy set-default-soundcard program.

    Return True on success, and False if the value is not set.
    '''

    sds_transition()

    if not os.path.exists(our_conf_file):
        return False

    setting_re = re.compile(setting_re_template % prmtr)

    try:
        for line in open(our_conf_file):
            m = setting_re.match(line)
            if m:
                print m.group(1).strip()
                return True
        return False
    except IOError:
        return False

def list():
    '''Get card names from /proc/asound/cards'''

    cardspath = '/proc/asound/cards'
    if not os.path.exists(cardspath):
        return False
    procfile = open(cardspath, 'rb')
    cardline = re.compile('^\s*\d+\s*\[')
    card_lines = []
    lines = procfile.readlines()
    for l in lines:
        if cardline.match(l):
            card_lines.append(re.sub(r'^\s*\d+\s*\[(\w+)\s*\].+','\\1',l))
    print "Names of available sound cards:"
    for cardname in card_lines:
        print cardname.strip()
    return True

def delete(prmtr):
    '''Delete the given parameter.

    Also transition from the legacy set-default-soundcard program.

    Return True on success, and False on an error.
    '''

    sds_transition()

    if not os.path.exists(our_conf_file):
        return False

    setting_re = re.compile(setting_re_template % prmtr)
    lines = []
    try:
        lines = open(our_conf_file).readlines()
    except IOError:
        return False

    found = 0
    for i in xrange(len(lines)):
        if setting_re.match(lines[i]):
            del lines[i]
            found = 1
            break

    if found:
        # write back file
        try:
            f = open(our_conf_file, 'w')
        except IOError:
            return False
        f.writelines(lines)

    return True


def set(prmtr, value):
    '''Set the given parameter to the given value

    Also transition from the legacy set-default-soundcard program.

    Return True on success, and False on an error.
    '''

    sds_transition()

    setting_re = re.compile(setting_re_template % prmtr)
    lines = []

    ensure_asound_rc_exists()
    # N.B. We continue even if asoundrc could not be created
    # and we do NOT ensure that our configuration is "active"

    if not ensure_our_conf_exists():
        return False

    try:
        lines = open(our_conf_file).readlines()
    except IOError:
        return False

    newsetting = '%s %s\n' % (prmtr, value)

    # if setting is already present, change it
    found = 0
    for i in xrange(len(lines)):
        if setting_re.match(lines[i]):
            lines[i] = newsetting
            found = 1
            break

    if not found:
        lines.append(newsetting)

    # write back file
    try:
        f = open(our_conf_file, 'w')
    except IOError:
        return False
    f.writelines(lines)
    return True

def set_default_card(card):
    clist = get_default_predefs()
    sep = re.compile('\s+')
    r = re.compile('^defaults.pcm.card')
    s = re.compile('^defaults.ctl.card')
    ## !defaults.pcm.card and defaults.ctl.card should lead
    ## the user's custom asoundrc.
    if set('!defaults.pcm.card', card) and \
       set('defaults.ctl.card', card):
        for i in clist:
        (j, k) = sep.split(i)
        if not r.match(j) and not s.match(j):
            if not set(j, k):
            return False
        return True
    else:
        return False

def reset_default_card():
    clist = get_default_predefs()
    sep = re.compile('\s+')
    for i in clist:
        (j, k) = sep.split(i)
        if not delete(j):
        return False
    return True

def delete_pcm_default():
    return delete('pcm.!default')

def delete_ctl_default():
    return delete('ctl.!default')

def set_pulseaudio():
    return set('pcm.!default', '{ type pulse }') and \
    set('ctl.!default', '{ type pulse }')

def unset_pulseaudio():
    return delete_pcm_default() and \
    delete_ctl_default()

def set_oss(device):
    endbrace = ' }'
    return set('pcm.!default { type oss  device', device + endbrace)

def unset_oss():
    return delete_pcm_default()

def exit_code(result):
    '''Exit program with code 0 if result is True, otherwise exit with code
    1.
    '''

    if result:
        sys.exit(0)
    else:
        sys.exit(1)


##
## main
##

if os.geteuid() == 0:
    print superuser_warn

if len(sys.argv) < 2 or sys.argv[1] == '--help' or sys.argv[1] == '-h':
    print usage
    sys.exit(0)

if sys.argv[1] == 'is-active':
    exit_code(is_active())

if sys.argv[1] == 'get':
    if len(sys.argv) != 3:
        print usage
        sys.exit(1)
    exit_code(get(sys.argv[2]))

if sys.argv[1] == 'delete':
    if len(sys.argv) != 3:
        print usage
        sys.exit(1)
    exit_code(delete(sys.argv[2]))

if sys.argv[1] == 'set':
    if len(sys.argv) != 4:
        print usage
        sys.exit(1)
    exit_code(set(sys.argv[2], sys.argv[3]))

if sys.argv[1] == 'list':
    exit_code(list())

if sys.argv[1] == 'set-default-card':
    if len(sys.argv) != 3:
    print needs_default_card
    sys.exit(1)
    exit_code(set_default_card(sys.argv[2]))

if sys.argv[1] == 'reset-default-card':
    exit_code(reset_default_card())

if sys.argv[1] == 'set-pulseaudio':
    exit_code(set_pulseaudio())

if sys.argv[1] == 'unset-pulseaudio':
    exit_code(unset_pulseaudio())

if sys.argv[1] == 'set-oss':
    if len(sys.argv) != 3:
    print needs_oss_dev
    sys.exit(1)
    exit_code(set_oss(sys.argv[2]))

if sys.argv[1] == 'unset-oss':
    exit_code(unset_oss())

print usage
sys.exit(1)

May be you will have permission problem launching it in a first place (i had) .
I simply (but may be a little dirty) sudo chmod 777 /usr/bin/asoundconf

well now, follow the tuto again
it will rock'n roll.

Thank you for the tuto it helps me so much to restore my open sonic.

Re: Sound in Open Sonic with PulseAudio

Here's what works for me on Ubuntu 10.10
First install alsa-oss you can find it in both the Ubuntu Software Center and in Synaptic Package Manager or in the terminal type sudo apt-get install  alsa-oss
Then edit your Main Menu System > Preferences > Main Menu
Find Open Sonic for me it was in Games
Once Open Sonic is highlighted click Properties
Then change Command: opensonic
to
Commnad: aoss opensonic
That's it close the Main Menu editor and run open sonic from the Main Menu to make sure it work

Good luck and I hope this helps
Dan

Re: Sound in Open Sonic with PulseAudio

It might be possible that if you uses my Ubuntu Launchpad repository, you won't have sound in the game, even after applying the above tutorial. This problem is caused by Allegro 4.4 and it affects the newest version of OpenSonic 0.1.4. I don't have an idea how to repair this, especially because allegro4.4 built locally on my computer don't cause this problem.

Luckily, today I have managed to find a temporary way to enable sound in these launchpad packages. You have to take the following steps:
1. Install alsa-oss package: (I didn't check if it is necessary)

sudo apt-get install alsa-oss

2. Load kernel modules: snd_pcm_oss and snd_mixer_oss

sudo modprobe snd_pcm_oss
sudo modprobe snd_mixer_oss

You have to do this after each reboot. If you don't want this, add these modules to /etc/modules:

sudo gedit /etc/modules

and now add two new lines:

snd_pcm_oss
snd_mixer_oss

3. Run opensonic with pasuspender:

pasuspender opensonic

Unfortunately, padsp and aoss still don't work with opensonic, even with this method.

I will try to find a better solution for this problem and make packages with the sound 'out of the box'.

Re: Sound in Open Sonic with PulseAudio

Today I installed the new Ubuntu in my computer and I could not get the sounds working by using any of the previous methods. The FAQ has also been updated with the following (works for me):

The game has no sound! (Linux)

Games made using the Allegro game programming library can't play sounds on some Linux distributions (like recent Ubuntu releases) due to a problem with pulseaudio (check out the full explanation). We'll show you a workaround.

* First of all, please open a terminal and go to the folder where the game is located.

* Download liballeg.so.4.4 from this link

wget http://opensnc.sourceforge.net/home/misc/liballeg.so.4.4

* Install the alsa-oss package. In Debian-based distributions (like Ubuntu), type:

sudo apt-get install alsa-oss

* Create a file named opensurge_with_sound in the game folder. Using a simple text editor (like nano, gedit, kate, etc.), write the following contents to it:

#!/bin/bash
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
aoss ./opensurge $@    # replace "./opensurge" with "./opensonic" if applicable

Finally, turn opensurge_with_sound into an executable by running chmod:

chmod +x opensurge_with_sound

Now you're ready to go. Whenever you want to play, run opensurge_with_sound:

./opensurge_with_sound

smile

That liballeg.so.4.4 is the same .so that is distributed in the official 0.1.4 binary package for Linux.

Re: Sound in Open Sonic with PulseAudio

With the newest version of Allegro (4.4.2) sound and music in OpenSonic or OpenSurge should now work "out of the box" with ALSA, PulseAudio on Ubuntu and Debian systems.
Check updates in my Ubuntu Launchpad repository: https://launchpad.net/~szymonw/+archive/ppa