Don't default to AL_FORMAT_STEREO16 when writing to the output buffer
[openal-soft.git] / Alc / ALu.c
blobf3cd24f51f316f0b39596b02c1e4cbae6a4c6bf0
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #define _CRT_SECURE_NO_DEPRECATE // get rid of sprintf security warnings on VS2005
23 #include "config.h"
25 #include <math.h>
26 #include "alMain.h"
27 #include "AL/al.h"
28 #include "AL/alc.h"
30 #if defined(HAVE_STDINT_H)
31 #include <stdint.h>
32 typedef int64_t ALint64;
33 #elif defined(HAVE___INT64)
34 typedef __int64 ALint64;
35 #elif (SIZEOF_LONG == 8)
36 typedef long ALint64;
37 #elif (SIZEOF_LONG_LONG == 8)
38 typedef long long ALint64;
39 #endif
41 #ifdef HAVE_SQRTF
42 #define aluSqrt(x) ((ALfloat)sqrtf((float)(x)))
43 #else
44 #define aluSqrt(x) ((ALfloat)sqrt((double)(x)))
45 #endif
47 // fixes for mingw32.
48 #if defined(max) && !defined(__max)
49 #define __max max
50 #endif
51 #if defined(min) && !defined(__min)
52 #define __min min
53 #endif
55 __inline ALuint aluBytesFromFormat(ALenum format)
57 switch(format)
59 case AL_FORMAT_MONO8:
60 case AL_FORMAT_STEREO8:
61 case AL_FORMAT_QUAD8:
62 case AL_FORMAT_51CHN8:
63 return 1;
65 case AL_FORMAT_MONO16:
66 case AL_FORMAT_STEREO16:
67 case AL_FORMAT_QUAD16:
68 case AL_FORMAT_51CHN16:
69 return 2;
71 case AL_FORMAT_MONO_FLOAT32:
72 case AL_FORMAT_STEREO_FLOAT32:
73 return 4;
75 default:
76 return 0;
80 __inline ALuint aluChannelsFromFormat(ALenum format)
82 switch(format)
84 case AL_FORMAT_MONO8:
85 case AL_FORMAT_MONO16:
86 case AL_FORMAT_MONO_FLOAT32:
87 return 1;
89 case AL_FORMAT_STEREO8:
90 case AL_FORMAT_STEREO16:
91 case AL_FORMAT_STEREO_FLOAT32:
92 return 2;
94 case AL_FORMAT_QUAD8:
95 case AL_FORMAT_QUAD16:
96 return 4;
98 case AL_FORMAT_51CHN8:
99 case AL_FORMAT_51CHN16:
100 return 6;
102 default:
103 return 0;
107 static __inline ALint aluF2L(ALfloat Value)
109 if(sizeof(ALint) == 4 && sizeof(double) == 8)
111 double temp;
112 temp = Value + (((65536.0*65536.0*16.0)+(65536.0*65536.0*8.0))*65536.0);
113 return *((ALint*)&temp);
115 return (ALint)Value;
118 static __inline ALshort aluF2S(ALfloat Value)
120 ALint i;
122 i = aluF2L(Value);
123 i = __min( 32767, i);
124 i = __max(-32768, i);
125 return ((ALshort)i);
128 static __inline ALvoid aluCrossproduct(ALfloat *inVector1,ALfloat *inVector2,ALfloat *outVector)
130 outVector[0] = inVector1[1]*inVector2[2] - inVector1[2]*inVector2[1];
131 outVector[1] = inVector1[2]*inVector2[0] - inVector1[0]*inVector2[2];
132 outVector[2] = inVector1[0]*inVector2[1] - inVector1[1]*inVector2[0];
135 static __inline ALfloat aluDotproduct(ALfloat *inVector1,ALfloat *inVector2)
137 return inVector1[0]*inVector2[0] + inVector1[1]*inVector2[1] +
138 inVector1[2]*inVector2[2];
141 static __inline ALvoid aluNormalize(ALfloat *inVector)
143 ALfloat length, inverse_length;
145 length = (ALfloat)aluSqrt(aluDotproduct(inVector, inVector));
146 if(length != 0)
148 inverse_length = 1.0f/length;
149 inVector[0] *= inverse_length;
150 inVector[1] *= inverse_length;
151 inVector[2] *= inverse_length;
155 static __inline ALvoid aluMatrixVector(ALfloat *vector,ALfloat matrix[3][3])
157 ALfloat result[3];
159 result[0] = vector[0]*matrix[0][0] + vector[1]*matrix[1][0] + vector[2]*matrix[2][0];
160 result[1] = vector[0]*matrix[0][1] + vector[1]*matrix[1][1] + vector[2]*matrix[2][1];
161 result[2] = vector[0]*matrix[0][2] + vector[1]*matrix[1][2] + vector[2]*matrix[2][2];
162 memcpy(vector, result, sizeof(result));
165 static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
166 ALenum isMono, ALenum OutputFormat,
167 ALfloat *drysend, ALfloat *wetsend,
168 ALfloat *pitch)
170 ALfloat ListenerOrientation[6],ListenerPosition[3],ListenerVelocity[3];
171 ALfloat InnerAngle,OuterAngle,OuterGain,Angle,Distance,DryMix,WetMix;
172 ALfloat Direction[3],Position[3],Velocity[3],SourceToListener[3];
173 ALfloat MinVolume,MaxVolume,MinDist,MaxDist,Rolloff;
174 ALfloat Pitch,ConeVolume,SourceVolume,PanningFB,PanningLR,ListenerGain;
175 ALfloat U[3],V[3],N[3];
176 ALfloat DopplerFactor, DopplerVelocity, flSpeedOfSound, flMaxVelocity;
177 ALfloat flVSS, flVLS;
178 ALint DistanceModel;
179 ALfloat Matrix[3][3];
180 ALint HeadRelative;
181 ALfloat flAttenuation;
183 //Get context properties
184 DopplerFactor = ALContext->DopplerFactor;
185 DistanceModel = ALContext->DistanceModel;
186 DopplerVelocity = ALContext->DopplerVelocity;
187 flSpeedOfSound = ALContext->flSpeedOfSound;
189 //Get listener properties
190 ListenerGain = ALContext->Listener.Gain;
191 memcpy(ListenerPosition, ALContext->Listener.Position, sizeof(ALContext->Listener.Position));
192 memcpy(ListenerVelocity, ALContext->Listener.Velocity, sizeof(ALContext->Listener.Velocity));
193 memcpy(&ListenerOrientation[0], ALContext->Listener.Forward, sizeof(ALContext->Listener.Forward));
194 memcpy(&ListenerOrientation[3], ALContext->Listener.Up, sizeof(ALContext->Listener.Up));
196 //Get source properties
197 Pitch = ALSource->flPitch;
198 SourceVolume = ALSource->flGain;
199 memcpy(Position, ALSource->vPosition, sizeof(ALSource->vPosition));
200 memcpy(Velocity, ALSource->vVelocity, sizeof(ALSource->vVelocity));
201 memcpy(Direction, ALSource->vOrientation, sizeof(ALSource->vOrientation));
202 MinVolume = ALSource->flMinGain;
203 MaxVolume = ALSource->flMaxGain;
204 MinDist = ALSource->flRefDistance;
205 MaxDist = ALSource->flMaxDistance;
206 Rolloff = ALSource->flRollOffFactor;
207 OuterGain = ALSource->flOuterGain;
208 InnerAngle = ALSource->flInnerAngle;
209 OuterAngle = ALSource->flOuterAngle;
210 HeadRelative = ALSource->bHeadRelative;
212 //Set working variables
213 DryMix = (ALfloat)(1.0f);
214 WetMix = (ALfloat)(0.0f);
216 //Only apply 3D calculations for mono buffers
217 if(isMono != AL_FALSE)
219 //1. Translate Listener to origin (convert to head relative)
220 if(HeadRelative==AL_FALSE)
222 Position[0] -= ListenerPosition[0];
223 Position[1] -= ListenerPosition[1];
224 Position[2] -= ListenerPosition[2];
227 //2. Calculate distance attenuation
228 Distance = aluSqrt(aluDotproduct(Position, Position));
230 flAttenuation = 1.0f;
231 switch (DistanceModel)
233 case AL_INVERSE_DISTANCE_CLAMPED:
234 Distance=__max(Distance,MinDist);
235 Distance=__min(Distance,MaxDist);
236 if (MaxDist < MinDist)
237 break;
238 //fall-through
239 case AL_INVERSE_DISTANCE:
240 if (MinDist > 0.0f)
242 if ((MinDist + (Rolloff * (Distance - MinDist))) > 0.0f)
243 flAttenuation = MinDist / (MinDist + (Rolloff * (Distance - MinDist)));
245 break;
247 case AL_LINEAR_DISTANCE_CLAMPED:
248 Distance=__max(Distance,MinDist);
249 Distance=__min(Distance,MaxDist);
250 if (MaxDist < MinDist)
251 break;
252 //fall-through
253 case AL_LINEAR_DISTANCE:
254 Distance=__min(Distance,MaxDist);
255 if (MaxDist != MinDist)
256 flAttenuation = 1.0f - (Rolloff*(Distance-MinDist)/(MaxDist - MinDist));
257 break;
259 case AL_EXPONENT_DISTANCE_CLAMPED:
260 Distance=__max(Distance,MinDist);
261 Distance=__min(Distance,MaxDist);
262 if (MaxDist < MinDist)
263 break;
264 //fall-through
265 case AL_EXPONENT_DISTANCE:
266 if ((Distance > 0.0f) && (MinDist > 0.0f))
267 flAttenuation = (ALfloat)pow(Distance/MinDist, -Rolloff);
268 break;
270 case AL_NONE:
271 default:
272 flAttenuation = 1.0f;
273 break;
276 // Source Gain + Attenuation
277 DryMix = SourceVolume * flAttenuation;
279 // Clamp to Min/Max Gain
280 DryMix = __min(DryMix,MaxVolume);
281 DryMix = __max(DryMix,MinVolume);
282 WetMix = __min(WetMix,MaxVolume);
283 WetMix = __max(WetMix,MinVolume);
284 //3. Apply directional soundcones
285 SourceToListener[0] = -Position[0];
286 SourceToListener[1] = -Position[1];
287 SourceToListener[2] = -Position[2];
288 aluNormalize(Direction);
289 aluNormalize(SourceToListener);
290 Angle = (ALfloat)(180.0*acos(aluDotproduct(Direction,SourceToListener))/3.141592654f);
291 if(Angle >= InnerAngle && Angle <= OuterAngle)
292 ConeVolume = (1.0f+(OuterGain-1.0f)*(Angle-InnerAngle)/(OuterAngle-InnerAngle));
293 else if(Angle > OuterAngle)
294 ConeVolume = (1.0f+(OuterGain-1.0f) );
295 else
296 ConeVolume = 1.0f;
298 //4. Calculate Velocity
299 if(DopplerFactor != 0.0f)
301 flVLS = aluDotproduct(ListenerVelocity, SourceToListener);
302 flVSS = aluDotproduct(Velocity, SourceToListener);
304 flMaxVelocity = (DopplerVelocity * flSpeedOfSound) / DopplerFactor;
306 if (flVSS >= flMaxVelocity)
307 flVSS = (flMaxVelocity - 1.0f);
308 else if (flVSS <= -flMaxVelocity)
309 flVSS = -flMaxVelocity + 1.0f;
311 if (flVLS >= flMaxVelocity)
312 flVLS = (flMaxVelocity - 1.0f);
313 else if (flVLS <= -flMaxVelocity)
314 flVLS = -flMaxVelocity + 1.0f;
316 pitch[0] = Pitch * ((flSpeedOfSound * DopplerVelocity) - (DopplerFactor * flVLS)) /
317 ((flSpeedOfSound * DopplerVelocity) - (DopplerFactor * flVSS));
319 else
320 pitch[0] = Pitch;
322 //5. Align coordinate system axes
323 aluCrossproduct(&ListenerOrientation[0], &ListenerOrientation[3], U); // Right-vector
324 aluNormalize(U); // Normalized Right-vector
325 memcpy(V, &ListenerOrientation[3], sizeof(V)); // Up-vector
326 aluNormalize(V); // Normalized Up-vector
327 memcpy(N, &ListenerOrientation[0], sizeof(N)); // At-vector
328 aluNormalize(N); // Normalized At-vector
329 Matrix[0][0] = U[0]; Matrix[0][1] = V[0]; Matrix[0][2] = -N[0];
330 Matrix[1][0] = U[1]; Matrix[1][1] = V[1]; Matrix[1][2] = -N[1];
331 Matrix[2][0] = U[2]; Matrix[2][1] = V[2]; Matrix[2][2] = -N[2];
332 aluMatrixVector(Position, Matrix);
334 //6. Convert normalized position into pannings, then into channel volumes
335 aluNormalize(Position);
336 switch(aluChannelsFromFormat(OutputFormat))
338 case 1:
339 drysend[0] = ConeVolume * ListenerGain * DryMix * aluSqrt(1.0f); //Direct
340 drysend[1] = ConeVolume * ListenerGain * DryMix * aluSqrt(1.0f); //Direct
341 wetsend[0] = ListenerGain * WetMix * aluSqrt(1.0f); //Room
342 wetsend[1] = ListenerGain * WetMix * aluSqrt(1.0f); //Room
343 break;
344 case 2:
345 PanningLR = 0.5f + 0.5f*Position[0];
346 drysend[0] = ConeVolume * ListenerGain * DryMix * aluSqrt(1.0f-PanningLR); //L Direct
347 drysend[1] = ConeVolume * ListenerGain * DryMix * aluSqrt( PanningLR); //R Direct
348 wetsend[0] = ListenerGain * WetMix * aluSqrt(1.0f-PanningLR); //L Room
349 wetsend[1] = ListenerGain * WetMix * aluSqrt( PanningLR); //R Room
350 break;
351 case 4:
352 /* TODO: Add center/lfe channel in spatial calculations? */
353 case 6:
354 // Apply a scalar so each individual speaker has more weight
355 PanningLR = 0.5f + (0.5f*Position[0]*1.41421356f);
356 PanningLR = __min(1.0f, PanningLR);
357 PanningLR = __max(0.0f, PanningLR);
358 PanningFB = 0.5f + (0.5f*Position[2]*1.41421356f);
359 PanningFB = __min(1.0f, PanningFB);
360 PanningFB = __max(0.0f, PanningFB);
361 drysend[0] = ConeVolume * ListenerGain * DryMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB)); //FL Direct
362 drysend[1] = ConeVolume * ListenerGain * DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB)); //FR Direct
363 drysend[2] = ConeVolume * ListenerGain * DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB)); //BL Direct
364 drysend[3] = ConeVolume * ListenerGain * DryMix * aluSqrt(( PanningLR)*( PanningFB)); //BR Direct
365 wetsend[0] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB)); //FL Room
366 wetsend[1] = ListenerGain * WetMix * aluSqrt(( PanningLR)*(1.0f-PanningFB)); //FR Room
367 wetsend[2] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB)); //BL Room
368 wetsend[3] = ListenerGain * WetMix * aluSqrt(( PanningLR)*( PanningFB)); //BR Room
369 break;
370 default:
371 break;
374 else
376 //1. Multi-channel buffers always play "normal"
377 drysend[0] = SourceVolume * 1.0f * ListenerGain;
378 drysend[1] = SourceVolume * 1.0f * ListenerGain;
379 drysend[2] = SourceVolume * 1.0f * ListenerGain;
380 drysend[3] = SourceVolume * 1.0f * ListenerGain;
381 drysend[4] = SourceVolume * 1.0f * ListenerGain;
382 drysend[5] = SourceVolume * 1.0f * ListenerGain;
383 wetsend[0] = SourceVolume * 0.0f * ListenerGain;
384 wetsend[1] = SourceVolume * 0.0f * ListenerGain;
385 wetsend[2] = SourceVolume * 0.0f * ListenerGain;
386 wetsend[3] = SourceVolume * 0.0f * ListenerGain;
387 wetsend[4] = SourceVolume * 0.0f * ListenerGain;
388 wetsend[5] = SourceVolume * 0.0f * ListenerGain;
390 pitch[0] = Pitch;
394 ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum format)
396 static float DryBuffer[BUFFERSIZE][OUTPUTCHANNELS];
397 static float WetBuffer[BUFFERSIZE][OUTPUTCHANNELS];
398 ALfloat DrySend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
399 ALfloat WetSend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
400 ALuint BlockAlign,BufferSize;
401 ALuint DataSize=0,DataPosInt=0,DataPosFrac=0;
402 ALuint Channels,Bits,Frequency,ulExtraSamples;
403 ALfloat Pitch;
404 ALint Looping,increment,State;
405 ALuint Buffer,fraction;
406 ALuint SamplesToDo;
407 ALsource *ALSource;
408 ALbuffer *ALBuffer;
409 ALfloat value;
410 ALshort *Data;
411 ALuint i,j,k;
412 ALbufferlistitem *BufferListItem;
413 ALuint loop;
414 ALint64 DataSize64,DataPos64;
416 SuspendContext(ALContext);
418 if(buffer)
420 //Figure output format variables
421 BlockAlign = aluChannelsFromFormat(format);
422 BlockAlign *= aluBytesFromFormat(format);
424 size /= BlockAlign;
425 while(size > 0)
427 //Setup variables
428 ALSource = (ALContext ? ALContext->Source : NULL);
429 SamplesToDo = min(size, BUFFERSIZE);
431 //Clear mixing buffer
432 memset(DryBuffer, 0, SamplesToDo*OUTPUTCHANNELS*sizeof(ALfloat));
433 memset(WetBuffer, 0, SamplesToDo*OUTPUTCHANNELS*sizeof(ALfloat));
435 //Actual mixing loop
436 while(ALSource)
438 j = 0;
439 State = ALSource->state;
440 while(State == AL_PLAYING && j < SamplesToDo)
442 DataSize = 0;
443 DataPosInt = 0;
444 DataPosFrac = 0;
446 //Get buffer info
447 if((Buffer = ALSource->ulBufferID))
449 ALBuffer = (ALbuffer*)ALTHUNK_LOOKUPENTRY(Buffer);
451 Data = ALBuffer->data;
452 Bits = aluBytesFromFormat(ALBuffer->format) * 8;
453 Channels = aluChannelsFromFormat(ALBuffer->format);
454 DataSize = ALBuffer->size;
455 Frequency = ALBuffer->frequency;
457 CalcSourceParams(ALContext, ALSource,
458 (Channels==1) ? AL_TRUE : AL_FALSE,
459 format, DrySend, WetSend, &Pitch);
462 Pitch = (Pitch*Frequency) / ALContext->Frequency;
463 DataSize = DataSize / (Bits*Channels/8);
465 //Get source info
466 DataPosInt = ALSource->position;
467 DataPosFrac = ALSource->position_fraction;
469 //Compute 18.14 fixed point step
470 increment = aluF2L(Pitch*(1L<<FRACTIONBITS));
471 if(increment > (MAX_PITCH<<FRACTIONBITS))
472 increment = (MAX_PITCH<<FRACTIONBITS);
474 //Figure out how many samples we can mix.
475 //Pitch must be <= 4 (the number below !)
476 DataSize64 = DataSize+MAX_PITCH;
477 DataSize64 <<= FRACTIONBITS;
478 DataPos64 = DataPosInt;
479 DataPos64 <<= FRACTIONBITS;
480 DataPos64 += DataPosFrac;
481 BufferSize = (ALuint)((DataSize64-DataPos64) / increment);
482 BufferListItem = ALSource->queue;
483 for(loop = 0; loop < ALSource->BuffersPlayed; loop++)
485 if(BufferListItem)
486 BufferListItem = BufferListItem->next;
488 if (BufferListItem)
490 if (BufferListItem->next)
492 if(BufferListItem->next->buffer &&
493 ((ALbuffer*)ALTHUNK_LOOKUPENTRY(BufferListItem->next->buffer))->data)
495 ulExtraSamples = min(((ALbuffer*)ALTHUNK_LOOKUPENTRY(BufferListItem->next->buffer))->size, (ALint)(16*Channels));
496 memcpy(&Data[DataSize*Channels], ((ALbuffer*)ALTHUNK_LOOKUPENTRY(BufferListItem->next->buffer))->data, ulExtraSamples);
499 else if (ALSource->bLooping)
501 if (ALSource->queue->buffer)
503 if(((ALbuffer*)ALTHUNK_LOOKUPENTRY(ALSource->queue->buffer))->data)
505 ulExtraSamples = min(((ALbuffer*)ALTHUNK_LOOKUPENTRY(ALSource->queue->buffer))->size, (ALint)(16*Channels));
506 memcpy(&Data[DataSize*Channels], ((ALbuffer*)ALTHUNK_LOOKUPENTRY(ALSource->queue->buffer))->data, ulExtraSamples);
511 BufferSize = min(BufferSize, (SamplesToDo-j));
513 //Actual sample mixing loop
514 Data += DataPosInt*Channels;
515 while(BufferSize--)
517 k = DataPosFrac>>FRACTIONBITS;
518 fraction = DataPosFrac&FRACTIONMASK;
519 if(Channels==1)
521 //First order interpolator
522 value = (ALfloat)((ALshort)(((Data[k]*((1L<<FRACTIONBITS)-fraction))+(Data[k+1]*(fraction)))>>FRACTIONBITS));
523 //Direct path final mix buffer and panning
524 DryBuffer[j][0] += value*DrySend[0];
525 DryBuffer[j][1] += value*DrySend[1];
526 DryBuffer[j][2] += value*DrySend[2];
527 DryBuffer[j][3] += value*DrySend[3];
528 //Room path final mix buffer and panning
529 WetBuffer[j][0] += value*WetSend[0];
530 WetBuffer[j][1] += value*WetSend[1];
531 WetBuffer[j][2] += value*WetSend[2];
532 WetBuffer[j][3] += value*WetSend[3];
534 else
536 //First order interpolator (left)
537 value = (ALfloat)((ALshort)(((Data[k*2 ]*((1L<<FRACTIONBITS)-fraction))+(Data[k*2+2]*(fraction)))>>FRACTIONBITS));
538 //Direct path final mix buffer and panning (left)
539 DryBuffer[j][0] += value*DrySend[0];
540 //Room path final mix buffer and panning (left)
541 WetBuffer[j][0] += value*WetSend[0];
542 //First order interpolator (right)
543 value = (ALfloat)((ALshort)(((Data[k*2+1]*((1L<<FRACTIONBITS)-fraction))+(Data[k*2+3]*(fraction)))>>FRACTIONBITS));
544 //Direct path final mix buffer and panning (right)
545 DryBuffer[j][1] += value*DrySend[1];
546 //Room path final mix buffer and panning (right)
547 WetBuffer[j][1] += value*WetSend[1];
549 DataPosFrac += increment;
550 j++;
552 DataPosInt += (DataPosFrac>>FRACTIONBITS);
553 DataPosFrac = (DataPosFrac&FRACTIONMASK);
555 //Update source info
556 ALSource->position = DataPosInt;
557 ALSource->position_fraction = DataPosFrac;
560 //Handle looping sources
561 if(!Buffer || DataPosInt >= DataSize)
563 //queueing
564 if(ALSource->queue)
566 Looping = ALSource->bLooping;
567 if(ALSource->BuffersPlayed < (ALSource->BuffersInQueue-1))
569 BufferListItem = ALSource->queue;
570 for(loop = 0; loop <= ALSource->BuffersPlayed; loop++)
572 if(BufferListItem)
574 if(!Looping)
575 BufferListItem->bufferstate = PROCESSED;
576 BufferListItem = BufferListItem->next;
579 if(!Looping)
580 ALSource->BuffersProcessed++;
581 if(BufferListItem)
582 ALSource->ulBufferID = BufferListItem->buffer;
583 ALSource->position = DataPosInt-DataSize;
584 ALSource->position_fraction = DataPosFrac;
585 ALSource->BuffersPlayed++;
587 else
589 if(!Looping)
591 /* alSourceStop */
592 ALSource->state = AL_STOPPED;
593 ALSource->inuse = AL_FALSE;
594 ALSource->BuffersPlayed = ALSource->BuffersProcessed = ALSource->BuffersInQueue;
595 BufferListItem = ALSource->queue;
596 while(BufferListItem != NULL)
598 BufferListItem->bufferstate = PROCESSED;
599 BufferListItem = BufferListItem->next;
602 else
604 /* alSourceRewind */
605 /* alSourcePlay */
606 ALSource->state = AL_PLAYING;
607 ALSource->inuse = AL_TRUE;
608 ALSource->play = AL_TRUE;
609 ALSource->BuffersPlayed = 0;
610 ALSource->BufferPosition = 0;
611 ALSource->lBytesPlayed = 0;
612 ALSource->BuffersProcessed = 0;
613 BufferListItem = ALSource->queue;
614 while(BufferListItem != NULL)
616 BufferListItem->bufferstate = PENDING;
617 BufferListItem = BufferListItem->next;
619 ALSource->ulBufferID = ALSource->queue->buffer;
621 ALSource->position = DataPosInt-DataSize;
622 ALSource->position_fraction = DataPosFrac;
628 //Get source state
629 State = ALSource->state;
632 ALSource = ALSource->next;
635 //Post processing loop
636 switch(format)
638 case AL_FORMAT_MONO8:
639 for(i = 0;i < SamplesToDo;i++)
641 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][0]+DryBuffer[i][1]+WetBuffer[i][0]+WetBuffer[i][1])>>8)+128);
642 buffer = ((ALubyte*)buffer) + 1;
644 break;
645 case AL_FORMAT_STEREO8:
646 for(i = 0;i < SamplesToDo;i++)
648 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][0]+WetBuffer[i][0])>>8)+128);
649 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][1]+WetBuffer[i][1])>>8)+128);
650 buffer = ((ALubyte*)buffer) + 2;
652 break;
653 case AL_FORMAT_QUAD8:
654 for(i = 0;i < SamplesToDo;i++)
656 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][0]+WetBuffer[i][0])>>8)+128);
657 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][1]+WetBuffer[i][1])>>8)+128);
658 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][2]+WetBuffer[i][2])>>8)+128);
659 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][3]+WetBuffer[i][3])>>8)+128);
660 buffer = ((ALubyte*)buffer) + 4;
662 break;
663 case AL_FORMAT_51CHN8:
664 for(i = 0;i < SamplesToDo;i++)
666 ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][0]+WetBuffer[i][0])>>8)+128);
667 ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][1]+WetBuffer[i][1])>>8)+128);
668 ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][2]+WetBuffer[i][2])>>8)+128);
669 ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][3]+WetBuffer[i][3])>>8)+128);
670 ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][4]+WetBuffer[i][4])>>8)+128);
671 ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][5]+WetBuffer[i][5])>>8)+128);
672 buffer = ((ALubyte*)buffer) + 6;
674 break;
675 case AL_FORMAT_MONO16:
676 for(i = 0;i < SamplesToDo;i++)
678 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][0]+DryBuffer[i][1]+WetBuffer[i][0]+WetBuffer[i][1]);
679 buffer = ((ALshort*)buffer) + 1;
681 break;
682 case AL_FORMAT_STEREO16:
683 for(i = 0;i < SamplesToDo;i++)
685 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][0]+WetBuffer[i][0]);
686 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][1]+WetBuffer[i][1]);
687 buffer = ((ALshort*)buffer) + 2;
689 break;
690 case AL_FORMAT_QUAD16:
691 for(i = 0;i < SamplesToDo;i++)
693 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][0]+WetBuffer[i][0]);
694 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][1]+WetBuffer[i][1]);
695 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][2]+WetBuffer[i][2]);
696 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][3]+WetBuffer[i][3]);
697 buffer = ((ALshort*)buffer) + 4;
699 break;
700 case AL_FORMAT_51CHN16:
701 for(i = 0;i < SamplesToDo;i++)
703 ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][0]+WetBuffer[i][0]);
704 ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][1]+WetBuffer[i][1]);
705 ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][2]+WetBuffer[i][2]);
706 ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][3]+WetBuffer[i][3]);
707 ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][4]+WetBuffer[i][4]);
708 ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][5]+WetBuffer[i][5]);
709 buffer = ((ALshort*)buffer) + 6;
711 break;
713 default:
714 break;
717 size -= SamplesToDo;
721 ProcessContext(ALContext);