source: trunk/src/dsound/dsmixer.cpp@ 21342

Last change on this file since 21342 was 21342, checked in by abwillis, 16 years ago

VAC365 build updates. dsound update seems to help VAC308 some here too.

File size: 7.5 KB
Line 
1/* $Id: dsmixer.cpp,v 1.5 2001-04-20 13:22:38 phaller Exp $ */
2/*
3 * DirectSound Software Mixer
4 *
5 * Copyright 2000 Michal Necasek
6 * Copyright 2000 Ondrej Necasek
7 *
8 * Project Odin Software License can be found in LICENSE.TXT
9 *
10 */
11
12
13/*@Header***********************************************************************
14* Header Files *
15*******************************************************************************/
16#define INCL_DOSMISC
17#include <os2win.h>
18
19#include <stdlib.h>
20#include <string.h>
21
22#define INITGUID
23#include <dsound.h>
24
25#include "os2dsound.h"
26#include "os2sndbuffer.h"
27#include "os2notify.h"
28#include <misc.h>
29
30//@@@ signed long mixbuf[2300*2]; /* enough for 50 ms at 44100Hz stereo */
31
32
33// The internal mixer buffer for sample calculations
34// It's allocated on demand by MixFunc.
35static signed long* mixbuf = NULL; // pointer to the mixer data buffer
36static ULONG ulMixerBufferSize = 0; // current size of the mixer buffer
37
38
39void MixCallback(ULONG cbMix)
40{
41 // Check for priority level here; for DSSCL_WRITEPRIMARY just play directly
42 // from the primary buffer; for all others mix the secondary buffers
43 if (OS2IDirectSoundBuffer::primary->parentDS->GetCoopLevel() != DSSCL_WRITEPRIMARY)
44 MixFunc(OS2IDirectSoundBuffer::dsbroot, OS2IDirectSoundBuffer::primary, cbMix);
45 else
46 {
47 }
48}
49
50
51void MixOneBuffer(OS2IDirectSoundBuffer *inBuf, int tomix, int outrate)
52{
53 unsigned char *data8b;
54 signed short *data16b;
55 int inpos, spd, i, j, sample, len, bytespersample, vol1, vol2;
56 int oldpos;
57
58 bytespersample = inBuf->lpfxFormat->wBitsPerSample *
59 inBuf->lpfxFormat->nChannels / 8;
60 inpos = inBuf->playpos / bytespersample * 1024 + inBuf->frac;
61 spd = 1024 * inBuf->frequency / outrate;
62 if (inBuf->pan <= 0)
63 vol1 = inBuf->volume;
64 else
65 vol1 = inBuf->volume * (256 - inBuf->pan) / 256;
66 if (inBuf->pan >= 0)
67 vol2 = inBuf->volume;
68 else
69 vol2 = inBuf->volume * (256 + inBuf->pan) / 256;
70
71 len = inBuf->bufferdesc.dwBufferBytes / bytespersample * 1024;
72 if ((inBuf->lpfxFormat->nChannels == 2) &&
73 (inBuf->lpfxFormat->wBitsPerSample == 16))
74 {
75 data16b = (signed short *) inBuf->lpBuffer;
76 for (i = 0; i < tomix; i++)
77 {
78 j = inpos / 1024 * 2;
79 mixbuf[i*2] += data16b[j] * vol1 / 256;
80 mixbuf[i*2+1] += data16b[j+1] * vol2 / 256;
81 inpos += spd;
82 if (inpos >= len)
83 {
84 if (inBuf->fLoop) inpos -= len;
85 else
86 {
87 inBuf->fPlaying = FALSE;
88 if (inBuf->notify != NULL)
89 inBuf->notify->CheckStop();
90
91 break;
92 }
93 }
94 }
95 }
96
97 if ((inBuf->lpfxFormat->nChannels == 1) &&
98 (inBuf->lpfxFormat->wBitsPerSample == 16))
99 {
100 data16b = (signed short *) inBuf->lpBuffer;
101 for (i = 0; i < tomix; i++)
102 {
103 j = inpos / 1024;
104 sample = data16b[j];
105 mixbuf[i*2] += sample * vol1 / 256;
106 mixbuf[i*2+1] += sample * vol2 / 256;
107 inpos += spd;
108 if (inpos >= len)
109 {
110 if (inBuf->fLoop) inpos -= len;
111 else
112 {
113 inBuf->fPlaying = FALSE;
114 if (inBuf->notify != NULL)
115 inBuf->notify->CheckStop();
116
117 break;
118 }
119 }
120 }
121 }
122
123 if ((inBuf->lpfxFormat->nChannels == 2) &&
124 (inBuf->lpfxFormat->wBitsPerSample == 8))
125 {
126 data8b = (unsigned char *) inBuf->lpBuffer;
127 for (i = 0; i < tomix; i++)
128 {
129 j = inpos / 1024 * 2;
130 sample = ((int) data8b[j] - 128) * vol1;
131 mixbuf[i*2] += sample;
132 sample = ((int) data8b[j+1] - 128) * vol2;
133 mixbuf[i*2+1] += sample;
134 inpos += spd;
135 if (inpos >= len)
136 {
137 if (inBuf->fLoop) inpos -= len;
138 else
139 {
140 inBuf->fPlaying = FALSE;
141 if (inBuf->notify != NULL)
142 inBuf->notify->CheckStop();
143
144 break;
145 }
146 }
147 }
148 }
149
150 if ((inBuf->lpfxFormat->nChannels == 1) &&
151 (inBuf->lpfxFormat->wBitsPerSample == 8))
152 {
153 data8b = (unsigned char *) inBuf->lpBuffer;
154 for (i = 0; i < tomix; i++)
155 {
156 j = inpos / 1024;
157 sample = (int) data8b[j] - 128;
158 mixbuf[i*2] += sample * vol1;
159 mixbuf[i*2+1] += sample * vol2;
160 inpos += spd;
161 if (inpos >= len)
162 {
163 if (inBuf->fLoop) inpos -= len;
164 else
165 {
166 inBuf->fPlaying = FALSE;
167 if (inBuf->notify != NULL)
168 inBuf->notify->CheckStop();
169
170 break;
171 }
172 }
173 }
174 }
175
176 oldpos = inBuf->playpos;
177 inBuf->playpos = inpos / 1024 * bytespersample;
178 inBuf->frac = inpos % 1024;
179
180 // Check if any notifications are to be signaled
181 if (inBuf->notify != NULL)
182 inBuf->notify->CheckPos(oldpos, inBuf->playpos);
183
184 // keep the write cursor about 15ms ahead of the play cursor
185 inBuf->writepos = inBuf->playpos + inBuf->frequency * bytespersample / 67;
186 inBuf->writepos %= inBuf->bufferdesc.dwBufferBytes;
187}
188
189
190void MixFunc (OS2IDirectSoundBuffer *firstBuf,
191 OS2IDirectSoundBuffer *outBuf,
192 ULONG cbMix)
193{
194 OS2IDirectSoundBuffer *inBuf = firstBuf;
195 int i;
196 int outbits;
197 int outrate;
198 int outnch;
199 int tomix;
200 int outpos;
201 int outlen;
202 unsigned char *data8b;
203 signed short *data16b;
204
205 outbits = outBuf->lpfxFormat->wBitsPerSample;
206 outrate = outBuf->lpfxFormat->nSamplesPerSec;
207 outnch = outBuf->lpfxFormat->nChannels;
208 tomix = cbMix * 8 / outbits / outnch;
209
210 // calculate required size (elements) of mixer buffer
211 ULONG ulRequiredSize = tomix * outnch;
212
213 // dynamically allocate the mixerbuffer as required
214 if (ulMixerBufferSize < ulRequiredSize)
215 {
216 // check if buffer has been allocated at all
217 if (NULL == mixbuf)
218 {
219 // allocate new buffer
220 mixbuf = (signed long*) malloc(ulRequiredSize * sizeof(mixbuf[0]));
221 ulMixerBufferSize = tomix;
222 }
223 else
224 {
225 // reallocate existing buffer
226 mixbuf = (signed long*) realloc(mixbuf, ulRequiredSize * sizeof(mixbuf[0]));
227 ulMixerBufferSize = tomix;
228 }
229 }
230
231
232 /* PH 2001-04-20 PowerDVD 3 comes in with tomix==4096
233 * (ulNumDartBuffers == 1.
234 * So below memset() crashed as the former static
235 * mixer buffer was way to small. The dynamic allocation
236 * is supposed to fix this.
237 *
238 * Also the assumption (?) of outnch == 2 is not met here.
239 * PowerDVD tries with 4 channels, thus requiring an even
240 * larger buffer.
241 */
242 memset(&mixbuf[0], 0, ulRequiredSize * sizeof(mixbuf[0]));
243
244
245 while (inBuf != NULL)
246 {
247 if (inBuf->fPlaying)
248 {
249 MixOneBuffer(inBuf, tomix, outrate);
250 }
251 inBuf = inBuf->next;
252 }
253
254 outpos = outBuf->playpos * 8 / outbits;
255 outlen = outBuf->bufferdesc.dwBufferBytes * 8 / outbits;
256
257 if (outbits == 16)
258 {
259 data16b = (signed short *) outBuf->lpBuffer;
260 for (i = 0; i < tomix * outnch; i++)
261 {
262 if (mixbuf[i] <= -32768)
263 data16b[outpos] = -32768;
264 else
265 if (mixbuf[i] >= 32767)
266 data16b[outpos] = 32767;
267 else
268 data16b[outpos] = (signed short)mixbuf[i];
269
270 outpos++;
271
272 if (outpos >= outlen)
273 outpos = 0;
274 }
275 }
276 else
277 {
278 data8b = (unsigned char *) outBuf->lpBuffer;
279 for (i = 0; i < tomix * outnch; i++)
280 {
281 if (mixbuf[i] <= -32768)
282 data8b[outpos] = 0;
283 else
284 if (mixbuf[i] >= 32767)
285 data8b[outpos] = 255;
286 else
287 data8b[outpos] = (signed short)mixbuf[i] / 256 + 128;
288
289 outpos++;
290 if (outpos >= outlen)
291 outpos = 0;
292 }
293 }
294
295 outBuf->playpos = outpos * outbits / 8;
296}
297
Note: See TracBrowser for help on using the repository browser.