Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/openal-0.0.8/src/alc/alc_speaker.c @ 17

Last change on this file since 17 was 17, checked in by landauf, 16 years ago

added openal

File size: 4.6 KB
Line 
1/* -*- mode: C; tab-width:8; c-basic-offset:8 -*-
2 * vi:set ts=8:
3 *
4 * alc_speaker.c
5 *
6 * functions related to the position of the speakers in the alc world.
7 *
8 * This speaker handling stuff is a little goofy.  Rotation code should be
9 * rewritten.  Also, the assumption is that speaker positions correspond to an
10 * interleaved layout of LRLRLR, or LF RF LB RB.  This might not always be the
11 * case.
12 */
13
14#include "al_siteconfig.h"
15
16#include <AL/al.h>
17#include <AL/alc.h>
18
19#include "al_debug.h"
20#include "al_main.h"
21#include "al_vector.h"
22#include "al_matrix.h"
23
24#include "alc/alc_error.h"
25#include "alc/alc_speaker.h"
26
27#ifndef M_SQRT1_2
28# define M_SQRT1_2      0.70710678118654752440  /* 1/sqrt(2) */
29#endif
30
31/*
32 * _alcSpeakerMove( ALuint cid )
33 *
34 * Moves speakers for context named by cid, using listener orientation and
35 * position as modifiers.
36 *
37 * If cid is invalid, set ALC_INVALID_CONTEXT.
38 *
39 * assumes context cid is locked
40 *
41 * FIXME:
42 *    please check my math
43 */
44void _alcSpeakerMove( ALuint cid ) {
45        AL_context *cc;
46        ALfloat vec[3];
47        ALfloat *pos;    /* listener position */
48        ALfloat *ori;    /* listener orientation */
49        ALfloat ipos[3]; /* inverse listener position */
50        ALuint i;
51        ALmatrix *m;
52        ALmatrix *pm;
53        ALmatrix *rm;
54
55        cc = _alcGetContext( cid );
56        if(cc == NULL) {
57                _alDebug(ALD_CONTEXT, __FILE__, __LINE__,
58                      "_alcSpeakerMove: invalid context id %d", cid);
59
60                _alcSetError( ALC_INVALID_CONTEXT );
61
62                return;
63        }
64
65        pos = cc->listener.position;
66        ori = cc->listener.orientation;
67
68        m  = _alMatrixAlloc(3, 3);
69        pm = _alMatrixAlloc(1, 3);
70        rm = _alMatrixAlloc(1, 3);
71
72        _alVectorCrossProduct(vec, ori + 0, ori + 3);
73        _alVectorNormalize(m->data[0], vec);
74
75        _alVectorCrossProduct(vec, m->data[0], ori + 0);
76        _alVectorNormalize(m->data[1], vec);
77
78        _alVectorNormalize(m->data[2], ori + 0);
79
80        /* reset speaker position */
81        _alcSpeakerInit(cid);
82
83        _alVectorInverse( ipos, cc->listener.position );
84
85        /* rotate about at and up vectors */
86        for(i = 0; i < _alcGetNumSpeakers(cid); i++) {
87                _alVectorTranslate(pm->data[0],
88                                   cc->_speaker_pos[i].pos, ipos);
89
90                _alMatrixMul(rm, pm, m);
91
92                _alVectorTranslate(cc->_speaker_pos[i].pos,
93                                   rm->data[0], pos);
94        }
95
96        _alDebug(ALD_MATH, __FILE__, __LINE__,
97                "SpAdj: l/r [%f|%f|%f] [%f|%f|%f]",
98                cc->_speaker_pos[0].pos[0],
99                cc->_speaker_pos[0].pos[1],
100                cc->_speaker_pos[0].pos[2],
101
102                cc->_speaker_pos[1].pos[0],
103                cc->_speaker_pos[1].pos[1],
104                cc->_speaker_pos[1].pos[2]);
105
106        _alMatrixFree(m);
107        _alMatrixFree(pm);
108        _alMatrixFree(rm);
109
110        return;
111}
112
113/*
114 * _alcSpeakerInit( ALuint cid )
115 *
116 * Initialize position wrt listener, w/o rt orientation.
117 *
118 * assumes locked context
119 */
120void _alcSpeakerInit( ALuint cid ) {
121        AL_context  *cc;
122        AL_listener *lis;
123        ALfloat *lpos;
124        ALfloat sdis; /* scaled distance */
125        ALuint i;
126        ALuint num;
127
128        cc  = _alcGetContext( cid );
129        lis = _alcGetListener( cid );
130        if(cc == NULL) {
131                /* invalid cid */
132                _alDebug(ALD_CONTEXT, __FILE__, __LINE__,
133                        "_alcSpeakerInit: invalid cid 0x%x", cid );
134
135                return;
136        }
137
138        if(lis == NULL) {
139                /* weird */
140                return;
141        }
142
143        lpos = lis->position;
144
145        /*
146         * A speaker distance of one simplifies the math later.
147         */
148        sdis = 1.0f;
149
150        _alDebug(ALD_CONTEXT, __FILE__, __LINE__,
151                "_alcSpeakerInit: ( sdis %f )", sdis );
152
153        for (i = 0; i < _ALC_MAX_CHANNELS; i++)
154        {
155                cc->_speaker_pos[i].pos[0]   = lpos[0];
156                cc->_speaker_pos[i].pos[1]   = lpos[1];
157                cc->_speaker_pos[i].pos[2]   = lpos[2];
158        }
159
160        num = _alcGetNumSpeakers(cid);
161
162        /* fourpoint */
163
164        if (num >= 4)
165        {
166                sdis *= M_SQRT1_2;
167
168                cc->_speaker_pos[ALS_LEFT].pos[2] += sdis;
169                cc->_speaker_pos[ALS_RIGHT].pos[2] += sdis;
170
171                cc->_speaker_pos[ALS_LEFTS].pos[0] -= sdis;
172                cc->_speaker_pos[ALS_LEFTS].pos[2] -= sdis;
173
174                cc->_speaker_pos[ALS_RIGHTS].pos[0] += sdis;
175                cc->_speaker_pos[ALS_RIGHTS].pos[2] -= sdis;
176        }
177
178        /* stereo */
179
180        if (num >= 2)
181        {
182                cc->_speaker_pos[ALS_LEFT].pos[0] -= sdis;
183                cc->_speaker_pos[ALS_RIGHT].pos[0] += sdis;
184        }
185        return;
186}
187
188/*
189 * _alcGetNumSpeakers( ALuint cid )
190 *
191 * Returns number of speakers available for context named cid.
192 *
193 * assumes locked context
194 */
195ALuint _alcGetNumSpeakers( ALuint cid ) {
196        return _alGetChannelsFromFormat( _alcGetWriteFormat( cid ) );
197}
198
199/*
200 * _alcGetSpeakerPosition( ALuint cid, ALuint speaker_num )
201 *
202 * Returns 3-float tuple giving the speaker position for speaker with offset
203 * speaker_num for the context named cid, or NULL on error.
204 *
205 * assumes locked context
206 */
207ALfloat *_alcGetSpeakerPosition( ALuint cid, ALuint speaker_num ) {
208        AL_context *cc;
209        ALuint nc;
210
211        cc = _alcGetContext( cid );
212        if(cc == NULL) {
213                return NULL;
214        }
215
216        nc = _alcGetNumSpeakers( cid );
217
218        if( speaker_num >= nc ) {
219                return NULL;
220        }
221
222        return cc->_speaker_pos[speaker_num].pos;
223}
Note: See TracBrowser for help on using the repository browser.