From b7d6ae781c4075a5481b2ddf592d1632df3c4d77 Mon Sep 17 00:00:00 2001 From: athomas Date: Tue, 8 Jul 2003 20:16:34 +0000 Subject: fill justified the paragraphs in the tutorials git-svn-id: file:///home/mbien/NetBeansProjects/JOGAMP/joal-sync/svn-server-sync-demos/joal-demos/trunk@33 235fdd13-0e8c-4fed-b5ee-0a390d04b286 --- www/devmaster/lesson6.html | 141 ++++++++++++++------------- www/devmaster/lesson7.html | 238 +++++++++++++++++++++++---------------------- 2 files changed, 194 insertions(+), 185 deletions(-) diff --git a/www/devmaster/lesson6.html b/www/devmaster/lesson6.html index 3a0c5ee..36e3660 100644 --- a/www/devmaster/lesson6.html +++ b/www/devmaster/lesson6.html @@ -32,16 +32,17 @@ OpenAL Tutorials from DevMaster.net. Reprinted with Permission.

Author: Jesse Maurais
Adapted For Java By: Athomas Goldberg

-

We've been doing some pretty simple stuff up until now that didn't require - us to be very precise in the way we've handled things. The reason for this is - that we have been writing code for simplicity in order to learn easier, rather - that for robustness. Since we are going to move into some advanced stuff soon - we will take some time to learn the proper ways. Most importantly we will learn - a more advanced way of handling errors. We will also reorganize the way we have - been loading audio data. There wasn't anything wrong with our methods in particular, - but we will need a more organized and flexible approach to the process.

-

We will first consider a few functions that will help us out a lot by the time - we have finished.

+

We've been doing some pretty simple stuff up until now that + didn't require us to be very precise in the way we've handled things. The reason + for this is that we have been writing code for simplicity in order to learn + easier, rather that for robustness. Since we are going to move into some advanced + stuff soon we will take some time to learn the proper ways. Most importantly + we will learn a more advanced way of handling errors. We will also reorganize + the way we have been loading audio data. There wasn't anything wrong with our + methods in particular, but we will need a more organized and flexible approach + to the process.

+

We will first consider a few functions that will help us out + a lot by the time we have finished.

/**
  * 1) Identify the error code.
  * 2) Return the error as a string.
@@ -99,13 +100,13 @@ public static int loadALBuffer(String path) throws<
 private static Vector buffers = new Vector(); // Holds all loaded buffers.
 private static Vector sources = new Vector(); // Holds all validated sources.
 
-

Take a close look at the functions and try to understand what we are going - to be doing. Basically what we are trying to create is a system in which we - no longer have to worry about the relationship between buffers and sources. - We can call for the creation of a source from a file and this system will handle - the buffer's creation on it's own so we don't duplicate a buffer (have two buffers - with the same data). This system will handle the buffers as a limited resource, - and will handle that resource efficiently.

+

Take a close look at the functions and try to understand what + we are going to be doing. Basically what we are trying to create is a system + in which we no longer have to worry about the relationship between buffers and + sources. We can call for the creation of a source from a file and this system + will handle the buffer's creation on it's own so we don't duplicate a buffer + (have two buffers with the same data). This system will handle the buffers as + a limited resource, and will handle that resource efficiently.

public String getALErrorString(int err) {
     switch(err) {
         case AL.AL_NO_ERROR: return "AL_NO_ERROR";
@@ -119,11 +120,11 @@ public static int loadALBuffer(String path) throws<
 }
 
 
-

This function will convert an OpenAL error code to a string so it can be read - on the console (or some other device). The OpenAL sdk says that the only exception - that needs be looked for in the current version is the 'AL_OUT_OF_MEMORY' error. - However, we will account for all the errors so that our code will be up to date - with later versions.

+

This function will convert an OpenAL error code to a string + so it can be read on the console (or some other device). The OpenAL sdk says + that the only exception that needs be looked for in the current version is the + 'AL_OUT_OF_MEMORY' error. However, we will account for all the errors so that + our code will be up to date with later versions.

public String getALCErrorString(int err) {
     switch(err) {
         case ALC_NO_ERROR: return "ALC_NO_ERROR";
@@ -137,14 +138,15 @@ public static int loadALBuffer(String path) throws<
 }
 
 
-

This function will perform a similar task as the previous one accept this one - will interpret Alc errors. OpenAL and Alc share common id's, but not common - enough and not dissimilar enough to use the same function for both.

-

One more note about the function 'alGetError': The OpenAL sdk defines that - it only holds a single error at a time (i.e. there is no stacking). When the - function is invoked it will return the first error that it has received, and - then clear the error bit to 'AL_NO_ERROR'. In other words an error will only - be stored in the error bit if no previous error is already stored there.

+

This function will perform a similar task as the previous one + accept this one will interpret Alc errors. OpenAL and Alc share common id's, + but not common enough and not dissimilar enough to use the same function for + both.

+

One more note about the function 'alGetError': The OpenAL sdk + defines that it only holds a single error at a time (i.e. there is no stacking). + When the function is invoked it will return the first error that it has received, + and then clear the error bit to 'AL_NO_ERROR'. In other words an error will + only be stored in the error bit if no previous error is already stored there.

public int loadALBuffer(String path) throws IOException {
     // Variables to store data which defines the buffer.
     int[] format = new int[1];
@@ -187,11 +189,12 @@ public static int loadALBuffer(String path) throws<
     return buffer[0];
 }
 
-

As you can see we do an error check at every possible phase of the load. Any - number of things can happen at this point which will cause an error to be thrown. - There could be no more system memory either for the buffer creation or the data - to be loaded, the wav file itself may not even exist, or an invalid value can - be passed to any one of the OpenAL functions which will generate an error.

+

As you can see we do an error check at every possible phase + of the load. Any number of things can happen at this point which will cause + an error to be thrown. There could be no more system memory either for the buffer + creation or the data to be loaded, the wav file itself may not even exist, or + an invalid value can be passed to any one of the OpenAL functions which will + generate an error.

public int getLoadedALBuffer(String path) throws IOException {
     int count = 0; // 'count' will be an index to the buffer list.
 
@@ -220,16 +223,16 @@ public static int loadALBuffer(String path) throws<
 }
 
 
-

This will probably be the piece of code most people have trouble with, but - it's really not that complex. We are doing a search through a list which contains - the file paths of all the wav's we have loaded so far. If one of the paths matches - the one we want to load, we will simply return the id to the buffer we loaded - it into the first time. This way as long as we consistently load our files through - this function, we will never have buffers wasted due to duplication. Every file - loaded this way must also be kept track of with it's own list. The 'buffers' - list is parallel to the 'loadedFiles' list. What I mean by this is that every - buffer in the index of 'buffers', is the same path of the index in 'loadedFiles' - from which that buffer was created.

+

This will probably be the piece of code most people have trouble + with, but it's really not that complex. We are doing a search through a list + which contains the file paths of all the wav's we have loaded so far. If one + of the paths matches the one we want to load, we will simply return the id to + the buffer we loaded it into the first time. This way as long as we consistently + load our files through this function, we will never have buffers wasted due + to duplication. Every file loaded this way must also be kept track of with it's + own list. The 'buffers' list is parallel to the 'loadedFiles' list. What I mean + by this is that every buffer in the index of 'buffers', is the same path of + the index in 'loadedFiles' from which that buffer was created.

public static int loadALSample(String path, boolean loop) throws IOException {
     int[] source = new int[1];
     int buffer;
@@ -260,11 +263,11 @@ public static int loadALBuffer(String path) throws<
     return source[0];
 }
 
-

Now that we have created a system which will handle the buffers for us, we - just need an extension to it that will get the sources. In this code we obtain - the result of a search for the file, which is the buffer id that the file was - loaded into. This buffer is bound to the new source. We save the source id internally - and also return it.

+

Now that we have created a system which will handle the buffers + for us, we just need an extension to it that will get the sources. In this code + we obtain the result of a search for the file, which is the buffer id that the + file was loaded into. This buffer is bound to the new source. We save the source + id internally and also return it.

public static void killALLoadedData() {
     loadedFiles.clear();
 }
@@ -287,13 +290,13 @@ public static int loadALBuffer(String path) throws<
 }
 
 
-

We have seen the function in previous tutorials. It will represent the part - of a program which loads all wav's used by the program. In it we can see why - our system is useful. Even though we have made a call to load the same wav file - into two distinct sources, the buffer for the file 'phaser.wav' will only be - created once, and the sources 'gPhaser1' and 'gPhaser2' will both use that buffer - for playback. There is no more concern for handling buffers because the system - will handle them automatically.

+

We have seen the function in previous tutorials. It will represent + the part of a program which loads all wav's used by the program. In it we can + see why our system is useful. Even though we have made a call to load the same + wav file into two distinct sources, the buffer for the file 'phaser.wav' will + only be created once, and the sources 'gPhaser1' and 'gPhaser2' will both use + that buffer for playback. There is no more concern for handling buffers because + the system will handle them automatically.

public static void killALData()
 {
     // Release all buffer data.
@@ -311,10 +314,10 @@ public static int loadALBuffer(String path) throws<
     sources.clear();
 }
 
-

All along we have been storing the buffer and source id's into stl vectors. - We free all the buffers and sources by going through them and releasing them - individually. After which we destroy the lists themselves. All we need to do - now is catch the OpenAL errors that we have thrown.

+

All along we have been storing the buffer and source id's into + stl vectors. We free all the buffers and sources by going through them and releasing + them individually. After which we destroy the lists themselves. All we need + to do now is catch the OpenAL errors that we have thrown.

    try {
         initOpenAL();
         loadALData();
@@ -323,14 +326,14 @@ public static int loadALBuffer(String path) throws<
     }
 
 
-

If something has gone wrong during the course of the load we will be notified - of it right away. When we catch the error it will be reported on the console. - We can use this for debugging or general error reporting.

-

That's it. A more advanced way of reporting errors, and a more robust way of - loading your wav files. We may find we need to do some modifications in the - future to allow for more flexibility, but for now we will be using this source - for basic file loading in future tutorials. Expect future tutorials to expand - on this code.

+

If something has gone wrong during the course of the load we + will be notified of it right away. When we catch the error it will be reported + on the console. We can use this for debugging or general error reporting.

+

That's it. A more advanced way of reporting errors, and a more + robust way of loading your wav files. We may find we need to do some modifications + in the future to allow for more flexibility, but for now we will be using this + source for basic file loading in future tutorials. Expect future tutorials to + expand on this code.

© 2003 DevMaster.net. diff --git a/www/devmaster/lesson7.html b/www/devmaster/lesson7.html index ddb54a3..4a716da 100644 --- a/www/devmaster/lesson7.html +++ b/www/devmaster/lesson7.html @@ -33,138 +33,144 @@ OpenAL Tutorials from DevMaster.net. Reprinted with Permission.
Maurais
Adapted For Java By: Athomas Goldberg

A Look at Real-World Physics

-

I know this will be boring review for anyone with a course in high school -physics, but lets humour ourselves. The Doppler effect can be a very tricky -concept for some people, but it is a logical process, and kind of interesting -when you get right down to it. To begin understanding the Doppler effect we -first must start to understand what a "sound" really is. Basically a sound is -your minds interpretation of a compression wave that is traveling through the -air. Whenever the air becomes disturbed it starts a wave which compresses the -air particles around it. This wave travels outward from it's point of origin. -Consider the following diagram.

-

In this diagram -(on the left) the big red "S" stands for the sources position, and the big -red "L" stands for (you guessed it), the Listener's position. Both source and -Listener are not moving. The source is emitting compression waves outward, which -are represented in this diagram by the blue circles. The Listener is -experiencing the sound exactly as it is being made in this diagram. The Doppler -effect is not actually present in this example since there is no motion; the -Doppler effect only describes the warping of sound due to motion.

-

What you should try to do is picture this diagram animated. When the source -emits a wave (the circles) it will look as though it is growing away from it's -point of origin, which is the sources position. A good example of a similar -effect is the ripples in a pond. When you throw a pebble into a calm body of -water it will emit waves which constantly move away from the point of impact. -Believe it or not this occurs from the exact same physical properties. But what -does this have to do with the Doppler effect? Check out the next diagram (on the -right).

+

I know this will be boring review for anyone with a course + in high school physics, but lets humour ourselves. The Doppler effect can be + a very tricky concept for some people, but it is a logical process, and kind + of interesting when you get right down to it. To begin understanding the Doppler + effect we first must start to understand what a "sound" really is. + Basically a sound is your minds interpretation of a compression wave that is + traveling through the air. Whenever the air becomes disturbed it starts a wave + which compresses the air particles around it. This wave travels outward from + it's point of origin. Consider the following diagram.

+

In + this diagram (on the left) the big red "S" stands for the sources + position, and the big red "L" stands for (you guessed it), the Listener's + position. Both source and Listener are not moving. The source is emitting compression + waves outward, which are represented in this diagram by the blue circles. The + Listener is experiencing the sound exactly as it is being made in this diagram. + The Doppler effect is not actually present in this example since there is no + motion; the Doppler effect only describes the warping of sound due to motion.

+

What you should try to do is picture this diagram animated. + When the source emits a wave (the circles) it will look as though it is growing + away from it's point of origin, which is the sources position. A good example + of a similar effect is the ripples in a pond. When you throw a pebble into a + calm body of water it will emit waves which constantly move away from the point + of impact. Believe it or not this occurs from the exact same physical properties. + But what does this have to do with the Doppler effect? Check out the next diagram + (on the right).

-

-Wow, what's going on here? The source is now in motion, indicated by the -little red arrow. In fact the source is now moving towards the Listener with an -implied velocity. Notice particularly that the waves (circles) are being -displaced inside each other. The displacement follows the approximate path of -the source which emits them. This is the key to the Doppler effect. Essentially -what has happened is that the source has emitted a wave at different points in -it's path of travel. The waves it emits do not move with it, but continue on -their own path of travel from the point they were emitted.

-

So how does this effect the perceived sound by the Listener? Well, notice too -in the last diagram that the waves (circles) that are between the source and the -Listener are kind of compressed together. This will cause the sound waves to run -together, which in turn causes the perceived sound seem like it's faster. What -we are talking about here is frequency. The distances between the waves effects -the frequency of the sound. When the source that emits the sound is in motion, -it causes a change in frequency. You may notice too that distance between the -waves varies at different points in space. For example, on the opposite side of -the moving source (anywhere along the previous path of travel) the distances are -actually wider, so the frequency will be lower (the distance and frequency have -an inverse relationship). What this implies is that the frequency perceived by -the Listener is relative to where the Listener is standing.

-

The motion of the Listener can also affect the frequency. This one is a -little harder to picture though. If the source is still, and the Listener is -moving toward the source, then the perceived frequency by the Listener will be -warped in the same exact manner that we described for the moving source.

+

Wow, + what's going on here? The source is now in motion, indicated by the little red + arrow. In fact the source is now moving towards the Listener with an implied + velocity. Notice particularly that the waves (circles) are being displaced inside + each other. The displacement follows the approximate path of the source which + emits them. This is the key to the Doppler effect. Essentially what has happened + is that the source has emitted a wave at different points in it's path of travel. + The waves it emits do not move with it, but continue on their own path of travel + from the point they were emitted.

+

So how does this effect the perceived sound by the Listener? + Well, notice too in the last diagram that the waves (circles) that are between + the source and the Listener are kind of compressed together. This will cause + the sound waves to run together, which in turn causes the perceived sound seem + like it's faster. What we are talking about here is frequency. The distances + between the waves effects the frequency of the sound. When the source that emits + the sound is in motion, it causes a change in frequency. You may notice too + that distance between the waves varies at different points in space. For example, + on the opposite side of the moving source (anywhere along the previous path + of travel) the distances are actually wider, so the frequency will be lower + (the distance and frequency have an inverse relationship). What this implies + is that the frequency perceived by the Listener is relative to where the Listener + is standing.

+

The motion of the Listener can also affect the frequency. This + one is a little harder to picture though. If the source is still, and the Listener + is moving toward the source, then the perceived frequency by the Listener will + be warped in the same exact manner that we described for the moving source. +

If you still have trouble picturing this, consider the following two diagrams:

  

-

These two diagrams will represent the sound in the form of a sine wave. Look -at the first one. Think of the peaks as the instance of the wave. The very top -point of the wave will be the same as the instance of the blue circle in the -previous set of diagrams. The valleys will be like the spaces in between the -blue circles. The second diagram represents a compressed wave. When you compare -the two you will notice an obvious difference. The second diagram simply has -more wave occurrences in the same amount of space. Other ways of saying this are -that they occur more often, with a greater regularity, or with a greater -frequency.

-

For anyone who is interested in some added information: The velocity of the -waves is the speed of sound. If the velocity of the source is greater than that -of the wave, then the source is breaking the sound barrier.

+

These two diagrams will represent the sound in the form of + a sine wave. Look at the first one. Think of the peaks as the instance of the + wave. The very top point of the wave will be the same as the instance of the + blue circle in the previous set of diagrams. The valleys will be like the spaces + in between the blue circles. The second diagram represents a compressed wave. + When you compare the two you will notice an obvious difference. The second diagram + simply has more wave occurrences in the same amount of space. Other ways of + saying this are that they occur more often, with a greater regularity, or with + a greater frequency.

+

For anyone who is interested in some added information: The + velocity of the waves is the speed of sound. If the velocity of the source is + greater than that of the wave, then the source is breaking the sound barrier.

The Physics of OpenAL

-

Ok, either you have understood my ramblings on the Doppler effect from above, -or you have skipped it because you already have full knowledge of the Doppler -effect and just want to know how it effects the OpenAL rendering pipeline. I -think the best start to his section will be to quote the OpenAL spec directly:

+

Ok, either you have understood my ramblings on the Doppler + effect from above, or you have skipped it because you already have full knowledge + of the Doppler effect and just want to know how it effects the OpenAL rendering + pipeline. I think the best start to his section will be to quote the OpenAL + spec directly:

-

"The Doppler Effect depends on the velocities of Source and Listener - relative to the medium, and the propagation speed of sound in that medium." - - chapter 3, subsection 7"

+

"The Doppler Effect depends on the velocities of + Source and Listener relative to the medium, and the propagation speed of sound + in that medium." - chapter 3, subsection 7"

-

We can take this to mean that there are 3 factors which are going to affect -the final frequency of the sound heard by the Listener. These factors are the -velocity of the source, the velocity of the Listener, and a predefined speed of -sound.

-

When we refer to a "medium", what we mean is the kind of material that both -the source and Listener are "in". For example, sounds that are heard from -underwater are much different than sounds that are heard in the open air. Air -and water are examples of different mediums. The reason that sound is so -different between these mediums has to do with the particle density. As we said -before, sound is nothing but the motion of particles in the air. In a medium -with a much greater particle density the sound will be much different because -the particles are in closer contact. When they are in closer contact it allows -for the wave to travel much better. As an example of the opposite, think of -outer space. In outer space there is an extremely low particle density. In fact -there is only a few very light particles (mostly hydrogen) scattered about. This -is why no sound can be heard from space.

+

We can take this to mean that there are 3 factors which are + going to affect the final frequency of the sound heard by the Listener. These + factors are the velocity of the source, the velocity of the Listener, and a + predefined speed of sound.

+

When we refer to a "medium", what we mean is the + kind of material that both the source and Listener are "in". For example, + sounds that are heard from underwater are much different than sounds that are + heard in the open air. Air and water are examples of different mediums. The + reason that sound is so different between these mediums has to do with the particle + density. As we said before, sound is nothing but the motion of particles in + the air. In a medium with a much greater particle density the sound will be + much different because the particles are in closer contact. When they are in + closer contact it allows for the wave to travel much better. As an example of + the opposite, think of outer space. In outer space there is an extremely low + particle density. In fact there is only a few very light particles (mostly hydrogen) + scattered about. This is why no sound can be heard from space.

-

Ok, lets get back on topic. OpenAL calculates the Doppler effect internally -for us, so we need only define a few parameters that will effect the -calculation. We would do this in case we don't want a realistic rendering. -Rather if want to exaggerate or deemphasize the effect. The calculation goes -like this.

+

Ok, lets get back on topic. OpenAL calculates the Doppler effect + internally for us, so we need only define a few parameters that will effect + the calculation. We would do this in case we don't want a realistic rendering. + Rather if want to exaggerate or deemphasize the effect. The calculation goes + like this.

    shift = DOPPLER_FACTOR * freq * (DOPPLER_VELOCITY - l.velocity) / (DOPPLER_VELOCITY + s.velocity)

-

Constants are written in all caps to differentiate. The "l" and "s" variables -are the Listener and source respectively. "freq" is the initial unaltered -frequency of the emitting wave, and "shift" is the altered frequency of the -wave. The term "shift" is the proper way to address the altered frequency and -will be used from now on. This final shifted frequency will be sampled by OpenAL -for all audio streaming that is affected.

+

Constants are written in all caps to differentiate. The "l" + and "s" variables are the Listener and source respectively. "freq" + is the initial unaltered frequency of the emitting wave, and "shift" + is the altered frequency of the wave. The term "shift" is the proper + way to address the altered frequency and will be used from now on. This final + shifted frequency will be sampled by OpenAL for all audio streaming that is + affected.

-

We already know that we can define the velocity of both source and Listener -by using the 'AL_VELOCITY' field to 'alListenerfv' and 'alSourcefv'. The 'freq' -parameter comes straight from the buffer properties when it was loaded from -file. To set the constant values the following functions are provided for us.

+

We already know that we can define the velocity of both source + and Listener by using the 'AL_VELOCITY' field to 'alListenerfv' and 'alSourcefv'. + The 'freq' parameter comes straight from the buffer properties when it was loaded + from file. To set the constant values the following functions are provided for + us.

public void alDopplerFactor(float factor);
 public void alDopplerVelocity(float velocity);
 
-

For 'alDopplerFactor' any non-negative value will suffice. Passing a negative -value will raise an error of 'AL_INVALID_VALUE', and the whole command will be -ignored. Passing zero is a perfectly valid argument. Doing this will disable the -Doppler effect and may in fact help overall performance (but won't be as -realistic). The effect of the Doppler factor will directly change the magnitude -of the equation. A value of 1.0 will not change the effect at all. Passing -anything between 0.0 and 1.0 will minimize the Doppler effect, and anything -greater than 1.0 will maximize the effect.

-

For 'alDopplerVelocity' any non-negative non-zero value will suffice. Passing -either a negative or a zero will raise an error of 'AL_INVALID_VALUE', and the -whole command will be ignored. The Doppler velocity is essentially the speed of -sound. Setting this will be like setting how fast sound can move through the -medium. OpenAL has no sense of medium, but setting the velocity will give the -effect of a medium. OpenAL also has no sense of units (kilometer, miles, -parsecs), so keep that in mind when you set this value so it is consistent with -all other notions of units that you have defined.

+

For 'alDopplerFactor' any non-negative value will suffice. + Passing a negative value will raise an error of 'AL_INVALID_VALUE', and the + whole command will be ignored. Passing zero is a perfectly valid argument. Doing + this will disable the Doppler effect and may in fact help overall performance + (but won't be as realistic). The effect of the Doppler factor will directly + change the magnitude of the equation. A value of 1.0 will not change the effect + at all. Passing anything between 0.0 and 1.0 will minimize the Doppler effect, + and anything greater than 1.0 will maximize the effect.

+

For 'alDopplerVelocity' any non-negative non-zero value will + suffice. Passing either a negative or a zero will raise an error of 'AL_INVALID_VALUE', + and the whole command will be ignored. The Doppler velocity is essentially the + speed of sound. Setting this will be like setting how fast sound can move through + the medium. OpenAL has no sense of medium, but setting the velocity will give + the effect of a medium. OpenAL also has no sense of units (kilometer, miles, + parsecs), so keep that in mind when you set this value so it is consistent with + all other notions of units that you have defined.

+

© 2003 DevMaster.net. -- cgit v1.2.3