2013年9月30日 星期一

OpenAL HRTF 3d sound on Linux & Android

source code download on 2016/06/25

https://github.com/kcat/openal-soft
also refer to
https://github.com/soundsrc/openal-soft

///////////////////////Ubuntu 14.04 linux system///////////////////////
1. preinstall
sudo apt-get install cmake
sudo apt-get install libsdl-sound1.2-dev

sudo add-apt-repository ppa:adrozdoff/ffmpeg-opti
sudo apt-get update
sudo apt-get install libavformat-ffmpeg-dev libavcodec-ffmpeg-dev libavutil-ffmpeg-dev libavfilter-ffmpeg-dev libswscale-ffmpeg-dev libswresample-ffmpeg-dev libpostproc-ffmpeg-dev

2. cmake

cd ~/openal-soft-172
cmake . -DCMAKE_BUILD_TYPE=Debug

3. EnumerateHrtf modify
gedit /root/openal-soft-172/Alc/hrtf.c

vector_HrtfEntry EnumerateHrtf(const_al_string devname)
{
...
    if(usedefaults)
    {
        //vector_al_string flist = SearchDataFiles(".mhr", "openal/hrtf");
        vector_al_string flist = SearchDataFiles(".mhr", "/root/openal-soft-172/hrtf");
        VECTOR_FOR_EACH_PARAMS(al_string, flist, AddFileEntry, &list);
        VECTOR_DEINIT(flist);
    }
...
}

4. AddFileEntry modify
gedit /root/openal-soft-172/Alc/hrtf.c
static void AddFileEntry(vector_HrtfEntry *list, al_string *filename)
{
...
done: //add here
    ext = strrchr(name, '.');
...
//done: //remove here
    al_string_deinit(filename);
}

5. modify alhrtf.c
gedit /root/openal-soft-172/examples/alhrtf.c
#include <stdio.h>
#include <assert.h>
#include <math.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

#include "AL/al.h"
#include "AL/alc.h"
#include "AL/alext.h"

#include "common/alhelpers.h"
#include "common/sdl_sound.h"

#ifndef M_PI
#define M_PI                         (3.14159265358979323846)
#endif

static LPALCGETSTRINGISOFT         alcGetStringiSOFT;
static LPALCRESETDEVICESOFT    alcResetDeviceSOFT;

static unsigned char* raw_data = NULL;

struct WHEADER
{
    unsigned char riff[4];                        // RIFF string
    unsigned int overall_size    ;                // overall size of file in bytes
    unsigned char wave[4];                        // WAVE string
    unsigned char fmt_chunk_marker[4];            // fmt string with trailing null char
    unsigned int length_of_fmt;                    // length of the format data
    unsigned int format_type;                    // format type. 1-PCM, 3- IEEE float, 6 - 8bit A law, 7 - 8bit mu law
    unsigned int channels;                        // no.of channels
    unsigned int sample_rate;                    // sampling rate (blocks per second)
    unsigned int byterate;                        // SampleRate * NumChannels * BitsPerSample/8
    unsigned int block_align;                    // NumChannels * BitsPerSample/8
    unsigned int bits_per_sample;                // bits per sample, 8- 8bits, 16- 16 bits etc
    unsigned char data_chunk_header [4];        // DATA string or FLLR string
    unsigned int data_size;                        // NumSamples * NumChannels * BitsPerSample/8 - size of the next chunk that will be read
};

static ALuint LoadSound(char *filename)
{
    ALuint                         al_buffer = 0;
    int                             read;
    char                         format_name[8] = {0};
    unsigned char     buffer4[4];
    unsigned char     buffer2[2];
    struct WHEADER    header;
    long                        num_samples;
    long                         size_of_each_sample;
    float                         duration_in_seconds;
    ALenum                     format;
    FILE*                        ptr;

     ptr = fopen(filename, "rb");
     if (ptr == NULL)
     {
        printf("Error opening file\n");
        return al_buffer;
     }

     // read header parts
     read = fread(header.riff, sizeof(header.riff), 1, ptr);
     printf("(1-4): %s \n", header.riff);

     read = fread(buffer4, sizeof(buffer4), 1, ptr);
     printf("%u %u %u %u\n", buffer4[0], buffer4[1], buffer4[2], buffer4[3]);

     // convert little endian to big endian 4 byte int
     header.overall_size  = buffer4[0] | (buffer4[1]<<8) | (buffer4[2]<<16) | (buffer4[3]<<24);
     printf("(5-8) Overall size: bytes:%u, Kb:%u \n", header.overall_size, header.overall_size/1024);

     read = fread(header.wave, sizeof(header.wave), 1, ptr);
     printf("(9-12) Wave marker: %s\n", header.wave);

     read = fread(header.fmt_chunk_marker, sizeof(header.fmt_chunk_marker), 1, ptr);
     printf("(13-16) Fmt marker: %s\n", header.fmt_chunk_marker);

     read = fread(buffer4, sizeof(buffer4), 1, ptr);
     printf("%u %u %u %u\n", buffer4[0], buffer4[1], buffer4[2], buffer4[3]);

     // convert little endian to big endian 4 byte integer
     header.length_of_fmt = buffer4[0] | (buffer4[1] << 8) | (buffer4[2] << 16) | (buffer4[3] << 24);
     printf("(17-20) Length of Fmt header: %u \n", header.length_of_fmt);

     read = fread(buffer2, sizeof(buffer2), 1, ptr); printf("%u %u \n", buffer2[0], buffer2[1]);

     header.format_type = buffer2[0] | (buffer2[1] << 8);
     if (header.format_type == 1)
         strcpy(format_name,"PCM");
     else if (header.format_type == 6)
         strcpy(format_name, "A-law");
     else if (header.format_type == 7)
         strcpy(format_name, "Mu-law");

     printf("(21-22) Format type: %u %s \n", header.format_type, format_name);

     read = fread(buffer2, sizeof(buffer2), 1, ptr);
     printf("%u %u \n", buffer2[0], buffer2[1]);

     header.channels = buffer2[0] | (buffer2[1] << 8);
     printf("(23-24) Channels: %u \n", header.channels);

     read = fread(buffer4, sizeof(buffer4), 1, ptr);
     printf("%u %u %u %u\n", buffer4[0], buffer4[1], buffer4[2], buffer4[3]);

     header.sample_rate = buffer4[0] |(buffer4[1] << 8) |(buffer4[2] << 16) | (buffer4[3] << 24);
     printf("(25-28) Sample rate: %u\n", header.sample_rate);

     read = fread(buffer4, sizeof(buffer4), 1, ptr);
     printf("%u %u %u %u\n", buffer4[0], buffer4[1], buffer4[2], buffer4[3]);

     header.byterate  = buffer4[0] |(buffer4[1] << 8) | (buffer4[2] << 16) | (buffer4[3] << 24);
     printf("(29-32) Byte Rate: %u , Bit Rate:%u\n", header.byterate, header.byterate*8);

     read = fread(buffer2, sizeof(buffer2), 1, ptr);
     printf("%u %u \n", buffer2[0], buffer2[1]);

     header.block_align = buffer2[0] | (buffer2[1] << 8);
     printf("(33-34) Block Alignment: %u \n", header.block_align);

     read = fread(buffer2, sizeof(buffer2), 1, ptr);
     printf("%u %u \n", buffer2[0], buffer2[1]);

     header.bits_per_sample = buffer2[0] | (buffer2[1] << 8);
     printf("(35-36) Bits per sample: %u \n", header.bits_per_sample);

     read = fread(header.data_chunk_header, sizeof(header.data_chunk_header), 1, ptr);
     printf("(37-40) Data Marker: %s \n", header.data_chunk_header);

     read = fread(buffer4, sizeof(buffer4), 1, ptr);
     printf("%u %u %u %u\n", buffer4[0], buffer4[1], buffer4[2], buffer4[3]);

     header.data_size = buffer4[0] | (buffer4[1] << 8) | (buffer4[2] << 16) |     (buffer4[3] << 24 );
     printf("(41-44) Size of data chunk: %u \n", header.data_size);

     // calculate no.of samples
     num_samples = (8 * header.data_size) / (header.channels * header.bits_per_sample);
     printf("Number of samples:%lu \n", num_samples);

     size_of_each_sample = (header.channels * header.bits_per_sample) / 8;
     printf("Size of each sample:%ld bytes\n", size_of_each_sample);

     // calculate duration of file
     duration_in_seconds = (float) header.overall_size / header.byterate;
     printf("Approx.Duration in seconds=%f\n", duration_in_seconds);

     // read each sample from data chunk if PCM
     if (header.format_type == 1)
     {
         raw_data    = malloc(size_of_each_sample*num_samples);
         read            = fread(raw_data, size_of_each_sample*num_samples, 1, ptr);

         if(header.bits_per_sample == 8)
         {
             if(header.channels == 1)
                 format = AL_FORMAT_MONO8;
             else if(header.channels == 2)
                 format = AL_FORMAT_STEREO8;
         }
         else if(header.bits_per_sample == 16)
         {
             if(header.channels == 1)
                 format = AL_FORMAT_MONO16;
             else if(header.channels == 2)
                 format = AL_FORMAT_STEREO16;
         }

         alGenBuffers(1, &al_buffer);
         alBufferData(al_buffer, format, raw_data, size_of_each_sample*num_samples, header.sample_rate);
     } //  if (header.format_type == 1)

     printf("Closing file..\n");
     fclose(ptr);

    return al_buffer;
}

int main(int argc, char **argv)
{
    ALuint             al_source, al_buffer;
    ALCint             hrtf_state;
    ALCint             num_hrtf;
    ALdouble        angle;
    ALenum        state;
    ALCint             attr[5];
    ALCint             index;
    ALCint             i;
    ALCdevice*    device;
    char*            hrtfname;
    char*            soundname;

    /* Print out usage if no file was specified */
    if(argc < 2 || (strcmp(argv[1], "-hrtf") == 0 && argc < 4))
    {
        fprintf(stderr, "Usage: %s [-hrtf <name>] <soundfile>\n", argv[0]);
        return 1;
    }

    /* Initialize OpenAL with the default device, and check for HRTF support. */
    if(InitAL() != 0)
        return 1;

    if(strcmp(argv[1], "-hrtf") == 0)
    {
        hrtfname = argv[2];
        soundname = argv[3];
    }
    else
    {
        hrtfname = NULL;
        soundname = argv[1];
    }

    device = alcGetContextsDevice(alcGetCurrentContext());
    if(!alcIsExtensionPresent(device, "ALC_SOFT_HRTF"))
    {
        fprintf(stderr, "Error: ALC_SOFT_HRTF not supported\n");
        CloseAL();
        return 1;
    }

    /* Define a macro to help load the function pointers. */
#define LOAD_PROC(d, x)  ((x) = alcGetProcAddress((d), #x))
    LOAD_PROC(device, alcGetStringiSOFT);
    LOAD_PROC(device, alcResetDeviceSOFT);
#undef LOAD_PROC

    /* Enumerate available HRTFs, and reset the device using one. */
    alcGetIntegerv(device, ALC_NUM_HRTF_SPECIFIERS_SOFT, 1, &num_hrtf);
    if(!num_hrtf)
        printf("No HRTFs found\n");
    else
    {
        index = -1;

        printf("Available HRTFs:\n");
        for(i = 0;i < num_hrtf; i++)
        {
            const ALCchar *name = alcGetStringiSOFT(device, ALC_HRTF_SPECIFIER_SOFT, i);
            printf("    %d: %s\n", i, name);

            /* Check if this is the HRTF the user requested. */
            if(hrtfname && strcmp(name, hrtfname) == 0)
                index = i;
        }

        i = 0;
        attr[i++] = ALC_HRTF_SOFT;
        attr[i++] = ALC_TRUE;
        if(index == -1)
        {
            if(hrtfname)
                printf("HRTF \"%s\" not found\n", hrtfname);
            printf("Using default HRTF...\n");
        }
        else
        {
            printf("Selecting HRTF %d...\n", index);
            attr[i++] = ALC_HRTF_ID_SOFT;
            attr[i++] = index;
        }
        attr[i] = 0;

        if(!alcResetDeviceSOFT(device, attr))
            printf("Failed to reset device: %s\n", alcGetString(device, alcGetError(device)));
    }

    /* Check if HRTF is enabled, and show which is being used. */
    alcGetIntegerv(device, ALC_HRTF_SOFT, 1, &hrtf_state);
    if(!hrtf_state)
        printf("HRTF not enabled!\n");
    else
    {
        const ALchar *name = alcGetString(device, ALC_HRTF_SPECIFIER_SOFT);
        printf("HRTF enabled, using %s\n", name);
    }
    fflush(stdout);

    /* Load the sound into a buffer. */
    al_buffer = LoadSound(soundname);
    if(!al_buffer)
    {
        CloseAL();
        return 1;
    }

    /* Create the al_source to play the sound with. */
    al_source = 0;
    alGenSources(1, &al_source);
    alSourcei(al_source, AL_SOURCE_RELATIVE, AL_TRUE);
    alSource3f(al_source, AL_POSITION, 0.0f, 0.0f, 1.0f);
    alSourcei(al_source, AL_BUFFER, al_buffer);
    assert(alGetError()==AL_NO_ERROR && "Failed to setup sound al_source");

    /* Play the sound until it finishes. */
    angle = 0.0;
    alSourcePlay(al_source);
    do
    {
        al_nssleep(10000000);

        /* Rotate the al_source around the listener by about 1/4 cycle per second.
         * Only affects mono sounds.
         */
        angle += 0.01 * M_PI * 0.5;
        alSource3f(al_source, AL_POSITION, (ALfloat)sin(angle), 0.0f, -(ALfloat)cos(angle));

        alGetSourcei(al_source, AL_SOURCE_STATE, &state);
    } while(alGetError() == AL_NO_ERROR && state == AL_PLAYING);

    /* All done. Delete resources, and close OpenAL. */
    alDeleteSources(1, &al_source);
    alDeleteBuffers(1, &al_buffer);

    CloseAL();

    free(raw_data);

    return 0;
}

6.
root@stone-linux:~/openal-soft-172# ./alhrtf -hrtf default-44100 /root/openal-soft-172/output16bitsmono.wav

///////////////////////Android system///////////////////////
1. my config.h for android
#ifndef CONFIG_H
#define CONFIG_H

#define AL_API        __attribute__((visibility("protected")))
#define ALC_API    __attribute__((visibility("protected")))

/* Define to the library version */
#define ALSOFT_VERSION "1.17.2"

/* Define any available alignment declaration */
#define ALIGN(x) __attribute__((aligned(x)))

/* Define if we have the C11 aligned_alloc function */
/* #undef HAVE_ALIGNED_ALLOC */

/* Define if we have the posix_memalign function */
/* #undef HAVE_POSIX_MEMALIGN */

/* Define if we have the _aligned_malloc function */
/* #undef HAVE__ALIGNED_MALLOC */

/* Define if we have SSE CPU extensions */
/* #undef HAVE_SSE */
/* #undef HAVE_SSE2 */
/* #undef HAVE_SSE3 */
/* #undef HAVE_SSE4_1 */

/* Define if we have ARM Neon CPU extensions */
/* #undef HAVE_NEON */

/* Define if we have the ALSA backend */
/* #undef HAVE_ALSA */

/* Define if we have the OSS backend */
/* #undef HAVE_OSS */

/* Define if we have the Solaris backend */
/* #undef HAVE_SOLARIS */

/* Define if we have the SndIO backend */
/* #undef HAVE_SNDIO */

/* Define if we have the QSA backend */
/* #undef HAVE_QSA */

/* Define if we have the MMDevApi backend */
/* #undef HAVE_MMDEVAPI */

/* Define if we have the DSound backend */
/* #undef HAVE_DSOUND */

/* Define if we have the Windows Multimedia backend */
/* #undef HAVE_WINMM */

/* Define if we have the PortAudio backend */
/* #undef HAVE_PORTAUDIO */

/* Define if we have the PulseAudio backend */
/* #undef HAVE_PULSEAUDIO */

/* Define if we have the JACK backend */
/* #undef HAVE_JACK */

/* Define if we have the CoreAudio backend */
/* #undef HAVE_COREAUDIO */

/* Define if we have the OpenSL backend */
#define HAVE_OPENSL

/* Define if we have the Wave Writer backend */
#define HAVE_WAVE

/* Define if we have the stat function */
#define HAVE_STAT

/* Define if we have the lrintf function */
#define HAVE_LRINTF

/* Define if we have the modff function */
#define HAVE_MODFF

/* Define if we have the strtof function */
/* #undef HAVE_STRTOF */

/* Define if we have the strnlen function */
#define HAVE_STRNLEN

/* Define if we have the __int64 type */
/* #undef HAVE___INT64 */

/* Define to the size of a long int type */
#define SIZEOF_LONG 4

/* Define to the size of a long long int type */
#define SIZEOF_LONG_LONG 8

/* Define if we have C99 variable-length array support */
#define HAVE_C99_VLA

/* Define if we have C99 _Bool support */
#define HAVE_C99_BOOL

/* Define if we have C11 _Static_assert support */
#define HAVE_C11_STATIC_ASSERT

/* Define if we have C11 _Alignas support */
/* #undef HAVE_C11_ALIGNAS */

/* Define if we have C11 _Atomic support */
/* #undef HAVE_C11_ATOMIC */

/* Define if we have GCC's destructor attribute */
#define HAVE_GCC_DESTRUCTOR

/* Define if we have GCC's format attribute */
#define HAVE_GCC_FORMAT

/* Define if we have stdint.h */
#define HAVE_STDINT_H

/* Define if we have stdbool.h */
#define HAVE_STDBOOL_H

/* Define if we have stdalign.h */
/* #undef HAVE_STDALIGN_H */

/* Define if we have windows.h */
/* #undef HAVE_WINDOWS_H */

/* Define if we have dlfcn.h */
#define HAVE_DLFCN_H

/* Define if we have pthread_np.h */
/* #undef HAVE_PTHREAD_NP_H */

/* Define if we have alloca.h */
/* #undef HAVE_ALLOCA_H */

/* Define if we have malloc.h */
#define HAVE_MALLOC_H

/* Define if we have dirent.h */
#define HAVE_DIRENT_H

/* Define if we have strings.h */
#define HAVE_STRINGS_H

/* Define if we have cpuid.h */
/* #undef HAVE_CPUID_H */

/* Define if we have intrin.h */
/* #undef HAVE_INTRIN_H */

/* Define if we have sys/sysconf.h */
#define HAVE_SYS_SYSCONF_H

/* Define if we have guiddef.h */
/* #undef HAVE_GUIDDEF_H */

/* Define if we have initguid.h */
/* #undef HAVE_INITGUID_H */

/* Define if we have ieeefp.h */
/* #undef HAVE_IEEEFP_H */

/* Define if we have float.h */
#define HAVE_FLOAT_H

/* Define if we have fenv.h */
#define HAVE_FENV_H

/* Define if we have GCC's __get_cpuid() */
/* #undef HAVE_GCC_GET_CPUID */

/* Define if we have the __cpuid() intrinsic */
/* #undef HAVE_CPUID_INTRINSIC */

/* Define if we have _controlfp() */
/* #undef HAVE__CONTROLFP */

/* Define if we have __control87_2() */
/* #undef HAVE___CONTROL87_2 */

/* Define if we have pthread_setschedparam() */
#define HAVE_PTHREAD_SETSCHEDPARAM

/* Define if we have pthread_setname_np() */
#define HAVE_PTHREAD_SETNAME_NP

/* Define if pthread_setname_np() only accepts one parameter */
/* #undef PTHREAD_SETNAME_NP_ONE_PARAM */

/* Define if we have pthread_set_name_np() */
/* #undef HAVE_PTHREAD_SET_NAME_NP */

/* Define if we have pthread_mutexattr_setkind_np() */
/* #undef HAVE_PTHREAD_MUTEXATTR_SETKIND_NP */

/* Define if we have pthread_mutex_timedlock() */
/* #undef HAVE_PTHREAD_MUTEX_TIMEDLOCK */

#define    STRING_SIZE    256
#define    ZIPFILENUM    64

#endif

2. gedit /root/openal-soft-android/android/jni/Android.mk
//
LOCAL_PATH := $(call my-dir)
##########################################################
include $(CLEAR_VARS)

LOCAL_MODULE     := tremolo
LOCAL_ARM_MODE   := arm
LOCAL_CPP_FEATURES += rtti

APP_DEBUG := $(strip $(NDK_DEBUG))
ifeq ($(APP_DEBUG),0)
    LOCAL_CFLAGS := -D_ARM_ASSEM_ -DANDROID_NDK -DBUILD_ANDROID -DGC_BUILD_ANDROID -DNDEBUG -DHAVE_NEON=1 -mfpu=neon -mfloat-abi=softfp
    LOCAL_CPPFLAGS := -DGC_BUILD_C -DANDROID_NDK -DBUILD_ANDROID -DNDEBUG -DHAVE_NEON=1 -mfpu=neon -mfloat-abi=softfp
else
    LOCAL_CFLAGS := -D_ARM_ASSEM_ -DANDROID_NDK -DBUILD_ANDROID -DGC_BUILD_ANDROID -D_DEBUG -DHAVE_NEON=1 -mfpu=neon -mfloat-abi=softfp
    LOCAL_CPPFLAGS := -DGC_BUILD_C -DANDROID_NDK -DBUILD_ANDROID -D_DEBUG -DHAVE_NEON=1 -mfpu=neon -mfloat-abi=softfp
endif

LOCAL_SRC_FILES  := \
../../tremolo/bitwise.c \
../../tremolo/bitwiseARM.s \
../../tremolo/codebook.c \
../../tremolo/dpen.s \
../../tremolo/dsp.c \
../../tremolo/floor0.c \
../../tremolo/floor1.c \
../../tremolo/floor1ARM.s \
../../tremolo/floor1LARM.s \
../../tremolo/floor_lookup.c \
../../tremolo/framing.c \
../../tremolo/info.c \
../../tremolo/mapping0.c \
../../tremolo/mdct.c \
../../tremolo/mdctARM.s \
../../tremolo/mdctLARM.s \
../../tremolo/misc.c \
../../tremolo/res012.c \
../../tremolo/speed.s \
../../tremolo/vorbisfile.c \
../../tremolo/speed.s

include $(BUILD_STATIC_LIBRARY)

##########################################################
include $(CLEAR_VARS)

LOCAL_MODULE     := common
LOCAL_ARM_MODE   := arm
LOCAL_CPP_FEATURES += rtti

APP_DEBUG := $(strip $(NDK_DEBUG))
ifeq ($(APP_DEBUG),0)
    LOCAL_CFLAGS := -DAL_BUILD_LIBRARY -DAL_ALEXT_PROTOTYPES -DANDROID_NDK -DBUILD_ANDROID -DGC_BUILD_ANDROID -DNDEBUG
    LOCAL_CPPFLAGS := -DGC_BUILD_C -DANDROID_NDK -DBUILD_ANDROID -DNDEBUG
else
    LOCAL_CFLAGS := -DAL_BUILD_LIBRARY -DAL_ALEXT_PROTOTYPES -DANDROID_NDK -DBUILD_ANDROID -DGC_BUILD_ANDROID -D_DEBUG
    LOCAL_CPPFLAGS := -DGC_BUILD_C -DANDROID_NDK -DBUILD_ANDROID -D_DEBUG
endif

LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/../.. \
$(LOCAL_PATH)/../../include \
$(LOCAL_PATH)/../../Alc \
$(LOCAL_PATH)/../../OpenAL32/Include

LOCAL_SRC_FILES  := \
../../common/almalloc.c \
../../common/atomic.c \
../../common/rwlock.c \
../../common/threads.c \
../../common/uintmap.c

include $(BUILD_STATIC_LIBRARY)

##########################################################
include $(CLEAR_VARS)

LOCAL_MODULE     := openal
LOCAL_ARM_MODE   := arm
LOCAL_CPP_FEATURES += rtti

APP_DEBUG := $(strip $(NDK_DEBUG))
ifeq ($(APP_DEBUG),0)
    LOCAL_CFLAGS := -DAL_ALEXT_PROTOTYPES -DAL_BUILD_LIBRARY -DANDROID_NDK -DBUILD_ANDROID -DGC_BUILD_ANDROID -DNDEBUG
    LOCAL_CPPFLAGS := -DGC_BUILD_C -DANDROID_NDK -DBUILD_ANDROID -DNDEBUG
else
    LOCAL_CFLAGS := -DAL_ALEXT_PROTOTYPES -DAL_BUILD_LIBRARY -DANDROID_NDK -DBUILD_ANDROID -DGC_BUILD_ANDROID -D_DEBUG
    LOCAL_CPPFLAGS := -DGC_BUILD_C -DANDROID_NDK -DBUILD_ANDROID -D_DEBUG
endif

LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/../.. \
$(LOCAL_PATH)/../../include \
$(LOCAL_PATH)/../../Alc \
$(LOCAL_PATH)/../../OpenAL32/Include \
$(LOCAL_PATH)/../../unzip \
$(LOCAL_PATH)/../../utils \
$(LOCAL_PATH)/../../tremolo \
$(LOCAL_PATH)/../cc_src

LOCAL_SRC_FILES  := \
../../Alc/ALc.c \
../../Alc/ALu.c \
../../Alc/alcConfig.c \
../../Alc/alcRing.c \
../../Alc/ambdec.c \
../../Alc/bformatdec.c \
../../Alc/bs2b.c \
../../Alc/bsinc.c \
../../Alc/helpers.c \
../../Alc/hrtf.c \
../../Alc/mixer.c \
../../Alc/mixer_c.c \
../../Alc/panning.c \
../../Alc/uhjfilter.c \
../../Alc/alstring.c \
../../Alc/backends/base.c \
../../Alc/backends/loopback.c \
../../Alc/backends/null.c \
../../Alc/backends/opensl.c \
../../Alc/backends/wave.c \
../../Alc/effects/autowah.c \
../../Alc/effects/chorus.c \
../../Alc/effects/compressor.c \
../../Alc/effects/dedicated.c \
../../Alc/effects/distortion.c \
../../Alc/effects/echo.c \
../../Alc/effects/equalizer.c \
../../Alc/effects/flanger.c \
../../Alc/effects/modulator.c \
../../Alc/effects/null.c \
../../Alc/effects/reverb.c \
../../OpenAL32/alAuxEffectSlot.c \
../../OpenAL32/alBuffer.c \
../../OpenAL32/alEffect.c \
../../OpenAL32/alError.c \
../../OpenAL32/alExtension.c \
../../OpenAL32/alFilter.c \
../../OpenAL32/alListener.c \
../../OpenAL32/alSource.c \
../../OpenAL32/alState.c \
../../OpenAL32/alThunk.c \
../../OpenAL32/sample_cvt.c \
../../OpenAL32/alMain.c \
../../unzip/zip.c \
../../unzip/unzip.c \
../../unzip/ioapi.c \
../../unzip/ioapi_mem.c \
../../unzip/filesystemzip.c \
../../utils/androidutil.c \
../../utils/jniapi.c \
../cc_src/example.c

LOCAL_STATIC_LIBRARIES := libtremolo libcommon
LOCAL_LDLIBS     := -ldl -llog -lz -lOpenSLES

include $(BUILD_SHARED_LIBRARY)

3. edit openAL.java
package com.example;

import android.app.Activity;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class OpenAL extends Activity
{
    public static native void nativeApkInit(String str);
    public static native void nativeApkRelease();
    public static native void nativeStartExample(String str);
    public static native void nativeEndExample();
   
    public int             play_times;
    public Button    button00;
    public Button    button01;
    public Thread     thread_openal;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        PackageManager    packMgmr;
        ApplicationInfo        appInfo;
       
        play_times = 0;
       
        System.loadLibrary("openal");

        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
                       
        try
        {
            packMgmr    = getApplication().getPackageManager();
            //input package name -> com.example
            appInfo        = packMgmr.getApplicationInfo("com.example", 0);
        }
        catch (NameNotFoundException e)
        {
            e.printStackTrace();
            throw new RuntimeException("Unable to locate assets, aborting...");
        }
       
        //input .apk filename from sourceDir
        nativeApkInit(appInfo.sourceDir);

//////////////////
        thread_openal = new Thread(new Runnable() 
        { 
            @Override 
            public void run() 
            { 
                //input sound filename
                nativeStartExample("explorers-melody.ogg");
            } 
        }); 

//////////////////
        button00 = (Button)findViewById(R.id.Button00);
        button00.setOnClickListener(new Button.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                if( play_times <= 0 )
                {
                    play_times++;
                    thread_openal.start();
                }
            }        
        });
       
        button01 = (Button)findViewById(R.id.Button01);
        button01.setOnClickListener(new Button.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                nativeEndExample();
                nativeApkRelease();
                finish();
            }        
        });
    }
}

///
Source code:
http://www.mediafire.com/file/h279wr4x7wrh8cz/libopenal_1.18.2_android.tar.gz
http://www.mediafire.com/download/m8ejfg2m62qdxlq/openal-soft-172.zip
http://www.mediafire.com/download/4v01owbdb90j242/openal-soft-android.zip 

Demo App:
http://www.mediafire.com/download/yh8bp9diae1s5p0/OpenAL.apk

沒有留言:

張貼留言