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 <exec/memory.h>
24 #include <proto/exec.h>
26 #define __NOGLOBALIFACE__
27 #include <proto/ahi.h>
29 #undef __NOGLOBALIFACE__
30 #include <proto/ahi_sub.h>
35 #include "effectinit.h"
41 #define IAHIsub audioctrl->ahiac_IAHIsub
44 /***********************************************
45 ***** NOTE: The mixing routine might execute while we are inside these
47 ***********************************************/
50 /******************************************************************************
51 ** MASTERVOLUME ***************************************************************
52 ******************************************************************************/
55 update_MasterVolume ( struct AHIPrivAudioCtrl
*audioctrl
)
57 struct Library
*AHIsubBase
;
58 struct AHIChannelData
*cd
;
62 /* In V5, clipping is always used:
64 * if(audioctrl->ac.ahiac_Flags & AHIACF_CLIPPING)
70 * volume = audioctrl->ahiac_SetMasterVolume;
76 /* Scale to what the echo effect think is best... */
77 volume
= (volume
* (audioctrl
->ahiac_EchoMasterVolume
>> 8)) >> 8;
79 /* This is the actual master volume in use */
80 audioctrl
->ahiac_MasterVolume
= volume
;
82 /* Update volume for channels */
84 AHIsubBase
= audioctrl
->ahiac_SubLib
;
86 AHIsub_Disable(&audioctrl
->ac
);
88 for(i
= audioctrl
->ac
.ahiac_Channels
, cd
= audioctrl
->ahiac_ChannelDatas
;
92 SelectAddRoutine(cd
->cd_VolumeLeft
, cd
->cd_VolumeRight
, cd
->cd_Type
, audioctrl
,
93 &cd
->cd_ScaleLeft
, &cd
->cd_ScaleRight
, (ADDFUNC
**) &cd
->cd_AddRoutine
);
94 SelectAddRoutine(cd
->cd_NextVolumeLeft
, cd
->cd_NextVolumeRight
, cd
->cd_NextType
, audioctrl
,
95 &cd
->cd_NextScaleLeft
, &cd
->cd_NextScaleRight
, (ADDFUNC
**) &cd
->cd_NextAddRoutine
);
98 AHIsub_Enable(&audioctrl
->ac
);
104 /******************************************************************************
105 ** DSPECHO ********************************************************************
106 ******************************************************************************/
108 #define mode_stereo 1
113 update_DSPEcho ( struct AHIEffDSPEcho
*echo
,
114 struct AHIPrivAudioCtrl
*audioctrl
)
116 ULONG size
, samplesize
;
119 ULONG data_flags
= MEMF_ANY
;
124 data_flags
= MEMF_PUBLIC
| MEMF_CLEAR
;
127 #if defined( ENABLE_WARPUP )
129 // Non-cached from both the PPC and m68k side
130 data_flags
= MEMF_PUBLIC
| MEMF_CLEAR
| MEMF_CHIP
;
135 /* Set up the delay buffer format */
137 switch(audioctrl
->ac
.ahiac_BuffType
)
154 return FALSE
; // Panic
157 size
= samplesize
* (echo
->ahiede_Delay
+ audioctrl
->ac
.ahiac_MaxBuffSamples
);
159 es
= AHIAllocVec( sizeof(struct Echo
) + size
,
166 es
->ahiecho_Offset
= 0;
167 es
->ahiecho_SrcPtr
= es
->ahiecho_Buffer
;
168 es
->ahiecho_DstPtr
= es
->ahiecho_Buffer
+ (samplesize
* echo
->ahiede_Delay
);
169 es
->ahiecho_EndPtr
= es
->ahiecho_Buffer
+ size
;
170 es
->ahiecho_BufferLength
= echo
->ahiede_Delay
+ audioctrl
->ac
.ahiac_MaxBuffSamples
;
171 es
->ahiecho_BufferSize
= size
;
173 switch(audioctrl
->ac
.ahiac_BuffType
)
176 echo
->ahiede_Cross
= 0;
182 echo
->ahiede_Cross
= 0;
186 mode
|= (mode_32bit
| mode_stereo
);
189 mode
|= (mode_32bit
| mode_multi
);
193 es
->ahiecho_Delay
= echo
->ahiede_Delay
;
194 es
->ahiecho_MixD
= echo
->ahiede_Mix
;
195 es
->ahiecho_MixN
= 0x10000 - echo
->ahiede_Mix
;
196 es
->ahiecho_FeedbackDO
= (echo
->ahiede_Feedback
>> 8) *
197 (echo
->ahiede_Cross
>> 8);
198 es
->ahiecho_FeedbackDS
= (echo
->ahiede_Feedback
>> 8) *
199 ((0x10000 - echo
->ahiede_Cross
) >> 8);
200 es
->ahiecho_FeedbackNO
= ((0x10000 - echo
->ahiede_Feedback
) >> 8) *
201 (echo
->ahiede_Cross
>> 8);
202 es
->ahiecho_FeedbackNS
= ((0x10000 - echo
->ahiede_Feedback
) >> 8) *
203 ((0x10000 - echo
->ahiede_Cross
) >> 8);
205 audioctrl
->ahiac_EchoMasterVolume
= 0x10000;
207 update_MasterVolume( audioctrl
);
213 es
->ahiecho_Code
= do_DSPEchoMono16
;
218 es
->ahiecho_Code
= do_DSPEchoStereo16
;
223 es
->ahiecho_Code
= do_DSPEchoMono32
;
228 es
->ahiecho_Code
= do_DSPEchoStereo32
;
231 // multichannel 32 bit
233 es
->ahiecho_Code
= do_DSPEchoMulti32
;
236 // Should not happen!
242 // Structure filled, make it available to the mixing routine
244 audioctrl
->ahiac_EffDSPEchoStruct
= es
;
254 free_DSPEcho ( struct AHIPrivAudioCtrl
*audioctrl
)
256 void *p
= audioctrl
->ahiac_EffDSPEchoStruct
;
258 // Hide it from mixing routine before freeing it!
259 audioctrl
->ahiac_EffDSPEchoStruct
= NULL
;
262 audioctrl
->ahiac_EchoMasterVolume
= 0x10000;
263 update_MasterVolume( audioctrl
);
269 /******************************************************************************
270 ** DSPMASK ********************************************************************
271 ******************************************************************************/
274 addchannel ( struct AHIChannelData
**list
, struct AHIChannelData
*cd
)
276 struct AHIChannelData
*ptr
;
285 while(ptr
->cd_Succ
!= NULL
)
296 update_DSPMask ( struct AHIEffDSPMask
*mask
,
297 struct AHIPrivAudioCtrl
*audioctrl
)
299 struct AHIChannelData
*cd
, *wet
= NULL
, *dry
= NULL
;
300 struct Library
*AHIsubBase
;
304 if(mask
->ahiedm_Channels
!= audioctrl
->ac
.ahiac_Channels
)
309 cd
= audioctrl
->ahiac_ChannelDatas
;
311 flag
= mask
->ahiedm_Mask
;
313 AHIsubBase
= audioctrl
->ahiac_SubLib
;
315 AHIsub_Disable(&audioctrl
->ac
);
317 for(i
= 0; i
< audioctrl
->ac
.ahiac_Channels
; i
++)
319 if(*flag
== AHIEDM_WET
)
321 addchannel(&wet
, cd
);
325 addchannel(&dry
, cd
);
332 audioctrl
->ahiac_WetList
= wet
;
333 audioctrl
->ahiac_DryList
= dry
;
335 AHIsub_Enable(&audioctrl
->ac
);
342 clear_DSPMask ( struct AHIPrivAudioCtrl
*audioctrl
)
344 struct AHIChannelData
*cd
;
345 struct Library
*AHIsubBase
;
348 // Make all channels wet
350 cd
= audioctrl
->ahiac_ChannelDatas
;
352 audioctrl
->ahiac_WetList
= cd
;
353 audioctrl
->ahiac_DryList
= NULL
;
355 AHIsubBase
= audioctrl
->ahiac_SubLib
;
357 AHIsub_Disable(&audioctrl
->ac
);
359 for(i
= 0; i
< audioctrl
->ac
.ahiac_Channels
- 1; i
++)
361 // Set link to next channel
362 cd
->cd_Succ
= cd
+ 1;
366 // Clear the last link;
369 AHIsub_Enable(&audioctrl
->ac
);