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,
27 #include <dos/dostags.h>
28 #include <exec/memory.h>
30 #include <proto/dos.h>
31 #include <proto/exec.h>
32 #include <proto/utility.h>
34 #define __NOGLOBALIFACE__
35 #include <proto/ahi.h>
37 #undef __NOGLOBALIFACE__
41 #include "addroutines.h"
49 #if defined( ENABLE_WARPUP )
53 #define min(a,b) (((a)<(b))?(a):(b))
54 #define max(a,b) (((a)>(b))?(a):(b))
56 /******************************************************************************
57 ** Prototypes *****************************************************************
58 ******************************************************************************/
61 CallSoundHook( struct AHIPrivAudioCtrl
*audioctrl
,
67 CallHookPkt( audioctrl
->ac
.ahiac_SoundFunc
,
72 #if defined( ENABLE_WARPUP )
74 WarpUpCallSoundHook( audioctrl
, arg
);
82 MixerFunc( struct Hook
* hook
,
83 struct AHIPrivAudioCtrl
* audioctrl
,
89 Mix( hook
, audioctrl
, dst
);
90 DoMasterVolume( dst
, audioctrl
);
91 DoOutputBuffer( dst
, audioctrl
);
92 DoChannelInfo( audioctrl
);
95 #if defined( ENABLE_WARPUP )
97 WarpUpCallMixer( audioctrl
, dst
);
98 DoOutputBuffer( dst
, audioctrl
);
99 DoChannelInfo( audioctrl
);
106 /******************************************************************************
107 ** InitMixroutine *************************************************************
108 ******************************************************************************/
110 // This function is used to initialize the mixer routine (called from
111 // AHI_AllocAudio()).
114 InitMixroutine( struct AHIPrivAudioCtrl
*audioctrl
)
118 // Allocate and initialize the AHIChannelData structures
119 // This structure could be accessed from from interrupts!
121 ULONG data_flags
= MEMF_ANY
;
126 data_flags
= MEMF_PUBLIC
| MEMF_CLEAR
;
129 #if defined( ENABLE_WARPUP )
131 // Non-cached from both the PPC and m68k side
132 data_flags
= MEMF_PUBLIC
| MEMF_CLEAR
| MEMF_CHIP
;
137 audioctrl
->ahiac_ChannelDatas
= AHIAllocVec(
138 audioctrl
->ac
.ahiac_Channels
* sizeof( struct AHIChannelData
),
141 // Allocate and initialize the AHISoundData structures
142 // This structure could be accessed from from interrupts!
144 audioctrl
->ahiac_SoundDatas
= AHIAllocVec(
145 audioctrl
->ac
.ahiac_Sounds
* sizeof( struct AHISoundData
),
148 // Now link the list and fill in the channel number for each structure.
150 if( audioctrl
->ahiac_ChannelDatas
!= NULL
151 && audioctrl
->ahiac_SoundDatas
!= NULL
)
153 struct AHIChannelData
*cd
;
154 struct AHISoundData
*sd
;
157 cd
= audioctrl
->ahiac_ChannelDatas
;
159 audioctrl
->ahiac_WetList
= cd
;
160 audioctrl
->ahiac_DryList
= NULL
;
162 for(i
= 0; i
< audioctrl
->ac
.ahiac_Channels
- 1; i
++)
165 cd
->cd_ChannelNo
= i
;
167 // Set link to next channel
168 cd
->cd_Succ
= cd
+ 1;
173 cd
->cd_ChannelNo
= i
;
175 // Clear the last link;
179 sd
= audioctrl
->ahiac_SoundDatas
;
181 for( i
= 0; i
< audioctrl
->ac
.ahiac_Sounds
; i
++)
183 sd
->sd_Type
= AHIST_NOTYPE
;
195 #if defined( ENABLE_WARPUP )
197 rc
= WarpUpInit( audioctrl
);
206 /******************************************************************************
207 ** CleanUpMixroutine **********************************************************
208 ******************************************************************************/
210 // This function is used to clean up after the mixer routine (called from
214 CleanUpMixroutine( struct AHIPrivAudioCtrl
*audioctrl
)
221 #if defined( ENABLE_WARPUP )
223 WarpUpCleanUp( audioctrl
);
228 AHIFreeVec( audioctrl
->ahiac_SoundDatas
);
229 audioctrl
->ahiac_SoundDatas
= NULL
;
231 AHIFreeVec( audioctrl
->ahiac_ChannelDatas
);
232 audioctrl
->ahiac_ChannelDatas
= NULL
;
236 /******************************************************************************
237 ** SelectAddRoutine ***********************************************************
238 ******************************************************************************/
240 // This routine gets called each time there is reason to believe that a new
241 // add-routine should be used (new sound selected, volume changed,
242 // mastervolume changed)
244 // Based on VolumeLeft, VolumeRight and SampleType, fill in ScaleLeft,
245 // ScaleRight and AddRoutine.
248 SelectAddRoutine ( Fixed VolumeLeft
,
251 struct AHIPrivAudioCtrl
*audioctrl
,
254 ADDFUNC
**AddRoutine
)
257 // This version only cares about the sample format and does not use any
258 // optimized add-routines.
262 VolumeLeft
= VolumeLeft
* (audioctrl
->ahiac_MasterVolume
>> 8) /
263 (audioctrl
->ahiac_Channels2
<< 8);
265 VolumeRight
= VolumeRight
* (audioctrl
->ahiac_MasterVolume
>> 8) /
266 (audioctrl
->ahiac_Channels2
<< 8);
268 // First, select HiFi or LoFi...
270 if( audioctrl
->ac
.ahiac_Flags
& AHIACF_HIFI
)
273 // Then, check the output format...
275 switch(audioctrl
->ac
.ahiac_BuffType
)
280 // ...and then the source format.
285 case AHIST_BW
|AHIST_M8S
:
286 *ScaleLeft
= VolumeLeft
+ VolumeRight
;
288 if(SampleType
& AHIST_BW
)
289 *AddRoutine
= AddByteMonoBPtr
;
291 *AddRoutine
= AddByteMonoPtr
;
295 case AHIST_BW
|AHIST_S8S
:
296 *ScaleLeft
= VolumeLeft
;
297 *ScaleRight
= VolumeRight
;
298 if(SampleType
& AHIST_BW
)
299 *AddRoutine
= AddBytesMonoBPtr
;
301 *AddRoutine
= AddBytesMonoPtr
;
305 case AHIST_BW
|AHIST_M16S
:
306 *ScaleLeft
= VolumeLeft
+ VolumeRight
;
308 if(SampleType
& AHIST_BW
)
309 *AddRoutine
= AddWordMonoBPtr
;
311 *AddRoutine
= AddWordMonoPtr
;
315 case AHIST_BW
|AHIST_S16S
:
316 *ScaleLeft
= VolumeLeft
;
317 *ScaleRight
= VolumeRight
;
318 if(SampleType
& AHIST_BW
)
319 *AddRoutine
= AddWordsMonoBPtr
;
321 *AddRoutine
= AddWordsMonoPtr
;
325 case AHIST_BW
|AHIST_M32S
:
326 *ScaleLeft
= VolumeLeft
+ VolumeRight
;
328 if(SampleType
& AHIST_BW
)
329 *AddRoutine
= AddLongMonoBPtr
;
331 *AddRoutine
= AddLongMonoPtr
;
335 case AHIST_BW
|AHIST_S32S
:
336 *ScaleLeft
= VolumeLeft
;
337 *ScaleRight
= VolumeRight
;
338 if(SampleType
& AHIST_BW
)
339 *AddRoutine
= AddLongsMonoBPtr
;
341 *AddRoutine
= AddLongsMonoPtr
;
345 case AHIST_BW
|AHIST_L7_1
:
346 *ScaleLeft
= VolumeLeft
;
347 *ScaleRight
= VolumeRight
;
348 if(SampleType
& AHIST_BW
)
349 *AddRoutine
= Add71MonoBPtr
;
351 *AddRoutine
= Add71MonoPtr
;
364 // ...and then the source format.
369 case AHIST_BW
|AHIST_M8S
:
370 *ScaleLeft
= VolumeLeft
;
371 *ScaleRight
= VolumeRight
;
372 if(SampleType
& AHIST_BW
)
373 *AddRoutine
= AddByteStereoBPtr
;
375 *AddRoutine
= AddByteStereoPtr
;
379 case AHIST_BW
|AHIST_S8S
:
380 *ScaleLeft
= VolumeLeft
;
381 *ScaleRight
= VolumeRight
;
382 if(SampleType
& AHIST_BW
)
383 *AddRoutine
= AddBytesStereoBPtr
;
385 *AddRoutine
= AddBytesStereoPtr
;
389 case AHIST_BW
|AHIST_M16S
:
390 *ScaleLeft
= VolumeLeft
;
391 *ScaleRight
= VolumeRight
;
392 if(SampleType
& AHIST_BW
)
393 *AddRoutine
= AddWordStereoBPtr
;
395 *AddRoutine
= AddWordStereoPtr
;
399 case AHIST_BW
|AHIST_S16S
:
400 *ScaleLeft
= VolumeLeft
;
401 *ScaleRight
= VolumeRight
;
402 if(SampleType
& AHIST_BW
)
403 *AddRoutine
= AddWordsStereoBPtr
;
405 *AddRoutine
= AddWordsStereoPtr
;
409 case AHIST_BW
|AHIST_M32S
:
410 *ScaleLeft
= VolumeLeft
;
411 *ScaleRight
= VolumeRight
;
412 if(SampleType
& AHIST_BW
)
413 *AddRoutine
= AddLongStereoBPtr
;
415 *AddRoutine
= AddLongStereoPtr
;
419 case AHIST_BW
|AHIST_S32S
:
420 *ScaleLeft
= VolumeLeft
;
421 *ScaleRight
= VolumeRight
;
422 if(SampleType
& AHIST_BW
)
423 *AddRoutine
= AddLongsStereoBPtr
;
425 *AddRoutine
= AddLongsStereoPtr
;
429 case AHIST_BW
|AHIST_L7_1
:
430 *ScaleLeft
= VolumeLeft
;
431 *ScaleRight
= VolumeRight
;
432 if(SampleType
& AHIST_BW
)
433 *AddRoutine
= Add71StereoBPtr
;
435 *AddRoutine
= Add71StereoPtr
;
448 // ...and then the source format.
453 case AHIST_BW
|AHIST_M8S
:
454 *ScaleLeft
= VolumeLeft
;
455 *ScaleRight
= VolumeRight
;
456 if(SampleType
& AHIST_BW
)
457 *AddRoutine
= AddByte71BPtr
;
459 *AddRoutine
= AddByte71Ptr
;
463 case AHIST_BW
|AHIST_S8S
:
464 *ScaleLeft
= VolumeLeft
;
465 *ScaleRight
= VolumeRight
;
466 if(SampleType
& AHIST_BW
)
467 *AddRoutine
= AddBytes71BPtr
;
469 *AddRoutine
= AddBytes71Ptr
;
473 case AHIST_BW
|AHIST_M16S
:
474 *ScaleLeft
= VolumeLeft
;
475 *ScaleRight
= VolumeRight
;
476 if(SampleType
& AHIST_BW
)
477 *AddRoutine
= AddWord71BPtr
;
479 *AddRoutine
= AddWord71Ptr
;
483 case AHIST_BW
|AHIST_S16S
:
484 *ScaleLeft
= VolumeLeft
;
485 *ScaleRight
= VolumeRight
;
486 if(SampleType
& AHIST_BW
)
487 *AddRoutine
= AddWords71BPtr
;
489 *AddRoutine
= AddWords71Ptr
;
493 case AHIST_BW
|AHIST_M32S
:
494 *ScaleLeft
= VolumeLeft
;
495 *ScaleRight
= VolumeRight
;
496 if(SampleType
& AHIST_BW
)
497 *AddRoutine
= AddLong71BPtr
;
499 *AddRoutine
= AddLong71Ptr
;
503 case AHIST_BW
|AHIST_S32S
:
504 *ScaleLeft
= VolumeLeft
;
505 *ScaleRight
= VolumeRight
;
506 if(SampleType
& AHIST_BW
)
507 *AddRoutine
= AddLongs71BPtr
;
509 *AddRoutine
= AddLongs71Ptr
;
513 case AHIST_BW
|AHIST_L7_1
:
514 *ScaleLeft
= VolumeLeft
;
515 *ScaleRight
= VolumeRight
;
516 if(SampleType
& AHIST_BW
)
517 *AddRoutine
= Add7171BPtr
;
519 *AddRoutine
= Add7171Ptr
;
540 // Then, check the output format...
542 switch(audioctrl
->ac
.ahiac_BuffType
)
547 // ...and then the source format.
552 case AHIST_BW
|AHIST_M8S
:
553 *ScaleLeft
= VolumeLeft
+ VolumeRight
;
555 if(SampleType
& AHIST_BW
)
556 *AddRoutine
= AddLofiByteMonoBPtr
;
558 *AddRoutine
= AddLofiByteMonoPtr
;
562 case AHIST_BW
|AHIST_S8S
:
563 *ScaleLeft
= VolumeLeft
;
564 *ScaleRight
= VolumeRight
;
565 if(SampleType
& AHIST_BW
)
566 *AddRoutine
= AddLofiBytesMonoBPtr
;
568 *AddRoutine
= AddLofiBytesMonoPtr
;
572 case AHIST_BW
|AHIST_M16S
:
573 *ScaleLeft
= VolumeLeft
+ VolumeRight
;
575 if(SampleType
& AHIST_BW
)
576 *AddRoutine
= AddLofiWordMonoBPtr
;
578 *AddRoutine
= AddLofiWordMonoPtr
;
582 case AHIST_BW
|AHIST_S16S
:
583 *ScaleLeft
= VolumeLeft
;
584 *ScaleRight
= VolumeRight
;
585 if(SampleType
& AHIST_BW
)
586 *AddRoutine
= AddLofiWordsMonoBPtr
;
588 *AddRoutine
= AddLofiWordsMonoPtr
;
592 case AHIST_BW
|AHIST_M32S
:
593 *ScaleLeft
= VolumeLeft
+ VolumeRight
;
595 if(SampleType
& AHIST_BW
)
596 *AddRoutine
= AddLofiLongMonoBPtr
;
598 *AddRoutine
= AddLofiLongMonoPtr
;
602 case AHIST_BW
|AHIST_S32S
:
603 *ScaleLeft
= VolumeLeft
;
604 *ScaleRight
= VolumeRight
;
605 if(SampleType
& AHIST_BW
)
606 *AddRoutine
= AddLofiLongsMonoBPtr
;
608 *AddRoutine
= AddLofiLongsMonoPtr
;
621 // ...and then the source format.
626 case AHIST_BW
|AHIST_M8S
:
627 *ScaleLeft
= VolumeLeft
;
628 *ScaleRight
= VolumeRight
;
629 if(SampleType
& AHIST_BW
)
630 *AddRoutine
= AddLofiByteStereoBPtr
;
632 *AddRoutine
= AddLofiByteStereoPtr
;
636 case AHIST_BW
|AHIST_S8S
:
637 *ScaleLeft
= VolumeLeft
;
638 *ScaleRight
= VolumeRight
;
639 if(SampleType
& AHIST_BW
)
640 *AddRoutine
= AddLofiBytesStereoBPtr
;
642 *AddRoutine
= AddLofiBytesStereoPtr
;
646 case AHIST_BW
|AHIST_M16S
:
647 *ScaleLeft
= VolumeLeft
;
648 *ScaleRight
= VolumeRight
;
649 if(SampleType
& AHIST_BW
)
650 *AddRoutine
= AddLofiWordStereoBPtr
;
652 *AddRoutine
= AddLofiWordStereoPtr
;
656 case AHIST_BW
|AHIST_S16S
:
657 *ScaleLeft
= VolumeLeft
;
658 *ScaleRight
= VolumeRight
;
659 if(SampleType
& AHIST_BW
)
660 *AddRoutine
= AddLofiWordsStereoBPtr
;
662 *AddRoutine
= AddLofiWordsStereoPtr
;
666 case AHIST_BW
|AHIST_M32S
:
667 *ScaleLeft
= VolumeLeft
;
668 *ScaleRight
= VolumeRight
;
669 if(SampleType
& AHIST_BW
)
670 *AddRoutine
= AddLofiLongStereoBPtr
;
672 *AddRoutine
= AddLofiLongStereoPtr
;
676 case AHIST_BW
|AHIST_S32S
:
677 *ScaleLeft
= VolumeLeft
;
678 *ScaleRight
= VolumeRight
;
679 if(SampleType
& AHIST_BW
)
680 *AddRoutine
= AddLofiLongsStereoBPtr
;
682 *AddRoutine
= AddLofiLongsStereoPtr
;
703 /******************************************************************************
704 ** Mix ************************************************************************
705 ******************************************************************************/
707 // This is the function that the driver calls each time it want more data
711 Mix( struct Hook
* unused_Hook
,
712 struct AHIPrivAudioCtrl
* audioctrl
,
715 struct AHIChannelData
*cd
;
719 /* Clear the buffer */
721 memset( dst
, 0, audioctrl
->ahiac_BuffSizeNow
);
722 /* Mix the samples */
724 audioctrl
->ahiac_WetOrDry
= AHIEDM_WET
;
726 cd
= audioctrl
->ahiac_WetList
;
730 while(cd
!= NULL
) // .nextchannel
732 samplesleft
= audioctrl
->ac
.ahiac_BuffSamples
;
735 while(TRUE
) // .contchannel
740 /* Call Sound Hook */
745 if(audioctrl
->ac
.ahiac_SoundFunc
!= NULL
)
747 CallSoundHook( audioctrl
, &cd
->cd_ChannelNo
);
753 if( cd
->cd_AntiClickCount
> 0 && cd
->cd_FreqOK
&& cd
->cd_SoundOK
)
755 // Sound is ok and we're looking for a zero-crossing.
759 samples
= min( samplesleft
, cd
->cd_Samples
);
760 try_samples
= min( samples
, cd
->cd_AntiClickCount
);
762 if( try_samples
> 0 )
764 cd
->cd_TempStartPointL
= cd
->cd_StartPointL
;
765 cd
->cd_TempStartPointR
= cd
->cd_StartPointR
;
766 cd
->cd_TempStartPointRL
= cd
->cd_StartPointRL
;
767 cd
->cd_TempStartPointRR
= cd
->cd_StartPointRR
;
768 cd
->cd_TempStartPointSL
= cd
->cd_StartPointSL
;
769 cd
->cd_TempStartPointSR
= cd
->cd_StartPointSR
;
770 cd
->cd_TempStartPointC
= cd
->cd_StartPointC
;
771 cd
->cd_TempStartPointLFE
= cd
->cd_StartPointLFE
;
773 processed
= ((ADDFUNC
*) cd
->cd_AddRoutine
)( try_samples
,
776 &cd
->cd_TempStartPointL
,
777 &cd
->cd_TempStartPointR
,
785 cd
->cd_Samples
-= processed
;
786 samplesleft
-= processed
;
793 if( processed
!= try_samples
|| // Found zero-crossing
794 try_samples
<= cd
->cd_AntiClickCount
) // End-of-sound or
797 // We either found a zero-crossing, looked as far as
798 // we were allowed to or reached the end of sound.
800 // To be perfect, the we should not run this code if the
801 // end-of-sound was reached. Instead, since cd_Samples is zero
802 // and the second cd_AddRoutine call below will have no effect,
803 // we should just go onand the cd_Next#? variables will be copied
804 // instead. However, that requires two sets of delay variables:
805 // The one we have now and one delayed set of "next" variables.
806 // I might do that another time, but not today...
808 // Now start the delayed sound.
810 if( cd
->cd_VolDelayed
)
812 cd
->cd_VolDelayed
= FALSE
;
813 cd
->cd_VolumeLeft
= cd
->cd_DelayedVolumeLeft
;
814 cd
->cd_VolumeRight
= cd
->cd_DelayedVolumeRight
;
815 cd
->cd_ScaleLeft
= cd
->cd_DelayedScaleLeft
;
816 cd
->cd_ScaleRight
= cd
->cd_DelayedScaleRight
;
817 cd
->cd_AddRoutine
= cd
->cd_DelayedAddRoutine
;
820 if( cd
->cd_FreqDelayed
)
822 cd
->cd_FreqDelayed
= FALSE
;
823 cd
->cd_FreqOK
= cd
->cd_DelayedFreqOK
;
824 cd
->cd_Add
= cd
->cd_DelayedAdd
;
826 // Since we have advanced, cd_Samples must be recalculated!
827 cd
->cd_Samples
= CalcSamples( cd
->cd_Add
,
833 if( cd
->cd_SoundDelayed
)
835 cd
->cd_SoundDelayed
= FALSE
;
837 cd
->cd_SoundOK
= cd
->cd_DelayedSoundOK
;
839 cd
->cd_StartPointL
= 0;
840 cd
->cd_StartPointR
= 0;
842 cd
->cd_Offset
= cd
->cd_DelayedOffset
;
843 cd
->cd_FirstOffsetI
= cd
->cd_DelayedFirstOffsetI
;
844 cd
->cd_LastOffset
= cd
->cd_DelayedLastOffset
;
845 cd
->cd_DataStart
= cd
->cd_DelayedDataStart
;
847 cd
->cd_Type
= cd
->cd_DelayedType
;
848 cd
->cd_AddRoutine
= cd
->cd_DelayedAddRoutine
;
850 cd
->cd_Samples
= cd
->cd_DelayedSamples
;
852 cd
->cd_ScaleLeft
= cd
->cd_DelayedScaleLeft
;
853 cd
->cd_ScaleRight
= cd
->cd_DelayedScaleRight
;
854 cd
->cd_AddRoutine
= cd
->cd_DelayedAddRoutine
;
858 if( cd
->cd_VolDelayed
|| cd
->cd_FreqDelayed
|| cd
->cd_SoundDelayed
)
860 cd
->cd_AntiClickCount
-= processed
;
864 cd
->cd_AntiClickCount
= 0;
868 if( cd
->cd_FreqOK
&& cd
->cd_SoundOK
)
870 // Sound is still ok, let's rock'n roll.
872 samples
= min( samplesleft
, cd
->cd_Samples
);
876 cd
->cd_TempStartPointL
= cd
->cd_StartPointL
;
877 cd
->cd_TempStartPointR
= cd
->cd_StartPointR
;
878 cd
->cd_TempStartPointRL
= cd
->cd_StartPointRL
;
879 cd
->cd_TempStartPointRR
= cd
->cd_StartPointRR
;
880 cd
->cd_TempStartPointSL
= cd
->cd_StartPointSL
;
881 cd
->cd_TempStartPointSR
= cd
->cd_StartPointSR
;
882 cd
->cd_TempStartPointC
= cd
->cd_StartPointC
;
883 cd
->cd_TempStartPointLFE
= cd
->cd_StartPointLFE
;
885 processed
= ((ADDFUNC
*) cd
->cd_AddRoutine
)( samples
,
888 &cd
->cd_TempStartPointL
,
889 &cd
->cd_TempStartPointR
,
896 cd
->cd_Samples
-= processed
;
897 samplesleft
-= processed
;
900 if( cd
->cd_Samples
== 0 )
902 /* Linear interpol. stuff */
904 ULONG lo
= (ULONG
) (cd
->cd_LastOffset
>> 32);
906 switch( cd
->cd_Type
) {
909 cd
->cd_StartPointL
= ((BYTE
*) cd
->cd_DataStart
)[ lo
] << 8;
913 cd
->cd_StartPointL
= ((BYTE
*) cd
->cd_DataStart
)[ lo
*2+0 ] << 8;
914 cd
->cd_StartPointR
= ((BYTE
*) cd
->cd_DataStart
)[ lo
*2+1 ] << 8;
918 cd
->cd_StartPointL
= ((WORD
*) cd
->cd_DataStart
)[ lo
];
922 cd
->cd_StartPointL
= ((WORD
*) cd
->cd_DataStart
)[ lo
*2+0 ];
923 cd
->cd_StartPointR
= ((WORD
*) cd
->cd_DataStart
)[ lo
*2+1 ];
927 cd
->cd_StartPointL
= ((LONG
*) cd
->cd_DataStart
)[ lo
] >> 16;
931 cd
->cd_StartPointL
= ((LONG
*) cd
->cd_DataStart
)[ lo
*2+0 ] >> 16;
932 cd
->cd_StartPointR
= ((LONG
*) cd
->cd_DataStart
)[ lo
*2+1 ] >> 16;
936 // This old code is totally fucked up ... Why didn't anybody
938 // cd->cd_StartPointL = cd->cd_TempStartPointL;
939 // cd->cd_StartPointR = cd->cd_TempStartPointR;
941 /* KPrintF( "cd->cd_StartPointL=%08lx, cd->cd_StartPointR=%08lx\n", */
942 /* cd->cd_StartPointL, cd->cd_StartPointR ); */
944 ** Offset always points OUTSIDE the sample after this
945 ** call. Ie, if we read a sample at offset (Offset.I)
946 ** now, it does not belong to the sample just played.
947 ** This is true for both backward and forward mixing.
950 /* KPrintF( "cd->cd_Add=0x%08lx:%08lx\n", */
951 /* (ULONG) (cd->cd_Add >> 32), (ULONG) cd->cd_Add ); */
952 /* KPrintF( "cd->cd_Offset=0x%08lx:%08lx, " */
953 /* "cd->cd_LastOffset=0x%08lx:%08lx," */
954 /* "cd->cd_FirstOffset=%08lx\n", */
955 /* (ULONG) (cd->cd_Offset >> 32), (ULONG) cd->cd_Offset, */
956 /* (ULONG) (cd->cd_LastOffset >> 32), (ULONG) cd->cd_LastOffset, */
957 /* cd->cd_FirstOffsetI ); */
959 /* What we do now is to calculate how much futher we have
962 cd
->cd_Offset
-= cd
->cd_LastOffset
+ 1;
964 /* KPrintF( "cd->cd_Offset=0x%08lx:%08lx, " */
965 /* "cd->cd_LastOffset=0x%08lx:%08lx," */
966 /* "cd->cd_FirstOffset=%08lx\n", */
967 /* (ULONG) (cd->cd_Offset >> 32), (ULONG) cd->cd_Offset, */
968 /* (ULONG) (cd->cd_LastOffset >> 32), (ULONG) cd->cd_LastOffset, */
969 /* cd->cd_FirstOffsetI ); */
972 ** Offset should now be added to the NEXT Offset. Offset
973 ** is positive of the sample was mixed forwards, and
974 ** negative if the sample was mixed backwards. There is
975 ** one catch, however. If the direction is about to
976 ** change now, Offset should instead be SUBTRACTED.
980 if( (cd
->cd_Type
^ cd
->cd_NextType
) & AHIST_BW
)
982 cd
->cd_Offset
= -cd
->cd_Offset
;
985 cd
->cd_Offset
+= cd
->cd_NextOffset
;
987 // cd->cd_FirstOffsetI = cd->cd_Offset >> 32;
988 cd
->cd_FirstOffsetI
= cd
->cd_NextOffset
>> 32;
990 /* KPrintF( "cd->cd_Offset=0x%08lx:%08lx, " */
991 /* "cd->cd_LastOffset=0x%08lx:%08lx," */
992 /* "cd->cd_FirstOffset=%08lx\n", */
993 /* (ULONG) (cd->cd_Offset >> 32), (ULONG) cd->cd_Offset, */
994 /* (ULONG) (cd->cd_LastOffset >> 32), (ULONG) cd->cd_LastOffset, */
995 /* cd->cd_FirstOffsetI ); */
997 ** But what if the next sample is so short that we just
998 ** passed it!? Here is the nice part. CalcSamples
999 ** checks this, and sets cd_Samples to 0 in that case.
1000 ** And the add routines doesn't do anything when asked to
1001 ** mix 0 samples. Assume we have passed a sample with 4
1002 ** samples, and the next one is only 3. CalcSamples
1003 ** returns 0. The (ADDFUNC) call above does not do
1004 ** anything at all, OffsetI is still 4. Now we subtract
1005 ** LastOffsetI, which is 3. Result: We have passed the
1006 ** sample with 1. And guess what? That's in range.
1009 /* Now, let's copy the rest of the cd_Next#? stuff... */
1011 cd
->cd_FreqOK
= cd
->cd_NextFreqOK
;
1012 cd
->cd_SoundOK
= cd
->cd_NextSoundOK
;
1013 cd
->cd_Add
= cd
->cd_NextAdd
;
1014 cd
->cd_DataStart
= cd
->cd_NextDataStart
;
1015 cd
->cd_LastOffset
= cd
->cd_NextLastOffset
;
1016 cd
->cd_ScaleLeft
= cd
->cd_NextScaleLeft
;
1017 cd
->cd_ScaleRight
= cd
->cd_NextScaleRight
;
1018 cd
->cd_AddRoutine
= cd
->cd_NextAddRoutine
;
1019 cd
->cd_VolumeLeft
= cd
->cd_NextVolumeLeft
;
1020 cd
->cd_VolumeRight
= cd
->cd_NextVolumeRight
;
1021 cd
->cd_Type
= cd
->cd_NextType
;
1023 cd
->cd_Samples
= CalcSamples( cd
->cd_Add
,
1028 /* Also update all cd_Delayed#? stuff */
1030 if( !cd
->cd_VolDelayed
)
1032 cd
->cd_DelayedVolumeLeft
= cd
->cd_NextVolumeLeft
;
1033 cd
->cd_DelayedVolumeRight
= cd
->cd_NextVolumeRight
;
1036 if( !cd
->cd_FreqDelayed
)
1038 cd
->cd_DelayedFreqOK
= cd
->cd_NextFreqOK
;
1039 cd
->cd_DelayedAdd
= cd
->cd_NextAdd
;
1042 if( !cd
->cd_SoundDelayed
)
1044 cd
->cd_DelayedSoundOK
= cd
->cd_NextSoundOK
;
1045 cd
->cd_DelayedOffset
= cd
->cd_NextOffset
;
1046 cd
->cd_DelayedFirstOffsetI
= cd
->cd_FirstOffsetI
; // See above
1047 cd
->cd_DelayedLastOffset
= cd
->cd_NextLastOffset
;
1048 cd
->cd_DelayedType
= cd
->cd_NextType
;
1049 cd
->cd_DelayedDataStart
= cd
->cd_NextDataStart
;
1052 if( !cd
->cd_VolDelayed
&& !cd
->cd_SoundDelayed
)
1054 cd
->cd_DelayedScaleLeft
= cd
->cd_NextScaleLeft
;
1055 cd
->cd_DelayedScaleRight
= cd
->cd_NextScaleRight
;
1056 cd
->cd_DelayedAddRoutine
= cd
->cd_NextAddRoutine
;
1059 if( !cd
->cd_FreqDelayed
&& !cd
->cd_SoundDelayed
)
1061 cd
->cd_DelayedSamples
= cd
->cd_Samples
;
1064 cd
->cd_EOS
= TRUE
; // signal End-Of-Sample
1065 continue; // .contchannel (same channel, new sound)
1067 } // FreqOK && SoundOK
1068 break; // .contchannel
1075 if(audioctrl
->ahiac_WetOrDry
== AHIEDM_WET
)
1077 audioctrl
->ahiac_WetOrDry
= AHIEDM_DRY
;
1079 /*** AHIET_DSPECHO ***/
1080 if(audioctrl
->ahiac_EffDSPEchoStruct
!= NULL
)
1082 audioctrl
->ahiac_EffDSPEchoStruct
->ahiecho_Code(
1083 audioctrl
->ahiac_EffDSPEchoStruct
, dst
, audioctrl
);
1086 cd
= audioctrl
->ahiac_DryList
;
1088 if(audioctrl
->ac
.ahiac_Flags
& AHIACF_POSTPROC
)
1090 /*** AHIET_MASTERVOLUME ***/
1092 DoMasterVolume(dst
, audioctrl
);
1095 ** When AHIACB_POSTPROC is set, the dry data shall be placed
1096 ** immediate after the wet data. This is done by modifying the
1100 dst
= (char *) dst
+ audioctrl
->ac
.ahiac_BuffSamples
*
1101 _AHI_SampleFrameSize( audioctrl
->ac
.ahiac_BuffType
, AHIBase
);
1104 continue; /* while(TRUE) */
1108 break; /* while(TRUE) */
1116 /******************************************************************************
1117 ** DoMasterVolume *************************************************************
1118 ******************************************************************************/
1121 ** This function would be better if it was written in assembler,
1122 ** since overflow could then be detected. Instead we reduce the
1123 ** number of bits to 20 and then scale and compare.
1127 DoMasterVolume( void *buffer
,
1128 struct AHIPrivAudioCtrl
*audioctrl
)
1134 cnt
= audioctrl
->ac
.ahiac_BuffSamples
;
1136 switch(audioctrl
->ac
.ahiac_BuffType
)
1156 if( audioctrl
->ac
.ahiac_BuffType
== AHIST_M32S
1157 || audioctrl
->ac
.ahiac_BuffType
== AHIST_S32S
1158 || audioctrl
->ac
.ahiac_BuffType
== AHIST_L7_1
)
1162 vol
= audioctrl
->ahiac_SetMasterVolume
>> 8;
1168 sample
= (*dst
>> 12) * vol
;
1170 if(sample
> (LONG
) 0x07ffffff)
1171 sample
= 0x07ffffff;
1172 else if(sample
< (LONG
) 0xf8000000)
1173 sample
= 0xf8000000;
1175 *dst
++ = sample
<< 4;
1182 vol
= audioctrl
->ahiac_SetMasterVolume
>> 4;
1188 sample
= *dst
* vol
;
1190 if(sample
> (LONG
) 0x07ffffff)
1191 sample
= 0x07ffffff;
1192 else if(sample
< (LONG
) 0xf8000000)
1193 sample
= 0xf8000000;
1195 *dst
++ = sample
>> 12;
1202 /******************************************************************************
1203 ** DoOutputBuffer *************************************************************
1204 ******************************************************************************/
1207 DoOutputBuffer( void *buffer
,
1208 struct AHIPrivAudioCtrl
*audioctrl
)
1210 struct AHIEffOutputBuffer
*ob
;
1212 ob
= audioctrl
->ahiac_EffOutputBufferStruct
;
1216 ob
->ahieob_Buffer
= buffer
;
1217 ob
->ahieob_Length
= audioctrl
->ac
.ahiac_BuffSamples
;
1218 ob
->ahieob_Type
= audioctrl
->ac
.ahiac_BuffType
;
1220 CallHookPkt( ob
->ahieob_Func
,
1227 /******************************************************************************
1228 ** DoChannelInfo **************************************************************
1229 ******************************************************************************/
1232 DoChannelInfo( struct AHIPrivAudioCtrl
*audioctrl
)
1234 struct AHIEffChannelInfo
*ci
;
1235 struct AHIChannelData
*cd
;
1238 ci
= audioctrl
->ahiac_EffChannelInfoStruct
;
1244 cd
= audioctrl
->ahiac_ChannelDatas
;
1245 offsets
= ci
->ahieci_Offset
;
1247 for(i
= ci
->ahieci_Channels
; i
> 0; i
--)
1249 *offsets
++ = cd
->cd_Offset
>> 32;
1253 CallHookPkt( ci
->ahieci_Func
,
1260 /******************************************************************************
1261 ** CalcSamples ****************************************************************
1262 ******************************************************************************/
1265 CalcSamples ( Fixed64 Add
,
1273 if( Type
& AHIST_BW
)
1275 len
= Offset
- LastOffset
;
1279 len
= LastOffset
- Offset
;
1282 if(len
< 0 || Add
== 0) return 0; // Error!
1284 return (LONG
) ( len
/ Add
) + 1;