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

Last change on this file since 3099 was 3099, checked in by sandervl, 25 years ago

replaced dsound by new version

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
60 len = inBuf->bufferdesc.dwBufferBytes / bytespersample * 1024;
61 if ((inBuf->lpfxFormat->nChannels == 2) && (inBuf->lpfxFormat->wBitsPerSample == 16)) {
62 data16b = (signed short *) inBuf->lpBuffer;
63 for (i = 0; i < tomix; i++) {
64 j = inpos / 1024 * 2;
65 mixbuf[i*2] += data16b[j] * vol1 / 256;
66 mixbuf[i*2+1] += data16b[j+1] * vol2 / 256;
67 inpos += spd;
68 if (inpos >= len) {
69 if (inBuf->fLoop) inpos -= len;
70 else {
71 inBuf->fPlaying = FALSE;
72 if (inBuf->notify != NULL)
73 inBuf->notify->CheckStop();
74 break;
75 }
76 }
77 }
78 }
79 if ((inBuf->lpfxFormat->nChannels == 1) && (inBuf->lpfxFormat->wBitsPerSample == 16)) {
80 data16b = (signed short *) inBuf->lpBuffer;
81 for (i = 0; i < tomix; i++) {
82 j = inpos / 1024;
83 sample = data16b[j];
84 mixbuf[i*2] += sample * vol1 / 256;
85 mixbuf[i*2+1] += sample * vol2 / 256;
86 inpos += spd;
87 if (inpos >= len) {
88 if (inBuf->fLoop) inpos -= len;
89 else {
90 inBuf->fPlaying = FALSE;
91 if (inBuf->notify != NULL)
92 inBuf->notify->CheckStop();
93 break;
94 }
95 }
96 }
97 }
98 if ((inBuf->lpfxFormat->nChannels == 2) && (inBuf->lpfxFormat->wBitsPerSample == 8)) {
99 data8b = (unsigned char *) inBuf->lpBuffer;
100 for (i = 0; i < tomix; i++) {
101 j = inpos / 1024 * 2;
102 sample = ((int) data8b[j] - 128) * vol1;
103 mixbuf[i*2] += sample;
104 sample = ((int) data8b[j+1] - 128) * vol2;
105 mixbuf[i*2+1] += sample;
106 inpos += spd;
107 if (inpos >= len) {
108 if (inBuf->fLoop) inpos -= len;
109 else {
110 inBuf->fPlaying = FALSE;
111 if (inBuf->notify != NULL)
112 inBuf->notify->CheckStop();
113 break;
114 }
115 }
116 }
117 }
118 if ((inBuf->lpfxFormat->nChannels == 1) && (inBuf->lpfxFormat->wBitsPerSample == 8)) {
119 data8b = (unsigned char *) inBuf->lpBuffer;
120 for (i = 0; i < tomix; i++) {
121 j = inpos / 1024;
122 sample = (int) data8b[j] - 128;
123 mixbuf[i*2] += sample * vol1;
124 mixbuf[i*2+1] += sample * vol2;
125 inpos += spd;
126 if (inpos >= len) {
127 if (inBuf->fLoop) inpos -= len;
128 else {
129 inBuf->fPlaying = FALSE;
130 if (inBuf->notify != NULL)
131 inBuf->notify->CheckStop();
132 break;
133 }
134 }
135 }
136 }
137 oldpos = inBuf->playpos;
138 inBuf->playpos = inpos / 1024 * bytespersample;
139 inBuf->frac = inpos % 1024;
140
141 // Check if any notifications are to be signaled
142 if (inBuf->notify != NULL)
143 inBuf->notify->CheckPos(oldpos, inBuf->playpos);
144
145 // keep the write cursor about 15ms ahead of the play cursor
146 inBuf->writepos = inBuf->playpos + inBuf->frequency * bytespersample / 67;
147 inBuf->writepos %= inBuf->bufferdesc.dwBufferBytes;
148}
149
150void MixFunc (OS2IDirectSoundBuffer *firstBuf, OS2IDirectSoundBuffer *outBuf,
151 ULONG cbMix) {
152 OS2IDirectSoundBuffer *inBuf = firstBuf;
153 int i, outbits, outrate, outnch, tomix, outpos, outlen;
154 unsigned char *data8b;
155 signed short *data16b;
156
157 outbits = outBuf->lpfxFormat->wBitsPerSample;
158 outrate = outBuf->lpfxFormat->nSamplesPerSec;
159 outnch = outBuf->lpfxFormat->nChannels;
160 tomix = cbMix * 8 / outbits / outnch;
161
162 memset(&mixbuf, 0, tomix * 2 * sizeof(mixbuf[0]));
163
164 while (inBuf != NULL) {
165 if (inBuf->fPlaying) {
166 MixOneBuffer(inBuf, tomix, outrate);
167 }
168 inBuf = inBuf->next;
169 }
170
171 outpos = outBuf->playpos * 8 / outbits;
172 outlen = outBuf->bufferdesc.dwBufferBytes * 8 / outbits;
173 if (outbits == 16) {
174 data16b = (signed short *) outBuf->lpBuffer;
175 for (i = 0; i < tomix * outnch; i++) {
176 if (mixbuf[i] <= -32768) data16b[outpos] = -32768;
177 else if (mixbuf[i] >= 32767) data16b[outpos] = 32767;
178 else data16b[outpos] = mixbuf[i];
179 outpos++;
180 if (outpos >= outlen) outpos = 0;
181 }
182 } else {
183 data8b = (unsigned char *) outBuf->lpBuffer;
184 for (i = 0; i < tomix * outnch; i++) {
185 if (mixbuf[i] <= -32768) data16b[outpos] = 0;
186 else if (mixbuf[i] >= 32767) data16b[outpos] = 255;
187 else data16b[outpos] = mixbuf[i] / 256 + 128;
188 outpos++;
189 if (outpos >= outlen) outpos = 0;
190 }
191 }
192 outBuf->playpos = outpos * outbits / 8;
193}
194
Note: See TracBrowser for help on using the repository browser.