How can I make BASS 3D sounds match Irrlicht's coords?

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
Ruxify
Posts: 33
Joined: Tue Oct 16, 2012 12:37 am

How can I make BASS 3D sounds match Irrlicht's coords?

Post by Ruxify »

So I know that Irrlicht uses a "right-handed" coordinate system while BASS uses a "left-handed" one. I've been reading that in order to convert them, you need to multiply the Z axis by -1 but that doesn't seem to work. The problem is that sometimes the sound seems to be coming from the wrong place. How can I properly match BASS's and Irrlicht's coordinate systems? Thanks in advance.

Here is my sound_manager class for my game:

sound_manager.h

Code: Select all

/*
    This class is used for all sound management, 2D and 3D.
*/
 
#ifndef SOUND_MANAGER_H
#define SOUND_MANAGER_H
 
#include <iostream>
#include <cstdlib>
 
#include <irrlicht.h>
#include <bass.h>
 
using namespace std;
using namespace irr;
using namespace core;
using namespace video;
using namespace io;
using namespace scene;
using namespace gui;
 
HSTREAM createSoundHandle(IReadFile* snd, DWORD flags = 0); //This function creates an HSTREAM from the sound file in the .zip.
 
struct sound_instance_2d
{
    sound_instance_2d(); //Constructor.
    int soundID; //What sound is this?
    int soundInstance; //What is the index of this sound in the sound manager?
    HSTREAM handle; //The HSTREAM sound handle.
    IReadFile* file_handle; //The handle to the read file.
    bool loop; //Should this sound loop?
};
 
struct sound_instance_3d
{
    sound_instance_3d(); //Constructor.
    int soundID; //What sound is this?
    int soundInstance; //What is the index of this sound in the sound manager?
    HSTREAM handle; //The HSTREAM sound handle.
    IReadFile* file_handle; //The handle to the read file.
    ISceneNode* node; //The node to follow.
    bool loop; //Should this sound loop?
};
 
class sound_manager
{
    public:
        //Constructor/Deconstructor
        sound_manager(IrrlichtDevice* irrdv, float basevol);
        ~sound_manager();
 
        //Routines
        void update(); //Update the manager.
        void loadSounds(); //Loads in all the sounds and music.
        void unloadSounds(); //Unloads all the sounds.
        int play2DSound(int id, float vol, bool loop); //Play a 2D sound.
        int play3DSound(int id, ISceneNode* node, float dist, float vol, bool loop); //Play a 3D sound.
        void stop2DSound(int id); //Stops a 2D sound.
        void stop3DSound(int id); //Stops a 3D sound.
        void stopAll2DSounds(); //Stops all 2D sounds.
        void stopAll3DSounds(); //Stops all 3D sounds.
        void stopAllSounds(); //Stops ALL sounds.
 
        //Setters
        void setMasterVolume(float vol); //Sets the master volume.
        void setListenCamera(ICameraSceneNode* cam); //Sets the 3D listening camera.
 
        //Getters
        float getMasterVolume(); //Gets the master volume.
        ICameraSceneNode* getListenCamera(); //Returns the 3D listening camera.
        bool getAreSoundsLoaded(); //Returns whether or not sounds are loaded.
        sound_instance_2d* get2DSoundInstance(int id); //Gets the 2D sound instance.
        sound_instance_3d* get3DSoundInstance(int id); //Gets the 3D sound instance.
 
    private:
        IrrlichtDevice* irrdevice;
        IFileSystem* irrio;
 
        float master_volume; //Main volume.
        ICameraSceneNode* listencam; //The camera where the 3D listener is.
        bool sounds_loaded; //Are the sounds loaded in?
 
        stringc sound_bank[100]; //The list of sounds, loaded into memory.
 
        sound_instance_2d* sounds2d[100]; //List of currently playing 2D sounds.
        sound_instance_3d* sounds3d[100]; //List of currently playing 3D sounds.
};
 
#endif
 
sound_manager.cpp

Code: Select all

#include "sound_manager.h"
 
using namespace std;
using namespace irr;
using namespace core;
using namespace video;
using namespace io;
using namespace scene;
using namespace gui;
 
HSTREAM createSoundHandle(IReadFile* snd, DWORD flags)
{
    void* buffer = malloc(snd->getSize());
    snd->read(buffer, snd->getSize());
    HSTREAM tmp_snd = BASS_StreamCreateFile(true, buffer, 0, snd->getSize(), flags);
 
    return tmp_snd;
}
 
sound_instance_2d::sound_instance_2d()
{
    soundID = -1;
    soundInstance = -1;
    handle = 0;
    file_handle = 0;
    loop = false;
}
 
sound_instance_3d::sound_instance_3d()
{
    soundID = -1;
    soundInstance = -1;
    handle = 0;
    file_handle = 0;
    node = 0;
    loop = false;
}
 
sound_manager::sound_manager(IrrlichtDevice* irrdv, float basevol)
{
    irrdevice = irrdv;
    irrio = irrdevice->getFileSystem();
    setMasterVolume(basevol);
    listencam = 0;
    sounds_loaded = false;
    for(int i=0;i<100;i++)
    {
        sound_bank[i] = "";
        sounds2d[i] = 0;
        sounds3d[i] = 0;
    }
 
    BASS_3DVECTOR pos;
    pos.x = 0;
    pos.y = 0;
    pos.z = 0;
    BASS_Set3DPosition(&pos, &pos, &pos, &pos);
}
 
sound_manager::~sound_manager()
{
    unloadSounds();
}
 
void sound_manager::update()
{
    if(sounds_loaded)
    {
        for(int i=0;i<100;i++)
        {
            //2D
            if(sounds2d[i])
            {
                HSTREAM whndle = sounds2d[i]->handle;
                if(BASS_ChannelGetPosition(whndle, BASS_POS_BYTE) == BASS_ChannelGetLength(whndle, BASS_POS_BYTE))
                {
                    if(sounds2d[i]->loop)
                    {
                        BASS_ChannelPlay(whndle, true);
                    }
                    else
                    {
                        stop2DSound(i);
                    }
                }
            }
 
            //Handle listener.
            if(listencam)
            {
                vector3df cpos = listencam->getAbsolutePosition();
                vector3df ctargpos = listencam->getTarget();
                vector3df cup = listencam->getUpVector();
 
                BASS_3DVECTOR pos, targ, up;
                pos.x = cpos.X;
                pos.y = cpos.Y;
                pos.z = cpos.Z;
                targ.x = ctargpos.X;
                targ.y = ctargpos.Y;
                targ.z = ctargpos.Z;
                up.x = cup.X;
                up.y = cup.Y;
                up.z = cup.Z;
 
                BASS_Set3DPosition(&pos, 0, &targ, &up);
            }
            else
            {
                BASS_3DVECTOR pos;
                pos.x = 0;
                pos.y = 0;
                pos.z = 0;
                BASS_Set3DPosition(&pos, &pos, &pos, &pos);
            }
 
            //3D
            if(sounds3d[i])
            {
                HSTREAM whndle = sounds3d[i]->handle;
 
                BASS_3DVECTOR tmpps;
                tmpps.x = sounds3d[i]->node->getAbsolutePosition().X;
                tmpps.y = sounds3d[i]->node->getAbsolutePosition().Y;
                tmpps.z = sounds3d[i]->node->getAbsolutePosition().Z;
                BASS_ChannelSet3DPosition(whndle, &tmpps, 0, 0);
 
                if(BASS_ChannelGetPosition(whndle, BASS_POS_BYTE) == BASS_ChannelGetLength(whndle, BASS_POS_BYTE))
                {
                    if(sounds3d[i]->loop)
                    {
                        BASS_ChannelPlay(whndle, true);
                    }
                    else
                    {
                        stop3DSound(i);
                    }
                }
            }
        }
 
        BASS_Apply3D();
    }
}
 
void sound_manager::loadSounds()
{
    if(!sounds_loaded)
    {
        sound_bank[0] = "menumusic.mp3";
        sound_bank[1] = "button_click.mp3";
        sound_bank[2] = "button_hover.mp3";
        sound_bank[3] = "forestambience.mp3";
        sound_bank[4] = "monsterspot.mp3";
        sound_bank[5] = "monsterchasemusic.mp3";
        sound_bank[6] = "creditsmusic.mp3";
        sound_bank[7] = "pony_walking.mp3";
        sound_bank[8] = "pony_running.mp3";
 
        sounds_loaded = true;
    }
}
 
void sound_manager::unloadSounds()
{
    if(sounds_loaded)
    {
        stopAllSounds();
 
        for(int i=0;i<100;i++)
        {
            if(sound_bank[i] != "")
            {
                sound_bank[i] = "";
            }
        }
 
        sounds_loaded = false;
    }
}
 
int sound_manager::play2DSound(int id, float vol, bool loop)
{
    int slot_num = -1;
    if(sounds_loaded && sound_bank[id] != "")
    {
        if(vol >= 0 && vol <= 1)
        {
            for(int i=0;i<100;i++)
            {
                if(!sounds2d[i])
                {
                    slot_num = i;
 
                    sounds2d[i] = new sound_instance_2d();
                    sounds2d[i]->soundID = id;
                    sounds2d[i]->soundInstance = i;
                    sounds2d[i]->loop = loop;
                    sounds2d[i]->file_handle = irrio->createAndOpenFile(sound_bank[id].c_str());
                    sounds2d[i]->handle = createSoundHandle(sounds2d[i]->file_handle);
 
                    float newvol = vol;
                    if(newvol > master_volume)
                    {
                        newvol = master_volume;
                    }
                    else
                    {
                        newvol = vol * master_volume;
                    }
 
                    BASS_ChannelSetAttribute(sounds2d[i]->handle, BASS_ATTRIB_VOL, newvol);
 
                    BASS_ChannelPlay(sounds2d[i]->handle, true);
                    break;
                }
            }
        }
    }
 
    return slot_num;
}
 
int sound_manager::play3DSound(int id, ISceneNode* node, float dist, float vol, bool loop)
{
    int slot_num = -1;
    if(sounds_loaded && sound_bank[id] != "")
    {
        if(vol >= 0 && vol <= 1)
        {
            for(int i=0;i<100;i++)
            {
                if(!sounds3d[i])
                {
                    slot_num = i;
 
                    sounds3d[i] = new sound_instance_3d();
                    sounds3d[i]->soundID = id;
                    sounds3d[i]->soundInstance = i;
                    sounds3d[i]->loop = loop;
                    sounds3d[i]->node = node;
                    sounds3d[i]->file_handle = irrio->createAndOpenFile(sound_bank[id].c_str());
                    sounds3d[i]->handle = createSoundHandle(sounds3d[i]->file_handle, BASS_SAMPLE_3D);
 
                    BASS_3DVECTOR tmpps;
                    tmpps.x = node->getAbsolutePosition().X;
                    tmpps.y = node->getAbsolutePosition().Y;
                    tmpps.z = node->getAbsolutePosition().Z;
 
                    BASS_ChannelSet3DAttributes(sounds3d[i]->handle, -1, dist, 0, 360, 360, 0);
                    BASS_ChannelSet3DPosition(sounds3d[i]->handle, &tmpps, 0, 0);
 
                    float newvol = vol;
                    if(newvol > master_volume)
                    {
                        newvol = master_volume;
                    }
                    else
                    {
                        newvol = vol * master_volume;
                    }
 
                    BASS_ChannelSetAttribute(sounds3d[i]->handle, BASS_ATTRIB_VOL, newvol);
 
                    BASS_ChannelPlay(sounds3d[i]->handle, true);
                    break;
                }
            }
        }
    }
 
    return slot_num;
}
 
void sound_manager::stop2DSound(int id)
{
    if(sounds_loaded)
    {
        if(sounds2d[id])
        {
            BASS_ChannelStop(sounds2d[id]->handle);
            BASS_StreamFree(sounds2d[id]->handle);
            sounds2d[id]->file_handle->drop();
            sounds2d[id] = 0;
        }
    }
}
 
void sound_manager::stop3DSound(int id)
{
    if(sounds_loaded)
    {
        if(sounds3d[id])
        {
            BASS_ChannelStop(sounds3d[id]->handle);
            BASS_StreamFree(sounds3d[id]->handle);
            sounds3d[id]->file_handle->drop();
            sounds3d[id] = 0;
        }
    }
}
 
void sound_manager::stopAll2DSounds()
{
    for(int i=0;i<100;i++)
    {
        stop2DSound(i);
    }
}
 
void sound_manager::stopAll3DSounds()
{
    for(int i=0;i<100;i++)
    {
        stop3DSound(i);
    }
}
 
void sound_manager::stopAllSounds()
{
    stopAll2DSounds();
    stopAll3DSounds();
}
 
void sound_manager::setMasterVolume(float vol)
{
    if(vol >= 0 && vol <= 1)
    {
        master_volume = vol;
    }
}
 
void sound_manager::setListenCamera(ICameraSceneNode* cam)
{
    listencam = cam;
}
 
float sound_manager::getMasterVolume()
{
    return master_volume;
}
 
ICameraSceneNode* sound_manager::getListenCamera()
{
    return listencam;
}
 
bool sound_manager::getAreSoundsLoaded()
{
    return sounds_loaded;
}
 
sound_instance_2d* sound_manager::get2DSoundInstance(int id)
{
    return sounds2d[id];
}
 
sound_instance_3d* sound_manager::get3DSoundInstance(int id)
{
    return sounds3d[id];
}
 
hybrid
Admin
Posts: 14144
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Re: How can I make BASS 3D sounds match Irrlicht's coords?

Post by hybrid »

Actually, Irrlicht uses a left-handed coord system as well. And in case you still have to convert: You can switch from right-handed to left.handed by negating any one coord, so you have to check the exact coord orientation. Irrlicht has y-up, which gives z-axis into the screen. So check where your app has the axes and how you have to flip them.
Ruxify
Posts: 33
Joined: Tue Oct 16, 2012 12:37 am

Re: How can I make BASS 3D sounds match Irrlicht's coords?

Post by Ruxify »

hybrid wrote:Actually, Irrlicht uses a left-handed coord system as well. And in case you still have to convert: You can switch from right-handed to left.handed by negating any one coord, so you have to check the exact coord orientation. Irrlicht has y-up, which gives z-axis into the screen. So check where your app has the axes and how you have to flip them.
Oh ok, it's just that I read somewhere on these forums that it was right handed. I'll fiddle with the values and hopefully it'll come out right.

EDIT: Well, I give up. I'm going to try and switch my game over to the irrKlang library. I didn't use it in the first place cause for some reason I thought you had to buy it to use it at all. :oops:
hybrid
Admin
Posts: 14144
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Re: How can I make BASS 3D sounds match Irrlicht's coords?

Post by hybrid »

No, OpenGL is right-handed by default, but in Irrlicht all coords are left-handed, as are the rotations. On the BASS forums, you can also find one reference to a guy who tried to use BASS with OpenGL and failed to position things correctly. Unfortunately, he didn't get any answer to his questions, either. So it seems that you have to grab through the BASS manual, try things with code tests, or switch the library as you suggested. I think the problem is the orientation and also the correct handling of all vectors you use with BASS (i.e. forward vector and positions). Anyway, irrKlang should do as well, unless you need some special effects that only BASS provides.
Post Reply