2 AHI - Hardware independent audio subsystem
3 Copyright (C) 2017 The AROS Dev Team
4 Copyright (C) 1996-2005 Martin Blom <martin@blom.org>
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with this library; if not, write to the
18 Free Software Foundation, Inc., 59 Temple Place - Suite 330, Cambridge,
28 #include <dos/dostags.h>
29 #include <exec/memory.h>
31 #include <proto/dos.h>
32 #include <proto/exec.h>
33 #include <proto/utility.h>
35 #define __NOGLOBALIFACE__
36 #include <proto/ahi.h>
38 #undef __NOGLOBALIFACE__
42 #include "addroutines.h"
50 #if defined( ENABLE_WARPUP )
54 #define min(a,b) (((a)<(b))?(a):(b))
55 #define max(a,b) (((a)>(b))?(a):(b))
57 /******************************************************************************
58 ** Prototypes *****************************************************************
59 ******************************************************************************/
62 CallSoundHook( struct AHIPrivAudioCtrl
*audioctrl
,
68 CallHookPkt( audioctrl
->ac
.ahiac_SoundFunc
,
73 #if defined( ENABLE_WARPUP )
75 WarpUpCallSoundHook( audioctrl
, arg
);
83 MixerFunc( struct Hook
* hook
,
84 struct AHIPrivAudioCtrl
* audioctrl
,
90 Mix( hook
, audioctrl
, dst
);
91 DoMasterVolume( dst
, audioctrl
);
92 DoOutputBuffer( dst
, audioctrl
);
93 DoChannelInfo( audioctrl
);
96 #if defined( ENABLE_WARPUP )
98 WarpUpCallMixer( audioctrl
, dst
);
99 DoOutputBuffer( dst
, audioctrl
);
100 DoChannelInfo( audioctrl
);
107 /******************************************************************************
108 ** InitMixroutine *************************************************************
109 ******************************************************************************/
111 // This function is used to initialize the mixer routine (called from
112 // AHI_AllocAudio()).
115 InitMixroutine( struct AHIPrivAudioCtrl
*audioctrl
)
119 // Allocate and initialize the AHIChannelData structures
120 // This structure could be accessed from from interrupts!
122 ULONG data_flags
= MEMF_ANY
;
127 data_flags
= MEMF_PUBLIC
| MEMF_CLEAR
;
130 #if defined( ENABLE_WARPUP )
132 // Non-cached from both the PPC and m68k side
133 data_flags
= MEMF_PUBLIC
| MEMF_CLEAR
| MEMF_CHIP
;
138 audioctrl
->ahiac_ChannelDatas
= AHIAllocVec(
139 audioctrl
->ac
.ahiac_Channels
* sizeof( struct AHIChannelData
),
142 // Allocate and initialize the AHISoundData structures
143 // This structure could be accessed from from interrupts!
145 audioctrl
->ahiac_SoundDatas
= AHIAllocVec(
146 audioctrl
->ac
.ahiac_Sounds
* sizeof( struct AHISoundData
),
149 // Now link the list and fill in the channel number for each structure.
151 if( audioctrl
->ahiac_ChannelDatas
!= NULL
152 && audioctrl
->ahiac_SoundDatas
!= NULL
)
154 struct AHIChannelData
*cd
;
155 struct AHISoundData
*sd
;
158 cd
= audioctrl
->ahiac_ChannelDatas
;
160 audioctrl
->ahiac_WetList
= cd
;
161 audioctrl
->ahiac_DryList
= NULL
;
163 for(i
= 0; i
< audioctrl
->ac
.ahiac_Channels
- 1; i
++)
166 cd
->cd_ChannelNo
= i
;
168 // Set link to next channel
169 cd
->cd_Succ
= cd
+ 1;
174 cd
->cd_ChannelNo
= i
;
176 // Clear the last link;
180 sd
= audioctrl
->ahiac_SoundDatas
;
182 for( i
= 0; i
< audioctrl
->ac
.ahiac_Sounds
; i
++)
184 sd
->sd_Type
= AHIST_NOTYPE
;
196 #if defined( ENABLE_WARPUP )
198 rc
= WarpUpInit( audioctrl
);
207 /******************************************************************************
208 ** CleanUpMixroutine **********************************************************
209 ******************************************************************************/
211 // This function is used to clean up after the mixer routine (called from
215 CleanUpMixroutine( struct AHIPrivAudioCtrl
*audioctrl
)
222 #if defined( ENABLE_WARPUP )
224 WarpUpCleanUp( audioctrl
);
229 AHIFreeVec( audioctrl
->ahiac_SoundDatas
);
230 audioctrl
->ahiac_SoundDatas
= NULL
;
232 AHIFreeVec( audioctrl
->ahiac_ChannelDatas
);
233 audioctrl
->ahiac_ChannelDatas
= NULL
;
237 /******************************************************************************
238 ** SelectAddRoutine ***********************************************************
239 ******************************************************************************/
241 // This routine gets called each time there is reason to believe that a new
242 // add-routine should be used (new sound selected, volume changed,
243 // mastervolume changed)
245 // Based on VolumeLeft, VolumeRight and SampleType, fill in ScaleLeft,
246 // ScaleRight and AddRoutine.
249 SelectAddRoutine ( Fixed VolumeLeft
,
252 struct AHIPrivAudioCtrl
*audioctrl
,
255 ADDFUNC
**AddRoutine
)
258 // This version only cares about the sample format and does not use any
259 // optimized add-routines.
263 VolumeLeft
= VolumeLeft
* (audioctrl
->ahiac_MasterVolume
>> 8) /
264 (audioctrl
->ahiac_Channels2
<< 8);
266 VolumeRight
= VolumeRight
* (audioctrl
->ahiac_MasterVolume
>> 8) /
267 (audioctrl
->ahiac_Channels2
<< 8);
269 // First, select HiFi or LoFi...
271 if( audioctrl
->ac
.ahiac_Flags
& AHIACF_HIFI
)
274 // Then, check the output format...
276 switch(audioctrl
->ac
.ahiac_BuffType
)
281 // ...and then the source format.
286 case AHIST_BW
|AHIST_M8S
:
287 *ScaleLeft
= VolumeLeft
+ VolumeRight
;
289 if(SampleType
& AHIST_BW
)
290 *AddRoutine
= AddByteMonoBPtr
;
292 *AddRoutine
= AddByteMonoPtr
;
296 case AHIST_BW
|AHIST_S8S
:
297 *ScaleLeft
= VolumeLeft
;
298 *ScaleRight
= VolumeRight
;
299 if(SampleType
& AHIST_BW
)
300 *AddRoutine
= AddBytesMonoBPtr
;
302 *AddRoutine
= AddBytesMonoPtr
;
306 case AHIST_BW
|AHIST_M16S
:
307 *ScaleLeft
= VolumeLeft
+ VolumeRight
;
309 if(SampleType
& AHIST_BW
)
310 *AddRoutine
= AddWordMonoBPtr
;
312 *AddRoutine
= AddWordMonoPtr
;
316 case AHIST_BW
|AHIST_S16S
:
317 *ScaleLeft
= VolumeLeft
;
318 *ScaleRight
= VolumeRight
;
319 if(SampleType
& AHIST_BW
)
320 *AddRoutine
= AddWordsMonoBPtr
;
322 *AddRoutine
= AddWordsMonoPtr
;
326 case AHIST_BW
|AHIST_M32S
:
327 *ScaleLeft
= VolumeLeft
+ VolumeRight
;
329 if(SampleType
& AHIST_BW
)
330 *AddRoutine
= AddLongMonoBPtr
;
332 *AddRoutine
= AddLongMonoPtr
;
336 case AHIST_BW
|AHIST_S32S
:
337 *ScaleLeft
= VolumeLeft
;
338 *ScaleRight
= VolumeRight
;
339 if(SampleType
& AHIST_BW
)
340 *AddRoutine
= AddLongsMonoBPtr
;
342 *AddRoutine
= AddLongsMonoPtr
;
346 case AHIST_BW
|AHIST_L7_1
:
347 *ScaleLeft
= VolumeLeft
;
348 *ScaleRight
= VolumeRight
;
349 if(SampleType
& AHIST_BW
)
350 *AddRoutine
= Add71MonoBPtr
;
352 *AddRoutine
= Add71MonoPtr
;
365 // ...and then the source format.
370 case AHIST_BW
|AHIST_M8S
:
371 *ScaleLeft
= VolumeLeft
;
372 *ScaleRight
= VolumeRight
;
373 if(SampleType
& AHIST_BW
)
374 *AddRoutine
= AddByteStereoBPtr
;
376 *AddRoutine
= AddByteStereoPtr
;
380 case AHIST_BW
|AHIST_S8S
:
381 *ScaleLeft
= VolumeLeft
;
382 *ScaleRight
= VolumeRight
;
383 if(SampleType
& AHIST_BW
)
384 *AddRoutine
= AddBytesStereoBPtr
;
386 *AddRoutine
= AddBytesStereoPtr
;
390 case AHIST_BW
|AHIST_M16S
:
391 *ScaleLeft
= VolumeLeft
;
392 *ScaleRight
= VolumeRight
;
393 if(SampleType
& AHIST_BW
)
394 *AddRoutine
= AddWordStereoBPtr
;
396 *AddRoutine
= AddWordStereoPtr
;
400 case AHIST_BW
|AHIST_S16S
:
401 *ScaleLeft
= VolumeLeft
;
402 *ScaleRight
= VolumeRight
;
403 if(SampleType
& AHIST_BW
)
404 *AddRoutine
= AddWordsStereoBPtr
;
406 *AddRoutine
= AddWordsStereoPtr
;
410 case AHIST_BW
|AHIST_M32S
:
411 *ScaleLeft
= VolumeLeft
;
412 *ScaleRight
= VolumeRight
;
413 if(SampleType
& AHIST_BW
)
414 *AddRoutine
= AddLongStereoBPtr
;
416 *AddRoutine
= AddLongStereoPtr
;
420 case AHIST_BW
|AHIST_S32S
:
421 *ScaleLeft
= VolumeLeft
;
422 *ScaleRight
= VolumeRight
;
423 if(SampleType
& AHIST_BW
)
424 *AddRoutine
= AddLongsStereoBPtr
;
426 *AddRoutine
= AddLongsStereoPtr
;
430 case AHIST_BW
|AHIST_L7_1
:
431 *ScaleLeft
= VolumeLeft
;
432 *ScaleRight
= VolumeRight
;
433 if(SampleType
& AHIST_BW
)
434 *AddRoutine
= Add71StereoBPtr
;
436 *AddRoutine
= Add71StereoPtr
;
449 // ...and then the source format.
454 case AHIST_BW
|AHIST_M8S
:
455 *ScaleLeft
= VolumeLeft
;
456 *ScaleRight
= VolumeRight
;
457 if(SampleType
& AHIST_BW
)
458 *AddRoutine
= AddByte71BPtr
;
460 *AddRoutine
= AddByte71Ptr
;
464 case AHIST_BW
|AHIST_S8S
:
465 *ScaleLeft
= VolumeLeft
;
466 *ScaleRight
= VolumeRight
;
467 if(SampleType
& AHIST_BW
)
468 *AddRoutine
= AddBytes71BPtr
;
470 *AddRoutine
= AddBytes71Ptr
;
474 case AHIST_BW
|AHIST_M16S
:
475 *ScaleLeft
= VolumeLeft
;
476 *ScaleRight
= VolumeRight
;
477 if(SampleType
& AHIST_BW
)
478 *AddRoutine
= AddWord71BPtr
;
480 *AddRoutine
= AddWord71Ptr
;
484 case AHIST_BW
|AHIST_S16S
:
485 *ScaleLeft
= VolumeLeft
;
486 *ScaleRight
= VolumeRight
;
487 if(SampleType
& AHIST_BW
)
488 *AddRoutine
= AddWords71BPtr
;
490 *AddRoutine
= AddWords71Ptr
;
494 case AHIST_BW
|AHIST_M32S
:
495 *ScaleLeft
= VolumeLeft
;
496 *ScaleRight
= VolumeRight
;
497 if(SampleType
& AHIST_BW
)
498 *AddRoutine
= AddLong71BPtr
;
500 *AddRoutine
= AddLong71Ptr
;
504 case AHIST_BW
|AHIST_S32S
:
505 *ScaleLeft
= VolumeLeft
;
506 *ScaleRight
= VolumeRight
;
507 if(SampleType
& AHIST_BW
)
508 *AddRoutine
= AddLongs71BPtr
;
510 *AddRoutine
= AddLongs71Ptr
;
514 case AHIST_BW
|AHIST_L7_1
:
515 *ScaleLeft
= VolumeLeft
;
516 *ScaleRight
= VolumeRight
;
517 if(SampleType
& AHIST_BW
)
518 *AddRoutine
= Add7171BPtr
;
520 *AddRoutine
= Add7171Ptr
;
541 // Then, check the output format...
543 switch(audioctrl
->ac
.ahiac_BuffType
)
548 // ...and then the source format.
553 case AHIST_BW
|AHIST_M8S
:
554 *ScaleLeft
= VolumeLeft
+ VolumeRight
;
556 if(SampleType
& AHIST_BW
)
557 *AddRoutine
= AddLofiByteMonoBPtr
;
559 *AddRoutine
= AddLofiByteMonoPtr
;
563 case AHIST_BW
|AHIST_S8S
:
564 *ScaleLeft
= VolumeLeft
;
565 *ScaleRight
= VolumeRight
;
566 if(SampleType
& AHIST_BW
)
567 *AddRoutine
= AddLofiBytesMonoBPtr
;
569 *AddRoutine
= AddLofiBytesMonoPtr
;
573 case AHIST_BW
|AHIST_M16S
:
574 *ScaleLeft
= VolumeLeft
+ VolumeRight
;
576 if(SampleType
& AHIST_BW
)
577 *AddRoutine
= AddLofiWordMonoBPtr
;
579 *AddRoutine
= AddLofiWordMonoPtr
;
583 case AHIST_BW
|AHIST_S16S
:
584 *ScaleLeft
= VolumeLeft
;
585 *ScaleRight
= VolumeRight
;
586 if(SampleType
& AHIST_BW
)
587 *AddRoutine
= AddLofiWordsMonoBPtr
;
589 *AddRoutine
= AddLofiWordsMonoPtr
;
593 case AHIST_BW
|AHIST_M32S
:
594 *ScaleLeft
= VolumeLeft
+ VolumeRight
;
596 if(SampleType
& AHIST_BW
)
597 *AddRoutine
= AddLofiLongMonoBPtr
;
599 *AddRoutine
= AddLofiLongMonoPtr
;
603 case AHIST_BW
|AHIST_S32S
:
604 *ScaleLeft
= VolumeLeft
;
605 *ScaleRight
= VolumeRight
;
606 if(SampleType
& AHIST_BW
)
607 *AddRoutine
= AddLofiLongsMonoBPtr
;
609 *AddRoutine
= AddLofiLongsMonoPtr
;
622 // ...and then the source format.
627 case AHIST_BW
|AHIST_M8S
:
628 *ScaleLeft
= VolumeLeft
;
629 *ScaleRight
= VolumeRight
;
630 if(SampleType
& AHIST_BW
)
631 *AddRoutine
= AddLofiByteStereoBPtr
;
633 *AddRoutine
= AddLofiByteStereoPtr
;
637 case AHIST_BW
|AHIST_S8S
:
638 *ScaleLeft
= VolumeLeft
;
639 *ScaleRight
= VolumeRight
;
640 if(SampleType
& AHIST_BW
)
641 *AddRoutine
= AddLofiBytesStereoBPtr
;
643 *AddRoutine
= AddLofiBytesStereoPtr
;
647 case AHIST_BW
|AHIST_M16S
:
648 *ScaleLeft
= VolumeLeft
;
649 *ScaleRight
= VolumeRight
;
650 if(SampleType
& AHIST_BW
)
651 *AddRoutine
= AddLofiWordStereoBPtr
;
653 *AddRoutine
= AddLofiWordStereoPtr
;
657 case AHIST_BW
|AHIST_S16S
:
658 *ScaleLeft
= VolumeLeft
;
659 *ScaleRight
= VolumeRight
;
660 if(SampleType
& AHIST_BW
)
661 *AddRoutine
= AddLofiWordsStereoBPtr
;
663 *AddRoutine
= AddLofiWordsStereoPtr
;
667 case AHIST_BW
|AHIST_M32S
:
668 *ScaleLeft
= VolumeLeft
;
669 *ScaleRight
= VolumeRight
;
670 if(SampleType
& AHIST_BW
)
671 *AddRoutine
= AddLofiLongStereoBPtr
;
673 *AddRoutine
= AddLofiLongStereoPtr
;
677 case AHIST_BW
|AHIST_S32S
:
678 *ScaleLeft
= VolumeLeft
;
679 *ScaleRight
= VolumeRight
;
680 if(SampleType
& AHIST_BW
)
681 *AddRoutine
= AddLofiLongsStereoBPtr
;
683 *AddRoutine
= AddLofiLongsStereoPtr
;
704 /******************************************************************************
705 ** Mix ************************************************************************
706 ******************************************************************************/
708 // This is the function that the driver calls each time it want more data
712 Mix( struct Hook
* unused_Hook
,
713 struct AHIPrivAudioCtrl
* audioctrl
,
716 struct AHIChannelData
*cd
;
720 /* Clear the buffer */
722 memset( dst
, 0, audioctrl
->ahiac_BuffSizeNow
);
723 /* Mix the samples */
725 audioctrl
->ahiac_WetOrDry
= AHIEDM_WET
;
727 cd
= audioctrl
->ahiac_WetList
;
731 while(cd
!= NULL
) // .nextchannel
733 samplesleft
= audioctrl
->ac
.ahiac_BuffSamples
;
736 while(TRUE
) // .contchannel
741 /* Call Sound Hook */
746 if(audioctrl
->ac
.ahiac_SoundFunc
!= NULL
)
748 CallSoundHook( audioctrl
, &cd
->cd_ChannelNo
);
754 if( cd
->cd_AntiClickCount
> 0 && cd
->cd_FreqOK
&& cd
->cd_SoundOK
)
756 // Sound is ok and we're looking for a zero-crossing.
760 samples
= min( samplesleft
, cd
->cd_Samples
);
761 try_samples
= min( samples
, cd
->cd_AntiClickCount
);
763 if( try_samples
> 0 )
765 cd
->cd_TempStartPointL
= cd
->cd_StartPointL
;
766 cd
->cd_TempStartPointR
= cd
->cd_StartPointR
;
767 cd
->cd_TempStartPointRL
= cd
->cd_StartPointRL
;
768 cd
->cd_TempStartPointRR
= cd
->cd_StartPointRR
;
769 cd
->cd_TempStartPointSL
= cd
->cd_StartPointSL
;
770 cd
->cd_TempStartPointSR
= cd
->cd_StartPointSR
;
771 cd
->cd_TempStartPointC
= cd
->cd_StartPointC
;
772 cd
->cd_TempStartPointLFE
= cd
->cd_StartPointLFE
;
774 processed
= ((ADDFUNC
*) cd
->cd_AddRoutine
)( try_samples
,
777 &cd
->cd_TempStartPointL
,
778 &cd
->cd_TempStartPointR
,
786 cd
->cd_Samples
-= processed
;
787 samplesleft
-= processed
;
794 if( processed
!= try_samples
|| // Found zero-crossing
795 try_samples
<= cd
->cd_AntiClickCount
) // End-of-sound or
798 // We either found a zero-crossing, looked as far as
799 // we were allowed to or reached the end of sound.
801 // To be perfect, the we should not run this code if the
802 // end-of-sound was reached. Instead, since cd_Samples is zero
803 // and the second cd_AddRoutine call below will have no effect,
804 // we should just go onand the cd_Next#? variables will be copied
805 // instead. However, that requires two sets of delay variables:
806 // The one we have now and one delayed set of "next" variables.
807 // I might do that another time, but not today...
809 // Now start the delayed sound.
811 if( cd
->cd_VolDelayed
)
813 cd
->cd_VolDelayed
= FALSE
;
814 cd
->cd_VolumeLeft
= cd
->cd_DelayedVolumeLeft
;
815 cd
->cd_VolumeRight
= cd
->cd_DelayedVolumeRight
;
816 cd
->cd_ScaleLeft
= cd
->cd_DelayedScaleLeft
;
817 cd
->cd_ScaleRight
= cd
->cd_DelayedScaleRight
;
818 cd
->cd_AddRoutine
= cd
->cd_DelayedAddRoutine
;
821 if( cd
->cd_FreqDelayed
)
823 cd
->cd_FreqDelayed
= FALSE
;
824 cd
->cd_FreqOK
= cd
->cd_DelayedFreqOK
;
825 cd
->cd_Add
= cd
->cd_DelayedAdd
;
827 // Since we have advanced, cd_Samples must be recalculated!
828 cd
->cd_Samples
= CalcSamples( cd
->cd_Add
,
834 if( cd
->cd_SoundDelayed
)
836 cd
->cd_SoundDelayed
= FALSE
;
838 cd
->cd_SoundOK
= cd
->cd_DelayedSoundOK
;
840 cd
->cd_StartPointL
= 0;
841 cd
->cd_StartPointR
= 0;
843 cd
->cd_Offset
= cd
->cd_DelayedOffset
;
844 cd
->cd_FirstOffsetI
= cd
->cd_DelayedFirstOffsetI
;
845 cd
->cd_LastOffset
= cd
->cd_DelayedLastOffset
;
846 cd
->cd_DataStart
= cd
->cd_DelayedDataStart
;
848 cd
->cd_Type
= cd
->cd_DelayedType
;
849 cd
->cd_AddRoutine
= cd
->cd_DelayedAddRoutine
;
851 cd
->cd_Samples
= cd
->cd_DelayedSamples
;
853 cd
->cd_ScaleLeft
= cd
->cd_DelayedScaleLeft
;
854 cd
->cd_ScaleRight
= cd
->cd_DelayedScaleRight
;
855 cd
->cd_AddRoutine
= cd
->cd_DelayedAddRoutine
;
859 if( cd
->cd_VolDelayed
|| cd
->cd_FreqDelayed
|| cd
->cd_SoundDelayed
)
861 cd
->cd_AntiClickCount
-= processed
;
865 cd
->cd_AntiClickCount
= 0;
869 if( cd
->cd_FreqOK
&& cd
->cd_SoundOK
)
871 // Sound is still ok, let's rock'n roll.
873 samples
= min( samplesleft
, cd
->cd_Samples
);
877 cd
->cd_TempStartPointL
= cd
->cd_StartPointL
;
878 cd
->cd_TempStartPointR
= cd
->cd_StartPointR
;
879 cd
->cd_TempStartPointRL
= cd
->cd_StartPointRL
;
880 cd
->cd_TempStartPointRR
= cd
->cd_StartPointRR
;
881 cd
->cd_TempStartPointSL
= cd
->cd_StartPointSL
;
882 cd
->cd_TempStartPointSR
= cd
->cd_StartPointSR
;
883 cd
->cd_TempStartPointC
= cd
->cd_StartPointC
;
884 cd
->cd_TempStartPointLFE
= cd
->cd_StartPointLFE
;
886 processed
= ((ADDFUNC
*) cd
->cd_AddRoutine
)( samples
,
889 &cd
->cd_TempStartPointL
,
890 &cd
->cd_TempStartPointR
,
897 cd
->cd_Samples
-= processed
;
898 samplesleft
-= processed
;
901 if( cd
->cd_Samples
== 0 )
903 /* Linear interpol. stuff */
905 ULONG lo
= (ULONG
) (cd
->cd_LastOffset
>> 32);
907 switch( cd
->cd_Type
) {
910 cd
->cd_StartPointL
= ((BYTE
*) cd
->cd_DataStart
)[ lo
] << 8;
914 cd
->cd_StartPointL
= ((BYTE
*) cd
->cd_DataStart
)[ lo
*2+0 ] << 8;
915 cd
->cd_StartPointR
= ((BYTE
*) cd
->cd_DataStart
)[ lo
*2+1 ] << 8;
919 cd
->cd_StartPointL
= ((WORD
*) cd
->cd_DataStart
)[ lo
];
923 cd
->cd_StartPointL
= ((WORD
*) cd
->cd_DataStart
)[ lo
*2+0 ];
924 cd
->cd_StartPointR
= ((WORD
*) cd
->cd_DataStart
)[ lo
*2+1 ];
928 cd
->cd_StartPointL
= ((LONG
*) cd
->cd_DataStart
)[ lo
] >> 16;
932 cd
->cd_StartPointL
= ((LONG
*) cd
->cd_DataStart
)[ lo
*2+0 ] >> 16;
933 cd
->cd_StartPointR
= ((LONG
*) cd
->cd_DataStart
)[ lo
*2+1 ] >> 16;
937 // This old code is totally fucked up ... Why didn't anybody
939 // cd->cd_StartPointL = cd->cd_TempStartPointL;
940 // cd->cd_StartPointR = cd->cd_TempStartPointR;
942 /* KPrintF( "cd->cd_StartPointL=%08lx, cd->cd_StartPointR=%08lx\n", */
943 /* cd->cd_StartPointL, cd->cd_StartPointR ); */
945 ** Offset always points OUTSIDE the sample after this
946 ** call. Ie, if we read a sample at offset (Offset.I)
947 ** now, it does not belong to the sample just played.
948 ** This is true for both backward and forward mixing.
951 /* KPrintF( "cd->cd_Add=0x%08lx:%08lx\n", */
952 /* (IPTR) (cd->cd_Add >> 32), (IPTR) cd->cd_Add ); */
953 /* KPrintF( "cd->cd_Offset=0x%08lx:%08lx, " */
954 /* "cd->cd_LastOffset=0x%08lx:%08lx," */
955 /* "cd->cd_FirstOffset=%08lx\n", */
956 /* (IPTR) (cd->cd_Offset >> 32), (IPTR) cd->cd_Offset, */
957 /* (IPTR) (cd->cd_LastOffset >> 32), (IPTR) cd->cd_LastOffset, */
958 /* cd->cd_FirstOffsetI ); */
960 /* What we do now is to calculate how much futher we have
963 cd
->cd_Offset
-= cd
->cd_LastOffset
+ 1;
965 /* KPrintF( "cd->cd_Offset=0x%08lx:%08lx, " */
966 /* "cd->cd_LastOffset=0x%08lx:%08lx," */
967 /* "cd->cd_FirstOffset=%08lx\n", */
968 /* (IPTR) (cd->cd_Offset >> 32), (IPTR) cd->cd_Offset, */
969 /* (IPTR) (cd->cd_LastOffset >> 32), (IPTR) cd->cd_LastOffset, */
970 /* cd->cd_FirstOffsetI ); */
973 ** Offset should now be added to the NEXT Offset. Offset
974 ** is positive of the sample was mixed forwards, and
975 ** negative if the sample was mixed backwards. There is
976 ** one catch, however. If the direction is about to
977 ** change now, Offset should instead be SUBTRACTED.
981 if( (cd
->cd_Type
^ cd
->cd_NextType
) & AHIST_BW
)
983 cd
->cd_Offset
= -cd
->cd_Offset
;
986 cd
->cd_Offset
+= cd
->cd_NextOffset
;
988 // cd->cd_FirstOffsetI = cd->cd_Offset >> 32;
989 cd
->cd_FirstOffsetI
= cd
->cd_NextOffset
>> 32;
991 /* KPrintF( "cd->cd_Offset=0x%08lx:%08lx, " */
992 /* "cd->cd_LastOffset=0x%08lx:%08lx," */
993 /* "cd->cd_FirstOffset=%08lx\n", */
994 /* (IPTR) (cd->cd_Offset >> 32), (IPTR) cd->cd_Offset, */
995 /* (IPTR) (cd->cd_LastOffset >> 32), (IPTR) cd->cd_LastOffset, */
996 /* cd->cd_FirstOffsetI ); */
998 ** But what if the next sample is so short that we just
999 ** passed it!? Here is the nice part. CalcSamples
1000 ** checks this, and sets cd_Samples to 0 in that case.
1001 ** And the add routines doesn't do anything when asked to
1002 ** mix 0 samples. Assume we have passed a sample with 4
1003 ** samples, and the next one is only 3. CalcSamples
1004 ** returns 0. The (ADDFUNC) call above does not do
1005 ** anything at all, OffsetI is still 4. Now we subtract
1006 ** LastOffsetI, which is 3. Result: We have passed the
1007 ** sample with 1. And guess what? That's in range.
1010 /* Now, let's copy the rest of the cd_Next#? stuff... */
1012 cd
->cd_FreqOK
= cd
->cd_NextFreqOK
;
1013 cd
->cd_SoundOK
= cd
->cd_NextSoundOK
;
1014 cd
->cd_Add
= cd
->cd_NextAdd
;
1015 cd
->cd_DataStart
= cd
->cd_NextDataStart
;
1016 cd
->cd_LastOffset
= cd
->cd_NextLastOffset
;
1017 cd
->cd_ScaleLeft
= cd
->cd_NextScaleLeft
;
1018 cd
->cd_ScaleRight
= cd
->cd_NextScaleRight
;
1019 cd
->cd_AddRoutine
= cd
->cd_NextAddRoutine
;
1020 cd
->cd_VolumeLeft
= cd
->cd_NextVolumeLeft
;
1021 cd
->cd_VolumeRight
= cd
->cd_NextVolumeRight
;
1022 cd
->cd_Type
= cd
->cd_NextType
;
1024 cd
->cd_Samples
= CalcSamples( cd
->cd_Add
,
1029 /* Also update all cd_Delayed#? stuff */
1031 if( !cd
->cd_VolDelayed
)
1033 cd
->cd_DelayedVolumeLeft
= cd
->cd_NextVolumeLeft
;
1034 cd
->cd_DelayedVolumeRight
= cd
->cd_NextVolumeRight
;
1037 if( !cd
->cd_FreqDelayed
)
1039 cd
->cd_DelayedFreqOK
= cd
->cd_NextFreqOK
;
1040 cd
->cd_DelayedAdd
= cd
->cd_NextAdd
;
1043 if( !cd
->cd_SoundDelayed
)
1045 cd
->cd_DelayedSoundOK
= cd
->cd_NextSoundOK
;
1046 cd
->cd_DelayedOffset
= cd
->cd_NextOffset
;
1047 cd
->cd_DelayedFirstOffsetI
= cd
->cd_FirstOffsetI
; // See above
1048 cd
->cd_DelayedLastOffset
= cd
->cd_NextLastOffset
;
1049 cd
->cd_DelayedType
= cd
->cd_NextType
;
1050 cd
->cd_DelayedDataStart
= cd
->cd_NextDataStart
;
1053 if( !cd
->cd_VolDelayed
&& !cd
->cd_SoundDelayed
)
1055 cd
->cd_DelayedScaleLeft
= cd
->cd_NextScaleLeft
;
1056 cd
->cd_DelayedScaleRight
= cd
->cd_NextScaleRight
;
1057 cd
->cd_DelayedAddRoutine
= cd
->cd_NextAddRoutine
;
1060 if( !cd
->cd_FreqDelayed
&& !cd
->cd_SoundDelayed
)
1062 cd
->cd_DelayedSamples
= cd
->cd_Samples
;
1065 cd
->cd_EOS
= TRUE
; // signal End-Of-Sample
1066 continue; // .contchannel (same channel, new sound)
1068 } // FreqOK && SoundOK
1069 break; // .contchannel
1076 if(audioctrl
->ahiac_WetOrDry
== AHIEDM_WET
)
1078 audioctrl
->ahiac_WetOrDry
= AHIEDM_DRY
;
1080 /*** AHIET_DSPECHO ***/
1081 if(audioctrl
->ahiac_EffDSPEchoStruct
!= NULL
)
1083 audioctrl
->ahiac_EffDSPEchoStruct
->ahiecho_Code(
1084 audioctrl
->ahiac_EffDSPEchoStruct
, dst
, audioctrl
);
1087 cd
= audioctrl
->ahiac_DryList
;
1089 if(audioctrl
->ac
.ahiac_Flags
& AHIACF_POSTPROC
)
1091 /*** AHIET_MASTERVOLUME ***/
1093 DoMasterVolume(dst
, audioctrl
);
1096 ** When AHIACB_POSTPROC is set, the dry data shall be placed
1097 ** immediate after the wet data. This is done by modifying the
1101 dst
= (char *) dst
+ audioctrl
->ac
.ahiac_BuffSamples
*
1102 _AHI_SampleFrameSize( audioctrl
->ac
.ahiac_BuffType
, AHIBase
);
1105 continue; /* while(TRUE) */
1109 break; /* while(TRUE) */
1117 /******************************************************************************
1118 ** DoMasterVolume *************************************************************
1119 ******************************************************************************/
1122 ** This function would be better if it was written in assembler,
1123 ** since overflow could then be detected. Instead we reduce the
1124 ** number of bits to 20 and then scale and compare.
1128 DoMasterVolume( void *buffer
,
1129 struct AHIPrivAudioCtrl
*audioctrl
)
1135 cnt
= audioctrl
->ac
.ahiac_BuffSamples
;
1137 switch(audioctrl
->ac
.ahiac_BuffType
)
1157 if( audioctrl
->ac
.ahiac_BuffType
== AHIST_M32S
1158 || audioctrl
->ac
.ahiac_BuffType
== AHIST_S32S
1159 || audioctrl
->ac
.ahiac_BuffType
== AHIST_L7_1
)
1163 vol
= audioctrl
->ahiac_SetMasterVolume
>> 8;
1169 sample
= (*dst
>> 12) * vol
;
1171 if(sample
> (LONG
) 0x07ffffff)
1172 sample
= 0x07ffffff;
1173 else if(sample
< (LONG
) 0xf8000000)
1174 sample
= 0xf8000000;
1176 *dst
++ = sample
<< 4;
1183 vol
= audioctrl
->ahiac_SetMasterVolume
>> 4;
1189 sample
= *dst
* vol
;
1191 if(sample
> (LONG
) 0x07ffffff)
1192 sample
= 0x07ffffff;
1193 else if(sample
< (LONG
) 0xf8000000)
1194 sample
= 0xf8000000;
1196 *dst
++ = sample
>> 12;
1203 /******************************************************************************
1204 ** DoOutputBuffer *************************************************************
1205 ******************************************************************************/
1208 DoOutputBuffer( void *buffer
,
1209 struct AHIPrivAudioCtrl
*audioctrl
)
1211 struct AHIEffOutputBuffer
*ob
;
1213 ob
= audioctrl
->ahiac_EffOutputBufferStruct
;
1217 ob
->ahieob_Buffer
= buffer
;
1218 ob
->ahieob_Length
= audioctrl
->ac
.ahiac_BuffSamples
;
1219 ob
->ahieob_Type
= audioctrl
->ac
.ahiac_BuffType
;
1221 CallHookPkt( ob
->ahieob_Func
,
1228 /******************************************************************************
1229 ** DoChannelInfo **************************************************************
1230 ******************************************************************************/
1233 DoChannelInfo( struct AHIPrivAudioCtrl
*audioctrl
)
1235 struct AHIEffChannelInfo
*ci
;
1236 struct AHIChannelData
*cd
;
1239 ci
= audioctrl
->ahiac_EffChannelInfoStruct
;
1245 cd
= audioctrl
->ahiac_ChannelDatas
;
1246 offsets
= ci
->ahieci_Offset
;
1248 for(i
= ci
->ahieci_Channels
; i
> 0; i
--)
1250 *offsets
++ = cd
->cd_Offset
>> 32;
1254 CallHookPkt( ci
->ahieci_Func
,
1261 /******************************************************************************
1262 ** CalcSamples ****************************************************************
1263 ******************************************************************************/
1266 CalcSamples ( Fixed64 Add
,
1274 if( Type
& AHIST_BW
)
1276 len
= Offset
- LastOffset
;
1280 len
= LastOffset
- Offset
;
1283 if(len
< 0 || Add
== 0) return 0; // Error!
1285 return (LONG
) ( len
/ Add
) + 1;