source: trunk/src/dsound/new/dsmixer.cpp@ 3027

Last change on this file since 3027 was 3027, checked in by mike, 26 years ago

* empty log message *

File size: 6.1 KB
Line 
1/*
2 * DirectSound Software Mixer
3 *
4 * Copyright 2000 Michal Necasek
5 * Copyright 2000 Ondrej Necasek
6 *
7 * Project Odin Software License can be found in LICENSE.TXT
8 *
9 */
10
11
12/*@Header***********************************************************************
13* Header Files *
14*******************************************************************************/
15#define INCL_DOSMISC
16#include <os2win.h>
17
18#include <stdlib.h>
19#include <string.h>
20
21#define INITGUID
22#include <dsound.h>
23
24#include "os2dsound.h"
25#include "os2sndbuffer.h"
26#include "os2notify.h"
27#include <misc.h>
28
29signed long mixbuf[2300*2]; /* enough for 50 ms at 44100Hz stereo */
30
31void MixCallback(ULONG cbMix) {
32 // Check for priority level here; for DSSCL_WRITEPRIMARY just play directly
33 // from the primary buffer; for all others mix the secondary buffers
34 if (OS2IDirectSoundBuffer::primary->parentDS->GetCoopLevel() != DSSCL_WRITEPRIMARY)
35 MixFunc(OS2IDirectSoundBuffer::dsbroot, OS2IDirectSoundBuffer::primary, cbMix);
36 else {
37 }
38}
39
40void MixOneBuffer(OS2IDirectSoundBuffer *inBuf, int tomix, int outrate)
41{
42 unsigned char *data8b;
43 signed short *data16b;
44 int inpos, spd, i, j, sample, len, bytespersample, vol1, vol2;
45 int oldpos;
46
47 bytespersample = inBuf->lpfxFormat->wBitsPerSample *
48 inBuf->lpfxFormat->nChannels / 8;
49 inpos = inBuf->playpos / bytespersample * 1024 + inBuf->frac;
50 spd = 1024 * inBuf->frequency / outrate;
51 if (inBuf->pan <= 0)
52 vol1 = inBuf->volume;
53 else
54 vol1 = inBuf->volume * (256 - inBuf->pan) / 256;
55 if (inBuf->pan >= 0)
56 vol2 = inBuf->volume;
57 else
58 vol2 = inBuf->volume * (256 + inBuf->pan) / 256;
59 len = inBuf->bufferdesc.dwBufferBytes / bytespersample * 1024;
60 if ((inBuf->lpfxFormat->nChannels == 2) && (inBuf->lpfxFormat->wBitsPerSample == 16)) {
61 data16b = (signed short *) inBuf->lpBuffer;
62 for (i = 0; i < tomix; i++) {
63 j = inpos / 1024 * 2;
64 mixbuf[i*2] += data16b[j] * vol1 / 256;
65 mixbuf[i*2+1] += data16b[j+1] * vol2 / 256;
66 inpos += spd;
67 if (inpos >= len) {
68 if (inBuf->fLoop) inpos -= len;
69 else {
70 inBuf->fPlaying = FALSE;
71 if (inBuf->notify != NULL)
72 inBuf->notify->CheckStop();
73 break;
74 }
75 }
76 }
77 }
78 if ((inBuf->lpfxFormat->nChannels == 1) && (inBuf->lpfxFormat->wBitsPerSample == 16)) {
79 data16b = (signed short *) inBuf->lpBuffer;
80 for (i = 0; i < tomix; i++) {
81 j = inpos / 1024;
82 sample = data16b[j];
83 mixbuf[i*2] += sample * vol1 / 256;
84 mixbuf[i*2+1] += sample * vol2 / 256;
85 inpos += spd;
86 if (inpos >= len) {
87 if (inBuf->fLoop) inpos -= len;
88 else {
89 inBuf->fPlaying = FALSE;
90 if (inBuf->notify != NULL)
91 inBuf->notify->CheckStop();
92 break;
93 }
94 }
95 }
96 }
97 if ((inBuf->lpfxFormat->nChannels == 2) && (inBuf->lpfxFormat->wBitsPerSample == 8)) {
98 data8b = (unsigned char *) inBuf->lpBuffer;
99 for (i = 0; i < tomix; i++) {
100 j = inpos / 1024 * 2;
101 sample = ((int) data8b[j] - 128) * vol1;
102 mixbuf[i*2] += sample;
103 sample = ((int) data8b[j+1] - 128) * vol2;
104 mixbuf[i*2+1] += sample;
105 inpos += spd;
106 if (inpos >= len) {
107 if (inBuf->fLoop) inpos -= len;
108 else {
109 inBuf->fPlaying = FALSE;
110 if (inBuf->notify != NULL)
111 inBuf->notify->CheckStop();
112 break;
113 }
114 }
115 }
116 }
117 if ((inBuf->lpfxFormat->nChannels == 1) && (inBuf->lpfxFormat->wBitsPerSample == 8)) {
118 data8b = (unsigned char *) inBuf->lpBuffer;
119 for (i = 0; i < tomix; i++) {
120 j = inpos / 1024;
121 sample = (int) data8b[j] - 128;
122 mixbuf[i*2] += sample * vol1;
123 mixbuf[i*2+1] += sample * vol2;
124 inpos += spd;
125 if (inpos >= len) {
126 if (inBuf->fLoop) inpos -= len;
127 else {
128 inBuf->fPlaying = FALSE;
129 if (inBuf->notify != NULL)
130 inBuf->notify->CheckStop();
131 break;
132 }
133 }
134 }
135 }
136 oldpos = inBuf->playpos;
137 inBuf->playpos = inpos / 1024 * bytespersample;
138 inBuf->frac = inpos % 1024;
139
140 // Check if any notifications are to be signaled
141 if (inBuf->notify != NULL)
142 inBuf->notify->CheckPos(oldpos, inBuf->playpos);
143
144 // keep the write cursor about 15ms ahead of the play cursor
145 inBuf->writepos = inBuf->playpos + inBuf->frequency * bytespersample / 67;
146 inBuf->writepos %= inBuf->bufferdesc.dwBufferBytes;
147}
148
149void MixFunc (OS2IDirectSoundBuffer *firstBuf, OS2IDirectSoundBuffer *outBuf,
150 ULONG cbMix) {
151 OS2IDirectSoundBuffer *inBuf = firstBuf;
152 int i, outbits, outrate, outnch, tomix, outpos, outlen;
153 unsigned char *data8b;
154 signed short *data16b;
155
156 outbits = outBuf->lpfxFormat->wBitsPerSample;
157 outrate = outBuf->lpfxFormat->nSamplesPerSec;
158 outnch = outBuf->lpfxFormat->nChannels;
159 tomix = cbMix * 8 / outbits / outnch;
160
161 memset(&mixbuf, 0, tomix * 2 * sizeof(mixbuf[0]));
162
163 while (inBuf != NULL) {
164 if (inBuf->fPlaying) {
165 MixOneBuffer(inBuf, tomix, outrate);
166 }
167 inBuf = inBuf->next;
168 }
169
170 outpos = outBuf->playpos * 8 / outbits;
171 outlen = outBuf->bufferdesc.dwBufferBytes * 8 / outbits;
172 if (outbits == 16) {
173 data16b = (signed short *) outBuf->lpBuffer;
174 for (i = 0; i < tomix * outnch; i++) {
175 if (mixbuf[i] <= -32768) data16b[outpos] = -32768;
176 else if (mixbuf[i] >= 32767) data16b[outpos] = 32767;
177 else data16b[outpos] = mixbuf[i];
178 outpos++;
179 if (outpos >= outlen) outpos = 0;
180 }
181 } else {
182 data8b = (unsigned char *) outBuf->lpBuffer;
183 for (i = 0; i < tomix * outnch; i++) {
184 if (mixbuf[i] <= -32768) data16b[outpos] = 0;
185 else if (mixbuf[i] >= 32767) data16b[outpos] = 255;
186 else data16b[outpos] = mixbuf[i] / 256 + 128;
187 outpos++;
188 if (outpos >= outlen) outpos = 0;
189 }
190 }
191 outBuf->playpos = outpos * outbits / 8;
192}
193
Note: See TracBrowser for help on using the repository browser.