2018-05-24 22:18:45

Hi there. A while ago i downloaded tdv's sourcecode and found the bpc shared component there and i've got a question about the dsound class. When i learnt how the library works, I wrote a wrapper for it which i'll be pasting the code below. Then tryed to make a simple thing where you move around and a sound loops and updates as you move but this thing gave me errors when setting sound's orientation. This one seems different than other libraries that i have seen. BPC wrapper code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BPCSharedComponent;
using BPCSharedComponent.ExtendedAudio;
using SharpDX;
using SharpDX.DirectInput;
using SharpDX.DirectSound;

namespace bpc_wrapper
    {
    public class audio
    {
        public  string soundpath;
        public  double max_distance;
        public  double min_distance;
        private         List<SecondarySoundBuffer> soundlist = new List<SecondarySoundBuffer>();
private         int slot;
        public audio(IntPtr handel,  bool encrypted,  string ss = "", string root="", string encryption_key="")
        {
            soundpath = ss;
            if (encrypted == false)
                DSound.initialize(handel, root);
            else
            {
                DSound.initialize(handel, encrypted, root);
                            }
                DSound.initializeOgg();
            DSound.SoundPath = soundpath;
                    }
        public  int play_stationary(string soundfile, bool closefirst=false, bool looping=false)
        {
            soundlist.Add(DSound.LoadSound(soundpath+"/"+soundfile));
            DSound.PlaySound(soundlist left braket soundlist.Count - 1 right braket , closefirst, looping);
            return soundlist.Count - 1;
        }
        public  void setOrientation(double x1, double y1, double z1,
            double x2, double y2, double z2)
        {
            DSound.setOrientation(x1, y1, z1, x2, y2, z2);
        }
public  int play_3d(string filename, double x, double y, double z, bool closefirst=false, bool looping=false)
        {
            soundlist.Add(DSound.LoadSound3d(soundpath+"/"+filename, min_distance, max_distance, true));
            DSound.PlaySound3d(soundlist left braket soundlist.Count - 1 right braket , closefirst, looping, x, y, z);
            return soundlist.Count - 1;
        }
        public  void update_listener(double x, double y, double z)
        {
            DSound.SetCoordinates(x, y, z);
        }
        public  bool is_playing(int index)
        {
            return DSound.isPlaying(soundlist left braket index right braket );
        }
        public  bool is_looping(int index)
        {
            return DSound.isLooping(soundlist left braket index right braket );
        }
        public  void playwait(string fn)
        {
            DSound.playAndWait(fn);
        }
        public  void setRootDirectory(string root)
        {
            DSound.setRootDirectory(root);
                    }
public  void cleanup()
        {
            DSound.cleanUp();
            for(int i=0; i<soundlist.Count; i++)
            {
                if (soundlist left braket i right braket  != null)
                {
                    soundlist left braket i right braket .Dispose();
                    soundlist left braket i right braket  = null;
                }
            }
        }
    }
}
Although this code have a fiew extra useless parts that i should remove but it doesn't make any problems in the runtime from what i know.
And here is the test class i wrote:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using bpc_wrapper;
using System.Windows.Input;
namespace bpc_wrapper_test
{
    public partial class Form1 : Form
    {
        System.Diagnostics.Stopwatch walktimer = new System.Diagnostics.Stopwatch();
        audio aud;
        double x, y, z;
        private void timer1_Tick(object sender, EventArgs e)
        {
            mainloop();
        }

        public Form1()
        {
            InitializeComponent();
            x = 1.0;
            y = 1.0;
           
           
            aud = new audio(this.Handle, false, "sounds");
            aud.min_distance = 5;
            aud.max_distance = 50;
            aud.update_listener(x, y, z);
            aud.play_3d("tm.wav", 1, 1, 1, false, true);
                        walktimer.Start();
        }
        void mainloop()
        {
                aud.update_listener(x, y, z);
                        if (walktimer.ElapsedMilliseconds >= 100)
            {
                if (Keyboard.IsKeyDown(Key.Down))
                {
                    walktimer.Restart();
                    y -= 1;
                }
                if (Keyboard.IsKeyDown(Key.Up))
                {
                    walktimer.Restart();
                    y += 1;
                                    }
                if (Keyboard.IsKeyDown(Key.Left))
                {
                    walktimer.Restart();
                    x -= 1;
                }
                if (Keyboard.IsKeyDown(Key.Right))
                {
                    walktimer.Restart();
                    x += 1;
                                                }
                updateRotation();
            }
            void updateRotation()
            {
                double X = this.x, Y = this.y, Z = this.z;
                aud.setOrientation(0.0, 0.0, 1.0, 0.0, 0.0, 1.0); //I didn't want to do this but just for test. Anyways I couldn't get x or y or z(all three values) to 0 as you can see. It raises a sharp dx error which i really don't understand why it can't handle them all as 0 and thus when i update the orientation when i'm moving, if i step on x/y 0 the program raises an exception.
}
        }
        }
}
I had to replace left brakets with " left braket " and right brakets with " right braket " to avoid forum warnings.
Thanks for reading. Any help really is a pritiated because it's likely the best wrapper i have ever found for sharp dx sound.

---
Co-founder of Sonorous Arts.
Check out Sonorous Arts on github: https://github.com/sonorous-arts/
my Discord: kianoosh.shakeri2#2988

2018-05-25 14:27:33

hi kianoosh,
I'm glad you're enjoying the library and hope you have fun with it! That's super cool that someone's using my shared component dll smile

Are you trying to set the orientation to 0, and this is where you're having issues? Please answer here so I can help you further.

2018-05-25 14:43:48 (edited by Munawar 2018-05-25 14:51:21)

Ok, I saw the last comment you left in your code. The thing is you're trying to set position on your listener object but you're using the orientation to do it.

A listener's orientation and position are different. You can use DSound.setCoordinates(x,y,z) to set the actual x, y and z position of the listener, as you're doing at the top of your mainloop function.

The setOrientation method turns the listener but doesn't actually change its position.

The reason you're getting an error is because the orientation is made up of two unit vectors. If you set them to the zero vector, the listener has nowhere to face.

I would recommend you to play with setCoordinates rather than setOrientation, unless you want to simulate turning the player left and right. If you do want to turn the player, I'll elaborate on how to do this properly. But for now, it seems like all you want to do is adjust the listener's position. So, keep the listener's orientation as the default (by setting the front vector to (0.0, 0.0, 1.0) and the top vector to (0.0, 1.0, 0.0).)

2018-05-25 14:54:46 (edited by kianoosh 2018-05-25 14:55:48)

Oh thanks Munawar. The thing is i'm planning to code a simple game with rotational support. I mean i was already doing it but had no success because the library that i was using was a bit strange, it's orientation setting function was seemed to be bugged but when i found your library i said that's the thing i want! Ok I have an integer in my game that represents the facing of the player in degrees. I've read that the orientation setting is like this: e.g in your library dsound.setOrientation(math.sine(facing), math.cos(facing), 0.0, 0.0, 0.0, 1.0);
Is this correct or it's something different?
Thanks for being so helpful to me smile

---
Co-founder of Sonorous Arts.
Check out Sonorous Arts on github: https://github.com/sonorous-arts/
my Discord: kianoosh.shakeri2#2988

2018-05-25 15:52:00 (edited by Munawar 2018-05-25 15:58:28)

Hi kianoosh,
No problem! I'm happy to help where I can smile

You're close with your code. You only have to do two things:
First, make sure your direction value is in radians:

d = d * 2.0 * Math.PI / 360.0;

or

d = d * Math.PI / 180.0;

Next, keep in mind that the orientation of the listener is a unit vector with an x, y and z property, and switch around the Sin and Cos functions. I'll show you the code a little later, but I'll explain first. The x value notes where the listener's front is facing from left to right. The y value notes where the listener's front is facing North to South, and the z value notes where the listener's front is facing relative to front and back (we often say it notes how far away something is from you.)

I usually explain it like this: imagine laying your monitor flat on your desk. If you were to travel left and right, you're noting the x orientation of the listener; if you travel up and down your monitor, you're traveling along the y axis; and if you travel from your monitor to the ground, you're traveling along the z axis.

Now if you put your monitor up again, you'll see that the x and z axis together define how the listener rotates according to your soundscape. So, we have to rotate the listener's orientation around the y axis to get our results. Think of it like sticking a pole straight up through your monitor. That pole is what the listener will turn around. If we consider the default front vector of (0.0, 0.0, 1.0) we can see that the listener is facing into the monitor.



So, what we want to do is modify the x and z values of the listener, and leave the y value the same (0.0.)

Putting all this together, you'd set your orientation like this:

setOrientation(Math.Cos(d), // the front vector-x unit, get the x component of your direction vector
  0.0, // The front vector-y unit
  Math.Sin(d), // The front vector-z unit, get the y component of your direction vector
  0.0, 1.0, 0.0) // The default top-facing vector.

I hope this helps!

2018-05-25 15:55:00

Thanks a lot dude. You cleared many things for me.

---
Co-founder of Sonorous Arts.
Check out Sonorous Arts on github: https://github.com/sonorous-arts/
my Discord: kianoosh.shakeri2#2988

2018-05-25 16:05:14

You're welcome. Good luck with your vectoring ventures xD

2018-05-25 16:17:59

Oh i'm sorry but there's a thing. I don't know what this way is called but my rotation is look like this. 0 is north, 90 is east, 180 is south and 270 is west. But the formula you just provided has the other way where 90 degrees is north, i think 45 is northeast, 135 is northwest, etc. Would you help me in the way i calculate my rotation, I can't use the way you provided because i don't know sine and CoSine and got the movement formulas from my other friend and it's for the way where 0 is north, etc. Thanks

---
Co-founder of Sonorous Arts.
Check out Sonorous Arts on github: https://github.com/sonorous-arts/
my Discord: kianoosh.shakeri2#2988

2018-05-25 16:39:13 (edited by Munawar 2018-05-25 16:41:23)

Yup, you're using naval directions. In shared/BPCSharedComponent/Degrees.cs, there's a function that will help you. It will convert your naval directions into standard degrees.

        private const Int16 m_North = 0;
        private const Int16 m_East = 90;
        private const Int16 m_South = 180;
        private const Int16 m_West = 270;
        private const Int16 m_NorthEast = 45;
        private const Int16 m_NorthWest = 315;
        private const Int16 m_SouthEast = 135;
        private const Int16 m_SouthWest = 225;

        //the following properties return the constant degree values for cardinal and subcardinal directions.
        //Note: this class runs under the assumption that 0.0 represents North, and progressing
        //degree values are in the clockwise direction.
        //Thus, East is 90.0 degrees.
        public static Int16 NORTH
        {
            get { return (m_North); }
        }
        public static Int16 EAST
        {
            get { return (m_East); }
        }
        public static Int16 SOUTH
        {
            get { return (m_South); }
        }
        public static Int16 WEST
        {
            get { return (m_West); }
        }
        public static Int16 NORTHEAST
        {
            get { return (m_NorthEast); }
        }
        public static Int16 SOUTHEAST
        {
            get { return (m_SouthEast); }
        }
        public static Int16 SOUTHWEST
        {
            get { return (m_SouthWest); }
        }
        public static Int16 NORTHWEST
        {
            get { return (m_NorthWest); }
        }

        //Adjusts a given degree value,
        //such that the returned value is shifted 90 degrees counterclockwise.
        private static int adjustDirection(int dir)
        {
            if (dir >= NORTH & dir <= EAST)
            {
                dir = 90 - dir;
            }
            else if (dir > EAST & dir <= SOUTH)
            {
                dir = 180 - dir + 270;
            }
            else if (dir > SOUTH & dir <= WEST)
            {
                dir = 270 - dir + 180;
            }
            else if (dir > WEST & dir <= 359)
            {
                dir = 359 - dir + 1 + 90;
            }
            return (dir);
        }

2018-05-25 16:55:28

I thought that 0 for north, 90 for east, 180 for south and 270 for west was a\ standard, I never knew there were other ways to measure it.

Facts with Tom MacDonald, Adam Calhoun, and Dax
End racism
End division
Become united

2018-05-25 17:05:29

The tricky thing is that it makes sense to use those values as cardinal directions, but the unit circle uses 0 for conceptual "East" and 90 for conceptual "North," because the degrees start from the bottom right side of the circle and progress positively while traveling anticlockwise around the circle.

2018-05-25 18:29:43

I did everything you told me but it is still not panning the sound correctly. assume that the sound is on 1 1 0 and the player is on 0 1 0, with the facing set to east(90 degrees). It should pan the sound to the left as player moves with right arrow but it simpley doesn't. Movement code is correct, it moves correctly. Here is the code:
void mainloop()
        {
                aud.update_listener(me.x, me.y, me.z);
                        if (walktimer.ElapsedMilliseconds >= 100)
            {
                if (Keyboard.IsKeyDown(Key.S))
                {
                    walktimer.Restart();
me=                                        r.move(me.x, me.y, me.z, r.turnleft(facing, 180.0), 0.0);
                }
                if (Keyboard.IsKeyDown(Key.W))
                {
                    walktimer.Restart();
                    me = r.move(me.x, me.y, me.z, facing, 0.0);
                                    }
                if (Keyboard.IsKeyDown(Key.A))
                {
                    walktimer.Restart();
                    me = r.move(me.x, me.y, me.z, r.turnleft(facing, 90), 0.0);
                }
                if (Keyboard.IsKeyDown(Key.D))
                {
                    walktimer.Restart();
                    me = r.move(me.x, me.y, me.z, r.turnright(facing, 90), 0.0);
                                                }
                if (kptimer.ElapsedMilliseconds >= 500)
                {
                    if(Keyboard.IsKeyDown(Key.C))
                    {
                        kptimer.Restart();
                        Tolk.Output(me.x + ", " + me.y + ", " + me.z);
                    }
                    if(Keyboard.IsKeyDown(Key.F))
                        {
                        kptimer.Restart();
                        Tolk.Output("facing " + facing + " degrees");
                    }
                }
                if (acttimer.ElapsedMilliseconds >= 25)
                {
                    if (Keyboard.IsKeyDown(Key.Left))
                    {
                        acttimer.Restart();
                        facing = r.turnleft(facing, 3);
                    }
                    if (Keyboard.IsKeyDown(Key.Right))
                    {
                        acttimer.Restart();
                        facing = r.turnright(facing, 3);
                    }
                                    }
                updateRotation();
            }
            void updateRotation()
            {
                                double xa = calculate_rad(facing);
                double xaa = r.adjustDirection(xa);
                aud.setOrientation(Math.Cos(xaa), 0.0, Math.Sin(xaa), 0.0, 1.0, 0.0);
                //aud.setOrientation(Math.Sin(xa), Math.Cos(xa), 0.0, 0.0, 1.0, 0.0);
            }
            double calculate_rad(double d)
            {
                return d * Math.PI / 180.0;
            }
And here is the class that the movement and some other stuff are handeled in it:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace bpc_wrapper_test
{
    public class rotation
    {
        public double pi;
        public double theta;
        const int north = 0;
        const int northeast = 45;
        const int east = 90;
        const int southeast = 135;
        const int south = 180;
        const int southwest = 225;
        const int west = 270;
        const int northwest = 315;
        const int half_up = 45;
        const int straight_up = 90;
        const int half_down = 135;
        const int straight_down = 180;

        public rotation()
        {
            pi = 3.1415926535897932384626433832795;
        }
        public Form1.vector move(double x, double y, double z, double deg, double zdeg)
        {
            Form1.vector temp;
            double newx, newy, newz;
            newx = x + Math.Sin(calculate_theta(deg));
            newy = y + Math.Cos(calculate_theta(deg));
            newz = z + Math.Sin(calculate_theta(zdeg));
            newx = Math.Round(newx, 2);
            newy = Math.Round(newy, 2);
            newz = Math.Round(newz, 2);
            temp.x = (float)newx;
            temp.y = (float)newy;
            temp.z = (float)newz;

            /*
            if (Form1.self.m.getwall(newx, newy, newz) != "")
            {
                Form1.self.engine.Play3D("sounds/walls/wall" + Form1.self.m.getwall(newx, newy, newz) + ".ogg", temp.x, temp.y, temp.z, false);
                temp.x = (float)x;
                temp.y = (float)y;
                temp.z = (float)z;
            }
            */
            return temp;
        }
        public double calculate_theta(double deg)
        {
            return deg * pi / 180;
        }
        public double getdir(double facing)
        {
            if (facing >= north && facing < northeast)
            {
                return north;
            }
            if (facing >= northeast && facing < east)
            {
                return northeast;
            }
            if (facing >= east && facing < southeast)
            {
                return east;
            }
            if (facing >= southeast && facing < south)
            {
                return southeast;
            }
            if (facing >= south && facing < southwest)
            {
                return south;
            }
            if (facing >= southwest && facing < west)
            {
                return southwest;
            }
            if (facing >= west && facing < northwest)
            {
                return west;
            }
            if (facing >= northwest)
            {
                return northwest;
            }
            return -1;
        }

        public double snapleft(double deg, int direction, double inc = 45)
        {
            double d = direction - inc;
            if (d < 0)
                d += 360;
            if (d == 360)
                d = 0;
            return d;
        }
        public double snapright(double deg, int direction, double inc = 45)
        {
            double d = direction + inc;
            if (d >= 360)
                d -= 360;
            return d;
        }
        public double turnleft(double deg, double inc)
        {
            deg -= inc;
            if (deg < 0)
                deg += 360;
            return deg;
        }
        public double turnright(double deg, double inc)
        {
            deg += inc;
            if (deg >= 360)
                deg -= 360;
            return deg;
        }
        public double adjustDirection(double dir)
        {
            if (dir >= north & dir <= east)
            {
                dir = 90 - dir;
            }
            else if (dir > east & dir <= south)
            {
                dir = 180 - dir + 270;
            }
            else if (dir > south & dir <= west)
            {
                dir = 270 - dir + 180;
            }
            else if (dir > west & dir <= 359)
            {
                dir = 359 - dir + 1 + 90;
            }
            return (dir);
        }
    }
}
form1.vector is a struct in the form1 class
struct vector {
public Flote x;
public Flote y;
public Flote z;
}
Sorry for asking this many questions. I Really want to turn this to a nice fps like game if i succeed with the sound's orientation haha

---
Co-founder of Sonorous Arts.
Check out Sonorous Arts on github: https://github.com/sonorous-arts/
my Discord: kianoosh.shakeri2#2988

2018-05-25 19:48:39

Test your x, y and z values. Are they updating?

Are you using the moveObject function from Degrees.cs? If so, keep in mind that x, y and z are reference parameters.

2018-05-25 19:51:21

Yes they are updating and i'm not using that function since i don't know what it does exactly

---
Co-founder of Sonorous Arts.
Check out Sonorous Arts on github: https://github.com/sonorous-arts/
my Discord: kianoosh.shakeri2#2988

2018-05-25 20:08:34 (edited by Munawar 2018-05-25 20:27:29)

If the source is at (1,1,0) and the player is at (0,1,0), with an orientation vector of (1, 0, 0) (East), as the player moves East, they will approach the sound. So, the sound will not be to the left or right of your listener, because the listener is facing forward along the positive x axis. In other words, they're facing the sound source.

2018-05-25 20:35:29 (edited by kianoosh 2018-05-25 20:36:59)

No no i think i couldn't explane it correctly. Asume the player is faced at 90 degrees, andhas a vector direction of 1.0, 0.0, 0.0 which is eastwards. So since we can walk with up, down, right and left arrow keys, each key moves in the coresponding direction. Like if they press up arrow player goes one step to the east(where it is facing). If they press right arrow they go one step to the south, if they press down arrow they go one step to the west and pressing left arrow takes them to the north. So when the sound is on 1 1 0, and the player is on 0 1 0, pressing right arrow moves player to 0 0 0 thus the sound should pan to the left side of the player(in case of facing being east) or if they press left arrow they go to 0 2 0 and the sound should pan to their right side. But this doesn't happen. It works only when the facing is set to north(vector is 0.0, 1.0, 0.0). so if they move left or right the sound pans correctly acording to their direction
How ever i think it is happening cause of the upvector i set it to 0.0, 1.0, 1.0 and it kind of did work but verse. Like when the facing is east pressing left arrow would pan the sound ot the left side and pressing right arrow would pan it to the right side which is exactly verse.

---
Co-founder of Sonorous Arts.
Check out Sonorous Arts on github: https://github.com/sonorous-arts/
my Discord: kianoosh.shakeri2#2988

2018-05-25 20:47:32

Oh Weird i was experrementing and fixed it on accident. I set the z parameter of up vector to -1.0 and it got fixed. IDK why but it did. Anyways thanks for all your helps and your patients against my infinet questions haha

---
Co-founder of Sonorous Arts.
Check out Sonorous Arts on github: https://github.com/sonorous-arts/
my Discord: kianoosh.shakeri2#2988

2018-05-25 21:27:40 (edited by Munawar 2018-05-25 21:29:10)

Oh ok, I see what you're trying to do now

Make sure you're passing the right values for x, y, and z to the sound's position coordinates. As it stands now,, the source sound is at (1,1,0) and the player is at (0,0,0). I'm assuming here the listener is also positioned at (0,0,0). In this case, the source sound is said to be "above" the player, not beside the player, because the y axis travels upward in the soundscape.

Set your source sound to position (1, 0, 1) and the listener's position to (0,0,0). This way, the sound is to the left of the listener because positive z values increase traveling forward further into the monitor. This is also assuming your listener is facing East.

Keep in mind the monitor example I gave in post #5, where we raised the monitor back up and established that the y axis travels upward through the top of the monitor.

So, to accomplish your task, when setting sound and listener positions, keep your y values at 0 and pass the y coordinate as the z value. For example, an object positioned at (2,3,0) would emit a sound at .SetPosition(2,0,3).