2 AHI - Hardware independent audio subsystem
3 Copyright (C) 1996-2005 Martin Blom <martin@blom.org>
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
10 This library 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 GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330, Cambridge,
23 #include "addroutines.h"
25 /******************************************************************************
26 ** Add-Routines ***************************************************************
27 ******************************************************************************/
33 ** LONG *StartPointLeft
34 ** LONG *StartPointRight
47 The fraction offset is divided by two in order to make sure that the
48 calculation of linearsample fits a LONG (0 =< offsetf <= 32767).
50 The routines could be faster, of course. One idea is to split the for loop
51 into two loops in order to eliminate the FirstOffsetI test in the second loop.
55 /*****************************************************************************/
57 /* Forward mixing code */
59 #define offseti ( (long) ( offset >> 32 ) )
61 #define offsetf ( (long) ( (unsigned long) ( offset & 0xffffffffULL ) >> 17) )
64 AddByteMono( ADDARGS
)
68 Fixed64 offset
= *Offset
;
70 LONG startpoint
, endpoint
= 0; // Make compiler happy
73 lastpoint
= 0; // 0 doesn't affect the StopAtZero code
75 for( i
= 0; i
< Samples
; i
++)
77 if( offseti
== FirstOffsetI
) {
78 startpoint
= *StartPointLeft
;
82 startpoint
= src
[ offseti
- 1 ] << 8;
85 endpoint
= src
[ offseti
] << 8;
87 startpoint
+= (((endpoint
- startpoint
) * offsetf
) >> 15);
90 ( ( lastpoint
< 0 && startpoint
>= 0 ) ||
91 ( lastpoint
> 0 && startpoint
<= 0 ) ) )
96 lastpoint
= startpoint
;
98 *dst
++ += ScaleLeft
* startpoint
;
103 *StartPointLeft
= endpoint
;
113 AddByteStereo( ADDARGS
)
117 Fixed64 offset
= *Offset
;
119 LONG startpoint
, endpoint
= 0; // Make compiler happy
122 lastpoint
= 0; // 0 doesn't affect the StopAtZero code
124 for( i
= 0; i
< Samples
; i
++)
126 if( offseti
== FirstOffsetI
) {
127 startpoint
= *StartPointLeft
;
131 startpoint
= src
[ offseti
- 1 ] << 8;
134 endpoint
= src
[ offseti
] << 8;
136 startpoint
+= (((endpoint
- startpoint
) * offsetf
) >> 15);
139 ( ( lastpoint
< 0 && startpoint
>= 0 ) ||
140 ( lastpoint
> 0 && startpoint
<= 0 ) ) )
145 lastpoint
= startpoint
;
147 *dst
++ += ScaleLeft
* startpoint
;
148 *dst
++ += ScaleRight
* startpoint
;
153 *StartPointLeft
= endpoint
;
163 AddBytesMono( ADDARGS
)
167 Fixed64 offset
= *Offset
;
169 LONG startpointL
, startpointR
, endpointL
= 0, endpointR
= 0; // Make compiler happy
170 LONG lastpointL
, lastpointR
;
172 lastpointL
= lastpointR
= 0; // 0 doesn't affect the StopAtZero code
174 for( i
= 0; i
< Samples
; i
++)
176 if( offseti
== FirstOffsetI
) {
177 startpointL
= *StartPointLeft
;
178 startpointR
= *StartPointRight
;
182 startpointL
= src
[ offseti
* 2 + 0 - 2 ] << 8;
183 startpointR
= src
[ offseti
* 2 + 1 - 2 ] << 8;
186 endpointL
= src
[ offseti
* 2 + 0 ] << 8;
187 endpointR
= src
[ offseti
* 2 + 1 ] << 8;
189 startpointL
+= (((endpointL
- startpointL
) * offsetf
) >> 15);
190 startpointR
+= (((endpointR
- startpointR
) * offsetf
) >> 15);
193 ( ( lastpointL
< 0 && startpointL
>= 0 ) ||
194 ( lastpointR
< 0 && startpointR
>= 0 ) ||
195 ( lastpointL
> 0 && startpointL
<= 0 ) ||
196 ( lastpointR
> 0 && startpointR
<= 0 ) ) )
201 lastpointL
= startpointL
;
202 lastpointR
= startpointR
;
204 *dst
++ += ScaleLeft
* startpointL
+ ScaleRight
* startpointR
;
209 *StartPointLeft
= endpointL
;
210 *StartPointRight
= endpointR
;
220 AddBytesStereo( ADDARGS
)
224 Fixed64 offset
= *Offset
;
226 LONG startpointL
, startpointR
, endpointL
= 0, endpointR
= 0; // Make compiler happy
227 LONG lastpointL
, lastpointR
;
229 lastpointL
= lastpointR
= 0; // 0 doesn't affect the StopAtZero code
231 for( i
= 0; i
< Samples
; i
++)
233 if( offseti
== FirstOffsetI
) {
234 startpointL
= *StartPointLeft
;
235 startpointR
= *StartPointRight
;
239 startpointL
= src
[ offseti
* 2 + 0 - 2 ] << 8;
240 startpointR
= src
[ offseti
* 2 + 1 - 2 ] << 8;
243 endpointL
= src
[ offseti
* 2 + 0 ] << 8;
244 endpointR
= src
[ offseti
* 2 + 1 ] << 8;
246 startpointL
+= (((endpointL
- startpointL
) * offsetf
) >> 15);
247 startpointR
+= (((endpointR
- startpointR
) * offsetf
) >> 15);
250 ( ( lastpointL
< 0 && startpointL
>= 0 ) ||
251 ( lastpointR
< 0 && startpointR
>= 0 ) ||
252 ( lastpointL
> 0 && startpointL
<= 0 ) ||
253 ( lastpointR
> 0 && startpointR
<= 0 ) ) )
258 lastpointL
= startpointL
;
259 lastpointR
= startpointR
;
261 *dst
++ += ScaleLeft
* startpointL
;
262 *dst
++ += ScaleRight
* startpointR
;
267 *StartPointLeft
= endpointL
;
268 *StartPointRight
= endpointR
;
278 AddWordMono( ADDARGS
)
282 Fixed64 offset
= *Offset
;
284 LONG startpoint
, endpoint
= 0; // Make compiler happy
287 lastpoint
= 0; // 0 doesn't affect the StopAtZero code
289 for( i
= 0; i
< Samples
; i
++)
291 if( offseti
== FirstOffsetI
) {
292 startpoint
= *StartPointLeft
;
296 startpoint
= src
[ offseti
- 1 ];
299 endpoint
= src
[ offseti
];
301 startpoint
+= (((endpoint
- startpoint
) * offsetf
) >> 15);
304 ( ( lastpoint
< 0 && startpoint
>= 0 ) ||
305 ( lastpoint
> 0 && startpoint
<= 0 ) ) )
310 lastpoint
= startpoint
;
312 *dst
++ += ScaleLeft
* startpoint
;
317 *StartPointLeft
= endpoint
;
327 AddWordStereo( ADDARGS
)
331 Fixed64 offset
= *Offset
;
333 LONG startpoint
, endpoint
= 0; // Make compiler happy
336 lastpoint
= 0; // 0 doesn't affect the StopAtZero code
338 for( i
= 0; i
< Samples
; i
++)
340 if( offseti
== FirstOffsetI
) {
341 startpoint
= *StartPointLeft
;
345 startpoint
= src
[ offseti
- 1 ];
348 endpoint
= src
[ offseti
];
350 startpoint
+= (((endpoint
- startpoint
) * offsetf
) >> 15);
353 ( ( lastpoint
< 0 && startpoint
>= 0 ) ||
354 ( lastpoint
> 0 && startpoint
<= 0 ) ) )
359 lastpoint
= startpoint
;
361 *dst
++ += ScaleLeft
* startpoint
;
362 *dst
++ += ScaleRight
* startpoint
;
367 *StartPointLeft
= endpoint
;
376 AddWordsMono( ADDARGS
)
380 Fixed64 offset
= *Offset
;
382 LONG startpointL
, startpointR
, endpointL
= 0, endpointR
= 0; // Make compiler happy
383 LONG lastpointL
, lastpointR
;
385 lastpointL
= lastpointR
= 0; // 0 doesn't affect the StopAtZero code
387 for( i
= 0; i
< Samples
; i
++)
389 if( offseti
== FirstOffsetI
) {
390 startpointL
= *StartPointLeft
;
391 startpointR
= *StartPointRight
;
395 startpointL
= src
[ offseti
* 2 + 0 - 2 ];
396 startpointR
= src
[ offseti
* 2 + 1 - 2 ];
399 endpointL
= src
[ offseti
* 2 + 0 ];
400 endpointR
= src
[ offseti
* 2 + 1 ];
402 startpointL
+= (((endpointL
- startpointL
) * offsetf
) >> 15);
403 startpointR
+= (((endpointR
- startpointR
) * offsetf
) >> 15);
406 ( ( lastpointL
< 0 && startpointL
>= 0 ) ||
407 ( lastpointR
< 0 && startpointR
>= 0 ) ||
408 ( lastpointL
> 0 && startpointL
<= 0 ) ||
409 ( lastpointR
> 0 && startpointR
<= 0 ) ) )
414 lastpointL
= startpointL
;
415 lastpointR
= startpointR
;
417 *dst
++ += ScaleLeft
* startpointL
+ ScaleRight
* startpointR
;
422 *StartPointLeft
= endpointL
;
423 *StartPointRight
= endpointR
;
433 AddWordsStereo( ADDARGS
)
437 Fixed64 offset
= *Offset
;
439 LONG startpointL
, startpointR
, endpointL
= 0, endpointR
= 0; // Make compiler happy
440 LONG lastpointL
, lastpointR
;
442 lastpointL
= lastpointR
= 0; // 0 doesn't affect the StopAtZero code
444 for( i
= 0; i
< Samples
; i
++)
446 if( offseti
== FirstOffsetI
) {
447 startpointL
= *StartPointLeft
;
448 startpointR
= *StartPointRight
;
452 startpointL
= src
[ offseti
* 2 + 0 - 2 ];
453 startpointR
= src
[ offseti
* 2 + 1 - 2 ];
456 endpointL
= src
[ offseti
* 2 + 0 ];
457 endpointR
= src
[ offseti
* 2 + 1 ];
459 startpointL
+= (((endpointL
- startpointL
) * offsetf
) >> 15);
460 startpointR
+= (((endpointR
- startpointR
) * offsetf
) >> 15);
463 ( ( lastpointL
< 0 && startpointL
>= 0 ) ||
464 ( lastpointR
< 0 && startpointR
>= 0 ) ||
465 ( lastpointL
> 0 && startpointL
<= 0 ) ||
466 ( lastpointR
> 0 && startpointR
<= 0 ) ) )
471 lastpointL
= startpointL
;
472 lastpointR
= startpointR
;
474 *dst
++ += ScaleLeft
* startpointL
;
475 *dst
++ += ScaleRight
* startpointR
;
480 *StartPointLeft
= endpointL
;
481 *StartPointRight
= endpointR
;
491 /*****************************************************************************/
493 /* Backward mixing code */
495 #define offsetf ( (long) ( 32768 - ( (unsigned long) ( offset & 0xffffffffULL ) >> 17 ) ) )
498 AddByteMonoB( ADDARGS
)
502 Fixed64 offset
= *Offset
;
504 LONG startpoint
, endpoint
= 0; // Make compiler happy
507 lastpoint
= 0; // 0 doesn't affect the StopAtZero code
509 for( i
= 0; i
< Samples
; i
++)
511 if( offseti
== FirstOffsetI
) {
512 startpoint
= *StartPointLeft
;
516 startpoint
= src
[ offseti
+ 1 ] << 8;
519 endpoint
= src
[ offseti
] << 8;
521 startpoint
+= (((endpoint
- startpoint
) * offsetf
) >> 15);
524 ( ( lastpoint
< 0 && startpoint
>= 0 ) ||
525 ( lastpoint
> 0 && startpoint
<= 0 ) ) )
530 lastpoint
= startpoint
;
532 *dst
++ += ScaleLeft
* startpoint
;
537 *StartPointLeft
= endpoint
;
547 AddByteStereoB( ADDARGS
)
551 Fixed64 offset
= *Offset
;
553 LONG startpoint
, endpoint
= 0; // Make compiler happy
556 lastpoint
= 0; // 0 doesn't affect the StopAtZero code
558 for( i
= 0; i
< Samples
; i
++)
560 if( offseti
== FirstOffsetI
) {
561 startpoint
= *StartPointLeft
;
565 startpoint
= src
[ offseti
+ 1 ] << 8;
568 endpoint
= src
[ offseti
] << 8;
570 startpoint
+= (((endpoint
- startpoint
) * offsetf
) >> 15);
573 ( ( lastpoint
< 0 && startpoint
>= 0 ) ||
574 ( lastpoint
> 0 && startpoint
<= 0 ) ) )
579 lastpoint
= startpoint
;
581 *dst
++ += ScaleLeft
* startpoint
;
582 *dst
++ += ScaleRight
* startpoint
;
587 *StartPointLeft
= endpoint
;
597 AddBytesMonoB( ADDARGS
)
601 Fixed64 offset
= *Offset
;
603 LONG startpointL
, startpointR
, endpointL
= 0, endpointR
= 0; // Make compiler happy
604 LONG lastpointL
, lastpointR
;
606 lastpointL
= lastpointR
= 0; // 0 doesn't affect the StopAtZero code
608 for( i
= 0; i
< Samples
; i
++)
610 if( offseti
== FirstOffsetI
) {
611 startpointL
= *StartPointLeft
;
612 startpointR
= *StartPointRight
;
616 startpointL
= src
[ offseti
* 2 + 0 + 2 ] << 8;
617 startpointR
= src
[ offseti
* 2 + 1 + 2 ] << 8;
620 endpointL
= src
[ offseti
* 2 + 0 ] << 8;
621 endpointR
= src
[ offseti
* 2 + 1 ] << 8;
623 startpointL
+= (((endpointL
- startpointL
) * offsetf
) >> 15);
624 startpointR
+= (((endpointR
- startpointR
) * offsetf
) >> 15);
627 ( ( lastpointL
< 0 && startpointL
>= 0 ) ||
628 ( lastpointR
< 0 && startpointR
>= 0 ) ||
629 ( lastpointL
> 0 && startpointL
<= 0 ) ||
630 ( lastpointR
> 0 && startpointR
<= 0 ) ) )
635 lastpointL
= startpointL
;
636 lastpointR
= startpointR
;
638 *dst
++ += ScaleLeft
* startpointL
+ ScaleRight
* startpointR
;
643 *StartPointLeft
= endpointL
;
644 *StartPointRight
= endpointR
;
654 AddBytesStereoB( ADDARGS
)
658 Fixed64 offset
= *Offset
;
660 LONG startpointL
, startpointR
, endpointL
= 0, endpointR
= 0; // Make compiler happy
661 LONG lastpointL
, lastpointR
;
663 lastpointL
= lastpointR
= 0; // 0 doesn't affect the StopAtZero code
665 for( i
= 0; i
< Samples
; i
++)
667 if( offseti
== FirstOffsetI
) {
668 startpointL
= *StartPointLeft
;
669 startpointR
= *StartPointRight
;
673 startpointL
= src
[ offseti
* 2 + 0 + 2 ] << 8;
674 startpointR
= src
[ offseti
* 2 + 1 + 2 ] << 8;
677 endpointL
= src
[ offseti
* 2 + 0 ] << 8;
678 endpointR
= src
[ offseti
* 2 + 1 ] << 8;
680 startpointL
+= (((endpointL
- startpointL
) * offsetf
) >> 15);
681 startpointR
+= (((endpointR
- startpointR
) * offsetf
) >> 15);
684 ( ( lastpointL
< 0 && startpointL
>= 0 ) ||
685 ( lastpointR
< 0 && startpointR
>= 0 ) ||
686 ( lastpointL
> 0 && startpointL
<= 0 ) ||
687 ( lastpointR
> 0 && startpointR
<= 0 ) ) )
692 lastpointL
= startpointL
;
693 lastpointR
= startpointR
;
695 *dst
++ += ScaleLeft
* startpointL
;
696 *dst
++ += ScaleRight
* startpointR
;
701 *StartPointLeft
= endpointL
;
702 *StartPointRight
= endpointR
;
712 AddWordMonoB( ADDARGS
)
716 Fixed64 offset
= *Offset
;
718 LONG startpoint
, endpoint
= 0; // Make compiler happy
721 lastpoint
= 0; // 0 doesn't affect the StopAtZero code
723 for( i
= 0; i
< Samples
; i
++)
725 if( offseti
== FirstOffsetI
) {
726 startpoint
= *StartPointLeft
;
730 startpoint
= src
[ offseti
+ 1 ];
733 endpoint
= src
[ offseti
];
735 startpoint
+= (((endpoint
- startpoint
) * offsetf
) >> 15);
738 ( ( lastpoint
< 0 && startpoint
>= 0 ) ||
739 ( lastpoint
> 0 && startpoint
<= 0 ) ) )
744 lastpoint
= startpoint
;
746 *dst
++ += ScaleLeft
* startpoint
;
751 *StartPointLeft
= endpoint
;
761 AddWordStereoB( ADDARGS
)
765 Fixed64 offset
= *Offset
;
767 LONG startpoint
, endpoint
= 0; // Make compiler happy
770 lastpoint
= 0; // 0 doesn't affect the StopAtZero code
772 for( i
= 0; i
< Samples
; i
++)
774 if( offseti
== FirstOffsetI
) {
775 startpoint
= *StartPointLeft
;
779 startpoint
= src
[ offseti
+ 1 ];
782 endpoint
= src
[ offseti
];
784 startpoint
+= (((endpoint
- startpoint
) * offsetf
) >> 15);
787 ( ( lastpoint
< 0 && startpoint
>= 0 ) ||
788 ( lastpoint
> 0 && startpoint
<= 0 ) ) )
793 lastpoint
= startpoint
;
795 *dst
++ += ScaleLeft
* startpoint
;
796 *dst
++ += ScaleRight
* startpoint
;
801 *StartPointLeft
= endpoint
;
811 AddWordsMonoB( ADDARGS
)
815 Fixed64 offset
= *Offset
;
817 LONG startpointL
, startpointR
, endpointL
= 0, endpointR
= 0; // Make compiler happy
818 LONG lastpointL
, lastpointR
;
820 lastpointL
= lastpointR
= 0; // 0 doesn't affect the StopAtZero code
822 for( i
= 0; i
< Samples
; i
++)
824 if( offseti
== FirstOffsetI
) {
825 startpointL
= *StartPointLeft
;
826 startpointR
= *StartPointRight
;
830 startpointL
= src
[ offseti
* 2 + 0 + 2 ];
831 startpointR
= src
[ offseti
* 2 + 1 + 2 ];
834 endpointL
= src
[ offseti
* 2 + 0 ];
835 endpointR
= src
[ offseti
* 2 + 1 ];
837 startpointL
+= (((endpointL
- startpointL
) * offsetf
) >> 15);
838 startpointR
+= (((endpointR
- startpointR
) * offsetf
) >> 15);
841 ( ( lastpointL
< 0 && startpointL
>= 0 ) ||
842 ( lastpointR
< 0 && startpointR
>= 0 ) ||
843 ( lastpointL
> 0 && startpointL
<= 0 ) ||
844 ( lastpointR
> 0 && startpointR
<= 0 ) ) )
849 lastpointL
= startpointL
;
850 lastpointR
= startpointR
;
852 *dst
++ += ScaleLeft
* startpointL
+ ScaleRight
* startpointR
;
857 *StartPointLeft
= endpointL
;
858 *StartPointRight
= endpointR
;
868 AddWordsStereoB( ADDARGS
)
872 Fixed64 offset
= *Offset
;
874 LONG startpointL
, startpointR
, endpointL
= 0, endpointR
= 0; // Make compiler happy
875 LONG lastpointL
, lastpointR
;
877 lastpointL
= lastpointR
= 0; // 0 doesn't affect the StopAtZero code
879 for( i
= 0; i
< Samples
; i
++)
881 if( offseti
== FirstOffsetI
) {
882 startpointL
= *StartPointLeft
;
883 startpointR
= *StartPointRight
;
887 startpointL
= src
[ offseti
* 2 + 0 + 2 ];
888 startpointR
= src
[ offseti
* 2 + 1 + 2 ];
891 endpointL
= src
[ offseti
* 2 + 0 ];
892 endpointR
= src
[ offseti
* 2 + 1 ];
894 startpointL
+= (((endpointL
- startpointL
) * offsetf
) >> 15);
895 startpointR
+= (((endpointR
- startpointR
) * offsetf
) >> 15);
898 ( ( lastpointL
< 0 && startpointL
>= 0 ) ||
899 ( lastpointR
< 0 && startpointR
>= 0 ) ||
900 ( lastpointL
> 0 && startpointL
<= 0 ) ||
901 ( lastpointR
> 0 && startpointR
<= 0 ) ) )
906 lastpointL
= startpointL
;
907 lastpointR
= startpointR
;
909 *dst
++ += ScaleLeft
* startpointL
;
910 *dst
++ += ScaleRight
* startpointR
;
915 *StartPointLeft
= endpointL
;
916 *StartPointRight
= endpointR
;
928 /*****************************************************************************/