Initial commit and fixing/working around compiler errors

This commit is contained in:
crt0mega 2021-02-17 17:37:53 +01:00
commit 33737e8c99
53 changed files with 7109 additions and 0 deletions

437
COPYING Normal file
View File

@ -0,0 +1,437 @@
GNU LIBRARY GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the library GPL. It is
numbered 2 because it goes with version 2 of the ordinary GPL.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Library General Public License, applies to some
specially designated Free Software Foundation software, and to any
other libraries whose authors decide to use it. You can use it for
your libraries, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if
you distribute copies of the library, or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link a program with the library, you must provide
complete object files to the recipients so that they can relink them
with the library, after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
Our method of protecting your rights has two steps: (1) copyright
the library, and (2) offer you this license which gives you legal
permission to copy, distribute and/or modify the library.
Also, for each distributor's protection, we want to make certain
that everyone understands that there is no warranty for this free
library. If the library is modified by someone else and passed on, we
want its recipients to know that what they have is not the original
version, so that any problems introduced by others will not reflect on
the original authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that companies distributing free
software will individually obtain patent licenses, thus in effect
transforming the program into proprietary software. To prevent this,
we have made it clear that any patent must be licensed for everyone's
free use or not licensed at all.
Most GNU software, including some libraries, is covered by the ordinary
GNU General Public License, which was designed for utility programs. This
license, the GNU Library General Public License, applies to certain
designated libraries. This license is quite different from the ordinary
one; be sure to read it in full, and don't assume that anything in it is
the same as in the ordinary license.
The reason we have a separate public license for some libraries is that
they blur the distinction we usually make between modifying or adding to a
program and simply using it. Linking a program with a library, without
changing the library, is in some sense simply using the library, and is
analogous to running a utility program or application program. However, in
a textual and legal sense, the linked executable is a combined work, a
derivative of the original library, and the ordinary General Public License
treats it as such.
Because of this blurred distinction, using the ordinary General
Public License for libraries did not effectively promote software
sharing, because most developers did not use the libraries. We
concluded that weaker conditions might promote sharing better.
However, unrestricted linking of non-free programs would deprive the
users of those programs of all benefit from the free status of the
libraries themselves. This Library General Public License is intended to
permit developers of non-free programs to use free libraries, while
preserving your freedom as a user of such programs to change the free
libraries that are incorporated in them. (We have not seen how to achieve
this as regards changes in header files, but we have achieved it as regards
changes in the actual functions of the Library.) The hope is that this
will lead to faster development of free libraries.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, while the latter only
works together with the library.
Note that it is possible for a library to be covered by the ordinary
General Public License rather than by this special one.
GNU LIBRARY GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library which
contains a notice placed by the copyright holder or other authorized
party saying it may be distributed under the terms of this Library
General Public License (also called "this License"). Each licensee is
addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also compile or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
c) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
d) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the source code distributed need not include anything that is normally
distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Library General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS

64
ChangeLog Normal file
View File

@ -0,0 +1,64 @@
Thu Jul 1 21:22:16 GMT 2004 C.J.Purnell (cjp@lost.org.uk)
* Version 0.1.2 releaased.
* Added a top level README with information about the
hw_params error message.
* Added more example speaker configurations.
Put a description for each in the README.
* It seems Audigy cards have twice the channels in the send
mixer controls. Added support for this.
* Changed the way it looks for a compatable card.
Instead of looking for a card with a "emu10k1" pcm device.
It now looks for a card with a "EMU10K1 PCM Send Routing"
mixer control.
* Removed float->int in the inner plackback loop.
Used 16.16 fixed point instead.
This should give us a speed increase.
* Changed the default value for the doppler factor.
Mon Jun 28 18:28:57 GMT 2004 C.J.Purnell (cjp@lost.org.uk)
* Version 0.1.1 released.
* Fixed buffering of 8bit mono data.
* Fixed a bug in the matrix multiply function.
Sun Jun 12 00:26:16 GMT 2004 C.J.Purnell (cjp@lost.org.uk)
* Version 0.1.0 released.
* Don't call snd_pcm_start() unless there is actually
some data to play.
Fri Jun 11 23:29:45 GMT 2004 C.J.Purnell (cjp@lost.org.uk)
* Version 0.0.4 released.
* Much tweeking of plackback internals.
* Added ALUT WAV file loading functions.
Tue Jun 8 19:46:43 GMT 2004 C.J.Purnell (cjp@lost.org.uk)
* Version 0.0.3 released.
* Fixed speaker config file parsing.
* Made thread safe.
Thu Jun 4 07:39:00 GMT 2004 C.J.Purnell (cjp@lost.org.uk)
* Version 0.0.2 released.
* Removed some debugging output.
Thu Jun 3 22:55:21 GMT 2004 C.J.Purnell (cjp@lost.org.uk)
* Version 0.0.1 released.

29
README Normal file
View File

@ -0,0 +1,29 @@
The error:
ALSA lib pcm_hw.c:324:(snd_pcm_hw_hw_params) SNDRV_PCM_IOCTL_HW_PARAMS failed: Cannot allocate memory
can be safely ignored in most cases. It is just the application trying to
allocate more sources than there are free hardware resources to accomodate.
This library can provide at most 21 sources. It may be more in the future.
Less sources will the avaiable if another application is doing audio playback.
If you are using UT2004 you can supress this message most of the time by
modifying your ~/.ut2004/System/UT2004.ini as follows:
[ALAudio.ALAudioSubsystem]
Channels=20
If on a Soundblaster Live, in your ~/.openal-speakers you have volumes set
for any more than the first two speakers you should manually zero the
following mixer controls:
Wave Surround Playback Volume
Wave Center Playback Volume
Wave LFE Playback Volume
You may not need to do this on an Audigy or Audigy2 but I've not been able to
test that.

86
etc/README Normal file
View File

@ -0,0 +1,86 @@
This directory contains example speaker configuration files.
To use one simple copy it to $HOME/.openal-speakers
The format is simple:
<n>: <gain> <x> <y> <z>
where <n> is a number indication which speaker:
0: front left
1: front right
2: rear left
3: rear right
4: center
5: lfe
6: side left
7: side right
<gain> is a per speaker gain control between 0.0 and 1.0.
Setting the gain to 0.0 disables output to the speaker.
<x> <y> <z> is the speaker position.
<x> is forward, <y> is up and <z> is to the right.
Only the direction of this vector is used.
Anything after a "#" is considered a comment.
speakers-mono:
This one is just simple example.
speakers-stereo:
This is the default configuration. If you are going to use this
you may as well not bother with a speakers file.
speakers-quadraphonic:
Fourpoint output. Each speaker placed in different corner of a square.
speakers-fivepoint-a:
This is what I'm told is the correct placement of speakers in a 5.1
setup. The front speakers are 30° from the center speaker and the rear
speakers are 110° from the center speaker. This is very front biased.
Due to they way I calculate the speaker gain/volume sound behind you ends up
being very quiet. I know there are schemes I could use that would allow for
this but they don't seems to cope very well with the lack of above of below
speakers.
speakers-fivepoint-b:
This is the five speakers placed evenly around the listener, such
that they are all 72° from their neighbours.
speakers-fivepoint-c:
This has the front are rear speakers placed the same as for the
quadraphonic configuration with the addition of the front speaker.
speakers-fivepoint-d:
This has the speakers each placed 60° from their neighbours. The
speakers would be placed evenly around the listener in this configuration
if there was a single rear speaker.
speakers-sevenpoint-a:
I have no idea what the correct placement for 7.1 systems is. This
is with the front three speakers placed the same as the 5.1 setup. The
side speakers are placed 90° from the front. And the rear are placed at
60° from their neighbours. The end result is a configuration where
everything would be placed evenly around the listener if you take away the
front speaker.
speakers-sevenpoint-b:
This is the seven speakers placed evenly around the listener.
This has them all at some funny angle from their neighbours.
speakers-sevenpoint-c:
This has the front and rear speakers placed the same as for the
quadraphonic configuration. And the side speakers are placed 90° from the
front. The speakers would be placed evenly around the listener in this
configuration with the addition of a rear center speaker.

8
etc/speakers-fivepoint-a Normal file
View File

@ -0,0 +1,8 @@
0: 1 -0.5 0 0.8860254
1: 1 0.5 0 0.8860254
2: 1 -0.93969262 0 -0.34202014
3: 1 0.93969262 0 -0.34202014
4: 1 0 0 1
5: 0 0 0 0
6: 0 0 0 0
7: 0 0 0 0

8
etc/speakers-fivepoint-b Normal file
View File

@ -0,0 +1,8 @@
0: 1 -0.95105652 0 0.30916994
1: 1 0.95105652 0 0.30916994
2: 1 -0.58778525 0 -0.80901699
3: 1 0.58778525 0 -0.80901699
4: 1 0 0 1
5: 0 0 0 0
6: 0 0 0 0
7: 0 0 0 0

8
etc/speakers-fivepoint-c Normal file
View File

@ -0,0 +1,8 @@
0: 1 -0.70710678 0 0.70710678
1: 1 0.70710678 0 0.70710678
2: 1 -0.70710678 0 -0.70710678
3: 1 0.70710678 0 -0.70710678
4: 1 0 0 1
5: 0 0 0 0
6: 0 0 0 0
7: 0 0 0 0

8
etc/speakers-fivepoint-d Normal file
View File

@ -0,0 +1,8 @@
0: 1 -0.8860254 0 0.5
1: 1 0.8860254 0 0.5
2: 1 -0.8860254 0 -0.5
3: 1 0.8860254 0 -0.5
4: 1 0 0 1
5: 0 0 0 0
6: 0 0 0 0
7: 0 0 0 0

8
etc/speakers-mono Normal file
View File

@ -0,0 +1,8 @@
0: 1 0 0 0
1: 1 0 0 0
2: 0 0 0 0
3: 0 0 0 0
4: 0 0 0 0
5: 0 0 0 0
6: 0 0 0 0
7: 0 0 0 0

View File

@ -0,0 +1,8 @@
0: 1 -0.70710678 0 0.70710678
1: 1 0.70710678 0 0.70710678
2: 1 -0.70710678 0 -0.70710678
3: 1 0.70710678 0 -0.70710678
4: 0 0 0 0
5: 0 0 0 0
6: 0 0 0 0
7: 0 0 0 0

View File

@ -0,0 +1,8 @@
0: 1 -0.5 0 0.8860254
1: 1 0.5 0 0.8860254
2: 1 -0.5 0 -0.8860254
3: 1 0.5 0 -0.8860254
4: 1 0 0 1
5: 0 0 0 0
6: 1 -1 0 0
7: 1 1 0 0

View File

@ -0,0 +1,8 @@
0: 1 -0.78183148 0 0.6234898
1: 1 0.78183148 0 0.6234898
2: 1 -0.43388374 0 -0.90096777
3: 1 0.43388374 0 -0.90096777
4: 1 0 0 1
5: 0 0 0 0
6: 1 0.97492791 0 -0.22252093
7: 1 -0.97492791 0 -0.22252093

View File

@ -0,0 +1,8 @@
0: 1 -0.70710678 0 0.70710678
1: 1 0.70710678 0 0.70710678
2: 1 -0.70710678 0 -0.70710678
3: 1 0.70710678 0 -0.70710678
4: 1 0 0 1
5: 0 0 0 0
6: 1 -1 0 0
7: 1 1 0 0

8
etc/speakers-stereo Normal file
View File

@ -0,0 +1,8 @@
0: 1 -1 0 0
1: 1 1 0 0
2: 0 0 0 0
3: 0 0 0 0
4: 0 0 0 0
5: 0 0 0 0
6: 0 0 0 0
7: 0 0 0 0

642
include/AL/al.h Normal file
View File

@ -0,0 +1,642 @@
#ifndef __al_h_
#define __al_h_
/**
* OpenAL cross platform audio library
* Copyright (C) 1999-2000 by authors.
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* Or go to http://www.gnu.org/copyleft/lgpl.html
*/
#include "altypes.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _WIN32
#ifdef _OPENAL32LIB
#define ALAPI __declspec(dllexport)
#else
#define ALAPI __declspec(dllimport)
#endif
#define ALAPIENTRY __cdecl
#define AL_CALLBACK
#else /* _WIN32 */
#ifdef TARGET_OS_MAC
#if TARGET_OS_MAC
#pragma export on
#endif /* TARGET_OS_MAC */
#endif /* TARGET_OS_MAC */
#ifndef ALAPI
#define ALAPI
#endif
#ifndef ALAPIENTRY
#define ALAPIENTRY
#endif
#ifndef CALLBACK
#define AL_CALLBACK
#endif
#endif /* _WIN32 */
#define OPENAL
#ifndef AL_NO_PROTOTYPES
/**
* OpenAL Maintenance Functions
* State Management and Query.
* Error Handling.
* Extension Support.
*/
/** Renderer State management. */
ALAPI void ALAPIENTRY alEnable( ALenum capability );
ALAPI void ALAPIENTRY alDisable( ALenum capability );
ALAPI ALboolean ALAPIENTRY alIsEnabled( ALenum capability );
/** Application preferences for driver performance choices. */
ALAPI void ALAPIENTRY alHint( ALenum target, ALenum mode );
/** State retrieval. */
ALAPI void ALAPIENTRY alGetBooleanv( ALenum param, ALboolean* data );
/** State retrieval. */
ALAPI void ALAPIENTRY alGetIntegerv( ALenum param, ALint* data );
/** State retrieval. */
ALAPI void ALAPIENTRY alGetFloatv( ALenum param, ALfloat* data );
/** State retrieval. */
ALAPI void ALAPIENTRY alGetDoublev( ALenum param, ALdouble* data );
/** State retrieval. */
#ifdef LINUX_AL
ALAPI const ALubyte* ALAPIENTRY alGetString( ALenum param );
#else
ALAPI ALubyte* ALAPIENTRY alGetString( ALenum param );
#endif
/** State retrieval.through return value ( for compatibility ) */
ALAPI ALboolean ALAPIENTRY alGetBoolean( ALenum param );
ALAPI ALint ALAPIENTRY alGetInteger( ALenum param );
ALAPI ALfloat ALAPIENTRY alGetFloat( ALenum param );
ALAPI ALdouble ALAPIENTRY alGetDouble( ALenum param );
/**
* Error support.
* Obtain the most recent error generated in the AL state machine.
*/
ALAPI ALenum ALAPIENTRY alGetError( ALvoid );
/**
* Extension support.
* Obtain the address of a function (usually an extension)
* with the name fname. All addresses are context-independent.
*/
#ifdef LINUX_AL
ALAPI ALboolean ALAPIENTRY alIsExtensionPresent( const ALubyte* fname );
#else
ALAPI ALboolean ALAPIENTRY alIsExtensionPresent( ALubyte* fname );
#endif
/**
* Extension support.
* Obtain the address of a function (usually an extension)
* with the name fname. All addresses are context-independent.
*/
#ifdef LINUX_AL
ALAPI void* ALAPIENTRY alGetProcAddress( const ALubyte* fname );
#else
ALAPI void* ALAPIENTRY alGetProcAddress( ALubyte* fname );
#endif
/**
* Extension support.
* Obtain the integer value of an enumeration (usually an extension) with the name ename.
*/
#ifdef LINUX_AL
ALAPI ALenum ALAPIENTRY alGetEnumValue( const ALubyte* ename );
#else
ALAPI ALenum ALAPIENTRY alGetEnumValue( ALubyte* ename );
#endif
/**
* LISTENER
* Listener is the sample position for a given context.
* The multi-channel (usually stereo) output stream generated
* by the mixer is parametrized by this Listener object:
* its position and velocity relative to Sources, within
* occluder and reflector geometry.
*/
/**
*
* Listener Gain: default 1.0f.
*/
ALAPI void ALAPIENTRY alListenerf( ALenum pname, ALfloat param );
ALAPI void ALAPIENTRY alListeneri( ALenum pname, ALint param );
/**
*
* Listener Position: ALfloat[3]
* Listener Velocity: ALfloat[3]
*/
ALAPI void ALAPIENTRY alListener3f( ALenum pname,
ALfloat f1, ALfloat f2, ALfloat f3 );
/**
*
* Listener Position: ALfloat[3]
* Listener Velocity: ALfloat[3]
* Listener Orientation: ALfloat[6] (forward and up vector).
*/
ALAPI void ALAPIENTRY alListenerfv( ALenum pname, ALfloat* param );
/*
* Retrieve listener information.
*/
ALAPI void ALAPIENTRY alGetListeneri( ALenum pname, ALint* value );
ALAPI void ALAPIENTRY alGetListenerf( ALenum pname, ALfloat* value );
#ifdef LINUX_AL
/* not defined under Windows and MacOS */
ALAPI void ALAPIENTRY alGetListeneriv( ALenum pname, ALint* value );
#endif
ALAPI void ALAPIENTRY alGetListenerfv( ALenum pname, ALfloat* values );
ALAPI void ALAPIENTRY alGetListener3f( ALenum pname,
ALfloat *f1, ALfloat *f2, ALfloat *f3 );
/**
* SOURCE
* Source objects are by default localized. Sources
* take the PCM data provided in the specified Buffer,
* apply Source-specific modifications, and then
* submit them to be mixed according to spatial
* arrangement etc.
*/
/** Create Source objects. */
ALAPI void ALAPIENTRY alGenSources( ALsizei n, ALuint* sources );
/** Delete Source objects. */
ALAPI void ALAPIENTRY alDeleteSources( ALsizei n, ALuint* sources );
/** Verify a handle is a valid Source. */
ALAPI ALboolean ALAPIENTRY alIsSource( ALuint sid );
/** Set an integer parameter for a Source object. */
ALAPI void ALAPIENTRY alSourcei( ALuint sid, ALenum param, ALint value );
ALAPI void ALAPIENTRY alSourcef( ALuint sid, ALenum param, ALfloat value );
ALAPI void ALAPIENTRY alSource3f( ALuint sid, ALenum param,
ALfloat f1, ALfloat f2, ALfloat f3 );
ALAPI void ALAPIENTRY alSourcefv( ALuint sid, ALenum param, ALfloat* values );
/** Get an integer parameter for a Source object. */
ALAPI void ALAPIENTRY alGetSourcei( ALuint sid, ALenum pname, ALint* value );
#ifdef LINUX_AL
/* not defined under Windows and MacOS */
ALAPI void ALAPIENTRY alGetSourceiv( ALuint sid, ALenum pname, ALint* values );
#endif
ALAPI void ALAPIENTRY alGetSourcef( ALuint sid, ALenum pname, ALfloat* value );
ALAPI void ALAPIENTRY alGetSourcefv( ALuint sid, ALenum pname, ALfloat* values );
/* deprecated, included for Win compatibility */
ALAPI void ALAPIENTRY alGetSource3f( ALuint sid, ALenum pname, ALfloat* value1,
ALfloat* value2, ALfloat* value3);
ALAPI void ALAPIENTRY alSourcePlayv( ALsizei ns, ALuint *ids );
ALAPI void ALAPIENTRY alSourceStopv( ALsizei ns, ALuint *ids );
ALAPI void ALAPIENTRY alSourceRewindv( ALsizei ns, ALuint *ids );
ALAPI void ALAPIENTRY alSourcePausev( ALsizei ns, ALuint *ids );
/** Activate a source, start replay. */
ALAPI void ALAPIENTRY alSourcePlay( ALuint sid );
/**
* Pause a source,
* temporarily remove it from the mixer list.
*/
ALAPI void ALAPIENTRY alSourcePause( ALuint sid );
/**
* Rewind a source,
* set the source to play at the beginning.
*/
ALAPI void ALAPIENTRY alSourceRewind( ALuint sid );
/**
* Stop a source,
* temporarily remove it from the mixer list,
* and reset its internal state to pre-Play.
* To remove a Source completely, it has to be
* deleted following Stop, or before Play.
*/
ALAPI void ALAPIENTRY alSourceStop( ALuint sid );
/**
* BUFFER
* Buffer objects are storage space for sample data.
* Buffers are referred to by Sources. There can be more than
* one Source using the same Buffer data. If Buffers have
* to be duplicated on a per-Source basis, the driver has to
* take care of allocation, copying, and deallocation as well
* as propagating buffer data changes.
*/
/** Buffer object generation. */
ALAPI void ALAPIENTRY alGenBuffers( ALsizei n, ALuint* buffers );
ALAPI void ALAPIENTRY alDeleteBuffers( ALsizei n, ALuint* buffers );
ALAPI ALboolean ALAPIENTRY alIsBuffer( ALuint buffer );
/**
* Specify the data to be filled into a buffer.
*/
ALAPI void ALAPIENTRY alBufferData( ALuint buffer,
ALenum format,
ALvoid* data,
ALsizei size,
ALsizei freq );
ALAPI void ALAPIENTRY alGetBufferi( ALuint buffer, ALenum param, ALint* value );
ALAPI void ALAPIENTRY alGetBufferf( ALuint buffer, ALenum param, ALfloat* value );
#ifdef LINUX_AL
/* not defined under Windows and MacOS */
ALAPI void ALAPIENTRY alGetBufferiv( ALuint buffer, ALenum param, ALint *v);
ALAPI void ALAPIENTRY alGetBufferfv( ALuint buffer, ALenum param, ALfloat *v);
#endif
/**
* Frequency Domain Filters are band filters.
* Attenuation in Media (distance based)
* Reflection Material
* Occlusion Material (separating surface)
*
* Temporal Domain Filters:
* Early Reflections
* Late Reverb
*
*/
#ifdef LINUX_AL
/* IASIG stuff never really used -- will probably be removed from Linux as well */
/**
* EXTENSION: IASIG Level 2 Environment.
* Environment object generation.
* This is an EXTension that describes the Environment/Reverb
* properties according to IASIG Level 2 specifications.
*/
/**
* Allocate n environment ids and store them in the array environs.
* Returns the number of environments actually allocated.
*/
ALAPI ALsizei ALAPIENTRY alGenEnvironmentIASIG( ALsizei n, ALuint* environs );
ALAPI void ALAPIENTRY alDeleteEnvironmentIASIG( ALsizei n, ALuint* environs );
ALAPI ALboolean ALAPIENTRY alIsEnvironmentIASIG( ALuint environ );
ALAPI void ALAPIENTRY alEnvironmentiIASIG( ALuint eid, ALenum param, ALint value );
ALAPI void ALAPIENTRY alEnvironmentfIASIG( ALuint eid, ALenum param, ALuint value );
#endif
/**
* Queue stuff
*/
ALAPI void ALAPIENTRY alSourceQueueBuffers( ALuint sid, ALsizei numEntries, ALuint *bids );
ALAPI void ALAPIENTRY alSourceUnqueueBuffers( ALuint sid, ALsizei numEntries, ALuint *bids );
#ifdef LINUX_AL
/* function no longer used */
ALAPI void ALAPIENTRY alQueuei( ALuint sid, ALenum param, ALint value );
#endif
/**
* Knobs and dials
*/
ALAPI void ALAPIENTRY alDopplerFactor( ALfloat value );
ALAPI void ALAPIENTRY alDopplerVelocity( ALfloat value );
ALAPI void ALAPIENTRY alDistanceModel( ALenum distanceModel );
#else /* AL_NO_PROTOTYPES */
/** OpenAL Maintenance Functions */
void (*alEnable)( ALenum capability );
void (*alDisable)( ALenum capability );
ALboolean (*alIsEnabled)( ALenum capability );
void (*alHint)( ALenum target, ALenum mode );
ALboolean (*alGetBoolean)( ALenum param );
ALint (*alGetInteger)( ALenum param );
ALfloat (*alGetFloat)( ALenum param );
ALdouble (*alGetDouble)( ALenum param );
void (*alGetBooleanv)( ALenum param,
ALboolean* data );
void (*alGetIntegerv)( ALenum param,
ALint* data );
void (*alGetFloatv)( ALenum param,
ALfloat* data );
void (*alGetDoublev)( ALenum param,
ALdouble* data );
#ifdef LINUX_AL
const ALubyte* (*alGetString)( ALenum param );
#else
ALubyte* (*alGetString)( ALenum param );
#endif
ALenum (*alGetError)( ALvoid );
/**
* Extension support.
* Query existance of extension
*/
#ifdef LINUX_AL
ALboolean (*alIsExtensionPresent)(const ALubyte* fname );
#else
ALboolean (*alIsExtensionPresent)(ALubyte* fname );
#endif
/**
* Extension support.
* Obtain the address of a function (usually an extension)
* with the name fname. All addresses are context-independent.
*/
#ifdef LINUX_AL
void* (*alGetProcAddress)( const ALubyte* fname );
#else
void* (*alGetProcAddress)( ALubyte* fname );
#endif
/**
* Extension support.
* Obtain the integer value of an enumeration (usually an extension) with the name ename.
*/
#ifdef LINUX_AL
ALenum (*alGetEnumValue)( const ALubyte* ename );
#else
ALenum (*alGetEnumValue)( ALubyte* ename);
#endif
/**
* LISTENER
* Listener is the sample position for a given context.
* The multi-channel (usually stereo) output stream generated
* by the mixer is parametrized by this Listener object:
* its position and velocity relative to Sources, within
* occluder and reflector geometry.
*/
/**
*
* Listener Gain: default 1.0f.
*/
void (*alListenerf)( ALenum pname, ALfloat param );
/**
*
* Listener Position: ALfloat[3]
* Listener Velocity: ALfloat[3]
* Listener Orientation: ALfloat[6] (forward and up vector).
*/
void (*alListenerfv)( ALenum pname, ALfloat* param );
/*
* Retrieve listener information.
*/
void (*alGetListeneri)( ALenum pname, ALint* value );
void (*alGetListenerf)( ALenum pname, ALfloat* value );
#ifdef LINUX_AL
void (*alGetListeneriv)( ALenum pname, ALint* values );
#endif
void (*alGetListenerfv)( ALenum pname, ALfloat* values );
/**
* SOURCE
* Source objects are by default localized. Sources
* take the PCM data provided in the specified Buffer,
* apply Source-specific modifications, and then
* submit them to be mixed according to spatial
* arrangement etc.
*/
/** Create Source objects. */
void (*alGenSources)( ALsizei n, ALuint* sources );
/** Delete Source objects. */
void (*alDeleteSources)( ALsizei n, ALuint* sources );
/** Verify a handle is a valid Source. */
ALboolean (*alIsSource)( ALuint sid );
/** Set an integer parameter for a Source object. */
void (*alSourcei)( ALuint sid, ALenum param, ALint value);
/** Set a float parameter for a Source object. */
void (*alSourcef)( ALuint sid, ALenum param, ALfloat value);
/** Set a 3 float parameter for a Source object. */
void (*alSource3f)( ALuint sid, ALenum param,
ALfloat f1, ALfloat f2, ALfloat f3 );
/** Set a float vector parameter for a Source object. */
void (*alSourcefv)( ALuint sid, ALenum param,
ALfloat* values );
/** Get an integer scalar parameter for a Source object. */
void (*alGetSourcei)( ALuint sid,
ALenum pname, ALint* value );
#ifdef LINUX_AL
/** Get an integer parameter for a Source object. */
void (*alGetSourceiv)( ALuint sid,
ALenum pname, ALint* values );
#endif
/** Get a float scalar parameter for a Source object. */
void (*alGetSourcef)( ALuint sid,
ALenum pname, ALfloat* value );
/** Get three float scalar parameter for a Source object. */
void (*alGetSource3f)( ALuint sid, ALenum pname,
ALfloat* value1,
ALfloat* value2,
ALfloat* value3);
/** Get a float vector parameter for a Source object. */
void (*alGetSourcefv)( ALuint sid,
ALenum pname, ALfloat* values );
/** Activate a source, start replay. */
void (*alSourcePlay)( ALuint sid );
/**
* Pause a source,
* temporarily remove it from the mixer list.
*/
void (*alSourcePause)( ALuint sid );
/**
* Stop a source,
* temporarily remove it from the mixer list,
* and reset its internal state to pre-Play.
* To remove a Source completely, it has to be
* deleted following Stop, or before Play.
*/
void (*alSourceStop)( ALuint sid );
/**
* Rewind a souce. Stopped paused and playing sources,
* resets the offset into the PCM data and sets state to
* AL_INITIAL.
*/
void (*alSourceRewind)( ALuint sid );
/**
* vector forms of those functions we all love
*/
void (*alSourcePlayv)( ALsizei ns, ALuint *ids );
void (*alSourceStopv)( ALsizei ns, ALuint *ids );
void (*alSourceRewindv)( ALsizei ns, ALuint *ids );
void (*alSourcePausev)( ALsizei ns, ALuint *ids );
/**
* BUFFER
* Buffer objects are storage space for sample data.
* Buffers are referred to by Sources. There can be more than
* one Source using the same Buffer data. If Buffers have
* to be duplicated on a per-Source basis, the driver has to
* take care of allocation, copying, and deallocation as well
* as propagating buffer data changes.
*/
/** Buffer object generation. */
void (*alGenBuffers)( ALsizei n, ALuint* buffers );
void (*alDeleteBuffers)( ALsizei n, ALuint* buffers );
ALboolean (*alIsBuffer)( ALuint buffer );
/**
* Specify the data to be filled into a buffer.
*/
void (*alBufferData)( ALuint buffer,
ALenum format,
ALvoid* data,
ALsizei size,
ALsizei freq );
void (*alGetBufferi)( ALuint buffer,
ALenum param, ALint* value );
void (*alGetBufferf)( ALuint buffer,
ALenum param, ALfloat* value );
#ifdef LINUX_AL
void (*alGetBufferiv)( ALuint buffer,
ALenum param, ALint* value );
void (*alGetBufferfv)( ALuint buffer,
ALenum param, ALfloat* value );
#endif
#ifdef LINUX_AL
/**
* EXTENSION: IASIG Level 2 Environment.
* Environment object generation.
* This is an EXTension that describes the Environment/Reverb
* properties according to IASIG Level 2 specifications.
*/
/**
* Allocate n environment ids and store them in the array environs.
* Returns the number of environments actually allocated.
*/
ALsizei (*alGenEnvironmentIASIG)( ALsizei n, ALuint* environs );
void (*alDeleteEnvironmentIASIG)(ALsizei n,
ALuint* environs);
ALboolean (*alIsEnvironmentIASIG)( ALuint environ );
void (*alEnvironmentiIASIG)( ALuint eid,
ALenum param, ALint value );
void (*alEnvironmentfIASIG)( ALuint eid,
ALenum param, ALuint value );
#endif
/**
* Queue stuff
*/
#ifdef LINUX_AL
void (*alQueuei)(ALuint sid, ALenum param, ALint value );
#endif
void (*alSourceUnqueueBuffers)(ALuint sid, ALsizei numEntries, ALuint *bids );
void (*alSourceQueueBuffers)(ALuint sid, ALsizei numEntries, ALuint *bids );
void (*alDopplerFactor)( ALfloat value );
void (*alDopplerVelocity)( ALfloat value );
void (*alDistanceModel)( ALenum distanceModel );
/**
* Frequency Domain Filters are band filters.
* Attenuation in Media (distance based)
* Reflection Material
* Occlusion Material (separating surface)
*
* Temporal Domain Filters:
* Early Reflections
* Late Reverb
*
*/
#endif /* AL_NO_PROTOTYPES */
#ifdef TARGET_OS_MAC
#if TARGET_OS_MAC
#pragma export off
#endif /* TARGET_OS_MAC */
#endif /* TARGET_OS_MAC */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* __al_h_ */

163
include/AL/alc.h Normal file
View File

@ -0,0 +1,163 @@
#ifndef ALC_CONTEXT_H_
#define ALC_CONTEXT_H_
#include "altypes.h"
#include "alctypes.h"
#ifdef __cplusplus
extern "C" {
#endif
#define ALC_VERSION_0_1 1
#ifdef _WIN32
#ifdef _OPENAL32LIB
#define ALCAPI __declspec(dllexport)
#else
#define ALCAPI __declspec(dllimport)
#endif
typedef struct ALCdevice_struct ALCdevice;
typedef struct ALCcontext_struct ALCcontext;
#define ALCAPIENTRY __cdecl
#else
#ifdef TARGET_OS_MAC
#if TARGET_OS_MAC
#pragma export on
#endif
#endif
#define ALCAPI
#define ALCAPIENTRY
#endif
#ifndef AL_NO_PROTOTYPES
ALCAPI ALCcontext * ALCAPIENTRY alcCreateContext( ALCdevice *dev,
ALCint* attrlist );
/**
* There is no current context, as we can mix
* several active contexts. But al* calls
* only affect the current context.
*/
#ifdef LINUX_AL
/* spec has return value as ALCboolean */
ALCAPI ALCenum ALCAPIENTRY alcMakeContextCurrent( ALCcontext *alcHandle );
#else
ALCAPI ALCboolean ALCAPIENTRY alcMakeContextCurrent(ALCcontext *alcHandle);
#endif
/**
* Perform processing on a synced context, non-op on a asynchronous
* context.
*/
#ifdef LINUX_AL
/* spec has return value as void */
ALCAPI ALCcontext * ALCAPIENTRY alcProcessContext( ALCcontext *alcHandle );
#else
ALCAPI ALvoid ALCAPIENTRY alcProcessContext(ALCcontext* context);
#endif
/**
* Suspend processing on an asynchronous context, non-op on a
* synced context.
*/
ALCAPI void ALCAPIENTRY alcSuspendContext( ALCcontext *alcHandle );
#ifdef LINUX_AL
/* spec has return value as void */
ALCAPI ALCenum ALCAPIENTRY alcDestroyContext( ALCcontext *alcHandle );
#else
ALCAPI ALvoid ALCAPIENTRY alcDestroyContext(ALCcontext* context);
#endif
ALCAPI ALCenum ALCAPIENTRY alcGetError( ALCdevice *dev );
ALCAPI ALCcontext * ALCAPIENTRY alcGetCurrentContext( ALvoid );
#ifdef LINUX_AL
ALCAPI ALCdevice * ALCAPIENTRY alcOpenDevice( const ALubyte *tokstr );
#else
ALCAPI ALCdevice * ALCAPIENTRY alcOpenDevice( ALubyte *tokstr );
#endif
ALCAPI void ALCAPIENTRY alcCloseDevice( ALCdevice *dev );
ALCAPI ALCboolean ALCAPIENTRY alcIsExtensionPresent(ALCdevice *device, ALCubyte *extName);
ALCAPI ALCvoid * ALCAPIENTRY alcGetProcAddress(ALCdevice *device, ALCubyte *funcName);
ALCAPI ALCenum ALCAPIENTRY alcGetEnumValue(ALCdevice *device, ALCubyte *enumName);
ALCAPI ALCdevice* ALCAPIENTRY alcGetContextsDevice(ALCcontext *context);
/**
* Query functions
*/
#ifdef LINUX_AL
const ALCubyte * ALCAPIENTRY alcGetString( ALCdevice *deviceHandle, ALCenum token );
#else
ALCAPI ALubyte* ALCAPIENTRY alcGetString(ALCdevice* device, ALenum param);
#endif
#ifdef LINUX_AL
ALCAPI void ALCAPIENTRY alcGetIntegerv( ALCdevice *deviceHandle, ALCenum token , ALCsizei size , ALCint *dest );
#else
ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALCsizei size,ALCint *data);
#endif
#else
ALCAPI ALCcontext * ALCAPIENTRY (*alcCreateContext)( ALCdevice *dev, ALCint* attrlist );
#ifdef LINUX_AL
ALCAPI ALCenum ALCAPIENTRY (*alcMakeContextCurrent)( ALCcontext *alcHandle );
#else
ALCAPI ALCboolean ALCAPIENTRY (*alcMakeContextCurrent)(ALCcontext *context);
#endif
#ifdef LINUX_AL
ALCAPI ALCcontext * ALCAPIENTRY (*alcProcessContext)( ALCcontext *alcHandle );
#else
ALCAPI ALCvoid * ALCAPIENTRY (*alcProcessContext)( ALCcontext *alcHandle );
#endif
ALCAPI void ALCAPIENTRY (*alcSuspendContext)( ALCcontext *alcHandle );
#ifdef LINUX_AL
ALCAPI ALCenum ALCAPIENTRY (*alcDestroyContext)( ALCcontext *alcHandle );
#else
ALCAPI ALvoid ALCAPIENTRY (*alcDestroyContext)( ALCcontext* context );
#endif
ALCAPI ALCenum ALCAPIENTRY (*alcGetError)( ALCdevice *dev );
ALCAPI ALCcontext * ALCAPIENTRY (*alcGetCurrentContext)( ALCvoid );
#ifdef LINUX_AL
ALCAPI ALCdevice * ALCAPIENTRY (*alcOpenDevice)( const ALCubyte *tokstr );
#else
ALCAPI ALCdevice * ALCAPIENTRY (*alcOpenDevice)( ALubyte *tokstr );
#endif
ALCAPI void ALCAPIENTRY (*alcCloseDevice)( ALCdevice *dev );
ALCAPI ALCboolean ALCAPIENTRY (*alcIsExtensionPresent)( ALCdevice *device, ALCubyte *extName );
ALCAPI ALCvoid * ALCAPIENTRY (*alcGetProcAddress)(ALCdevice *device, ALCubyte *funcName );
ALCAPI ALCenum ALCAPIENTRY (*alcGetEnumValue)(ALCdevice *device, ALCubyte *enumName);
ALCAPI ALCdevice* ALCAPIENTRY (*alcGetContextsDevice)(ALCcontext *context);
#ifdef LINUX_AL
ALCAPI const ALCubyte* ALCAPIENTRY (*alcGetString)( ALCdevice *deviceHandle, ALCenum token );
#else
ALCAPI ALCubyte* ALCAPIENTRY (*alcGetString)( ALCdevice *deviceHandle, ALCenum token );
#endif
#ifdef LINUX_AL
ALCAPI void ALCAPIENTRY (*alcGetIntegerv*)( ALCdevice *deviceHandle, ALCenum token , ALCsizei size , ALCint *dest );
#else
ALCAPI ALCvoid ALCAPIENTRY (*alcGetIntegerv*)( ALCdevice *deviceHandle, ALCenum token , ALCsizei size , ALCint *dest );
#endif
#endif /* AL_NO_PROTOTYPES */
#ifdef TARGET_OS_MAC
#if TARGET_OS_MAC
#pragma export off
#endif /* TARGET_OS_MAC */
#endif /* TARGET_OS_MAC */
#ifdef __cplusplus
}
#endif
#endif /* ALC_CONTEXT_H_ */

121
include/AL/alctypes.h Normal file
View File

@ -0,0 +1,121 @@
#ifndef _ALCTYPES_H_
#define _ALCTYPES_H_
#if !defined(_WIN32)
struct _AL_device;
typedef struct _AL_device ALCdevice;
typedef void ALCcontext;
#endif /* _WIN32 */
typedef int ALCenum;
/** ALC boolean type. */
typedef char ALCboolean;
/** ALC 8bit signed byte. */
typedef char ALCbyte;
/** ALC 8bit unsigned byte. */
typedef unsigned char ALCubyte;
/** ALC 16bit signed short integer type. */
typedef short ALCshort;
/** ALC 16bit unsigned short integer type. */
typedef unsigned short ALCushort;
/** ALC 32bit unsigned integer type. */
typedef unsigned ALCuint;
/** ALC 32bit signed integer type. */
typedef int ALCint;
/** ALC 32bit floating point type. */
typedef float ALCfloat;
/** ALC 64bit double point type. */
typedef double ALCdouble;
/** ALC 32bit type. */
typedef unsigned int ALCsizei;
/** ALC void type */
typedef void ALCvoid;
/* Enumerant values begin at column 50. No tabs. */
/* bad value */
#define ALC_INVALID 0
/* Boolean False. */
#define ALC_FALSE 0
/* Boolean True. */
#define ALC_TRUE 1
/**
* followed by <int> Hz
*/
#define ALC_FREQUENCY 0x1007
/**
* followed by <int> Hz
*/
#define ALC_REFRESH 0x1008
/**
* followed by AL_TRUE, AL_FALSE
*/
#define ALC_SYNC 0x1009
/**
* errors
*/
/**
* No error
*/
#define ALC_NO_ERROR ALC_FALSE
/**
* No device
*/
#define ALC_INVALID_DEVICE 0xA001
/**
* invalid context ID
*/
#define ALC_INVALID_CONTEXT 0xA002
/**
* bad enum
*/
#define ALC_INVALID_ENUM 0xA003
/**
* bad value
*/
#define ALC_INVALID_VALUE 0xA004
/**
* Out of memory.
*/
#define ALC_OUT_OF_MEMORY 0xA005
/**
* The Specifier string for default device
*/
#define ALC_DEFAULT_DEVICE_SPECIFIER 0x1004
#define ALC_DEVICE_SPECIFIER 0x1005
#define ALC_EXTENSIONS 0x1006
#define ALC_MAJOR_VERSION 0x1000
#define ALC_MINOR_VERSION 0x1001
#define ALC_ATTRIBUTES_SIZE 0x1002
#define ALC_ALL_ATTRIBUTES 0x1003
#endif /* _ALCTYPES_H */

76
include/AL/alext.h Normal file
View File

@ -0,0 +1,76 @@
#ifndef _LAL_EXT_H_
#define _LAL_EXT_H_
#include "AL/altypes.h"
#include "alexttypes.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef ALAPI
#define ALAPI extern
#endif
#ifndef ALAPIENTRY
#define ALAPIENTRY
#endif
/* loki */
ALAPI ALfloat alcGetAudioChannel_LOKI(ALuint channel);
ALAPI void alcSetAudioChannel_LOKI(ALuint channel, ALfloat volume);
ALAPI void alBombOnError_LOKI(void);
ALAPI void alBufferi_LOKI(ALuint bid, ALenum param, ALint value);
ALAPI void alBufferDataWithCallback_LOKI(ALuint bid,
int (*Callback)(ALuint, ALuint, ALshort *, ALenum, ALint, ALint));
ALAPI void alBufferWriteData_LOKI( ALuint buffer,
ALenum format,
ALvoid* data,
ALsizei size,
ALsizei freq,
ALenum internalFormat );
ALAPI void ALAPIENTRY alGenStreamingBuffers_LOKI( ALsizei n, ALuint *samples );
ALAPI ALsizei alBufferAppendData_LOKI( ALuint buffer,
ALenum format,
ALvoid* data,
ALsizei size,
ALsizei freq );
ALAPI ALsizei alBufferAppendWriteData_LOKI( ALuint buffer,
ALenum format,
ALvoid* data,
ALsizei size,
ALsizei freq,
ALenum internalFormat );
/* Capture api */
ALAPI ALboolean alCaptureInit_EXT( ALenum format, ALuint rate, ALsizei bufferSize );
ALAPI ALboolean alCaptureDestroy_EXT( ALvoid );
ALAPI ALboolean alCaptureStart_EXT( ALvoid );
ALAPI ALboolean alCaptureStop_EXT( ALvoid );
/* Non-blocking device read */
ALAPI ALsizei alCaptureGetData_EXT( ALvoid* data, ALsizei n, ALenum format, ALuint rate );
/* custom loaders */
ALAPI ALboolean alutLoadVorbis_LOKI(ALuint bid, ALvoid *data, ALint size);
ALAPI ALboolean ALAPIENTRY alutLoadRAW_ADPCMData_LOKI(ALuint bid, ALvoid *data,
ALuint size, ALuint freq,
ALenum format);
ALAPI ALboolean ALAPIENTRY alutLoadIMA_ADPCMData_LOKI(ALuint bid, ALvoid *data,
ALuint size,
alIMAADPCM_state_LOKI *ias);
ALAPI ALboolean ALAPIENTRY alutLoadMS_ADPCMData_LOKI(ALuint bid,
void *data, int size,
alMSADPCM_state_LOKI *mss);
#ifdef __cplusplus
}
#endif
#endif /* _LAL_EXT_H_ */

161
include/AL/alexttypes.h Normal file
View File

@ -0,0 +1,161 @@
#ifndef _LAL_EXTTYPES_H_
#define _LAL_EXTTYPES_H_
#define LAL_OPENAL 1
/* format base 0x10000 */
#define AL_FORMAT_IMA_ADPCM_MONO16_EXT 0x10000
#define AL_FORMAT_IMA_ADPCM_STEREO16_EXT 0x10001
#define AL_FORMAT_WAVE_EXT 0x10002
#define AL_FORMAT_VORBIS_EXT 0x10003
/* four point formats */
#define AL_FORMAT_QUAD8_LOKI 0x10004
#define AL_FORMAT_QUAD16_LOKI 0x10005
/**
* token extensions, base 0x20000
*/
/**
* Indicate the gain (volume amplification) applied, in a
* normalized linear scale. This affects the value retrieved
* by AL_GAIN.
*
* Type: ALfloat.
* Range: ]0.0- ]
* A value of 1.0 means un-attenuated/unchanged.
* A value of 0.0 is interpreted as zero volume - the channel
* is effectively disabled.
*/
#define AL_GAIN_LINEAR_LOKI 0x20000
/*
* types for special loaders. This should be deprecated in favor
* of the special format tags.
*/
typedef struct WaveFMT {
ALushort encoding;
ALushort channels; /* 1 = mono, 2 = stereo */
ALuint frequency; /* One of 11025, 22050, or 44100 Hz */
ALuint byterate; /* Average bytes per second */
ALushort blockalign; /* Bytes per sample block */
ALushort bitspersample;
} alWaveFMT_LOKI;
typedef struct _MS_ADPCM_decodestate {
ALubyte hPredictor;
ALushort iDelta;
ALshort iSamp1;
ALshort iSamp2;
} alMSADPCM_decodestate_LOKI;
typedef struct MS_ADPCM_decoder {
alWaveFMT_LOKI wavefmt;
ALushort wSamplesPerBlock;
ALushort wNumCoef;
ALshort aCoeff[7][2];
/* * * */
alMSADPCM_decodestate_LOKI state[2];
} alMSADPCM_state_LOKI;
typedef struct IMA_ADPCM_decodestate_s {
ALint valprev; /* Previous output value */
ALbyte index; /* Index into stepsize table */
} alIMAADPCM_decodestate_LOKI;
typedef struct IMA_ADPCM_decoder {
alWaveFMT_LOKI wavefmt;
ALushort wSamplesPerBlock;
/* * * */
alIMAADPCM_decodestate_LOKI state[2];
} alIMAADPCM_state_LOKI;
/**
* Context creation extension tokens
* base 0x200000
*/
/**
* followed by ### of sources
*/
#define ALC_SOURCES_LOKI 0x200000
/**
* followed by ### of buffers
*/
#define ALC_BUFFERS_LOKI 0x200001
/*
* Channel operations are probably a big no-no and destined
* for obsolesence.
*
* base 0x300000
*/
#define ALC_CHAN_MAIN_LOKI 0x300000
#define ALC_CHAN_PCM_LOKI 0x300001
#define ALC_CHAN_CD_LOKI 0x300002
typedef void (*PFNALCSETAUDIOCHANNELPROC)(ALuint channel, ALfloat volume);
typedef ALfloat (*PFNALCGETAUDIOCHANNELPROC)(ALuint channel);
typedef void (*PFNALBOMBONERRORPROC)(void);
typedef void (*PFNALBUFFERIPROC)(ALuint bid, ALenum param, ALint value);
typedef void (*PFNALBUFFERDATAWITHCALLBACKPROC)(ALuint bid,
int (*Callback)(ALuint, ALuint, ALshort *, ALenum, ALint, ALint));
typedef void (*PFNALBUFFERWRITEDATAPROC)( ALuint buffer,
ALenum format,
ALvoid* data,
ALsizei size,
ALsizei freq,
ALenum internalFormat );
typedef void (*PFNALGENSTREAMINGBUFFERSPROC)( ALsizei n, ALuint *samples );
typedef ALsizei (*PFNALBUFFERAPPENDDATAPROC)( ALuint buffer,
ALenum format,
ALvoid* data,
ALsizei size,
ALsizei freq );
typedef ALsizei (*PFNALBUFFERAPPENDWRITEDATAPROC)( ALuint buffer,
ALenum format,
ALvoid* data,
ALsizei size,
ALsizei freq,
ALenum internalFormat );
/* captures */
typedef ALboolean (*PFNALCAPTUREINITPROC)( ALenum format, ALuint rate, ALsizei bufferSize );
typedef ALboolean (*PFNALCAPTUREDESTROYPROC)( ALvoid );
typedef ALboolean (*PFNALCAPTURESTARTPROC)( ALvoid );
typedef ALboolean (*PFNALCAPTURESTOPPROC)( ALvoid );
/* Non-blocking device read */
typedef ALsizei (*PFNALCAPTUREGETDATAPROC)( ALvoid* data, ALsizei n, ALenum format, ALuint rate );
/* vorbis */
typedef ALboolean (*PFNALUTLOADVORBISPROC)(ALuint bid, ALvoid *data, ALint size);
/* custom loaders */
typedef ALboolean (*PFNALUTLOADRAW_ADPCMDATAPROC)( ALuint bid,
ALvoid *data, ALuint size, ALuint freq,
ALenum format);
typedef ALboolean (*ALUTLOADIMA_ADPCMDATAPROC)(ALuint bid,
ALvoid *data, ALuint size,
alIMAADPCM_state_LOKI *ias);
typedef ALboolean (*ALUTLOADMS_ADPCMDATAPROC)(ALuint bid,
void *data, int size,
alMSADPCM_state_LOKI *mss);
#endif /* _LAL_EXTTYPES_H_ */

484
include/AL/altypes.h Normal file
View File

@ -0,0 +1,484 @@
#ifndef _AL_TYPES_H_
#define _AL_TYPES_H_
/* define platform type */
#if !defined(MACINTOSH_AL) && !defined(LINUX_AL) && !defined(WINDOWS_AL)
#ifdef __APPLE__
#define MACINTOSH_AL
#else
#ifdef _WIN32
#define WINDOWS_AL
#else
#define LINUX_AL
#endif
#endif
#endif
/** OpenAL bool type. */
typedef char ALboolean;
/** OpenAL 8bit signed byte. */
#ifdef LINUX_AL
typedef signed char ALbyte;
#else
typedef char ALbyte;
#endif
/** OpenAL 8bit unsigned byte. */
typedef unsigned char ALubyte;
/** OpenAL 16bit signed short integer type. */
typedef short ALshort;
/** OpenAL 16bit unsigned short integer type. */
typedef unsigned short ALushort;
/** OpenAL 32bit unsigned integer type. */
typedef unsigned int ALuint;
/** OpenAL 32bit signed integer type. */
typedef int ALint;
/** OpenAL 32bit floating point type. */
typedef float ALfloat;
/** OpenAL 64bit double point type. */
typedef double ALdouble;
/** OpenAL 32bit type. */
/** OpenAL 8bit signed byte. */
#ifdef LINUX_AL
typedef signed int ALsizei;
#else
typedef unsigned int ALsizei;
#endif
/** OpenAL void type (for params, not returns). */
#ifdef LINUX_AL
typedef void ALvoid;
#else
#define ALvoid void
#endif
/** OpenAL enumerations. */
typedef int ALenum;
/** OpenAL bitfields. */
typedef unsigned int ALbitfield;
/** OpenAL clamped float. */
typedef ALfloat ALclampf;
/** Openal clamped double. */
typedef ALdouble ALclampd;
/* Enumerant values begin at column 50. No tabs. */
/* bad value */
#define AL_INVALID -1
#define AL_NONE 0
/* Boolean False. */
#define AL_FALSE 0
/** Boolean True. */
#define AL_TRUE 1
/**
* Indicate the type of AL_SOURCE.
* Sources can be spatialized
*/
#define AL_SOURCE_TYPE 0x200
/** Indicate source has absolute coordinates. */
#define AL_SOURCE_ABSOLUTE 0x201
/** Indicate Source has relative coordinates. */
#define AL_SOURCE_RELATIVE 0x202
/**
* Directional source, inner cone angle, in degrees.
* Range: [0-360]
* Default: 360
*/
#define AL_CONE_INNER_ANGLE 0x1001
/**
* Directional source, outer cone angle, in degrees.
* Range: [0-360]
* Default: 360
*/
#define AL_CONE_OUTER_ANGLE 0x1002
/**
* Specify the pitch to be applied, either at source,
* or on mixer results, at listener.
* Range: [0.5-2.0]
* Default: 1.0
*/
#define AL_PITCH 0x1003
/**
* Specify the current location in three dimensional space.
* OpenAL, like OpenGL, uses a right handed coordinate system,
* where in a frontal default view X (thumb) points right,
* Y points up (index finger), and Z points towards the
* viewer/camera (middle finger).
* To switch from a left handed coordinate system, flip the
* sign on the Z coordinate.
* Listener position is always in the world coordinate system.
*/
#define AL_POSITION 0x1004
/** Specify the current direction. */
#define AL_DIRECTION 0x1005
/** Specify the current velocity in three dimensional space. */
#define AL_VELOCITY 0x1006
/**
* Indicate whether source is looping.
* Type: ALboolean?
* Range: [AL_TRUE, AL_FALSE]
* Default: FALSE.
*/
#define AL_LOOPING 0x1007
#ifdef LINUX_AL
/* no longer used -- will probably be removed */
/**
* Indicate whether source is meant to be streaming.
* Type: ALboolean?
* Range: [AL_TRUE, AL_FALSE]
* Default: FALSE.
*/
#define AL_STREAMING 0x1008
#endif
/**
* Indicate the buffer to provide sound samples.
* Type: ALuint.
* Range: any valid Buffer id.
*/
#define AL_BUFFER 0x1009
/**
* Indicate the gain (volume amplification) applied.
* Type: ALfloat.
* Range: ]0.0- ]
* A value of 1.0 means un-attenuated/unchanged.
* Each division by 2 equals an attenuation of -6dB.
* Each multiplicaton with 2 equals an amplification of +6dB.
* A value of 0.0 is meaningless with respect to a logarithmic
* scale; it is interpreted as zero volume - the channel
* is effectively disabled.
*/
#define AL_GAIN 0x100A
#ifdef LINUX_AL
/* byte offset into source (in canon format). -1 if source
* is not playing. Don't set this, get this.
*
* Type: ALint
* Range: -1 - +inf
*/
#define AL_BYTE_LOKI 0x100C
#endif
/*
* Indicate minimum source attenuation
* Type: ALfloat
* Range: [0.0 - 1.0]
*
* Logarthmic
*/
#define AL_MIN_GAIN 0x100D
/**
* Indicate maximum source attenuation
* Type: ALfloat
* Range: [0.0 - 1.0]
*
* Logarthmic
*/
#define AL_MAX_GAIN 0x100E
/**
* Indicate listener orientation.
*
* at/up
*/
#define AL_ORIENTATION 0x100F
/**
* Specify the channel mask. (Creative)
* Type: ALuint
* Range: [0 - 255]
*/
#define AL_CHANNEL_MASK 0x3000
/**
* Source state information.
*/
#define AL_SOURCE_STATE 0x1010
#define AL_INITIAL 0x1011
#define AL_PLAYING 0x1012
#define AL_PAUSED 0x1013
#define AL_STOPPED 0x1014
/**
* Buffer Queue params
*/
#define AL_BUFFERS_QUEUED 0x1015
#define AL_BUFFERS_PROCESSED 0x1016
/** Sound samples: format specifier. */
#define AL_FORMAT_MONO8 0x1100
#define AL_FORMAT_MONO16 0x1101
#define AL_FORMAT_STEREO8 0x1102
#define AL_FORMAT_STEREO16 0x1103
/**
* source specific reference distance
* Type: ALfloat
* Range: 0.0 - +inf
*
* At 0.0, no distance attenuation occurs. Default is
* 1.0.
*/
#define AL_REFERENCE_DISTANCE 0x1020
/**
* source specific rolloff factor
* Type: ALfloat
* Range: 0.0 - +inf
*
*/
#define AL_ROLLOFF_FACTOR 0x1021
/**
* Directional source, outer cone gain.
*
* Default: 0.0
* Range: [0.0 - 1.0]
* Logarithmic
*/
#define AL_CONE_OUTER_GAIN 0x1022
/**
* Indicate distance above which sources are not
* attenuated using the inverse clamped distance model.
*
* Default: +inf
* Type: ALfloat
* Range: 0.0 - +inf
*/
#define AL_MAX_DISTANCE 0x1023
/**
* Sound samples: frequency, in units of Hertz [Hz].
* This is the number of samples per second. Half of the
* sample frequency marks the maximum significant
* frequency component.
*/
#define AL_FREQUENCY 0x2001
#define AL_BITS 0x2002
#define AL_CHANNELS 0x2003
#define AL_SIZE 0x2004
#define AL_DATA 0x2005
/**
* Buffer state.
*
* Not supported for public use (yet).
*/
#define AL_UNUSED 0x2010
#define AL_PENDING 0x2011
#define AL_PROCESSED 0x2012
/** Errors: No Error. */
#define AL_NO_ERROR AL_FALSE
/**
* Invalid Name paramater passed to AL call.
*/
#define AL_INVALID_NAME 0xA001
/**
* Invalid parameter passed to AL call.
*/
#define AL_ILLEGAL_ENUM 0xA002
#define AL_INVALID_ENUM 0xA002
/**
* Invalid enum parameter value.
*/
#define AL_INVALID_VALUE 0xA003
/**
* Illegal call.
*/
#define AL_ILLEGAL_COMMAND 0xA004
#define AL_INVALID_OPERATION 0xA004
/**
* No mojo.
*/
#define AL_OUT_OF_MEMORY 0xA005
/** Context strings: Vendor Name. */
#define AL_VENDOR 0xB001
#define AL_VERSION 0xB002
#define AL_RENDERER 0xB003
#define AL_EXTENSIONS 0xB004
/** Global tweakage. */
/**
* Doppler scale. Default 1.0
*/
#define AL_DOPPLER_FACTOR 0xC000
/**
* Tweaks speed of propagation.
*/
#define AL_DOPPLER_VELOCITY 0xC001
#ifdef LINUX_AL
/* no longer used -- will probably be removed */
/**
* Distance scaling
*/
#define AL_DISTANCE_SCALE 0xC002
#endif
/**
* Distance models
*
* used in conjunction with DistanceModel
*
* implicit: NONE, which disances distance attenuation.
*/
#define AL_DISTANCE_MODEL 0xD000
#define AL_INVERSE_DISTANCE 0xD001
#define AL_INVERSE_DISTANCE_CLAMPED 0xD002
#ifdef LINUX_AL
/* all the IASIG stuff was never used -- will probably be removed */
/**
* enables
*/
/* #define AL_SOME_ENABLE 0xE000 */
/** IASIG Level 2 Environment. */
/**
* Parameter: IASIG ROOM blah
* Type: intgeger
* Range: [-10000, 0]
* Default: -10000
*/
#define AL_ENV_ROOM_IASIG 0x3001
/**
* Parameter: IASIG ROOM_HIGH_FREQUENCY
* Type: integer
* Range: [-10000, 0]
* Default: 0
*/
#define AL_ENV_ROOM_HIGH_FREQUENCY_IASIG 0x3002
/**
* Parameter: IASIG ROOM_ROLLOFF_FACTOR
* Type: float
* Range: [0.0, 10.0]
* Default: 0.0
*/
#define AL_ENV_ROOM_ROLLOFF_FACTOR_IASIG 0x3003
/**
* Parameter: IASIG DECAY_TIME
* Type: float
* Range: [0.1, 20.0]
* Default: 1.0
*/
#define AL_ENV_DECAY_TIME_IASIG 0x3004
/**
* Parameter: IASIG DECAY_HIGH_FREQUENCY_RATIO
* Type: float
* Range: [0.1, 2.0]
* Default: 0.5
*/
#define AL_ENV_DECAY_HIGH_FREQUENCY_RATIO_IASIG 0x3005
/**
* Parameter: IASIG REFLECTIONS
* Type: integer
* Range: [-10000, 1000]
* Default: -10000
*/
#define AL_ENV_REFLECTIONS_IASIG 0x3006
/**
* Parameter: IASIG REFLECTIONS_DELAY
* Type: float
* Range: [0.0, 0.3]
* Default: 0.02
*/
#define AL_ENV_REFLECTIONS_DELAY_IASIG 0x3006
/**
* Parameter: IASIG REVERB
* Type: integer
* Range: [-10000,2000]
* Default: -10000
*/
#define AL_ENV_REVERB_IASIG 0x3007
/**
* Parameter: IASIG REVERB_DELAY
* Type: float
* Range: [0.0, 0.1]
* Default: 0.04
*/
#define AL_ENV_REVERB_DELAY_IASIG 0x3008
/**
* Parameter: IASIG DIFFUSION
* Type: float
* Range: [0.0, 100.0]
* Default: 100.0
*/
#define AL_ENV_DIFFUSION_IASIG 0x3009
/**
* Parameter: IASIG DENSITY
* Type: float
* Range: [0.0, 100.0]
* Default: 100.0
*/
#define AL_ENV_DENSITY_IASIG 0x300A
/**
* Parameter: IASIG HIGH_FREQUENCY_REFERENCE
* Type: float
* Range: [20.0, 20000.0]
* Default: 5000.0
*/
#define AL_ENV_HIGH_FREQUENCY_REFERENCE_IASIG 0x300B
#endif
#endif

61
include/AL/alu.h Normal file
View File

@ -0,0 +1,61 @@
#ifndef __alu_h_
#define __alu_h_
#ifdef _WIN32
#define ALUAPI
#define ALUAPIENTRY __cdecl
#define BUFFERSIZE 48000
#define FRACTIONBITS 14
#define FRACTIONMASK ((1L<<FRACTIONBITS)-1)
#define OUTPUTCHANNELS 2
#else /* _WIN32 */
#ifdef TARGET_OS_MAC
#if TARGET_OS_MAC
#pragma export on
#endif /* TARGET_OS_MAC */
#endif /* TARGET_OS_MAC */
#define ALAPI
#define ALAPIENTRY
#define AL_CALLBACK
#endif /* _WIN32 */
#if defined(__MACH__) && defined(__APPLE__)
#include <OpenAL/al.h>
#include <OpenAL/alutypes.h>
#else
#include <AL/al.h>
#include <AL/alutypes.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _WIN32
ALUAPI ALint ALUAPIENTRY aluF2L(ALfloat value);
ALUAPI ALshort ALUAPIENTRY aluF2S(ALfloat value);
ALUAPI ALvoid ALUAPIENTRY aluCrossproduct(ALfloat *inVector1,ALfloat *inVector2,ALfloat *outVector);
ALUAPI ALfloat ALUAPIENTRY aluDotproduct(ALfloat *inVector1,ALfloat *inVector2);
ALUAPI ALvoid ALUAPIENTRY aluNormalize(ALfloat *inVector);
ALUAPI ALvoid ALUAPIENTRY aluMatrixVector(ALfloat *vector,ALfloat matrix[3][3]);
ALUAPI ALvoid ALUAPIENTRY aluCalculateSourceParameters(ALuint source,ALuint channels,ALfloat *drysend,ALfloat *wetsend,ALfloat *pitch);
ALUAPI ALvoid ALUAPIENTRY aluMixData(ALvoid *context,ALvoid *buffer,ALsizei size,ALenum format);
ALUAPI ALvoid ALUAPIENTRY aluSetReverb(ALvoid *Reverb,ALuint Environment);
ALUAPI ALvoid ALUAPIENTRY aluReverb(ALvoid *Reverb,ALfloat Buffer[][2],ALsizei BufferSize);
#endif
#ifdef TARGET_OS_MAC
#if TARGET_OS_MAC
#pragma export off
#endif /* TARGET_OS_MAC */
#endif /* TARGET_OS_MAC */
#ifdef __cplusplus
}
#endif
#endif /* __alu_h_ */

101
include/AL/alut.h Normal file
View File

@ -0,0 +1,101 @@
#ifndef _ALUT_H_
#define _ALUT_H_
/* define platform type */
#if !defined(MACINTOSH_AL) && !defined(LINUX_AL) && !defined(WINDOWS_AL)
#ifdef __APPLE__
#define MACINTOSH_AL
#else
#ifdef _WIN32
#define WINDOWS_AL
#else
#define LINUX_AL
#endif
#endif
#endif
#include "altypes.h"
#include "aluttypes.h"
#ifdef _WIN32
#define ALUTAPI
#define ALUTAPIENTRY __cdecl
#define AL_CALLBACK
#else /* _WIN32 */
#ifdef TARGET_OS_MAC
#if TARGET_OS_MAC
#pragma export on
#endif /* TARGET_OS_MAC */
#endif /* TARGET_OS_MAC */
#ifndef ALUTAPI
#define ALUTAPI
#endif
#ifndef ALUTAPIENTRY
#define ALUTAPIENTRY
#endif
#ifndef AL_CALLBACK
#define AL_CALLBACK
#endif
#endif /* _WIN32 */
#ifdef __cplusplus
extern "C" {
#endif
#ifndef AL_NO_PROTOTYPES
ALUTAPI void ALUTAPIENTRY alutInit(int *argc, char *argv[]);
ALUTAPI void ALUTAPIENTRY alutExit(ALvoid);
#ifdef LINUX_AL
/* this function is Linux-specific and will probably be removed from this header */
ALUTAPI ALboolean ALUTAPIENTRY alutLoadWAV( const char *fname, ALvoid **wave, ALsizei *format, ALsizei *size, ALsizei *bits, ALsizei *freq );
#endif
#ifndef MACINTOSH_AL
/* Windows and Linux versions have a loop parameter, Macintosh doesn't */
ALUTAPI void ALUTAPIENTRY alutLoadWAVFile(ALbyte *file, ALenum *format, ALvoid **data, ALsizei *size, ALsizei *freq, ALboolean *loop);
ALUTAPI void ALUTAPIENTRY alutLoadWAVMemory(ALbyte *memory, ALenum *format, ALvoid **data, ALsizei *size, ALsizei *freq, ALboolean *loop);
#else
ALUTAPI void ALUTAPIENTRY alutLoadWAVFile(ALbyte *file, ALenum *format, ALvoid **data, ALsizei *size, ALsizei *freq);
ALUTAPI void ALUTAPIENTRY alutLoadWAVMemory(ALbyte *memory, ALenum *format, ALvoid **data, ALsizei *size, ALsizei *freq);
#endif
ALUTAPI void ALUTAPIENTRY alutUnloadWAV(ALenum format, ALvoid *data, ALsizei size, ALsizei freq);
#else
ALUTAPI void ALUTAPIENTRY (*alutInit)(int *argc, char *argv[]);
ALUTAPI void ALUTAPIENTRY (*alutExit)(ALvoid);
#ifdef LINUX_AL
/* this function is Linux-specific and will probably be removed from this header */
ALUTAPI ALboolean ALUTAPIENTRY (*alutLoadWAV)( const char *fname, ALvoid **wave, ALsizei *format, ALsizei *size, ALsizei *bits, ALsizei *freq );
#endif
#ifndef MACINTOSH_AL
ALUTAPI void ALUTAPIENTRY (*alutLoadWAVFile(ALbyte *file,ALenum *format,ALvoid **data,ALsizei *size,ALsizei *freq,ALboolean *loop);
ALUTAPI void ALUTAPIENTRY (*alutLoadWAVMemory)(ALbyte *memory,ALenum *format,ALvoid **data,ALsizei *size,ALsizei *freq,ALboolean *loop);
#else
ALUTAPI void ALUTAPIENTRY (*alutLoadWAVFile(ALbyte *file,ALenum *format,ALvoid **data,ALsizei *size,ALsizei *freq);
ALUTAPI void ALUTAPIENTRY (*alutLoadWAVMemory)(ALbyte *memory,ALenum *format,ALvoid **data,ALsizei *size,ALsizei *freq);
#endif
ALUTAPI void ALUTAPIENTRY (*alutUnloadWAV)(ALenum format,ALvoid *data,ALsizei size,ALsizei freq);
#endif /* AL_NO_PROTOTYPES */
#ifdef TARGET_OS_MAC
#if TARGET_OS_MAC
#pragma export off
#endif /* TARGET_OS_MAC */
#endif /* TARGET_OS_MAC */
#ifdef __cplusplus
}
#endif
#endif

6
include/AL/aluttypes.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef _ALUTTYPES_H_
#define _ALUTTYPES_H_
#define AL_PROVIDES_ALUT 1
#endif /* _ALUTTYPES_H_ */

5
include/AL/alutypes.h Normal file
View File

@ -0,0 +1,5 @@
#ifndef _ALUTYPES_H_
#define _ALUTYPES_H_
#endif /* _ALUTYPES_H_ */

62
src/Makefile Normal file
View File

@ -0,0 +1,62 @@
# Copyright (C) 2004 Christopher John Purnell
# cjp@lost.org.uk
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
SONAME = libopenal.so.0
SUFFIX = 1.2
LIB=$(SONAME).$(SUFFIX)
PIC=-fPIC
CC=gcc
#CFLAGS=-O2 -W -Wall -Wmissing-prototypes -Werror $(PIC)
CFLAGS=-O2 -W -Wall -Wmissing-prototypes $(PIC)
LIBS=-lasound -lpthread -lm
SHARED=-shared -Wl,-soname,$(SONAME)
CPPFLAGS=-I../include
OFILES= al_listener.o al_source.o al_buffer.o al_play.o al_able.o al_state.o \
al_doppler.o al_distance.o al_error.o al_ext.o al_vector.o \
alc_context.o alc_speaker.o alc_device.o alc_state.o alc_error.o \
alc_ext.o alut_main.o alut_wav.o
CFILES= al_listener.c al_source.c al_buffer.c al_play.c al_able.c al_state.c \
al_doppler.c al_distance.c al_error.c al_ext.c al_vector.c \
alc_context.c alc_speaker.c alc_device.c alc_state.c alc_error.c \
alc_ext.c alut_main.c alut_wav.c
all: $(LIB)
$(LIB): $(OFILES)
$(CC) $(SHARED) -o $(LIB) $(OFILES) $(LIBS)
.c.o:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
distclean: clean
rm -f $(LIB) $(PROGS) .depend
clean: tidy
rm -f *.o
tidy:
rm -f *~ *.bak *.orig
depend:
$(CC) $(CPPFLAGS) -M $(CFILES) > .depend
ifeq (.depend, $(wildcard .depend))
include .depend
endif

38
src/al_able.c Normal file
View File

@ -0,0 +1,38 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <ansidecl.h>
#include "al_error.h"
ALvoid alEnable(ALenum cap ATTRIBUTE_UNUSED)
{
_alSetError(AL_ILLEGAL_ENUM);
}
ALvoid alDisable(ALenum cap ATTRIBUTE_UNUSED)
{
_alSetError(AL_ILLEGAL_ENUM);
}
ALboolean alIsEnabled(ALenum cap ATTRIBUTE_UNUSED)
{
_alSetError(AL_ILLEGAL_ENUM);
return AL_FALSE;
}

462
src/al_buffer.c Normal file
View File

@ -0,0 +1,462 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <sys/types.h>
#include <stdlib.h>
#include <alloca.h>
#include <pthread.h>
#include "al_buffer.h"
#include "al_error.h"
#define HASH_SIZE 0x100
#define HASH_MASK 0x0FF
static pthread_mutex_t _al_buffer_mutex = PTHREAD_MUTEX_INITIALIZER;
static ALuint _al_last_buffer_id = 0;
static AL_buffer *_al_buffers[HASH_SIZE];
static AL_buffer *_alFindBuffer(ALuint bid)
{
AL_buffer *buf;
for (buf = _al_buffers[bid & HASH_MASK]; buf; buf = buf->next)
{
if (buf->id == bid)
{
return buf;
}
}
return 0;
}
AL_buffer *_alLockBuffer(ALuint bid)
{
AL_buffer *buf;
pthread_mutex_lock(&_al_buffer_mutex);
if ((buf = _alFindBuffer(bid)))
{
buf->used++;
}
pthread_mutex_unlock(&_al_buffer_mutex);
return buf;
}
ALvoid _alUnlockBuffer(AL_buffer *buf)
{
pthread_mutex_lock(&_al_buffer_mutex);
buf->used--;
pthread_mutex_unlock(&_al_buffer_mutex);
}
static AL_buffer *_alGenBuffer(ALvoid)
{
AL_buffer *buf;
ALuint bid;
if (!(buf = malloc(sizeof(AL_buffer))))
{
_alSetError(AL_OUT_OF_MEMORY);
return 0;
}
buf->used = 0;
buf->data = 0;
buf->size = 0;
buf->freq = 0;
bid = _al_last_buffer_id;
while (!++bid || _alFindBuffer(bid));
_al_last_buffer_id = bid;
buf->id = bid;
buf->next = _al_buffers[bid & HASH_MASK];
_al_buffers[bid & HASH_MASK] = buf;
return buf;
}
static ALvoid _alDeleteBuffer(AL_buffer *buf)
{
AL_buffer *b, **p;
for (p = &_al_buffers[buf->id & HASH_MASK]; (b = *p); p = &b->next)
{
if (b->id == buf->id)
{
*p = b->next;
break;
}
}
if (buf->data) free(buf->data);
free(buf);
}
ALvoid alGenBuffers(ALsizei n, ALuint *buffers)
{
ALsizei i;
AL_buffer **temp;
if (n == 0)
return;
if (n < 0)
{
_alSetError(AL_INVALID_VALUE);
return;
}
temp = alloca(n * sizeof(AL_buffer *));
pthread_mutex_lock(&_al_buffer_mutex);
for (i = 0; i < n; i++)
{
if (!(temp[i] = _alGenBuffer()))
{
ALsizei j;
for (j = 0; j < i; j++)
{
_alDeleteBuffer(temp[j]);
}
goto unlock;
}
}
for (i = 0; i < n; i++)
{
buffers[i] = temp[i]->id;
}
unlock:
pthread_mutex_unlock(&_al_buffer_mutex);
}
ALvoid alDeleteBuffers(ALsizei n, ALuint *buffers)
{
ALsizei i;
AL_buffer **temp;
if (n == 0)
{
return;
}
if (n < 0)
{
_alSetError(AL_INVALID_VALUE);
return;
}
temp = alloca(n * sizeof(AL_buffer *));
pthread_mutex_lock(&_al_buffer_mutex);
for (i = 0; i < n; i++)
{
if (!(temp[i] = _alFindBuffer(buffers[i])))
{
_alSetError(AL_INVALID_NAME);
goto unlock;
}
if (temp[i]->used)
{
_alSetError(AL_INVALID_OPERATION);
goto unlock;
}
}
for (i = 0; i < n; i++)
{
_alDeleteBuffer(temp[i]);
}
unlock:
pthread_mutex_unlock(&_al_buffer_mutex);
}
ALboolean alIsBuffer(ALuint bid)
{
ALboolean value;
pthread_mutex_lock(&_al_buffer_mutex);
value = _alFindBuffer(bid) ? AL_TRUE : AL_FALSE;
pthread_mutex_unlock(&_al_buffer_mutex);
return value;
}
static ALvoid _alBufferMono8(AL_buffer *buf, ALvoid *data,
ALsizei size, ALsizei freq)
{
ALvoid *copy;
ALsizei frames = size;
if (!(copy = malloc(frames << 2)))
{
_alSetError(AL_OUT_OF_MEMORY);
return;
}
{
__uint8_t *from = data;
__int16_t *to = copy;
ALsizei i;
for (i = 0; i < frames; i++)
{
__int16_t value = (*(from++) - 128) << 8;
*(to++) = value;
*(to++) = value;
}
}
buf->data = copy;
buf->size = frames;
buf->freq = freq;
}
static ALvoid _alBufferMono16(AL_buffer *buf, ALvoid *data,
ALsizei size, ALsizei freq)
{
ALvoid *copy;
ALsizei frames = size >> 1;
if (!(copy = malloc(frames << 2)))
{
_alSetError(AL_OUT_OF_MEMORY);
return;
}
{
__int16_t *from = data;
__int16_t *to = copy;
ALsizei i;
for (i = 0; i < frames; i++)
{
__int16_t value = *(from++);
*(to++) = value;
*(to++) = value;
}
}
buf->data = copy;
buf->size = frames;
buf->freq = freq;
}
static ALvoid _alBufferStereo8(AL_buffer *buf, ALvoid *data,
ALsizei size, ALsizei freq)
{
ALvoid *copy;
ALsizei frames = size >> 1;
if (!(copy = malloc(frames << 2)))
{
_alSetError(AL_OUT_OF_MEMORY);
return;
}
{
__uint8_t *from = data;
__int16_t *to = copy;
ALsizei i;
for (i = 0; i < frames; i++)
{
*(to++) = (*(from++) - 128) << 8;
*(to++) = (*(from++) - 128) << 8;
}
}
buf->data = copy;
buf->size = frames;
buf->freq = freq;
}
static ALvoid _alBufferStereo16(AL_buffer *buf, ALvoid *data,
ALsizei size, ALsizei freq)
{
ALvoid *copy;
ALsizei frames = size >> 2;
if (!(copy = malloc(frames << 2)))
{
_alSetError(AL_OUT_OF_MEMORY);
return;
}
{
__int32_t *from = data;
__int32_t *to = copy;
ALsizei i;
for (i = 0; i < frames; i++)
{
*(to++) = *(from++);
}
}
buf->data = copy;
buf->size = frames;
buf->freq = freq;
}
ALvoid alBufferData(ALuint bid, ALenum format, ALvoid *data,
ALsizei size, ALsizei freq)
{
AL_buffer *buf;
if (!(buf = _alLockBuffer(bid)))
{
_alSetError(AL_INVALID_NAME);
return;
}
if (buf->used > 1)
{
_alSetError(AL_INVALID_OPERATION);
goto unlock;
}
if (buf->data)
{
free(buf->data);
buf->data = 0;
buf->size = 0;
}
switch (format)
{
case AL_FORMAT_MONO8:
_alBufferMono8(buf, data, size, freq);
break;
case AL_FORMAT_MONO16:
_alBufferMono16(buf, data, size, freq);
break;
case AL_FORMAT_STEREO8:
_alBufferStereo8(buf, data, size, freq);
break;
case AL_FORMAT_STEREO16:
_alBufferStereo16(buf, data, size, freq);
break;
default:
_alSetError(AL_INVALID_ENUM);
break;
}
unlock:
_alUnlockBuffer(buf);
}
ALvoid alGetBufferi(ALuint bid, ALenum param, ALint *value)
{
AL_buffer *buf;
pthread_mutex_lock(&_al_buffer_mutex);
if (!(buf = _alFindBuffer(bid)))
{
_alSetError(AL_INVALID_NAME);
goto unlock;
}
switch (param)
{
case AL_FREQUENCY:
*value = (ALint)buf->freq;
break;
case AL_BITS:
*value = 16;
break;
case AL_CHANNELS:
*value = 2;
break;
case AL_SIZE:
*value = (ALint)(buf->size << 2);
break;
default:
_alSetError(AL_INVALID_ENUM);
break;
}
unlock:
pthread_mutex_unlock(&_al_buffer_mutex);
}
ALvoid alGetBufferf(ALuint bid, ALenum param, ALfloat *value)
{
AL_buffer *buf;
pthread_mutex_lock(&_al_buffer_mutex);
if (!(buf = _alLockBuffer(bid)))
{
_alSetError(AL_INVALID_NAME);
goto unlock;
}
switch (param)
{
case AL_FREQUENCY:
*value = (ALfloat)buf->freq;
break;
case AL_BITS:
*value = 16.0f;
break;
case AL_CHANNELS:
*value = 2.0f;
break;
case AL_SIZE:
*value = (ALfloat)(buf->size << 2);
break;
default:
_alSetError(AL_INVALID_ENUM);
break;
}
unlock:
pthread_mutex_lock(&_al_buffer_mutex);
}
ALvoid alGetBufferiv(ALuint bid, ALenum param, ALint *values)
{
alGetBufferi(bid, param, values);
}
ALvoid alGetBufferfv(ALuint bid, ALenum param, ALfloat *values)
{
alGetBufferf(bid, param, values);
}

40
src/al_buffer.h Normal file
View File

@ -0,0 +1,40 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _AL_BUFFER_H_
#define _AL_BUFFER_H_
#include <AL/al.h>
#include <AL/alc.h>
typedef struct _AL_buffer
{
struct _AL_buffer *next;
ALuint id;
ALuint used;
int32_t *data;
ALuint size;
ALuint freq;
}
AL_buffer;
AL_buffer *_alLockBuffer(ALuint);
ALvoid _alUnlockBuffer(AL_buffer *);
#endif

93
src/al_distance.c Normal file
View File

@ -0,0 +1,93 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "al_source.h"
#include "al_error.h"
#include "alc_context.h"
static ALfloat _alDistanceNone(AL_source *src, ALfloat dist ATTRIBUTE_UNUSED)
{
return src->gain;
}
ALfloat _alDistanceInverse(AL_source *src, ALfloat dist)
{
ALfloat ref = src->reference_distance;
if (dist < ref)
{
dist = ref;
}
return src->gain * ref / (ref + src->rolloff_factor * (dist - ref));
}
static ALfloat _alDistanceInverseClamped(AL_source *src, ALfloat dist)
{
ALfloat ref = src->reference_distance;
if (dist < ref)
{
dist = ref;
}
if (dist > src->max_distance)
{
dist = src->max_distance;
}
return src->gain * ref / (ref + src->rolloff_factor * (dist - ref));
}
ALvoid alDistanceModel(ALenum model)
{
AL_context *ctx;
ALfloat (*df)(AL_source *, ALfloat);
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
switch (model)
{
case AL_NONE:
df = _alDistanceNone;
break;
case AL_INVERSE_DISTANCE:
df = _alDistanceInverse;
break;
case AL_INVERSE_DISTANCE_CLAMPED:
df = _alDistanceInverseClamped;
break;
default:
_alSetError(AL_ILLEGAL_ENUM);
goto unlock;
}
ctx->distance_model = model;
ctx->distance_func = df;
unlock:
_alcUnlockContext(ctx);
}

55
src/al_doppler.c Normal file
View File

@ -0,0 +1,55 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "alc_context.h"
#include "al_error.h"
ALvoid alDopplerFactor(ALfloat value)
{
AL_context *ctx;
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
_alRangedAssign1(ctx->doppler_factor, value, 0.0f);
_alcUnlockContext(ctx);
}
ALvoid alDopplerVelocity(ALfloat value)
{
AL_context *ctx;
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
_alRangedAssign1(ctx->doppler_velocity, value, 0.0f);
_alcUnlockContext(ctx);
}

37
src/al_error.c Normal file
View File

@ -0,0 +1,37 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "al_error.h"
static ALenum __al_error = AL_NO_ERROR;
ALenum alGetError(ALvoid)
{
ALenum err = __al_error;
__al_error = AL_NO_ERROR;
return err;
}
ALvoid _alSetError(ALenum err)
{
if (__al_error == AL_NO_ERROR)
{
__al_error = err;
}
}

42
src/al_error.h Normal file
View File

@ -0,0 +1,42 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _AL_ERROR_H_
#define _AL_ERROR_H_
#include <AL/al.h>
extern ALvoid _alSetError(ALenum);
#define _alRangedAssignB(x, v) \
x = v ? AL_TRUE : AL_FALSE
#define _alRangedAssign1(x, v, lo) \
if (v < lo) \
_alSetError(AL_INVALID_VALUE); \
else \
x = (ALfloat)v
#define _alRangedAssign2(x, v, lo, hi) \
if (v < lo || v > hi) \
_alSetError(AL_INVALID_VALUE); \
else \
x = (ALfloat)v
#endif

140
src/al_ext.c Normal file
View File

@ -0,0 +1,140 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <string.h>
#include <ansidecl.h>
#include <AL/al.h>
#include <AL/alc.h>
static struct { const ALubyte *name; ALenum value; } _al_enums[]= {
{ "AL_INVALID", AL_INVALID },
{ "AL_NONE", AL_NONE },
{ "AL_FALSE", AL_FALSE },
{ "AL_TRUE", AL_TRUE },
{ "ALC_INVALID", ALC_INVALID },
{ "ALC_TRUE", ALC_TRUE },
{ "ALC_FALSE", ALC_FALSE },
{ "AL_SOURCE_RELATIVE", AL_SOURCE_RELATIVE },
{ "AL_CONE_INNER_ANGLE", AL_CONE_INNER_ANGLE },
{ "AL_CONE_OUTER_ANGLE", AL_CONE_OUTER_ANGLE },
{ "AL_PITCH", AL_PITCH },
{ "AL_POSITION", AL_POSITION },
{ "AL_DIRECTION", AL_DIRECTION },
{ "AL_VELOCITY", AL_VELOCITY },
{ "AL_LOOPING", AL_LOOPING },
{ "AL_BUFFER", AL_BUFFER },
{ "AL_GAIN", AL_GAIN },
{ "AL_MIN_GAIN", AL_MIN_GAIN },
{ "AL_MAX_GAIN", AL_MAX_GAIN },
{ "AL_ORIENTATION", AL_ORIENTATION },
{ "AL_REFERENCE_DISTANCE", AL_REFERENCE_DISTANCE },
{ "AL_ROLLOFF_FACTOR", AL_ROLLOFF_FACTOR },
{ "AL_CONE_OUTER_GAIN", AL_CONE_OUTER_GAIN },
{ "AL_MAX_DISTANCE", AL_MAX_DISTANCE },
{ "AL_SOURCE_STATE", AL_SOURCE_STATE },
{ "AL_INITIAL", AL_INITIAL },
{ "AL_PLAYING", AL_PLAYING },
{ "AL_PAUSED", AL_PAUSED },
{ "AL_STOPPED", AL_STOPPED },
{ "AL_BUFFERS_QUEUED", AL_BUFFERS_QUEUED },
{ "AL_BUFFERS_PROCESSED", AL_BUFFERS_PROCESSED },
{ "AL_FORMAT_MONO8", AL_FORMAT_MONO8 },
{ "AL_FORMAT_MONO16", AL_FORMAT_MONO16 },
{ "AL_FORMAT_STEREO8", AL_FORMAT_STEREO8 },
{ "AL_FORMAT_STEREO16", AL_FORMAT_STEREO16 },
{ "AL_FREQUENCY", AL_FREQUENCY },
{ "AL_BITS", AL_BITS },
{ "AL_CHANNELS", AL_CHANNELS },
{ "AL_SIZE", AL_SIZE },
{ "AL_DATA", AL_DATA },
{ "AL_UNUSED", AL_UNUSED },
{ "AL_PENDING", AL_PENDING },
{ "AL_PROCESSED", AL_PROCESSED },
{ "ALC_MAJOR_VERSION", ALC_MAJOR_VERSION },
{ "ALC_MINOR_VERSION", ALC_MINOR_VERSION },
{ "ALC_ATTRIBUTES_SIZE", ALC_ATTRIBUTES_SIZE },
{ "ALC_ALL_ATTRIBUTES", ALC_ALL_ATTRIBUTES },
{ "ALC_DEFAULT_DEVICE_SPECIFIER", ALC_DEFAULT_DEVICE_SPECIFIER },
{ "ALC_DEVICE_SPECIFIER", ALC_DEVICE_SPECIFIER },
{ "ALC_EXTENSIONS", ALC_EXTENSIONS },
{ "ALC_FREQUENCY", ALC_FREQUENCY },
{ "ALC_REFRESH", ALC_REFRESH },
{ "ALC_SYNC", ALC_SYNC },
{ "AL_NO_ERROR", AL_NO_ERROR },
{ "AL_INVALID_NAME", AL_INVALID_NAME },
{ "AL_INVALID_ENUM", AL_INVALID_ENUM },
{ "AL_INVALID_VALUE", AL_INVALID_VALUE },
{ "AL_INVALID_OPERATION", AL_INVALID_OPERATION },
{ "AL_OUT_OF_MEMORY", AL_OUT_OF_MEMORY },
{ "ALC_NO_ERROR", ALC_NO_ERROR },
{ "ALC_INVALID_DEVICE", ALC_INVALID_DEVICE },
{ "ALC_INVALID_CONTEXT", ALC_INVALID_CONTEXT },
{ "ALC_INVALID_ENUM", ALC_INVALID_ENUM },
{ "ALC_INVALID_VALUE", ALC_INVALID_VALUE },
{ "ALC_OUT_OF_MEMORY", ALC_OUT_OF_MEMORY },
{ "AL_VENDOR", AL_VENDOR },
{ "AL_VERSION", AL_VERSION },
{ "AL_RENDERER", AL_RENDERER },
{ "AL_EXTENSIONS", AL_EXTENSIONS },
{ "AL_DOPPLER_FACTOR", AL_DOPPLER_FACTOR },
{ "AL_DOPPLER_VELOCITY", AL_DOPPLER_VELOCITY },
{ "AL_DISTANCE_MODEL", AL_DISTANCE_MODEL },
{ "AL_INVERSE_DISTANCE", AL_INVERSE_DISTANCE },
{ "AL_INVERSE_DISTANCE_CLAMPED", AL_INVERSE_DISTANCE_CLAMPED },
{ 0, 0 }
};
ALboolean alIsExtensionPresent(const ALubyte *name ATTRIBUTE_UNUSED)
{
return AL_FALSE;
}
ALvoid *alGetProcAddress(const ALubyte *name ATTRIBUTE_UNUSED)
{
return 0;
}
ALenum alGetEnumValue(const ALubyte *name)
{
ALuint i=0;
while ((_al_enums[i].name) && strcmp(_al_enums[i].name, name))
{
i++;
}
return _al_enums[i].value;
}

300
src/al_listener.c Normal file
View File

@ -0,0 +1,300 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "al_listener.h"
#include "al_error.h"
#include "al_vector.h"
#include "alc_context.h"
static ALvoid _alListenerSetSpeakers(AL_listener *listener,
AL_speaker *speakers)
{
ALfloat matrix[9];
ALuint i;
_alVectorCrossProduct(matrix + 0, listener->orientation,
listener->orientation + 3);
_alVectorNormalize(matrix + 0, matrix + 0);
_alVectorCrossProduct(matrix + 3, listener->orientation + 0,
matrix + 0);
_alVectorNormalize(matrix + 3, matrix + 3);
_alVectorNormalize(matrix + 6, listener->orientation + 0);
for (i = 0; i < _ALC_NUM_SPEAKERS; i++)
{
_alVectorMatrix(listener->speakers[i].position,
speakers[i].position, matrix);
}
}
ALvoid _alInitListener(AL_listener *listener, AL_speaker *speakers)
{
ALuint i;
listener->gain = 1.0f;
listener->position[0] = 0.0f;
listener->position[1] = 0.0f;
listener->position[2] = 0.0f;
listener->velocity[0] = 0.0f;
listener->velocity[1] = 0.0f;
listener->velocity[2] = 0.0f;
listener->orientation[0] = 0.0f;
listener->orientation[1] = 0.0f;
listener->orientation[2] = 0.0f;
listener->orientation[3] = 0.0f;
listener->orientation[4] = 0.0f;
listener->orientation[5] = 0.0f;
for (i = 0; i < _ALC_NUM_SPEAKERS; i++)
{
listener->speakers[i].gain = speakers[i].gain;
}
_alListenerSetSpeakers(listener, speakers);
}
ALvoid alListeneri(ALenum pname, ALint value)
{
alListenerf(pname, (ALfloat)value);
}
ALvoid alListenerf(ALenum pname, ALfloat value)
{
AL_context *ctx;
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
switch (pname)
{
case AL_GAIN:
_alRangedAssign1(ctx->listener.gain, value, 0.0f);
break;
default:
_alSetError(AL_INVALID_ENUM);
break;
}
_alcUnlockContext(ctx);
}
ALvoid alListener3f(ALenum pname, ALfloat f1, ALfloat f2, ALfloat f3)
{
AL_context *ctx;
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
switch (pname)
{
case AL_POSITION:
ctx->listener.position[0] = f1;
ctx->listener.position[1] = f2;
ctx->listener.position[2] = f3;
break;
case AL_VELOCITY:
ctx->listener.velocity[0] = f1;
ctx->listener.velocity[1] = f2;
ctx->listener.velocity[2] = f3;
break;
default:
_alSetError(AL_INVALID_ENUM);
break;
}
_alcUnlockContext(ctx);
}
ALvoid alListenerfv(ALenum pname, ALfloat* values)
{
AL_context *ctx;
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
switch (pname)
{
case AL_POSITION:
ctx->listener.position[0] = values[0];
ctx->listener.position[1] = values[1];
ctx->listener.position[2] = values[2];
break;
case AL_VELOCITY:
ctx->listener.velocity[0] = values[0];
ctx->listener.velocity[1] = values[1];
ctx->listener.velocity[2] = values[2];
break;
case AL_GAIN:
_alRangedAssign1(ctx->listener.gain, values[0], 0.0f);
break;
case AL_ORIENTATION:
ctx->listener.orientation[0] = values[0];
ctx->listener.orientation[1] = values[1];
ctx->listener.orientation[2] = values[2];
ctx->listener.orientation[3] = values[3];
ctx->listener.orientation[4] = values[4];
ctx->listener.orientation[5] = values[5];
_alListenerSetSpeakers(&ctx->listener, ctx->speakers);
break;
default:
_alSetError(AL_INVALID_ENUM);
break;
}
_alcUnlockContext(ctx);
}
ALvoid alGetListeneri(ALenum pname, ALint *value)
{
ALint values[6];
values[0] = *value;
alGetListeneriv(pname, values);
*value = values[0];
}
ALvoid alGetListeneriv(ALenum pname, ALint* values)
{
AL_context *ctx;
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
switch (pname)
{
case AL_POSITION:
values[0] = (ALint)ctx->listener.position[0];
values[1] = (ALint)ctx->listener.position[1];
values[2] = (ALint)ctx->listener.position[2];
break;
case AL_VELOCITY:
values[0] = (ALint)ctx->listener.velocity[0];
values[1] = (ALint)ctx->listener.velocity[1];
values[2] = (ALint)ctx->listener.velocity[2];
break;
case AL_GAIN:
values[0] = (ALint)ctx->listener.gain;
break;
case AL_ORIENTATION:
values[0] = (ALint)ctx->listener.orientation[0];
values[1] = (ALint)ctx->listener.orientation[1];
values[2] = (ALint)ctx->listener.orientation[2];
values[3] = (ALint)ctx->listener.orientation[3];
values[4] = (ALint)ctx->listener.orientation[4];
values[5] = (ALint)ctx->listener.orientation[5];
break;
default:
_alSetError(AL_INVALID_ENUM);
break;
}
_alcUnlockContext(ctx);
}
ALvoid alGetListenerf(ALenum pname, ALfloat *value)
{
ALfloat values[6];
values[0] = *value;
alGetListenerfv(pname, values);
*value = values[0];
}
ALvoid alGetListener3f(ALenum pname, ALfloat *f1, ALfloat *f2, ALfloat *f3)
{
ALfloat values[6];
values[0] = *f1;
values[1] = *f2;
values[2] = *f3;
alGetListenerfv(pname, values);
*f1 = values[0];
*f2 = values[1];
*f3 = values[2];
}
ALvoid alGetListenerfv(ALenum pname, ALfloat* values)
{
AL_context *ctx;
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
switch (pname)
{
case AL_POSITION:
values[0] = ctx->listener.position[0];
values[1] = ctx->listener.position[1];
values[2] = ctx->listener.position[2];
break;
case AL_VELOCITY:
values[0] = ctx->listener.velocity[0];
values[1] = ctx->listener.velocity[1];
values[2] = ctx->listener.velocity[2];
break;
case AL_GAIN:
values[0] = ctx->listener.gain;
break;
case AL_ORIENTATION:
values[0] = ctx->listener.orientation[0];
values[1] = ctx->listener.orientation[1];
values[2] = ctx->listener.orientation[2];
values[3] = ctx->listener.orientation[3];
values[4] = ctx->listener.orientation[4];
values[5] = ctx->listener.orientation[5];
break;
default:
_alSetError(AL_INVALID_ENUM);
break;
}
_alcUnlockContext(ctx);
}

37
src/al_listener.h Normal file
View File

@ -0,0 +1,37 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _AL_LISTENER_H_
#define _AL_LISTENER_H_
#include <AL/al.h>
#include "alc_speaker.h"
typedef struct _AL_listener {
ALfloat gain;
ALfloat position[3];
ALfloat velocity[3];
ALfloat orientation[6];
AL_speaker speakers[_ALC_NUM_SPEAKERS];
} AL_listener;
extern ALvoid _alInitListener(AL_listener *, AL_speaker *);
#endif

642
src/al_play.c Normal file
View File

@ -0,0 +1,642 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <sys/time.h>
#include <math.h>
#include <alloca.h>
#include <string.h>
#include "al_source.h"
#include "al_error.h"
#include "al_vector.h"
#include "alc_device.h"
#include "alc_context.h"
static ALfloat _alCalculateGainAndPitch(AL_source *src)
{
AL_context *ctx = src->context;
ALCdevice *dev = ctx->device;
ALfloat position[3];
position[0] = src->position[0];
position[1] = src->position[1];
position[2] = src->position[2];
if (!src->relative)
{
position[0] -= ctx->listener.position[0];
position[1] -= ctx->listener.position[1];
position[2] -= ctx->listener.position[2];
}
/* Master Gain */
{
ALint volume;
ALfloat gain = ctx->listener.gain;
ALfloat dist = _alVectorMagnitude(position);
gain *= ctx->distance_func(src, dist);
if (dist)
{
position[0] /= dist;
position[1] /= dist;
position[2] /= dist;
}
if (src->conic)
{
ALfloat a;
a = _alVectorDotProduct(position, src->direction);
a = acos(-a) * 360.0 / M_PI;
if (a > src->cone_inner_angle)
{
if (a >= src->cone_outer_angle)
{
gain *= src->cone_outer_gain;
}
else
{
a -= src->cone_inner_angle;
a *= (src->cone_outer_gain - 1.0f);
a /= (src->cone_outer_angle -
src->cone_inner_angle);
gain *= (1.0f + a);
}
}
}
if (gain > src->max_gain)
{
gain = src->max_gain;
}
else if (gain < src->min_gain)
{
gain = src->min_gain;
}
volume = (ALint)(65535.0f * gain);
snd_ctl_elem_value_set_integer(src->vol_ctl, 1, volume);
snd_ctl_elem_value_set_integer(src->vol_ctl, 2, volume);
}
/* Speaker Gains */
{
ALuint i;
ALint volume[_ALC_NUM_SPEAKERS];
for (i = 0; i < _ALC_NUM_SPEAKERS; i++)
{
AL_speaker *speaker = &ctx->listener.speakers[i];
volume[i] = speaker->gain ?
(ALint)((_alVectorDotProduct
(position, speaker->position) + 1.0f)
* speaker->gain) : 0;
}
if (dev->send_count == 24)
{
snd_ctl_elem_value_set_integer(src->send_ctl, 8,
volume[0]);
snd_ctl_elem_value_set_integer(src->send_ctl, 10,
volume[2]);
snd_ctl_elem_value_set_integer(src->send_ctl, 12,
(volume[4] + 1) >> 1);
snd_ctl_elem_value_set_integer(src->send_ctl, 13,
(volume[5] + 1) >> 1);
snd_ctl_elem_value_set_integer(src->send_ctl, 14,
volume[6]);
snd_ctl_elem_value_set_integer(src->send_ctl, 17,
volume[1]);
snd_ctl_elem_value_set_integer(src->send_ctl, 19,
volume[3]);
snd_ctl_elem_value_set_integer(src->send_ctl, 20,
volume[4] >> 1);
snd_ctl_elem_value_set_integer(src->send_ctl, 21,
volume[5] >> 1);
snd_ctl_elem_value_set_integer(src->send_ctl, 23,
volume[7]);
}
else
{
snd_ctl_elem_value_set_integer(src->send_ctl, 4,
volume[0]);
snd_ctl_elem_value_set_integer(src->send_ctl, 5,
volume[2]);
snd_ctl_elem_value_set_integer(src->send_ctl, 6,
(volume[4] + 1) >> 1);
snd_ctl_elem_value_set_integer(src->send_ctl, 7,
(volume[5] + 1) >> 1);
snd_ctl_elem_value_set_integer(src->send_ctl, 8,
volume[1]);
snd_ctl_elem_value_set_integer(src->send_ctl, 9,
volume[3]);
snd_ctl_elem_value_set_integer(src->send_ctl, 10,
volume[4] >> 1);
snd_ctl_elem_value_set_integer(src->send_ctl, 11,
volume[5] >> 1);
}
}
/* Pitch */
{
ALfloat vl, vs;
ALfloat pitch = src->pitch;
if (ctx->doppler_factor)
{
vl = _alVectorDotProduct(ctx->listener.velocity,
position);
vs = _alVectorDotProduct(src->velocity, position);
vl *= ctx->doppler_factor;
vs *= ctx->doppler_factor;
vl += ctx->doppler_velocity;
vs += ctx->doppler_velocity;
pitch *= vl / vs;
}
if (pitch < 0.0f)
{
pitch = 0.0f;
}
return pitch;
}
}
static snd_pcm_uframes_t _alWriteData(AL_source *src, ALfloat pitch,
int32_t *dest, snd_pcm_uframes_t frames)
{
AL_queue *que;
AL_buffer *buf;
ALfloat f;
ALuint inc, acc;
ALuint i;
if (!src->playing)
{
return 0;
}
if ((que = src->current_q) ||
((que = src->first_q) && (que->state == AL_PENDING)))
{
buf = que->buffer;
}
else if ((buf = src->buffer))
{
que = 0;
}
else
{
src->playing = AL_FALSE;
return 0;
}
f = pitch * (ALfloat)buf->freq / (ALfloat)src->freq;
inc = (f >= 65535.0) ? 0xFFFF0000 : (ALuint)(f * 65536.0);
acc = 0;
i = 0;
while (i < frames)
{
ALuint j = src->index;
if (j >= buf->size)
{
src->index = 0;
if (que)
{
que->state = AL_PROCESSED;
src->current_q = que->next;
}
else if(!src->looping)
{
src->playing = AL_FALSE;
}
break;
}
dest[i++] = buf->data[j];
acc += inc;
src->index = j + (acc >> 16);
acc &= 0xFFFF;
}
return i;
}
ALvoid _alProcessSource(AL_source *src)
{
const snd_pcm_channel_area_t *area;
snd_pcm_sframes_t avail;
ALfloat pitch;
int state;
if (src->state != AL_PLAYING)
{
return;
}
snd_pcm_hwsync(src->handle);
state = snd_pcm_state(src->handle);
if (state != SND_PCM_STATE_RUNNING)
{
if (src->playing)
{
snd_pcm_prepare(src->handle);
}
else
{
src->state = AL_STOPPED;
return;
}
}
pitch = _alCalculateGainAndPitch(src);
avail = snd_pcm_avail_update(src->handle);
while (avail > 0)
{
snd_pcm_uframes_t offset;
snd_pcm_uframes_t frames = avail;
snd_pcm_uframes_t written = 0;
int32_t *map;
if (snd_pcm_mmap_begin(src->handle, &area, &offset, &frames))
{
return;
}
avail -= frames;
map = area->addr + ((area->first + area->step * offset) >> 3);
while (frames)
{
snd_pcm_uframes_t f;
if (!(f = _alWriteData(src, pitch, map, frames)))
{
bzero(map, frames << 2);
avail = 0;
break;
}
map += f;
written += f;
frames -= f;
}
snd_pcm_mmap_commit(src->handle, offset, written);
}
{
AL_context *ctx = src->context;
ALCdevice *dev = ctx->device;
snd_ctl_elem_write(dev->ctl, src->vol_ctl);
snd_ctl_elem_write(dev->ctl, src->send_ctl);
}
if (state != SND_PCM_STATE_RUNNING)
{
if (!snd_pcm_delay(src->handle, &avail))
{
if (avail)
{
snd_pcm_start(src->handle);
}
}
}
if (!src->playing)
{
snd_pcm_drain(src->handle);
}
}
static ALvoid _alSourcePlay(AL_source *src)
{
switch(src->state)
{
case AL_PAUSED:
snd_pcm_pause(src->handle, 0);
break;
case AL_PLAYING:
src->index = 0;
break;
}
src->state = AL_PLAYING;
src->playing = AL_TRUE;
}
static ALvoid _alSourceStop(AL_source *src)
{
switch (src->state)
{
case AL_PAUSED:
snd_pcm_pause(src->handle, 0);
break;
case AL_PLAYING:
snd_pcm_drop(src->handle);
break;
}
src->state = AL_STOPPED;
src->index = 0;
}
static ALvoid _alSourcePause(AL_source *src)
{
if (src->state == AL_PLAYING)
{
snd_pcm_pause(src->handle, 1);
src->state = AL_PAUSED;
}
}
static ALvoid _alSourceRewind(AL_source *src)
{
switch (src->state)
{
case AL_PAUSED:
snd_pcm_pause(src->handle, 0);
break;
case AL_PLAYING:
snd_pcm_drop(src->handle);
break;
}
src->state = AL_INITIAL;
src->index = 0;
}
ALvoid alSourcePlay(ALuint sid)
{
AL_context *ctx;
AL_source *src;
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
if (!(src = _alFindSource(ctx, sid)))
{
_alSetError(AL_INVALID_NAME);
}
else
{
_alSourcePlay(src);
}
_alcUnlockContext(ctx);
}
ALvoid alSourceStop(ALuint sid)
{
AL_context *ctx;
AL_source *src;
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
if (!(src = _alFindSource(ctx, sid)))
{
_alSetError(AL_INVALID_NAME);
}
else
{
_alSourceStop(src);
}
_alcUnlockContext(ctx);
}
ALvoid alSourcePause(ALuint sid)
{
AL_context *ctx;
AL_source *src;
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
if (!(src = _alFindSource(ctx, sid)))
{
_alSetError(AL_INVALID_NAME);
}
else
{
_alSourcePause(src);
}
_alcUnlockContext(ctx);
}
ALvoid alSourceRewind(ALuint sid)
{
AL_context *ctx;
AL_source *src;
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
if (!(src = _alFindSource(ctx, sid)))
{
_alSetError(AL_INVALID_NAME);
}
else
{
_alSourceRewind(src);
}
_alcUnlockContext(ctx);
}
ALvoid alSourcePlayv(ALsizei ns, ALuint *ids)
{
AL_context *ctx;
AL_source **src;
ALsizei i;
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
src = alloca(ns * sizeof(AL_source *));
for (i = 0; i < ns; i++)
{
if (!(src[i] = _alFindSource(ctx, ids[i])))
{
_alSetError(AL_INVALID_NAME);
goto unlock;
}
}
for (i = 0; i < ns; i++)
{
_alSourcePlay(src[i]);
}
unlock:
_alcUnlockContext(ctx);
}
ALvoid alSourceStopv(ALsizei ns, ALuint *ids)
{
AL_context *ctx;
AL_source **src;
ALsizei i;
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
src = alloca(ns * sizeof(AL_source *));
for (i = 0; i < ns; i++)
{
if (!(src[i] = _alFindSource(ctx, ids[i])))
{
_alSetError(AL_INVALID_NAME);
goto unlock;
}
}
for (i = 0; i < ns; i++)
{
_alSourceStop(src[i]);
}
unlock:
_alcUnlockContext(ctx);
}
ALvoid alSourcePausev(ALsizei ns, ALuint *ids)
{
AL_context *ctx;
AL_source **src;
ALsizei i;
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
src = alloca(ns * sizeof(AL_source *));
for (i = 0; i < ns; i++)
{
if (!(src[i] = _alFindSource(ctx, ids[i])))
{
_alSetError(AL_INVALID_NAME);
goto unlock;
}
}
for (i = 0; i < ns; i++)
{
_alSourcePause(src[i]);
}
unlock:
_alcUnlockContext(ctx);
}
ALvoid alSourceRewindv(ALsizei ns, ALuint *ids)
{
AL_context *ctx;
AL_source **src;
ALsizei i;
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
src = alloca(ns * sizeof(AL_source *));
for (i = 0; i < ns; i++)
{
if (!(src[i] = _alFindSource(ctx, ids[i])))
{
_alSetError(AL_INVALID_NAME);
goto unlock;
}
}
for (i = 0; i < ns; i++)
{
_alSourceRewind(src[i]);
}
unlock:
_alcUnlockContext(ctx);
}

939
src/al_source.c Normal file
View File

@ -0,0 +1,939 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <float.h>
#include <alloca.h>
#include "al_source.h"
#include "al_vector.h"
#include "al_error.h"
#include "alc_device.h"
#include "alc_context.h"
#define AL_FIRST_SOURCE_ID 0x4000
AL_source *_alFindSource(AL_context *ctx, ALuint cid)
{
cid -= AL_FIRST_SOURCE_ID;
if (cid >= ctx->device->subdevs)
{
return 0;
}
return ctx->sources[cid];
}
static AL_source *_alGenSource(AL_context *ctx)
{
AL_source *src;
if (!(src = malloc(sizeof(AL_source))))
{
_alSetError(AL_OUT_OF_MEMORY);
return 0;
}
src->context = ctx;
src->handle = 0;
src->vol_ctl = 0;
src->send_ctl = 0;
src->subdev = -1;
src->freq = 0;
src->state = AL_INITIAL;
src->playing = AL_FALSE;
src->buffer = 0;
src->index = 0;
src->first_q = 0;
src->current_q = 0;
src->last_q = &src->first_q;
if (!_alcOpenSource(src))
{
_alcCloseSource(src);
free(src);
_alSetError(AL_OUT_OF_MEMORY);
return 0;
}
src->relative = AL_FALSE;
src->looping = AL_FALSE;
src->conic = AL_FALSE;
src->position[0] = 0.0f;
src->position[1] = 0.0f;
src->position[2] = 0.0f;
src->direction[0] = 0.0f;
src->direction[1] = 0.0f;
src->direction[2] = 0.0f;
src->velocity[0] = 0.0f;
src->velocity[1] = 0.0f;
src->velocity[2] = 0.0f;
src->pitch = 1.0f;
src->gain = 1.0f;
src->min_gain = 0.0f;
src->max_gain = 1.0f;
src->reference_distance = 1.0f;
src->rolloff_factor = 1.0f;
src->max_distance = FLT_MAX;
src->cone_inner_angle = 360.0f;
src->cone_outer_angle = 360.0f;
src->cone_outer_gain = 0.0f;
ctx->sources[src->subdev] = src;
return src;
}
ALvoid _alDeleteSource(AL_source *src)
{
AL_queue *que;
AL_context *ctx = src->context;
ctx->sources[src->subdev] = 0;
_alcCloseSource(src);
que = src->first_q;
while (que)
{
AL_queue *next = que->next;
_alUnlockBuffer(que->buffer);
free(que);
que = next;
}
if (src->buffer)
{
_alUnlockBuffer(src->buffer);
}
free(src);
}
ALvoid alGenSources(ALsizei n, ALuint *sources)
{
AL_context *ctx;
AL_source **temp;
ALsizei i;
if (n == 0)
{
return;
}
if (n < 0)
{
_alSetError(AL_INVALID_VALUE);
return;
}
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
temp = alloca(n * sizeof(AL_source *));
for (i = 0; i < n; i++)
{
if (!(temp[i] = _alGenSource(ctx)))
{
ALsizei j;
for (j = 0; j < i; j++)
_alDeleteSource(temp[j]);
goto unlock;
}
}
for (i = 0; i < n; i++)
{
sources[i] = temp[i]->subdev + AL_FIRST_SOURCE_ID;
}
unlock:
_alcUnlockContext(ctx);
}
ALvoid alDeleteSources(ALsizei n, ALuint* sources)
{
AL_context *ctx;
AL_source **temp;
ALsizei i;
if (n == 0)
{
return;
}
if (n < 0)
{
_alSetError(AL_INVALID_VALUE);
return;
}
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
temp = alloca(n * sizeof(AL_source *));
for (i = 0; i < n; i++)
{
if (!(temp[i] = _alFindSource(ctx, sources[i])))
{
_alSetError(AL_INVALID_NAME);
goto unlock;
}
}
for (i = 0; i < n; i++)
{
_alDeleteSource(temp[i]);
}
unlock:
_alcUnlockContext(ctx);
}
ALboolean alIsSource(ALuint sid)
{
AL_context *ctx;
ALboolean value;
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return AL_FALSE;
}
_alcLockContext(ctx);
value = _alFindSource(ctx, sid) ? AL_TRUE : AL_FALSE;
_alcUnlockContext(ctx);
return value;
}
static ALvoid _alNormalizeDirection(AL_source *src)
{
ALfloat mag = _alVectorMagnitude(src->direction);
if (mag)
{
src->conic = AL_TRUE;
src->direction[0] /= mag;
src->direction[1] /= mag;
src->direction[2] /= mag;
}
else
{
src->conic = AL_FALSE;
}
}
ALvoid alSourcei(ALuint sid, ALenum param, ALint value)
{
AL_context *ctx;
AL_source *src;
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
if (!(src = _alFindSource(ctx, sid)))
{
_alSetError(AL_INVALID_NAME);
goto unlock;
}
switch(param)
{
case AL_SOURCE_RELATIVE:
_alRangedAssignB(src->relative, value);
break;
case AL_LOOPING:
_alRangedAssignB(src->looping, value);
break;
case AL_PITCH:
_alRangedAssign1(src->pitch, value, 0);
break;
case AL_GAIN:
_alRangedAssign1(src->gain, value, 0);
break;
case AL_MIN_GAIN:
_alRangedAssign2(src->min_gain, value, 0, 1);
break;
case AL_MAX_GAIN:
_alRangedAssign2(src->max_gain, value, 0, 1);
break;
case AL_REFERENCE_DISTANCE:
_alRangedAssign1(src->reference_distance, value, 0);
break;
case AL_ROLLOFF_FACTOR:
_alRangedAssign1(src->rolloff_factor, value, 0);
break;
case AL_MAX_DISTANCE:
_alRangedAssign1(src->max_distance, value, 0);
break;
case AL_CONE_INNER_ANGLE:
_alRangedAssign2(src->cone_inner_angle, value, 0, 360);
break;
case AL_CONE_OUTER_ANGLE:
_alRangedAssign2(src->cone_outer_angle, value, 0, 360);
break;
case AL_CONE_OUTER_GAIN:
_alRangedAssign2(src->cone_outer_gain, value, 0, 1);
break;
case AL_BUFFER:
{
AL_buffer *buf;
if (value)
{
if (!(buf = _alLockBuffer(value)))
{
_alSetError(AL_INVALID_VALUE);
break;
}
}
else
{
buf = 0;
}
if (src->buffer)
{
_alUnlockBuffer(src->buffer);
}
src->buffer = buf;
}
break;
default:
_alSetError(AL_INVALID_ENUM);
break;
}
unlock:
_alcUnlockContext(ctx);
}
ALvoid alSourcef(ALuint sid, ALenum param, ALfloat value)
{
AL_context *ctx;
AL_source *src;
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
if (!(src = _alFindSource(ctx, sid)))
{
_alSetError(AL_INVALID_NAME);
goto unlock;
}
switch(param)
{
case AL_SOURCE_RELATIVE:
_alRangedAssignB(src->relative, value);
break;
case AL_LOOPING:
_alRangedAssignB(src->looping, value);
break;
case AL_PITCH:
_alRangedAssign1(src->pitch, value, 0.0f);
break;
case AL_GAIN:
_alRangedAssign1(src->gain, value, 0.0f);
break;
case AL_MIN_GAIN:
_alRangedAssign2(src->min_gain, value, 0.0f, 1.0f);
break;
case AL_MAX_GAIN:
_alRangedAssign2(src->max_gain, value, 0.0f, 1.0f);
break;
case AL_REFERENCE_DISTANCE:
_alRangedAssign1(src->reference_distance, value, 0.0f);
break;
case AL_ROLLOFF_FACTOR:
_alRangedAssign1(src->rolloff_factor, value, 0.0f);
break;
case AL_MAX_DISTANCE:
_alRangedAssign1(src->max_distance, value, 0.0f);
break;
case AL_CONE_INNER_ANGLE:
_alRangedAssign2(src->cone_inner_angle, value, 0.0f, 360.0f);
break;
case AL_CONE_OUTER_ANGLE:
_alRangedAssign2(src->cone_outer_angle, value, 0.0f, 360.0f);
break;
case AL_CONE_OUTER_GAIN:
_alRangedAssign2(src->cone_outer_gain, value, 0.0f, 1.0f);
break;
default:
_alSetError(AL_INVALID_ENUM);
break;
}
unlock:
_alcUnlockContext(ctx);
}
ALvoid alSource3f(ALuint sid, ALenum param, ALfloat f1, ALfloat f2, ALfloat f3)
{
AL_context *ctx;
AL_source *src;
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
if (!(src = _alFindSource(ctx, sid)))
{
_alSetError(AL_INVALID_NAME);
goto unlock;
}
switch(param)
{
case AL_POSITION:
src->position[0] = f1;
src->position[1] = f2;
src->position[2] = f3;
break;
case AL_DIRECTION:
src->direction[0] = f1;
src->direction[1] = f2;
src->direction[2] = f3;
_alNormalizeDirection(src);
break;
case AL_VELOCITY:
src->velocity[0] = f1;
src->velocity[1] = f2;
src->velocity[2] = f3;
break;
default:
_alSetError(AL_INVALID_ENUM);
break;
}
unlock:
_alcUnlockContext(ctx);
}
ALvoid alSourcefv(ALuint sid, ALenum param, ALfloat *values)
{
AL_context *ctx;
AL_source *src;
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
if (!(src = _alFindSource(ctx, sid)))
{
_alSetError(AL_INVALID_NAME);
goto unlock;
}
switch(param)
{
case AL_SOURCE_RELATIVE:
_alRangedAssignB(src->relative, values[0]);
break;
case AL_LOOPING:
_alRangedAssignB(src->looping, values[0]);
break;
case AL_PITCH:
_alRangedAssign1(src->pitch, values[0], 0.0f);
break;
case AL_GAIN:
_alRangedAssign1(src->gain, values[0], 0.0f);
break;
case AL_MIN_GAIN:
_alRangedAssign2(src->min_gain, values[0], 0.0f, 1.0f);
break;
case AL_MAX_GAIN:
_alRangedAssign2(src->max_gain, values[0], 0.0f, 1.0f);
break;
case AL_REFERENCE_DISTANCE:
_alRangedAssign1(src->reference_distance, values[0], 0.0f);
break;
case AL_ROLLOFF_FACTOR:
_alRangedAssign1(src->rolloff_factor, values[0], 0.0f);
break;
case AL_MAX_DISTANCE:
_alRangedAssign1(src->max_distance, values[0], 0.0f);
break;
case AL_CONE_INNER_ANGLE:
_alRangedAssign2(src->cone_inner_angle, values[0],
0.0f, 360.0f);
break;
case AL_CONE_OUTER_ANGLE:
_alRangedAssign2(src->cone_outer_angle, values[0],
0.0f, 360.0f);
break;
case AL_CONE_OUTER_GAIN:
_alRangedAssign2(src->cone_outer_gain, values[0], 0.0f, 1.0f);
break;
case AL_POSITION:
src->position[0] = values[0];
src->position[1] = values[1];
src->position[2] = values[2];
break;
case AL_DIRECTION:
src->direction[0] = values[0];
src->direction[1] = values[1];
src->direction[2] = values[2];
_alNormalizeDirection(src);
break;
case AL_VELOCITY:
src->velocity[0] = values[0];
src->velocity[1] = values[1];
src->velocity[2] = values[2];
break;
default:
_alSetError(AL_INVALID_ENUM);
break;
}
unlock:
_alcUnlockContext(ctx);
}
static ALint _alBuffersQueued(AL_source *src)
{
AL_queue *q;
ALint count = 0;
for (q = src->first_q; q; q = q->next)
{
count++;
}
return count;
}
static ALint _alBuffersProcessed(AL_source *src)
{
AL_queue *q;
ALint count = 0;
for (q = src->first_q; q; q = q->next)
{
if (q->state != AL_PROCESSED)
{
break;
}
count++;
}
return count;
}
ALvoid alGetSourcei(ALuint sid, ALenum param, ALint *value)
{
ALint values[3];
values[0] = *value;
alGetSourceiv(sid, param, values);
*value = values[0];
}
ALvoid alGetSourceiv(ALuint sid, ALenum param, ALint *values)
{
AL_context *ctx;
AL_source *src;
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
if (!(src = _alFindSource(ctx, sid)))
{
_alSetError(AL_INVALID_NAME);
goto unlock;
}
switch(param)
{
case AL_SOURCE_RELATIVE:
values[0] = src->relative;
break;
case AL_SOURCE_STATE:
values[0] = src->state;
break;
case AL_LOOPING:
values[0] = src->looping;
break;
case AL_PITCH:
values[0] = (ALint)src->pitch;
break;
case AL_GAIN:
values[0] = (ALint)src->gain;
break;
case AL_MIN_GAIN:
values[0] = (ALint)src->min_gain;
break;
case AL_MAX_GAIN:
values[0] = (ALint)src->max_gain;
break;
case AL_REFERENCE_DISTANCE:
values[0] = (ALint)src->reference_distance;
break;
case AL_ROLLOFF_FACTOR:
values[0] = (ALint)src->rolloff_factor;
break;
case AL_MAX_DISTANCE:
values[0] = (ALint)src->max_distance;
break;
case AL_CONE_INNER_ANGLE:
values[0] = (ALint)src->cone_inner_angle;
break;
case AL_CONE_OUTER_ANGLE:
values[0] = (ALint)src->cone_outer_angle;
break;
case AL_CONE_OUTER_GAIN:
values[0] = (ALint)src->cone_outer_gain;
break;
case AL_POSITION:
values[0] = (ALint)src->position[0];
values[1] = (ALint)src->position[1];
values[2] = (ALint)src->position[2];
break;
case AL_DIRECTION:
values[0] = (ALint)src->direction[0];
values[1] = (ALint)src->direction[1];
values[2] = (ALint)src->direction[2];
break;
case AL_VELOCITY:
values[0] = (ALint)src->velocity[0];
values[1] = (ALint)src->velocity[1];
values[2] = (ALint)src->velocity[2];
break;
case AL_BUFFER:
values[0] = src->buffer ? src->buffer->id : 0;
break;
case AL_BUFFERS_QUEUED:
values[0] = _alBuffersQueued(src);
break;
case AL_BUFFERS_PROCESSED:
values[0] = _alBuffersProcessed(src);
break;
default:
_alSetError(AL_INVALID_ENUM);
break;
}
unlock:
_alcUnlockContext(ctx);
}
ALvoid alGetSourcef(ALuint sid, ALenum param, ALfloat *value)
{
ALfloat values[3];
values[0] = *value;
alGetSourcefv(sid, param, values);
*value = values[0];
}
ALvoid alGetSource3f(ALuint sid, ALenum param,
ALfloat *f1, ALfloat *f2, ALfloat *f3)
{
ALfloat values[6];
values[0] = *f1;
values[1] = *f2;
values[2] = *f3;
alGetSourcefv(sid, param, values);
*f1 = values[0];
*f2 = values[1];
*f3 = values[2];
}
ALvoid alGetSourcefv(ALuint sid, ALenum param, ALfloat* values)
{
AL_context *ctx;
AL_source *src;
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
if (!(src = _alFindSource(ctx, sid)))
{
_alSetError(AL_INVALID_NAME);
goto unlock;
}
switch(param)
{
case AL_SOURCE_RELATIVE:
values[0] = src->relative;
break;
case AL_SOURCE_STATE:
values[0] = (ALfloat)src->state;
break;
case AL_LOOPING:
values[0] = (ALfloat)src->looping;
break;
case AL_PITCH:
values[0] = src->pitch;
break;
case AL_GAIN:
values[0] = src->gain;
break;
case AL_MIN_GAIN:
values[0] = src->min_gain;
break;
case AL_MAX_GAIN:
values[0] = src->max_gain;
break;
case AL_REFERENCE_DISTANCE:
values[0] = src->reference_distance;
break;
case AL_ROLLOFF_FACTOR:
values[0] = src->rolloff_factor;
break;
case AL_MAX_DISTANCE:
values[0] = src->max_distance;
break;
case AL_CONE_INNER_ANGLE:
values[0] = src->cone_inner_angle;
break;
case AL_CONE_OUTER_ANGLE:
values[0] = src->cone_outer_angle;
break;
case AL_CONE_OUTER_GAIN:
values[0] = src->cone_outer_gain;
break;
case AL_POSITION:
values[0] = src->position[0];
values[1] = src->position[1];
values[2] = src->position[2];
break;
case AL_DIRECTION:
values[0] = src->direction[0];
values[1] = src->direction[1];
values[2] = src->direction[2];
break;
case AL_VELOCITY:
values[0] = src->velocity[0];
values[1] = src->velocity[1];
values[2] = src->velocity[2];
break;
case AL_BUFFERS_QUEUED:
values[0] = (ALfloat)_alBuffersQueued(src);
break;
case AL_BUFFERS_PROCESSED:
values[0] = (ALfloat)_alBuffersProcessed(src);
break;
default:
_alSetError(AL_INVALID_ENUM);
break;
}
unlock:
_alcUnlockContext(ctx);
}
ALvoid alSourceQueueBuffers(ALuint sid, ALsizei n, ALuint *buffers)
{
AL_context *ctx;
AL_source *src;
ALsizei i;
AL_queue *first_q;
AL_queue **last_q;
if (n == 0)
{
return;
}
if (n < 0)
{
_alSetError(AL_INVALID_VALUE);
return;
}
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
if (!(src = _alFindSource(ctx, sid)))
{
_alSetError(AL_INVALID_NAME);
goto unlock;
}
first_q = 0;
last_q = &first_q;
for (i = 0; i < n; i++)
{
AL_buffer *buf;
AL_queue *que;
if (!buffers[i])
continue;
if (!(buf = _alLockBuffer(buffers[i])))
{
while ((que = first_q))
{
first_q = que->next;
_alUnlockBuffer(que->buffer);
free(que);
}
_alSetError(AL_INVALID_NAME);
goto unlock;
}
if (!(que = malloc(sizeof(AL_queue))))
{
while ((que = first_q))
{
first_q = que->next;
_alUnlockBuffer(que->buffer);
free(que);
}
_alSetError(AL_OUT_OF_MEMORY);
goto unlock;
}
que->next = 0;
que->buffer = buf;
que->state = AL_PENDING;
*last_q = que;
last_q = &que->next;
}
if (first_q)
{
*src->last_q = first_q;
src->last_q = last_q;
}
unlock:
_alcUnlockContext(ctx);
}
ALvoid alSourceUnqueueBuffers(ALuint sid, ALsizei n, ALuint *buffers)
{
AL_context *ctx;
AL_source *src;
ALsizei i;
if (n == 0)
{
return;
}
if (n < 0)
{
_alSetError(AL_INVALID_VALUE);
return;
}
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
if (!(src = _alFindSource(ctx, sid)))
{
_alSetError(AL_INVALID_NAME);
goto unlock;
}
if (_alBuffersProcessed(src) < n)
{
_alSetError(AL_INVALID_OPERATION);
goto unlock;
}
for (i = 0; i < n; i++)
{
AL_queue *que = src->first_q;
src->first_q = que->next;
buffers[i] = que->buffer->id;
_alUnlockBuffer(que->buffer);
free(que);
}
unlock:
_alcUnlockContext(ctx);
}

81
src/al_source.h Normal file
View File

@ -0,0 +1,81 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _AL_SOURCE_H_
#define _AL_SOURCE_H_
#include <alsa/asoundlib.h>
#include <AL/al.h>
#include <AL/alc.h>
#include "al_buffer.h"
typedef struct _AL_queue
{
struct _AL_queue *next;
AL_buffer *buffer;
ALenum state;
}
AL_queue;
typedef struct _AL_source
{
ALCcontext *context;
snd_pcm_t *handle;
snd_ctl_elem_value_t *vol_ctl;
snd_ctl_elem_value_t *send_ctl;
ALint subdev;
ALuint freq;
ALenum state;
ALboolean playing;
AL_buffer *buffer;
ALuint index;
AL_queue *first_q;
AL_queue **last_q;
AL_queue *current_q;
ALboolean relative;
ALboolean looping;
ALboolean conic;
ALfloat position[3];
ALfloat direction[3];
ALfloat velocity[3];
ALfloat pitch;
ALfloat gain;
ALfloat min_gain;
ALfloat max_gain;
ALfloat reference_distance;
ALfloat rolloff_factor;
ALfloat max_distance;
ALfloat cone_inner_angle;
ALfloat cone_outer_angle;
ALfloat cone_outer_gain;
}
AL_source;
ALvoid _alDeleteSource(AL_source *);
ALvoid _alProcessSource(AL_source *);
#endif

216
src/al_state.c Normal file
View File

@ -0,0 +1,216 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "alc_context.h"
#include "al_error.h"
ALboolean alGetBoolean(ALenum param)
{
ALboolean value = AL_FALSE;
alGetBooleanv(param, &value);
return value;
}
ALint alGetInteger(ALenum param)
{
ALint value = AL_FALSE;
alGetIntegerv(param, &value);
return value;
}
ALfloat alGetFloat(ALenum param)
{
ALfloat value = AL_FALSE;
alGetFloatv(param, &value);
return value;
}
ALdouble alGetDouble(ALenum param)
{
ALdouble value = AL_FALSE;
alGetDoublev(param, &value);
return value;
}
ALvoid alGetBooleanv(ALenum param, ALboolean *values)
{
AL_context *ctx;
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
switch(param)
{
case AL_DOPPLER_FACTOR:
*values = (ctx->doppler_factor != 0.0f) ?
AL_TRUE : AL_FALSE;
break;
case AL_DOPPLER_VELOCITY:
*values = (ctx->doppler_velocity != 0.0f) ?
AL_TRUE : AL_FALSE;
break;
case AL_DISTANCE_MODEL:
*values = (ctx->distance_model != AL_INVERSE_DISTANCE) ?
AL_TRUE : AL_FALSE;
break;
default:
_alSetError(AL_INVALID_ENUM);
break;
}
_alcUnlockContext(ctx);
}
ALvoid alGetIntegerv(ALenum param, ALint *values)
{
AL_context *ctx;
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
switch(param)
{
case AL_DOPPLER_FACTOR:
*values = (ALint)ctx->doppler_factor;
break;
case AL_DOPPLER_VELOCITY:
*values = (ALint)ctx->doppler_velocity;
break;
case AL_DISTANCE_MODEL:
*values = ctx->distance_model;
break;
default:
_alSetError(AL_INVALID_ENUM);
break;
}
_alcUnlockContext(ctx);
}
ALvoid alGetFloatv(ALenum param, ALfloat *values)
{
AL_context *ctx;
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
switch(param)
{
case AL_DOPPLER_FACTOR:
*values = ctx->doppler_factor;
break;
case AL_DOPPLER_VELOCITY:
*values = ctx->doppler_velocity;
break;
case AL_DISTANCE_MODEL:
*values = (ALfloat)ctx->distance_model;
break;
default:
_alSetError(AL_INVALID_ENUM);
break;
}
_alcUnlockContext(ctx);
}
ALvoid alGetDoublev(ALenum param, ALdouble *values)
{
AL_context *ctx;
if (!(ctx = _alcCurrentContext))
{
_alSetError(AL_INVALID_OPERATION);
return;
}
_alcLockContext(ctx);
switch(param)
{
case AL_DOPPLER_FACTOR:
*values = (ALdouble)ctx->doppler_factor;
break;
case AL_DOPPLER_VELOCITY:
*values = (ALdouble)ctx->doppler_velocity;
break;
case AL_DISTANCE_MODEL:
*values = (ALdouble)ctx->distance_model;
break;
default:
_alSetError(AL_INVALID_ENUM);
break;
}
_alcUnlockContext(ctx);
}
const ALubyte *alGetString(ALenum param)
{
switch (param)
{
case AL_NO_ERROR:
return "No error";
case AL_INVALID_NAME:
return "Invalid Name parameter";
case AL_INVALID_ENUM:
return "Illegal paramater";
case AL_INVALID_VALUE:
return "Invalid enum parameter value";
case AL_INVALID_OPERATION:
return "Illegal call";
case AL_OUT_OF_MEMORY:
return "Unable to allocate memory";
case AL_VENDOR:
return "Christopher John Purnell";
case AL_VERSION:
return "0.1.2";
case AL_RENDERER:
return "EMU10K1";
case AL_EXTENSIONS:
return "";
default:
_alSetError(AL_INVALID_ENUM);
break;
}
return 0;
}

64
src/al_vector.c Normal file
View File

@ -0,0 +1,64 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <math.h>
#include "al_vector.h"
ALfloat _alVectorMagnitude(ALfloat *v)
{
return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
}
ALvoid _alVectorNormalize(ALfloat *d, ALfloat *s)
{
ALfloat mag;
if (!(mag = _alVectorMagnitude(s)))
{
d[0] = 0.0f;
d[1] = 0.0f;
d[2] = 0.0f;
}
else
{
d[0] = s[0] / mag;
d[1] = s[1] / mag;
d[2] = s[2] / mag;
}
}
ALvoid _alVectorCrossProduct(ALfloat *d, ALfloat *v1, ALfloat *v2)
{
d[0] = v1[1] * v2[2] - v1[2] * v2[1];
d[1] = v1[2] * v2[0] - v1[0] * v2[2];
d[2] = v1[0] * v2[1] - v1[1] * v2[0];
}
ALfloat _alVectorDotProduct(ALfloat *v1, ALfloat *v2)
{
return (v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]);
}
ALvoid _alVectorMatrix(ALfloat *d, ALfloat *s, ALfloat *m)
{
d[0] = s[0] * m[0] + s[1] * m[3] + s[2] * m[6];
d[1] = s[0] * m[1] + s[1] * m[4] + s[2] * m[7];
d[2] = s[0] * m[2] + s[1] * m[5] + s[2] * m[8];
}

31
src/al_vector.h Normal file
View File

@ -0,0 +1,31 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _AL_VECTOR_H_
#define _AL_VECTOR_H_
#include <AL/al.h>
ALfloat _alVectorMagnitude(ALfloat *);
ALvoid _alVectorNormalize(ALfloat *, ALfloat *);
ALvoid _alVectorCrossProduct(ALfloat *, ALfloat *, ALfloat *);
ALfloat _alVectorDotProduct(ALfloat *, ALfloat *);
ALvoid _alVectorMatrix(ALfloat *, ALfloat *, ALfloat *);
#endif

292
src/alc_context.c Normal file
View File

@ -0,0 +1,292 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <sys/time.h>
#include <stdlib.h>
#include <ansidecl.h>
#include "al_listener.h"
#include "al_source.h"
#include "alc_context.h"
#include "alc_error.h"
AL_context *_alcCurrentContext = 0;
static ALCvoid *_alcThread(ALCcontext *cc)
{
AL_context *ctx = cc;
ALCdevice *dev = ctx->device;
ALuint i;
struct timeval tv;
struct timespec ts;
long ns = 1000000000 / dev->refresh;
pthread_mutex_lock(&ctx->mutex);
do
{
gettimeofday(&tv, 0);
for (i = 0; i < dev->subdevs; i++)
{
AL_source *src;
if ((src = ctx->sources[i]))
{
_alProcessSource(src);
}
}
ts.tv_sec = tv.tv_sec;
if ((ts.tv_nsec = (tv.tv_usec * 1000) + ns) >= 1000000000)
{
ts.tv_sec += 1;
ts.tv_nsec -= 1000000000;
}
}
while (pthread_cond_timedwait(&ctx->cond, &ctx->mutex, &ts));
pthread_mutex_unlock(&ctx->mutex);
return 0;
}
static ALCboolean _alcCreateContext(AL_context *ctx)
{
ALCdevice *dev = ctx->device;
ALuint i;
pthread_mutex_init(&ctx->mutex, 0);
if (!(ctx->sources = malloc(dev->subdevs * sizeof(AL_source*))))
{
return AL_FALSE;
}
for (i = 0; i < dev->subdevs; i++)
{
ctx->sources[i] = 0;
}
if (!dev->sync)
{
pthread_cond_init(&ctx->cond, 0);
if (pthread_create(&ctx->thread, 0, _alcThread, ctx))
{
return AL_FALSE;
}
}
return ALC_TRUE;
}
static ALCvoid _alcDestroyContext(AL_context *ctx)
{
ALCdevice *dev;
ALuint i;
dev = ctx->device;
for (i = 0; i < dev->subdevs; i++)
{
AL_source *src;
if ((src = ctx->sources[i]))
{
_alDeleteSource(src);
}
}
if (ctx->thread)
{
pthread_cond_signal(&ctx->cond);
pthread_join(ctx->thread, 0);
pthread_cond_destroy(&ctx->cond);
}
if (ctx->sources)
{
free(ctx->sources);
}
pthread_mutex_destroy(&ctx->mutex);
free(ctx);
}
ALCcontext *alcCreateContext(ALCdevice *dev, ALCint *attrlist)
{
AL_context *ctx;
if (!dev)
{
_alcSetError(ALC_INVALID_DEVICE);
return 0;
}
if (!(ctx = malloc(sizeof(AL_context))))
{
_alcSetError(ALC_OUT_OF_MEMORY);
return 0;
}
ctx->device = dev;
while (attrlist)
{
ALCint value;
switch (*(attrlist++))
{
case ALC_FREQUENCY:
if ((value = *(attrlist++)) > 0)
{
dev->freq = value;
}
break;
case ALC_REFRESH:
if ((value = *(attrlist++)) > 0)
{
dev->refresh = value;
}
break;
case ALC_SYNC:
dev->sync = *(attrlist++) ? AL_TRUE: AL_FALSE;
break;
default:
attrlist = 0;
break;
}
}
if (dev->refresh > dev->freq)
{
dev->refresh = dev->freq;
}
ctx->sources = 0;
ctx->thread = 0;
_alcLoadSpeakers(ctx->speakers);
_alInitListener(&ctx->listener, ctx->speakers);
ctx->doppler_factor = 1.0f;
ctx->doppler_velocity = 1.0f;
ctx->distance_model = AL_INVERSE_DISTANCE;
ctx->distance_func = _alDistanceInverse;
if (_alcCreateContext(ctx))
return ctx;
_alcDestroyContext(ctx);
_alcSetError(ALC_OUT_OF_MEMORY);
return 0;
}
ALCenum alcDestroyContext(ALCcontext *cc)
{
AL_context *ctx;
if (!(ctx = cc))
{
_alcSetError(ALC_INVALID_CONTEXT);
return ALC_INVALID_CONTEXT;
}
if (ctx == _alcCurrentContext)
{
_alcCurrentContext = 0;
}
_alcDestroyContext(ctx);
return ALC_NO_ERROR;
}
ALCenum alcMakeContextCurrent(ALCcontext *cc)
{
_alcCurrentContext = cc;
return ALC_NO_ERROR;
}
ALCcontext *alcGetCurrentContext(ALCvoid)
{
return _alcCurrentContext;
}
ALCdevice *alcGetContextsDevice(ALCcontext *cc)
{
AL_context *ctx;
if (!(ctx = cc))
{
_alcSetError(ALC_INVALID_CONTEXT);
return 0;
}
return ctx->device;
}
ALCvoid alcSuspendContext(ALCcontext *cc ATTRIBUTE_UNUSED)
{
/* FIXME */
}
ALCvoid *alcProcessContext(ALCcontext *cc)
{
AL_context *ctx;
ALCdevice *dev;
ALuint i;
if (!(ctx = cc))
{
_alcSetError(ALC_INVALID_CONTEXT);
return 0;
}
if (ctx->thread)
{
return cc;
}
_alcLockContext(ctx);
dev = ctx->device;
for (i = 0; i < dev->subdevs; i++)
{
AL_source *src;
if ((src = ctx->sources[i]))
{
_alProcessSource(src);
}
}
_alcUnlockContext(ctx);
return cc;
}

62
src/alc_context.h Normal file
View File

@ -0,0 +1,62 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _ALC_CONTEXT_H_
#define _ALC_CONTEXT_H_
#include <pthread.h>
#include <semaphore.h>
#include <AL/al.h>
#include <AL/alc.h>
#include "alc_speaker.h"
#include "alc_device.h"
#include "al_source.h"
#include "al_listener.h"
typedef struct _AL_context
{
ALCdevice *device;
AL_source **sources;
pthread_t thread;
pthread_mutex_t mutex;
pthread_cond_t cond;
AL_listener listener;
AL_speaker speakers[_ALC_NUM_SPEAKERS];
ALfloat doppler_factor;
ALfloat doppler_velocity;
ALenum distance_model;
ALfloat (*distance_func)(AL_source *, ALfloat);
}
AL_context;
extern AL_context *_alcCurrentContext;
#define _alcLockContext(ctx) pthread_mutex_lock(&ctx->mutex)
#define _alcUnlockContext(ctx) pthread_mutex_unlock(&ctx->mutex)
AL_source *_alFindSource(AL_context *, ALuint);
ALfloat _alDistanceInverse(AL_source *, ALfloat);
#endif

227
src/alc_device.c Normal file
View File

@ -0,0 +1,227 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <sys/types.h>
#include <sys/fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <ansidecl.h>
#include <alsa/asoundlib.h>
#include "alc_device.h"
#include "alc_context.h"
#include "alc_error.h"
#define _ALC_DEF_FREQ 44100
#define _ALC_DEF_REFRESH 20
#define _ALC_NUM_PERIODS 2
static int live_send_routing[] = {
0, 1, 2, 3,
0, 2, 6, 7,
1, 3, 6, 7
};
static int audigy_send_routing[] = {
8, 9, 2, 3, 6, 7, 14, 15,
8, 9, 2, 3, 6, 7, 14, 15,
8, 9, 2, 3, 6, 7, 14, 15
};
ALCboolean _alcOpenSource(AL_source *src)
{
snd_pcm_hw_params_t *hw_params;
snd_pcm_info_t *info;
snd_ctl_elem_value_t *route_ctl;
snd_pcm_uframes_t size;
unsigned i;
AL_context *ctx = src->context;
ALCdevice *dev = ctx->device;
int *send_routing;
if (snd_pcm_open(&src->handle, dev->device, SND_PCM_STREAM_PLAYBACK,
SND_PCM_NONBLOCK))
return ALC_FALSE;
snd_pcm_hw_params_alloca(&hw_params);
if (snd_pcm_hw_params_any(src->handle, hw_params))
return ALC_FALSE;
if (snd_pcm_hw_params_set_access(src->handle, hw_params,
SND_PCM_ACCESS_MMAP_INTERLEAVED))
return ALC_FALSE;
if (snd_pcm_hw_params_set_format(src->handle, hw_params,
SND_PCM_FORMAT_S16))
return ALC_FALSE;
if (snd_pcm_hw_params_set_channels(src->handle, hw_params, 2))
return ALC_FALSE;
src->freq = dev->freq;
if (snd_pcm_hw_params_set_rate_near(src->handle, hw_params,
&src->freq, 0))
return ALC_FALSE;
if (snd_pcm_hw_params_set_periods(src->handle, hw_params,
_ALC_NUM_PERIODS, 0))
return ALC_FALSE;
size = src->freq * _ALC_NUM_PERIODS / dev->refresh;
if (snd_pcm_hw_params_set_buffer_size_near(src->handle, hw_params,
&size))
return ALC_FALSE;
if (snd_pcm_hw_params(src->handle, hw_params))
return ALC_FALSE;
snd_pcm_info_alloca(&info);
if (snd_pcm_info(src->handle, info))
return ALC_FALSE;
src->subdev = snd_pcm_info_get_subdevice(info);
if (snd_ctl_elem_value_malloc(&src->vol_ctl))
return ALC_FALSE;
snd_ctl_elem_value_clear(src->vol_ctl);
snd_ctl_elem_value_set_interface(src->vol_ctl,
SND_CTL_ELEM_IFACE_MIXER);
snd_ctl_elem_value_set_name(src->vol_ctl,
"EMU10K1 PCM Volume");
snd_ctl_elem_value_set_index(src->vol_ctl, src->subdev);
if (snd_ctl_elem_value_malloc(&src->send_ctl))
return ALC_FALSE;
snd_ctl_elem_value_clear(src->send_ctl);
snd_ctl_elem_value_set_interface(src->send_ctl,
SND_CTL_ELEM_IFACE_MIXER);
snd_ctl_elem_value_set_name(src->send_ctl,
"EMU10K1 PCM Send Volume");
snd_ctl_elem_value_set_index(src->send_ctl, src->subdev);
snd_ctl_elem_value_alloca(&route_ctl);
snd_ctl_elem_value_clear(route_ctl);
snd_ctl_elem_value_set_interface(route_ctl,
SND_CTL_ELEM_IFACE_MIXER);
snd_ctl_elem_value_set_name(route_ctl,
"EMU10K1 PCM Send Routing");
snd_ctl_elem_value_set_index(route_ctl, src->subdev);
send_routing = (dev->send_count == 24) ?
audigy_send_routing : live_send_routing;
for (i = 0; i < dev->send_count; i++)
{
snd_ctl_elem_value_set_integer(route_ctl, i, send_routing[i]);
snd_ctl_elem_value_set_integer(src->send_ctl, i, 0);
}
if (snd_ctl_elem_write(dev->ctl, route_ctl))
return ALC_FALSE;
return ALC_TRUE;
}
ALCvoid _alcCloseSource(AL_source *src)
{
if (src->send_ctl) snd_ctl_elem_value_free(src->send_ctl);
if (src->vol_ctl) snd_ctl_elem_value_free(src->vol_ctl);
if (src->handle) snd_pcm_close(src->handle);
}
static ALCboolean _alcOpenDevice(ALCdevice *dev)
{
snd_ctl_elem_info_t *ctl_info;
snd_pcm_info_t *pcm_info;
int card = -1;
snd_ctl_elem_info_alloca(&ctl_info);
snd_ctl_elem_info_set_interface(ctl_info, SND_CTL_ELEM_IFACE_MIXER);
snd_ctl_elem_info_set_name(ctl_info, "EMU10K1 PCM Send Routing");
snd_ctl_elem_info_set_index(ctl_info, 0);
snd_pcm_info_alloca(&pcm_info);
while (snd_card_next(&card) >= 0 && card >= 0)
{
sprintf(dev->device, "hw:%d", card);
if (snd_ctl_open(&dev->ctl, dev->device, 0))
break;
if (snd_ctl_elem_info(dev->ctl, ctl_info))
continue;
dev->send_count = snd_ctl_elem_info_get_count(ctl_info);
if ((dev->send_count != 12) && (dev->send_count != 24))
continue;
if (snd_ctl_pcm_info(dev->ctl, pcm_info))
break;
dev->subdevs = snd_pcm_info_get_subdevices_count(pcm_info);
return ALC_TRUE;
}
return ALC_FALSE;
}
static ALCvoid _alcCloseDevice(ALCdevice *dev)
{
if (dev->ctl) snd_ctl_close(dev->ctl);
free(dev);
}
ALCdevice *alcOpenDevice(const ALubyte *spec ATTRIBUTE_UNUSED)
{
ALCdevice *dev;
if (!(dev = malloc(sizeof(ALCdevice))))
{
_alcSetError(ALC_OUT_OF_MEMORY);
return 0;
}
dev->ctl = 0;
dev->sync = ALC_FALSE;
dev->freq = _ALC_DEF_FREQ;
dev->refresh = _ALC_DEF_REFRESH;
if (_alcOpenDevice(dev))
return dev;
_alcCloseDevice(dev);
_alcSetError(ALC_INVALID_DEVICE);
return 0;
}
ALCvoid alcCloseDevice(ALCdevice *dev)
{
if (dev)
{
_alcCloseDevice(dev);
}
else
{
_alcSetError(ALC_INVALID_DEVICE);
}
}

44
src/alc_device.h Normal file
View File

@ -0,0 +1,44 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _ALC_DEVICE_H_
#define _ALC_DEVICE_H_
#include <alsa/asoundlib.h>
#include <AL/al.h>
#include <AL/alc.h>
#include "al_source.h"
struct _AL_device
{
char device[16];
ALuint subdevs;
snd_ctl_t *ctl;
ALuint send_count;
ALCboolean sync;
ALuint freq;
ALuint refresh;
};
ALCboolean _alcOpenSource(AL_source *);
ALCvoid _alcCloseSource(AL_source *);
#endif

39
src/alc_error.c Normal file
View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <ansidecl.h>
#include "alc_error.h"
static ALCenum __alc_error = ALC_NO_ERROR;
ALCenum alcGetError(ALCdevice *dev ATTRIBUTE_UNUSED)
{
ALCenum err = __alc_error;
__alc_error = ALC_NO_ERROR;
return err;
}
ALCvoid _alcSetError(ALCenum err)
{
if (__alc_error == ALC_NO_ERROR)
{
__alc_error = err;
}
}

28
src/alc_error.h Normal file
View File

@ -0,0 +1,28 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _ALC_ERROR_H_
#define _ALC_ERROR_H_
#include <AL/al.h>
#include <AL/alc.h>
extern ALCvoid _alcSetError(ALCenum);
#endif

42
src/alc_ext.c Normal file
View File

@ -0,0 +1,42 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <ansidecl.h>
#include <AL/al.h>
#include <AL/alc.h>
ALCboolean alcIsExtensionPresent(ALCdevice *dev ATTRIBUTE_UNUSED,
ALCubyte *name ATTRIBUTE_UNUSED)
{
return ALC_FALSE;
}
ALCvoid *alcGetProcAddress(ALCdevice *dev ATTRIBUTE_UNUSED,
ALubyte *name ATTRIBUTE_UNUSED)
{
return 0;
}
ALCenum alcGetEnumValue(ALCdevice *dev ATTRIBUTE_UNUSED, ALCubyte *name)
{
return alGetEnumValue(name);
}

91
src/alc_speaker.c Normal file
View File

@ -0,0 +1,91 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "alc_speaker.h"
#include "al_vector.h"
static AL_speaker _alcDefaultSpeakers[_ALC_NUM_SPEAKERS] =
{
{ 127.5f, { -1.0f, 0.0f, 0.0f } }, /* Front Left */
{ 127.5f, { 1.0f, 0.0f, 0.0f } }, /* Front Right */
{ 0.0f, { 0.0f, 0.0f, 0.0f } }, /* Rear Left */
{ 0.0f, { 0.0f, 0.0f, 0.0f } }, /* Rear Right */
{ 0.0f, { 0.0f, 0.0f, 0.0f } }, /* Center */
{ 0.0f, { 0.0f, 0.0f, 0.0f } }, /* LFE */
{ 0.0f, { 0.0f, 0.0f, 0.0f } }, /* Side Left */
{ 0.0f, { 0.0f, 0.0f, 0.0f } } /* Side Right */
};
ALvoid _alcLoadSpeakers(AL_speaker *speakers)
{
char *s, buf[1024];
FILE *fp;
ALuint i;
ALfloat gain;
ALfloat pos[3];
memcpy(speakers, _alcDefaultSpeakers, sizeof(_alcDefaultSpeakers));
if (!(s = getenv("HOME")))
{
return;
}
sprintf(buf, "%s/.openal-speakers", s);
if (!(fp = fopen(buf, "r")))
{
return;
}
while (fgets(buf, 1024, fp))
{
if ((s = strchr(buf, '#')))
{
*s = '\0';
}
if (sscanf(buf, "%u: %f %f %f %f", &i, &gain,
pos + 0, pos + 1, pos + 2) == 5)
{
if (i >= _ALC_NUM_SPEAKERS)
{
continue;
}
if (gain < 0.0)
{
gain = 0.0;
}
else if (gain > 1.0)
{
gain = 1.0;
}
speakers[i].gain = gain * 127.5;
_alVectorNormalize(speakers[i].position, pos);
}
}
fclose(fp);
}

37
src/alc_speaker.h Normal file
View File

@ -0,0 +1,37 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _ALC_SPEAKER_H_
#define _ALC_SPEAKER_H_
#include <AL/al.h>
#include <AL/alc.h>
#define _ALC_NUM_SPEAKERS 8
typedef struct _AL_speaker
{
ALfloat gain;
ALfloat position[3];
}
AL_speaker;
ALvoid _alcLoadSpeakers(AL_speaker *);
#endif

104
src/alc_state.c Normal file
View File

@ -0,0 +1,104 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <ansidecl.h>
#include "alc_device.h"
#include "alc_error.h"
ALCvoid alcGetIntegerv(ALCdevice *dev, ALCenum param,
ALCsizei size, ALCint *data)
{
if (!data || size < sizeof(ALCint))
{
_alcSetError(ALC_INVALID_VALUE);
return;
}
switch(param)
{
case ALC_MAJOR_VERSION:
*data = 1;
break;
case ALC_MINOR_VERSION:
*data = 0;
break;
case ALC_ATTRIBUTES_SIZE:
if (!dev)
{
_alcSetError(ALC_INVALID_DEVICE);
break;
}
*data = 8 * sizeof(ALCint);
break;
case ALC_ALL_ATTRIBUTES:
if (!dev)
{
_alcSetError(ALC_INVALID_DEVICE);
break;
}
if (size < (8 * sizeof(ALCint)))
{
_alcSetError(ALC_INVALID_VALUE);
break;
}
data[0] = ALC_FREQUENCY;
data[1] = dev->freq;
data[2] = ALC_REFRESH;
data[3] = dev->refresh;
data[4] = ALC_SYNC;
data[5] = dev->sync;
data[6] = ALC_INVALID;
data[7] = 0;
break;
default:
_alcSetError(ALC_INVALID_ENUM);
break;
}
}
const ALubyte *alcGetString(ALCdevice *dev ATTRIBUTE_UNUSED, ALCenum param)
{
switch (param)
{
case ALC_DEFAULT_DEVICE_SPECIFIER:
return "";
case ALC_DEVICE_SPECIFIER:
return "";
case ALC_EXTENSIONS:
return "";
case ALC_NO_ERROR:
return "No error";
case ALC_INVALID_DEVICE:
return "There is no accessible sound device/driver/server";
case ALC_INVALID_CONTEXT:
return "The Context argument does not name a valid context";
case ALC_INVALID_ENUM:
return "Illegal paramater";
case ALC_INVALID_VALUE:
return "Invalid enum parameter value";
case ALC_OUT_OF_MEMORY:
return "Unable to allocate memory";
default:
_alcSetError(ALC_INVALID_ENUM);
break;
}
return 0;
}

60
src/alut_main.c Normal file
View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <ansidecl.h>
#include <AL/al.h>
#include <AL/alc.h>
#include <AL/alut.h>
void alutInit(int *argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
{
ALCcontext *ctx;
ALCdevice *dev;
if (!(dev = alcOpenDevice(0)))
{
return;
}
if (!(ctx = alcCreateContext(dev, 0)))
{
alcCloseDevice(dev);
return;
}
alcMakeContextCurrent(ctx);
}
void alutExit(void)
{
ALCcontext *ctx;
ALCdevice *dev;
if (!(ctx = alcGetCurrentContext()))
{
return;
}
dev = alcGetContextsDevice(ctx);
alcMakeContextCurrent(0);
alcDestroyContext(ctx);
alcCloseDevice(dev);
}

288
src/alut_wav.c Normal file
View File

@ -0,0 +1,288 @@
/*
* Copyright (C) 2004 Christopher John Purnell
* cjp@lost.org.uk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <ansidecl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <AL/alut.h>
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define WAV_RIFF 0x46464952
#define WAV_WAVE 0x45564157
#define WAV_fmt 0x20746D66
#define WAV_data 0x61746164
#define WAV_smpl 0x6C706D73
#define swap16le(D) (D)
#define swap32le(D) (D)
#elif __BYTE_ORDER == __BIG_ENDIAN
#define WAV_RIFF 0x52494646
#define WAV_WAVE 0x57415645
#define WAV_fmt 0x666D7420
#define WAV_data 0x64617461
#define WAV_smpl 0x736D706C
#define swap16le(D) (((D)<<8) | ((D)>>8))
#define swap32le(D) ((((D)<<24) | (((D)<<8)&0x00FF0000) | (((D)>>8)&0x0000FF00) | ((D)>>24)))
#else
#error "Unknown endian"
#endif
typedef struct
{
u_int32_t id;
u_int32_t size;
u_int32_t type;
u_int32_t *data;
u_int32_t len;
}
AL_wav_file;
typedef struct
{
u_int32_t id;
u_int32_t size;
u_int32_t *data;
}
AL_wav_chunk;
static ALboolean _alutReadWavHeader(AL_wav_file *file, u_int32_t *memory)
{
if ((file->id = *(memory++)) != WAV_RIFF)
{
return AL_FALSE;
}
file->size = swap32le(*(memory++));
if (file->size < 4)
{
return AL_FALSE;
}
if ((file->type = *(memory++)) != WAV_WAVE)
{
return AL_FALSE;
}
file->data = memory;
file->len = (file->size - 1) >> 2;
return AL_TRUE;
}
static ALboolean _alutReadWavChunk(AL_wav_file *file, AL_wav_chunk *chunk)
{
ALuint len;
if (file->len < 2)
{
return AL_FALSE;
}
chunk->id = file->data[0];
chunk->size = swap32le(file->data[1]);
len = (chunk->size + 11) >> 2;
if (file->len < len)
{
return AL_FALSE;
}
chunk->data = file->data + 2;
file->data += len;
file->len -= len;
return AL_TRUE;
}
ALvoid alutLoadWAVMemory(ALbyte *memory, ALenum *format, ALvoid **data,
ALsizei *size, ALsizei *freq, ALboolean *loop)
{
AL_wav_file file;
AL_wav_chunk chunk;
ALuint bits = 0;
*data = 0;
*size = 0;
*freq = 0;
*format = 0;
*loop = 0;
if (!_alutReadWavHeader(&file, (u_int32_t *)memory))
{
return;
}
while (_alutReadWavChunk(&file, &chunk))
{
u_int16_t *data16 = (u_int16_t *)chunk.data;
switch (chunk.id)
{
case WAV_fmt:
if (data16[0] != 1)
{
return;
}
bits = swap16le(data16[7]);
*freq = swap32le(chunk.data[1]);
switch (swap16le(data16[1]))
{
case 1:
switch (bits)
{
case 8:
*format = AL_FORMAT_MONO8;
break;
case 16:
*format = AL_FORMAT_MONO16;
break;
default:
return;
}
break;
case 2:
switch (bits)
{
case 8:
*format = AL_FORMAT_STEREO8;
break;
case 16:
*format = AL_FORMAT_STEREO16;
break;
default:
return;
}
break;
default:
return;
}
break;
case WAV_data:
if (!bits)
{
return;
}
*data = malloc(chunk.size);
*size = chunk.size;
#if __BYTE_ORDER == __LITTLE_ENDIAN
memcpy(*data, chunk.data, chunk.size);
#else
if (bits == 16)
{
u_int16_t *ptr = *data;
ALuint i, s = chunk.size << 1;
for (i = 0; i < s; i++)
{
ptr[i] = swap16le(data16[i]);
}
}
else
{
memcpy(*data, chunk.data, chunk.size);
}
#endif
break;
case WAV_smpl:
*loop = swap32le(chunk.data[7]);
break;
}
}
}
ALvoid alutLoadWAVFile(ALbyte *file, ALenum *format, ALvoid **data,
ALsizei *size, ALsizei *freq, ALboolean *loop)
{
int fd;
void *memory;
struct stat st;
if ((fd = open(file, O_RDONLY)) < 0)
{
return;
}
if (!fstat(fd, &st))
{
memory = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
if (memory != MAP_FAILED)
{
alutLoadWAVMemory(memory, format, data,
size, freq, loop);
munmap(memory, st.st_size);
}
}
close(fd);
}
ALboolean alutLoadWAV(const char *fname, ALvoid **wave, ALsizei *format, ALsizei *size, ALsizei *bits, ALsizei *freq )
{
ALboolean loop;
alutLoadWAVFile((ALubyte *)fname, format, wave, size, freq, &loop);
if (! *wave)
{
return AL_FALSE;
}
switch (*format)
{
case AL_FORMAT_MONO8:
case AL_FORMAT_STEREO8:
*bits = 8;
break;
case AL_FORMAT_MONO16:
case AL_FORMAT_STEREO16:
*bits = 16;
break;
}
return AL_TRUE;
}
ALvoid alutUnloadWAV(ALenum format ATTRIBUTE_UNUSED, ALvoid *data,
ALsizei size ATTRIBUTE_UNUSED,
ALsizei freq ATTRIBUTE_UNUSED)
{
if (data)
{
free(data);
}
}