OpenAL4Android

In the comments to my post on OpenAL on Android some visitors asked to provide some high-level examples of how to use OpenAL.

In this post you will find a light-weight Android Java library, consisting of four classes only, that allows you to create complex 3D sound scenes. An additional Hello World example building upon this library will show how to create a scene with three different sound sources.

OpenAL4Android Library

Download the library from http://pielot.org/wp-content/uploads/2011/11/OpenAL4Android.zip. The library contains the following classes:

  • OpenAlBridge: this class contains all the native methods used to communicate with the OpenAL native implementation
  • SoundEnv: this class allows to manage the sound scene. It for example allows registering new sounds and moving around the virtual listener
  • Buffer: a buffer is one sound file loaded into the RAM of the device. A buffer itself cannot be played.
  • Source: a source turns a buffer into an actually sounding object. The source allows changing the parameters of the sound, such as its position in 3D space, the playback volume, or the pitch. Each source as one buffer, but one buffer can be used by different sources.

If you turn it into an Android library, you can use it in several projects at the same time. Go to Properties -> Android and make sure that the check box “Is Library” is checked.

The following Hello World example shows how to use the library.

HelloOpenAL4Android

HelloOpenAL4Android is a demo application illustrating how to use OpenAL4Android. The complete code + Eclipse project files can be downloaded here.

Create a new Android project. Use Android 1.6 at least. Visit the project properties and add OpenAL4Android as library project (project -> android -> library). The the following code shows how to create a complex 3D scene.

To run without errors, the program requires two sound files named “lake.wav” and “park.wav” in the project’s assets folder. If the folder does not exist, just create it on the top level of the project, next to src, res, … .

package org.pielot.helloopenal;

import org.pielot.openal.Buffer;
import org.pielot.openal.SoundEnv;
import org.pielot.openal.Source;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

/**
 * This tutorial shows how to use the OpenAL4Android library. It creates a small
 * scene with two lakes (water) and one park (bird chanting).
 * @author Martin Pielot
 */
public class HelloOpenAL4AndroidActivity extends Activity {

    private final static String    TAG    = "HelloOpenAL4Android";

    private SoundEnv            env;

    private Source                lake1;
    private Source                lake2;
    private Source                park1;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i(TAG, "onCreate()");

        this.setContentView(R.layout.main);

        try {
            /* First we obtain the instance of the sound environment. */
            this.env = SoundEnv.getInstance(this);

            /*
             * Now we load the sounds into the memory that we want to play
             * later. Each sound has to be buffered once only. To add new sound
             * copy them into the assets folder of the Android project.
             * Currently only mono .wav files are supported.
             */
            Buffer lake = env.addBuffer("lake");
            Buffer park = env.addBuffer("park");

            /*
             * To actually play a sound and place it somewhere in the sound
             * environment, we have to create sources. Each source has its own
             * parameters, such as 3D position or pitch. Several sources can
             * share a single buffer.
             */
            this.lake1 = env.addSource(lake);
            this.lake2 = env.addSource(lake);
            this.park1 = env.addSource(park);

            // Now we spread the sounds throughout the sound room.
            this.lake1.setPosition(0, 0, -10);
            this.lake2.setPosition(-6, 0, 4);
            this.park1.setPosition(6, 0, -12);

            // and change the pitch of the second lake.
            this.lake2.setPitch(1.1f);

            /*
             * These sounds are perceived from the perspective of a virtual
             * listener. Initially the position of this listener is 0,0,0. The
             * position and the orientation of the virtual listener can be
             * adjusted via the SoundEnv class.
             */
            this.env.setListenerOrientation(20);
        } catch (Exception e) {
            Log.e(TAG, "could not initialise OpenAL4Android", e);
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.i(TAG, "onResume()");

        /*
         * Start playing all sources. 'true' as parameter specifies that the
         * sounds shall be played as a loop.
         */
        this.lake1.play(true);
        this.lake2.play(true);
        this.park1.play(true);
    }

    @Override
    public void onPause() {
        super.onPause();
        Log.i(TAG, "onPause()");

        // Stop all sounds
        this.lake1.stop();
        this.lake2.stop();
        this.park1.stop();

    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "onDestroy()");

        // Be nice with the system and release all resources
        this.env.stopAllSources();
        this.env.release();
    }

    @Override
    public void onLowMemory() {
        this.env.onLowMemory();
    }
}

11 thoughts on “OpenAL4Android”

  1. Hello Martin,

    For running this project is there any other step required other than just downloading and building the “HelloOpenAL4Android.zip ” and “OpenAL4Android.zip” projects and running the first one on a device? Is there anything mentioned in the first tutorial that needs to be done?

    I have run the HelloOpenAL4Android project on Samsung Galaxy S2 with API level 2.3.3 but the application keeps on crashing. In the logcat, the following message is repeated “Could not find method.org.pileot.openal.SoundEnv.” is repeated.

    What seems to be wrong?

  2. The error says that the HelloOpenAL4Android activity cannot find the library class SoundEnv. Have you added OpenAL4Android as library to the HelloOpenAL4Android project?

  3. hi!, Matin is chief of opencv cafe (http://opencv.co.kr)?
    I’m member of opencv cafe.

    I’m sorry. I can’t writing english very well.

    a, just… I want to know that you know your knowledge form original source.
    beacuse, I alone studied Android NDK (3D engine, javaCV, openCV …etc)…
    and I want to know Sound Library.

    I wnat to make English(study).Mp3 player for all users.
    just… I know. Thank you.

    This web page is very helped. see you later!

  4. Compiled it well with but app crashes. I’ve added GetEnv “mod” but still alcOpenDevice crashes. Exactly on line:
    ALc.c: if(ALCdevice_OpenPlayback(device, deviceName))
    Tested on Kindle Fire and Nexus One.

    Available playback devices:
    - Android Default
    - Null output
    Available capture devices:
    - !!! none !!!
    Default playback device: Android Default

    Anyone help?

    1. OK – done :)
      For everyone trying to compile it as STATIC library. It is possible, however app will crash cause JNI_onLoad isn’t called without Java System.loadLibrary function. Everything you need to do is just processing JavaVM* (ptr) “to library” object (javaVM from android.c ). You can get curr. JavaVM ptr from:
      android_app->activity->vm;

  5. I’m more looking to use openal as prebuilt static library in my native code, I’m not looking to access from java, rather want to use it in native code? Any light to shed?

    1. That should be easy!
      Download the .zip file from the post. Look for libs/armeabi/libopenal.so – that’s the prebuilt openal library. Look at jni/openalwrapper.h and jni/openalwrapper.c to learn how to use the library from native code in Android.

  6. Hi Martin, great piece of work and thanks for the code.

    I have the library working fine, but I’ve discovered a semantic issue.

    If I set a sound source position to (19,0,12) and the listener position to (19,0,10) with the listener orientation at ’90′, I would expect to hear sound coming from the left speaker, but it comes from the right. I’m thinking of x and z here like x and y on a graph (birds-eye view).

    What am I doing wrong?

    Thanks in advance, Liam.

    1. No worries, I’ve fixed it. I figured OpenAL uses the right handed cartesian coordinate system. I changed my implementation to left handed by negating the z value (*-1).

  7. hello,i want to do reverb effect and i want to save it. could you give me high level java code for this? very thank you!!!

  8. Hi,
    Great package, worked straight away :)
    Just a problem: I can get sound sources varying horizontally (left/right) but not vertically (up/down). Basically in ‘setPosition(x,y,z)’ it doesn’t rally matter which value I assign to ‘z’, the sound won’t change. Is it an OpenAL issue or what else?
    Many thanks
    Nicola

Comments are closed.