1 /*
2 Copyright (C) 2005 The Pentagram team
3 Copyright (C) 2010-2013 The Exult Team
4 
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 */
19 
20 #include "pent_include.h"
21 
22 #include "AudioChannel.h"
23 #include "AudioSample.h"
24 
25 #include <cstring>
26 namespace Pentagram {
27 
ReadSample(uint8 * src)28 sint16 ReadSample(uint8 *src) {
29 	sint16 val;
30 	std::memcpy(&val, src, sizeof(sint16));
31 	return val;
32 }
33 
34 // We divide the data by 2, to prevent overshots. Imagine this sample pattern:
35 // 0, 65535, 65535, 0. Now you want to compute a value between the two 65535.
36 // Obviously, it will be *bigger* than 65535 (it can get to about 80,000).
37 // It is possibly to clamp it, but that leads to a distored wave form. Compare
38 // this to turning up the volume of your stereo to much, it will start to sound
39 // bad at a certain level (depending on the power of your stereo, your speakers
40 // etc, this can be quite loud, though ;-). Hence we reduce the original range.
41 // A factor of roughly 1/1.2 = 0.8333 is sufficient. Since we want to avoid
42 // floating point, we approximate that by 27/32
43 #define RANGE_REDUX(x)	(((x) * 27) >> 5)
44 
AudioChannel(uint32 sample_rate_,bool stereo_)45 AudioChannel::AudioChannel(uint32 sample_rate_, bool stereo_) :
46 	sample_rate(sample_rate_), stereo(stereo_)
47 {
48 }
49 
~AudioChannel()50 AudioChannel::~AudioChannel()
51 {
52 	if (sample && playdata) sample->freeDecompressor(decomp);
53 	if (sample) sample->Release();
54 	playdata.reset();
55 	sample = nullptr;
56 }
57 
playSample(AudioSample * sample_,int loop_,int priority_,bool paused_,uint32 pitch_shift_,int lvol_,int rvol_,sint32 instance_id_)58 void AudioChannel::playSample(AudioSample *sample_, int loop_, int priority_, bool paused_, uint32 pitch_shift_, int lvol_, int rvol_, sint32 instance_id_)
59 {
60 	stop();
61 	sample = sample_;
62 
63 	loop = loop_;
64 	priority = priority_;
65 	lvol = lvol_;
66 	rvol = rvol_;
67 	paused = paused_;
68 	pitch_shift = pitch_shift_;
69 	instance_id = instance_id_;
70 	distance = 0;
71 	balance = 0;
72 
73 	if (!sample) return;
74 	sample->IncRef();
75 
76 	// Lambda to round size up to next multiple of maximum alignment size, if needed.
77 	auto round_up = [](size_t val) {
78 		constexpr const size_t maxalign = alignof(std::max_align_t);
79 		return ((val + maxalign - 1) / maxalign) * maxalign;
80 	};
81 	// Persistent data for the decompressor
82 	const size_t decompressor_size = round_up(sample->getDecompressorDataSize());
83 	const size_t frame_size = round_up(sample->getFrameSize());
84 	const size_t decompressor_align = sample->getDecompressorAlignment();
85 
86 	// Setup buffers
87 	if ((decompressor_size + frame_size * 2) > playdata_size)
88 	{
89 		playdata_size = decompressor_size + frame_size * 2 + decompressor_align;
90 		playdata = std::make_unique<uint8[]>(playdata_size);
91 	}
92 
93 	size_t avail_space = playdata_size;
94 	decomp = playdata.get();
95 	// Align decomp to required alignment.
96 	std::align(decompressor_align, decompressor_size, decomp, avail_space);
97 	// Align first frame.
98 	size_t delta = playdata_size - avail_space;
99 	avail_space -= decompressor_size;
100 	void *frameptr = playdata.get() + delta + decompressor_size;
101 	std::align(alignof(std::max_align_t), frame_size, frameptr, avail_space);
102 	frames[0] = static_cast<uint8*>(frameptr);
103 	// Second frame should be aligned for free.
104 	frames[1] = frames[0] + frame_size;
105 
106 	// Init the sample decompressor
107 	sample->initDecompressor(decomp);
108 
109 	// Reset counter and stuff
110 	frame_evenodd = 0;
111 	position = 0;
112 	fp_pos = 0;
113 	fp_speed = (pitch_shift*sample->getRate())/sample_rate;
114 
115 	// Decompress frame 0
116 	frame0_size = sample->decompressFrame(decomp, frames[0]);
117 
118 	// Decompress frame 1
119 	DecompressNextFrame();
120 
121 	// Setup resampler
122 	if (sample->getBits()==8 && !sample->isStereo())
123 	{
124 		uint8 *src = frames[0];
125 		int a = *(src+0); a = (a|(a << 8))-32768;
126 		int b = *(src+1); b = (a|(b << 8))-32768;
127 		int c = *(src+2); c = (a|(c << 8))-32768;
128 
129 		interp_l.init(RANGE_REDUX(a),RANGE_REDUX(b),RANGE_REDUX(c));
130 	}
131 
132 }
133 
resampleAndMix(sint16 * stream,uint32 bytes)134 void AudioChannel::resampleAndMix(sint16 *stream, uint32 bytes)
135 {
136 	if (!sample || paused)
137 		return;
138 
139 	// Update fp_speed
140 	fp_speed = (pitch_shift*sample->getRate())/sample_rate;
141 
142 	// Get and Mix data
143 	do
144 	{
145 		// 8 bit resampling
146 		if (sample->getBits()==8) {
147 			if (!sample->isStereo() && stereo)
148 				resampleFrameM8toS(stream,bytes);		// Mono Sample to Stereo Output
149 			else if (!sample->isStereo() && !stereo)
150 				resampleFrameM8toM(stream,bytes);		// Mono Sample to Stereo Output
151 			else if (sample->isStereo() && !stereo)
152 				resampleFrameS8toM(stream,bytes);		// Stereo Sample to Mono Output
153 			else
154 				resampleFrameS8toS(stream,bytes);		// Stereo Sample to Stereo Output
155 		}
156 		else if (sample->getBits()==16) {
157 			if (!sample->isStereo() && stereo)
158 				resampleFrameM16toS(stream,bytes);		// Mono Sample to Stereo Output
159 			else if (!sample->isStereo() && !stereo)
160 				resampleFrameM16toM(stream,bytes);		// Mono Sample to Mono Output
161 			else if (sample->isStereo() && !stereo)
162 				resampleFrameS16toM(stream,bytes);		// Stereo Sample to Mono Output
163 			else
164 				resampleFrameS16toS(stream,bytes);		// Stereo Sample to Stereo Output
165 		}
166 
167 		// We ran out of data
168 		if (bytes || (position == frame0_size)) {
169 
170 			// No more data
171 			if (!frame1_size) {
172 				if (sample) sample->Release();
173 				sample = nullptr;
174 				return;
175 			}
176 
177 			// Invert evenodd
178 			frame_evenodd = 1-frame_evenodd;
179 
180 			// Set frame1 to be frame0
181 			frame0_size = frame1_size;
182 			position = 0;
183 
184 			DecompressNextFrame();
185 		}
186 
187 	} while (bytes!=0);
188 }
189 
190 // Decompress a frame
DecompressNextFrame()191 void AudioChannel::DecompressNextFrame()
192 {
193 	// Get next frame of data
194 	uint8 *src2 = frames[1-frame_evenodd];
195 	frame1_size = sample->decompressFrame(decomp, src2);
196 
197 	// No stream, go back to beginning and get first frame
198 	if (!frame1_size && loop) {
199 		if (loop != -1) loop--;
200 		sample->rewind(decomp);
201 		frame1_size = sample->decompressFrame(decomp, src2);
202 	}
203 	else if (!frame1_size)
204 	{
205 		sample->freeDecompressor(decomp);
206 	}
207 }
208 
209 //
210 // 8 Bit
211 //
212 
213 // Resample a frame of mono 8bit unsigned to Stereo 16bit
resampleFrameM8toS(sint16 * & stream,uint32 & bytes)214 void AudioChannel::resampleFrameM8toS(sint16 *&stream, uint32 &bytes)
215 {
216 	uint8 *src = frames[frame_evenodd];
217 	uint8 *src2 = frames[1-frame_evenodd];
218 
219 	uint8 *src_end = src + frame0_size;
220 	uint8 *src2_end = src2 + frame1_size;
221 
222 	src += position;
223 
224 	int	lvol = this->lvol;
225 	int rvol = this->rvol;
226 
227 	calculate2DVolume(lvol,rvol);
228 
229 	do {
230 		// Add a new src sample (if required)
231 		if (fp_pos >= 0x10000)
232 		{
233 			if (src+2 < src_end) {
234 				int c = *(src+2);
235 				c = (c|(c << 8))-32768;
236 				interp_l.feedData(c);
237 			} else if (src2 < src2_end) {
238 				int c = *(src2);
239 				c = (c|(c << 8))-32768;
240 				interp_l.feedData(c);
241 				src2++;
242 			} else {
243 				interp_l.feedData();
244 			}
245 			src++;
246 			fp_pos -= 0x10000;
247 		}
248 
249 		if (fp_pos < 0x10000) do {
250 			// Do the interpolation
251 			int result = interp_l.interpolate(fp_pos);
252 
253 			int lresult = *(stream+0) + (result*lvol)/256;
254 			int rresult = *(stream+1) + (result*rvol)/256;
255 
256 			// Enforce range in case of an "overshot". Shouldn't happen since we
257 			// scale down already, but safe is safe.
258 			if (lresult < -32768) lresult = -32768;
259 			else if (lresult > 32767) lresult = 32767;
260 
261 			if (rresult < -32768) rresult = -32768;
262 			else if (rresult > 32767) rresult = 32767;
263 
264 			*stream++ = lresult;
265 			*stream++ = rresult;
266 			bytes -= 4;
267 			fp_pos += fp_speed;
268 
269 		} while (fp_pos < 0x10000 && bytes!=0);
270 
271 	} while (bytes!=0 && src != src_end);
272 
273 	position = frame0_size - (src_end - src);
274 }
275 
276 // Resample a frame of mono 8bit unsigned to Mono 16bit
resampleFrameM8toM(sint16 * & stream,uint32 & bytes)277 void AudioChannel::resampleFrameM8toM(sint16 *&stream, uint32 &bytes)
278 {
279 	uint8 *src = frames[frame_evenodd];
280 	uint8 *src2 = frames[1-frame_evenodd];
281 
282 	uint8 *src_end = src + frame0_size;
283 	uint8 *src2_end = src2 + frame1_size;
284 
285 	src += position;
286 
287 	int	lvol = this->lvol;
288 	int rvol = this->rvol;
289 
290 	calculate2DVolume(lvol,rvol);
291 
292 	int volume = (rvol + lvol)/2;
293 
294 	do {
295 		// Add a new src sample (if required)
296 		if (fp_pos >= 0x10000)
297 		{
298 			if (src+2 < src_end) {
299 				int c = *(src+2);
300 				c = (c|(c << 8))-32768;
301 				interp_l.feedData(c);
302 			} else if (src2 < src2_end) {
303 				int c = *(src2);
304 				c = (c|(c << 8))-32768;
305 				interp_l.feedData(c);
306 				src2++;
307 			} else {
308 				interp_l.feedData();
309 			}
310 			src++;
311 			fp_pos -= 0x10000;
312 		}
313 
314 		if (fp_pos < 0x10000) do {
315 			// Do the interpolation
316 			int result = (interp_l.interpolate(fp_pos)*volume)/256;
317 
318 			result += *stream;
319 
320 			// Enforce range in case of an "overshot". Shouldn't happen since we
321 			// scale down already, but safe is safe.
322 			if (result < -32768) result = -32768;
323 			else if (result > 32767) result = 32767;
324 
325 			*stream++ = result;
326 			bytes -= 2;
327 			fp_pos += fp_speed;
328 
329 		} while (fp_pos < 0x10000 && bytes!=0);
330 
331 	} while (bytes!=0 && src != src_end);
332 
333 	position = frame0_size - (src_end - src);
334 }
335 
336 // Resample a frame of stereo 8bit unsigned to Mono 16bit
resampleFrameS8toM(sint16 * & stream,uint32 & bytes)337 void AudioChannel::resampleFrameS8toM(sint16 *&stream, uint32 &bytes)
338 {
339 	uint8 *src = frames[frame_evenodd];
340 	uint8 *src2 = frames[1-frame_evenodd];
341 
342 	uint8 *src_end = src + frame0_size;
343 	uint8 *src2_end = src2 + frame1_size;
344 
345 	src += position;
346 
347 	int	lvol = this->lvol;
348 	int rvol = this->rvol;
349 
350 	calculate2DVolume(lvol,rvol);
351 
352 	do {
353 		// Add a new src sample (if required)
354 		if (fp_pos >= 0x10000)
355 		{
356 			if (src+4 < src_end) {
357 				int c = *(src+4);
358 				int c2 = *(src+5);
359 				interp_l.feedData((c|(c << 8))-32768);
360 				interp_r.feedData((c2|(c2 << 8))-32768);
361 			} else if (src2 < src2_end) {
362 				int c = *(src2);
363 				int c2 = *(src2+1);
364 				interp_l.feedData((c|(c << 8))-32768);
365 				interp_r.feedData((c2|(c2 << 8))-32768);
366 				src2+=2;
367 			} else {
368 				interp_l.feedData();
369 				interp_r.feedData();
370 			}
371 			src+=2;
372 			fp_pos -= 0x10000;
373 		}
374 
375 		if (fp_pos < 0x10000) do {
376 			// Do the interpolation
377 			int result = ((interp_l.interpolate(fp_pos)*lvol+interp_r.interpolate(fp_pos)*rvol))/512;
378 
379 			result += *stream;
380 
381 			// Enforce range in case of an "overshot". Shouldn't happen since we
382 			// scale down already, but safe is safe.
383 			if (result < -32768) result = -32768;
384 			else if (result > 32767) result = 32767;
385 
386 			*stream++ = result;
387 			bytes -= 2;
388 			fp_pos += fp_speed;
389 
390 		} while (fp_pos < 0x10000 && bytes!=0);
391 
392 	} while (bytes!=0 && src != src_end);
393 
394 	position = frame0_size - (src_end - src);
395 }
396 
397 // Resample a frame of stereo 8bit unsigned to Stereo 16bit
resampleFrameS8toS(sint16 * & stream,uint32 & bytes)398 void AudioChannel::resampleFrameS8toS(sint16 *&stream, uint32 &bytes)
399 {
400 	uint8 *src = frames[frame_evenodd];
401 	uint8 *src2 = frames[1-frame_evenodd];
402 
403 	uint8 *src_end = src + frame0_size;
404 	uint8 *src2_end = src2 + frame1_size;
405 
406 	src += position;
407 
408 	int	lvol = this->lvol;
409 	int rvol = this->rvol;
410 
411 	calculate2DVolume(lvol,rvol);
412 
413 	do {
414 		// Add a new src sample (if required)
415 		if (fp_pos >= 0x10000)
416 		{
417 			if (src+4 < src_end) {
418 				int c = *(src+4);
419 				int c2 = *(src+5);
420 				interp_l.feedData((c|(c << 8))-32768);
421 				interp_r.feedData((c2|(c2 << 8))-32768);
422 			} else if (src2 < src2_end) {
423 				int c = *(src2);
424 				int c2 = *(src2+1);
425 				interp_l.feedData((c|(c << 8))-32768);
426 				interp_r.feedData((c2|(c2 << 8))-32768);
427 				src2+=2;
428 			} else {
429 				interp_l.feedData();
430 				interp_r.feedData();
431 			}
432 			src+=2;
433 			fp_pos -= 0x10000;
434 		}
435 
436 		if (fp_pos < 0x10000) do {
437 			// Do the interpolation
438 			int lresult = *(stream+0) + (interp_l.interpolate(fp_pos)*lvol)/256;
439 			int rresult = *(stream+1) + (interp_r.interpolate(fp_pos)*rvol)/256;
440 
441 			// Enforce range in case of an "overshot". Shouldn't happen since we
442 			// scale down already, but safe is safe.
443 			if (lresult < -32768) lresult = -32768;
444 			else if (lresult > 32767) lresult = 32767;
445 
446 			if (rresult < -32768) rresult = -32768;
447 			else if (rresult > 32767) rresult = 32767;
448 
449 			*stream++ = lresult;
450 			*stream++ = rresult;
451 			bytes -= 4;
452 			fp_pos += fp_speed;
453 
454 		} while (fp_pos < 0x10000 && bytes!=0);
455 
456 	} while (bytes!=0 && src != src_end);
457 
458 	position = frame0_size - (src_end - src);
459 }
460 
461 
462 //
463 // 16 Bit
464 //
465 
466 // Resample a frame of mono 16bit unsigned to Stereo 16bit
resampleFrameM16toS(sint16 * & stream,uint32 & bytes)467 void AudioChannel::resampleFrameM16toS(sint16 *&stream, uint32 &bytes)
468 {
469 	uint8 *src = frames[frame_evenodd];
470 	uint8 *src2 = frames[1-frame_evenodd];
471 
472 	uint8 *src_end = src + frame0_size;
473 	uint8 *src2_end = src2 + frame1_size;
474 
475 	src += position;
476 
477 	int	lvol = this->lvol;
478 	int rvol = this->rvol;
479 
480 	calculate2DVolume(lvol,rvol);
481 
482 	do {
483 		// Add a new src sample (if required)
484 		if (fp_pos >= 0x10000)
485 		{
486 			if (src+4 < src_end) {
487 				int c = ReadSample(src+4);
488 				interp_l.feedData(c);
489 			} else if (src2 < src2_end) {
490 				int c = ReadSample(src2);
491 				interp_l.feedData(c);
492 				src2+=2;
493 			} else {
494 				interp_l.feedData();
495 			}
496 			src+=2;
497 			fp_pos -= 0x10000;
498 		}
499 
500 		if (fp_pos < 0x10000) do {
501 			// Do the interpolation
502 			int result = interp_l.interpolate(fp_pos);
503 
504 			int lresult = *(stream+0) + (result*lvol)/256;
505 			int rresult = *(stream+1) + (result*rvol)/256;
506 
507 			// Enforce range in case of an "overshot". Shouldn't happen since we
508 			// scale down already, but safe is safe.
509 			if (lresult < -32768) lresult = -32768;
510 			else if (lresult > 32767) lresult = 32767;
511 
512 			if (rresult < -32768) rresult = -32768;
513 			else if (rresult > 32767) rresult = 32767;
514 
515 			*stream++ = lresult;
516 			*stream++ = rresult;
517 			bytes -= 4;
518 			fp_pos += fp_speed;
519 
520 		} while (fp_pos < 0x10000 && bytes!=0);
521 
522 	} while (bytes!=0 && src != src_end);
523 
524 	position = frame0_size - (src_end - src);
525 }
526 
527 // Resample a frame of mono 16bit unsigned to Mono 16bit
resampleFrameM16toM(sint16 * & stream,uint32 & bytes)528 void AudioChannel::resampleFrameM16toM(sint16 *&stream, uint32 &bytes)
529 {
530 	uint8 *src = frames[frame_evenodd];
531 	uint8 *src2 = frames[1-frame_evenodd];
532 
533 	uint8 *src_end = src + frame0_size;
534 	uint8 *src2_end = src2 + frame1_size;
535 
536 	src += position;
537 
538 	int	lvol = this->lvol;
539 	int rvol = this->rvol;
540 
541 	calculate2DVolume(lvol,rvol);
542 
543 	int volume = (rvol + lvol)/2;
544 
545 	do {
546 		// Add a new src sample (if required)
547 		if (fp_pos >= 0x10000)
548 		{
549 			if (src+4 < src_end) {
550 				int c = ReadSample(src+4);
551 				interp_l.feedData(c);
552 			} else if (src2 < src2_end) {
553 				int c = ReadSample(src2);
554 				interp_l.feedData(c);
555 				src2+=2;
556 			} else {
557 				interp_l.feedData();
558 			}
559 			src+=2;
560 			fp_pos -= 0x10000;
561 		}
562 
563 		if (fp_pos < 0x10000) do {
564 			// Do the interpolation
565 			int result = (interp_l.interpolate(fp_pos)*volume)/256;
566 
567 			result += *stream;
568 
569 			// Enforce range in case of an "overshot". Shouldn't happen since we
570 			// scale down already, but safe is safe.
571 			if (result < -32768) result = -32768;
572 			else if (result > 32767) result = 32767;
573 
574 			*stream++ = result;
575 			bytes -= 2;
576 			fp_pos += fp_speed;
577 
578 		} while (fp_pos < 0x10000 && bytes!=0);
579 
580 	} while (bytes!=0 && src != src_end);
581 
582 	position = frame0_size - (src_end - src);
583 }
584 
585 // Resample a frame of stereo 16bit unsigned to Mono 16bit
resampleFrameS16toM(sint16 * & stream,uint32 & bytes)586 void AudioChannel::resampleFrameS16toM(sint16 *&stream, uint32 &bytes)
587 {
588 	uint8 *src = frames[frame_evenodd];
589 	uint8 *src2 = frames[1-frame_evenodd];
590 
591 	uint8 *src_end = src + frame0_size;
592 	uint8 *src2_end = src2 + frame1_size;
593 
594 	src += position;
595 
596 	int	lvol = this->lvol;
597 	int rvol = this->rvol;
598 
599 	calculate2DVolume(lvol,rvol);
600 
601 	do {
602 		// Add a new src sample (if required)
603 		if (fp_pos >= 0x10000)
604 		{
605 			if (src+8 < src_end) {
606 				int c  = ReadSample(src+8);
607 				int c2 = ReadSample(src+10);
608 				interp_l.feedData(c);
609 				interp_r.feedData(c2);
610 			} else if (src2 < src2_end) {
611 				int c  = ReadSample(src2);
612 				int c2 = ReadSample(src2+2);
613 				interp_l.feedData(c);
614 				interp_r.feedData(c2);
615 				src2+=4;
616 			} else {
617 				interp_l.feedData();
618 				interp_r.feedData();
619 			}
620 			src+=4;
621 			fp_pos -= 0x10000;
622 		}
623 
624 		if (fp_pos < 0x10000) do {
625 			// Do the interpolation
626 			int result = ((interp_l.interpolate(fp_pos)*lvol+interp_r.interpolate(fp_pos)*rvol))/512;
627 
628 			result += *stream;
629 
630 			// Enforce range in case of an "overshot". Shouldn't happen since we
631 			// scale down already, but safe is safe.
632 			if (result < -32768) result = -32768;
633 			else if (result > 32767) result = 32767;
634 
635 			*stream++ = result;
636 			bytes -= 2;
637 			fp_pos += fp_speed;
638 
639 		} while (fp_pos < 0x10000 && bytes!=0);
640 
641 	} while (bytes!=0 && src != src_end);
642 
643 	position = frame0_size - (src_end - src);
644 }
645 
646 // Resample a frame of stereo 16bit unsigned to Stereo 16bit
resampleFrameS16toS(sint16 * & stream,uint32 & bytes)647 void AudioChannel::resampleFrameS16toS(sint16 *&stream, uint32 &bytes)
648 {
649 	uint8 *src = frames[frame_evenodd];
650 	uint8 *src2 = frames[1-frame_evenodd];
651 
652 	uint8 *src_end = src + frame0_size;
653 	uint8 *src2_end = src2 + frame1_size;
654 
655 	src += position;
656 
657 	int	lvol = this->lvol;
658 	int rvol = this->rvol;
659 
660 	calculate2DVolume(lvol,rvol);
661 
662 	do {
663 		// Add a new src sample (if required)
664 		if (fp_pos >= 0x10000)
665 		{
666 			if (src+8 < src_end) {
667 				int c  = ReadSample(src+8);
668 				int c2 = ReadSample(src+10);
669 				interp_l.feedData(c);
670 				interp_r.feedData(c2);
671 			} else if (src2 < src2_end) {
672 				int c  = ReadSample(src2);
673 				int c2 = ReadSample(src2+2);
674 				interp_l.feedData(c);
675 				interp_r.feedData(c2);
676 				src2+=4;
677 			} else {
678 				interp_l.feedData();
679 				interp_r.feedData();
680 			}
681 			src+=4;
682 			fp_pos -= 0x10000;
683 		}
684 
685 		if (fp_pos < 0x10000) do {
686 			// Do the interpolation
687 			int lresult = *(stream+0) + (interp_l.interpolate(fp_pos)*lvol)/256;
688 			int rresult = *(stream+1) + (interp_r.interpolate(fp_pos)*rvol)/256;
689 
690 			// Enforce range in case of an "overshot". Shouldn't happen since we
691 			// scale down already, but safe is safe.
692 			if (lresult < -32768) lresult = -32768;
693 			else if (lresult > 32767) lresult = 32767;
694 
695 			if (rresult < -32768) rresult = -32768;
696 			else if (rresult > 32767) rresult = 32767;
697 
698 			*stream++ = lresult;
699 			*stream++ = rresult;
700 			bytes -= 4;
701 			fp_pos += fp_speed;
702 
703 		} while (fp_pos < 0x10000 && bytes!=0);
704 
705 	} while (bytes!=0 && src != src_end);
706 
707 	position = frame0_size - (src_end - src);
708 }
709 
calculate2DVolume(int & lvol,int & rvol)710 void AudioChannel::calculate2DVolume(int &lvol, int &rvol)
711 {
712 	if (distance > 255) {
713 		lvol = 0;
714 		rvol = 0;
715 		return;
716 	}
717 
718 	int lbal = 256;
719 	int rbal = 256;
720 
721 	if (balance < 0) {
722 		if (balance < -256) rbal = 0;
723 		else rbal = balance + 256;
724 	}
725 	else if (balance > 0) {
726 		if (balance > 256) lbal = 0;
727 		else lbal = 256 -balance;
728 	}
729 
730 	lvol = lvol*(256-distance)*lbal/65536;
731 	rvol = rvol*(256-distance)*rbal/65536;
732 }
733 
734 }
735 
736