1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Lesson 4: A Closer Look at ALC</title>
</head>
<body>
<div Align=center>
<img ID="NavBar" WIDTH=800 HEIGHT=64 SRC="http://games.dev.java.net/images/navbar2p.gif" VSPACE=0 HSPACE=0 ALIGN="TOP" BORDER=0 USEMAP="#NavBar_MAP" NOFINSIDE="~! ~!" > </div>
<MAP NAME="NavBar_Map">
<AREA SHAPE="rect" ALT="Projects" COORDS="356,14,440,46" HREF="http://games.dev.java.net" TARGET="_self">
<AREA SHAPE="rect" ALT="Wiki" COORDS="643,14,695,46" HREF="http://wiki.java.net/bin/view/Games">
<AREA SHAPE="rect" ALT="Weblogs" COORDS="562,15,624,46" HREF="http://weblogs.java.net/weblogs/project/games">
<AREA SHAPE="rect" COORDS="463,16,541,45" HREF="http://www.javagaming.org/cgi-bin/JGNetForums/YaBB.cgi" target="_top" ALT="Forums">
<AREA SHAPE="rect" ALT="JavaGames Home" COORDS="147,16,334,48" HREF="http://community.java.net/games">
<AREA SHAPE="rect" ALT="Java.net" COORDS="21,15,128,46" HREF="http://www.java.net" TARGET="_self">
</MAP>
<br>
OpenAL Tutorials from DevMaster.net. Reprinted with Permission.<br>
<br>
<table border="0" cellspacing="0" style="border-collapse: collapse" width="100%" cellpadding="0" id="AutoNumber1" height="12" bgcolor="#666699">
<tr>
<td width="47%" height="12" valign="middle"><p><b><font color="#FFFFFF">OpenAL
Tutorials</font></b></p></td>
<td width="53%" height="12" align="right" valign="middle"><p align="right"><a href="http://devmaster.net/"><font color="#66FF99">DevMaster.net</font></a></p></td>
</tr>
</table>
<p class="ArticleTitle"><font size="5">A Closer Look at ALC</font></p>
<p class="ArticleTitle"><font size="4"><strong>Lesson 4</strong></font></p>
<p align="right" class="ArticleAuthor">Author: <a href="mailto:lightonthewater@hotmail.com">Jesse
Maurais<br>
</a>Adapted for Java by: <a href="mailto:athomas@dev.java.net">Athomas
Goldberg </a></p>
<p align="justify">Up until now we have been letting Alut do all the real tricky
stuff for us. For example handling the audio devices. It's really nice that
the Alut library is there to provide this functionality, but any smart coder
will want to know exactly what their doing. We may want to, at some point, use
the Alc directly. In this tutorial we will expose the Alc layer and take a look
at how to handle the devices on our own.</p>
<pre class=code>
ALFactory.initialize();
ALC alc = ALFactory.getALC();
String deviceName = "DirectSound3D";
ALC.Device device = alc.alcOpenDevice(deviceName);
</pre>
<p align="justify">So what is an Alc device? Try to think of it in terms of a
resource. OpenAL grabs a handle to the hardware being used, which must in turn
be shared with the entire system. A device can be of a specific implementation
as well, as in this case where we are using DirectSound as the audio device.
This code grabs a handle to the hardware device and readies it to be used by
the application. Eventually we should see more devices made for specific soundcards.</p>
<p>Passing <font color="#0000FF" face="Courier New, Courier, mono">null</font>
to 'alcOpenDevice' is a perfectly valid argument. It forces the Alc to use a
default device.</p>
<pre>
ALC.Context context = alc.alcCreateContext(device, <font color="#0000FF">null</font>);
alc.alcMakeContextCurrent(context);
</pre>
<p align="justify">What is an Alc context? OpenGL coders will recall that there
was rendering contexts used by OpenGL that controlled the state management across
different windows. An 'HGLRC' as they are called could be created several times
to enable multiple rendering windows. And different rendering states for each
context could be achieved. An Alc context works on the same principal. First
we tell it which device to use (which we have already created), then we make
that context current. In theory you could create multiple rendering contexts
for different windows, and set the state variables differently and have it work
just fine. Although the term "rendering context" usually applies to
a visual rendering, this is the term preferred in the sdk docs and should be
the term used.</p>
<p align="justify">You may notice too that the second parameter in 'alcCreateContext'
has been set to <font face="Courier New, Courier, mono">null</font>. The OpenAL
sdk from Creative Labs defines the following variables which are optional flags
to that parameter.</p>
<ul>
<li>ALC_FREQUENCY</li>
<li>ALC_REFRESH</li>
<li>ALC_SYNC</li>
</ul>
<p align="justify">If you were to create multiple contexts you could make them
interchangeable by making a call to 'alcMakeContextCurrent'. Sending NULL to
'alcMakeContextCurrent' is also a perfectly valid argument. It will prevent
processing of any audio data. Be aware that even if you have multiple rendering
contexts, you can only have one current at a time, and when your application
needs to use two contexts interchangeably you must be the one to make sure the
appropriate context is current. And if you do decide to do this, then there
may be times when you want to know exactly which context is current without
going through a big check.</p>
<pre class=code>ALC.Context curContext = alc.alcGetCurrentContext();
</pre>
<p>Once you have your context you can also obtain the device in use by that context.</p>
<pre class=code>ALC.Device curDevice = alc.alcGetContextsDevice(curContext);
</pre>
<p align="justify">Above we used the context we retrieved to find out which device
it was using. There is also one other cool feature that was built into Alc for
handling contexts.</p>
<pre class=code>alc.alcSuspendContext(context);
<span class=codeComment><font color="#006600">// Processing has been suspended to context.</font></span>
alc.alcProcessContext(context);
<span class=codeComment><font color="#006600">// Processing has been re-enabled to context.</font></span>
</pre>
<p align="justify">What we have done above was stop, and then resume processing
of audio data to the context. When processing has been suspended, no sound will
be generated from data sent through that context. A further note on the rendering
context: the OpenAL 1.0 spec does imply, but does not explicitly say, that sources
and buffers may be used across contexts. The "lifetime" of a source
or buffer during the application, is said to be valid as long as the source
and buffer id is valid (i.e. they have not been deleted).</p>
<pre class=code>alc.alcMakeContextCurrent(<font color="#0000FF">null</font>);
alc.alcDestroyContext(context);
alc.alcCloseDevice(device);
</pre>
<p align="justify">And that is how we clean up. The current context is defaulted
to <font face="Courier New, Courier, mono">null</font>, the context we created
is released, and the handle to the device is given back to the system resources.
There is but a few more Alc functions we have not yet covered.</p>
<pre class=code><font color="#0000FF">public int</font> alcGetError();
<font color="#0000FF">public</font> <font color="#0000FF">boolean</font> alcIsExtensionPresent(ALC.Device device, String extName);
<font color="#0000FF">public</font> <font color="#0000FF">int</font> alcGetEnumValue(ALC.Device device, String enumName);
<font color="#0000FF">public </font>String alcGetString(ALC.Device device, <font color="#0000FF">int</font> token);
<font color="#0000FF">public</font> <font color="#0000FF">void</font> alcGetIntegerv(ALC.Device device, <font color="#0000FF">int</font> token, <font color="#0000FF">int</font> size, <font color="#0000FF">int</font>[] dest);
</pre>
<p align="justify">It may be pretty obvious to you what these do, but lets humour
ourselves and have a closer look. First we have 'alcGetError' which is just
like 'alGetError' but will return Alc errors. The next two functions are for
querying Alc extensions. This was just the creators planning ahead, as there
are no Alc extensions either. The last function, 'alcGetInteger', will return
the Alc version when passed 'ALC_MAJOR_VERSION' or 'ALC_MINOR_VERSION'.</p>
<p>The function 'alcGetString' is pretty cool. It can take any of the following
three parameters to 'token':</p>
<ul>
<li>ALC_DEFAULT_DEVICE_SPECIFIER</li>
<li>ALC_DEVICE_SPECIFIER</li>
<li>ALC_EXTENSIONS</li>
</ul>
<p align="justify">The first will return the device string which your OpenAL implementation
will prefer you to use. In current OpenAL this should be "DirectSound3D",
like we used above. The second token will return a list of specifiers, but in
current OpenAL will only return "DirectSound" (without the "3D"
for some reason). The last will return a list of Alc extensions, of which none
exist yet.</p>
<p align="justify">Well that's most of Alc for you. I hope it gave you a better
understanding of how OpenAL interacts with the operation system. You might try
writing your own initialization routines so you can cast off Alut altogether.
Either way have fun with it.</p>
<table border="0" cellspacing="1" style="border-collapse: collapse" width="100%" id="AutoNumber2" bgcolor="#666699">
<tr>
<td width="40%"> <p dir="ltr"><font color="#FFFFFF" size="2">� 2003 DevMaster.net.
All rights reserved.</font></td>
<td width="60%"> <p align="right" dir="ltr"><font size="2"><a href="mailto:webmaster@devmaster.net">
<font color="#FFFFFF">Contact us</font></a><font color="#FFFFFF"> if you
want to write for us or for any comments, suggestions, or feedback.</font></font></td>
</tr>
</table>
<p align="justify"> </p>
</body>
</html>
|