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 <utility/tagitem.h>
25 #include <proto/exec.h>
26 #include <proto/utility.h>
28 #define __NOGLOBALIFACE__
29 #include <proto/ahi.h>
31 #undef __NOGLOBALIFACE__
32 #include <proto/ahi_sub.h>
37 #include "effectinit.h"
41 #define IAHIsub audioctrl->ahiac_IAHIsub
44 /******************************************************************************
45 ** AHI_SetVol *****************************************************************
46 ******************************************************************************/
48 /***** ahi.device/AHI_SetVol ***********************************************
51 * AHI_SetVol -- set volume and stereo panning for a channel
54 * AHI_SetVol( channel, volume, pan, audioctrl, flags );
57 * void AHI_SetVol( UWORD, Fixed, sposition, struct AHIAudioCtrl *,
61 * Changes the volume and stereo panning for a channel.
64 * channel - The channel to set volume for.
65 * volume - The desired volume. Fixed is a LONG fixed-point value with
66 * 16 bits to the left of the point and 16 to the right
67 * (typedef LONG Fixed; from IFF-8SVX docs).
68 * Maximum volume is 1.0 (0x10000L) and 0.0 (0x0L) will turn off
69 * this channel. Note: The sound will continue to play, but you
70 * wont hear it. To stop a sound completely, use AHI_SetSound().
71 * Starting with V4 volume can also be negative, which tells AHI
72 * to invert the samples before playing. Note that all drivers
73 * may not be able to handle negative volume. In that case the
74 * absolute volume will be used.
75 * pan - The desired panning. sposition is the same as Fixed
76 * (typedef Fixed sposition; from IFF-8SVX.PAN docs).
77 * 1.0 (0x10000L) means that the sound is panned all the way to
78 * the right, 0.5 (0x8000L) means the sound is centered and 0.0
79 * (0x0L) means that the sound is panned all the way to the left.
80 * Try to set Pan to the 'correct' value even if you know it has no
81 * effect. For example, if you know you use a mono mode, set pan to
82 * 0.5 even if it does not matter.
83 * Starting with V4 pan can also be negative, which tells AHI to
84 * use the surround speaker for this channel. Note that all drivers
85 * may not be able to handle negative pan. In that case the absolute
87 * audioctrl - A pointer to an AHIAudioCtrl structure.
88 * flags - Only one flag is defined
89 * AHISF_IMM - Set this flag if this command should take effect
90 * immediately. If this bit is not set, the command will not
91 * take effect until the current sound is finished. MUST NOT
92 * be set if called from a SoundFunc. See the programming
93 * guidelines for more information about this flag.
100 * It is safe to call this function from an interrupt.
102 * Negative volume or negative pan may use more CPU time than positive.
104 * Using both negative volume and negative pan will play the inverted
105 * sound on the surround speaker.
110 * AHI_SetEffect(), AHI_SetFreq(), AHI_SetSound(), AHI_LoadSound()
113 ****************************************************************************
118 _AHI_SetVol ( UWORD channel
,
121 struct AHIPrivAudioCtrl
* audioctrl
,
123 struct AHIBase
* AHIBase
)
125 struct AHIChannelData
*cd
;
126 struct Library
*AHIsubBase
;
129 if(AHIBase
->ahib_DebugLevel
>= AHI_DEBUG_ALL
)
131 Debug_SetVol(channel
, volume
, pan
, audioctrl
, flags
);
134 AHIsubBase
= audioctrl
->ahiac_SubLib
;
136 rc
= AHIsub_SetVol(channel
, volume
, pan
, &audioctrl
->ac
, flags
);
138 if(audioctrl
->ac
.ahiac_Flags
& AHIACF_NOMIXING
139 || rc
!= AHIS_UNKNOWN
)
141 return 0; /* We're done! */
144 cd
= &audioctrl
->ahiac_ChannelDatas
[channel
];
146 if((audioctrl
->ac
.ahiac_Flags
& AHIACF_VOL
) == 0)
148 volume
= volume
& 0x10000; /* |volume|=0 or 0x10000 */
151 if((audioctrl
->ac
.ahiac_Flags
& AHIACF_PAN
) == 0)
153 pan
= (channel
& 1) << 16; /* pan = 0 or 0x10000 */
156 AHIsub_Disable(&audioctrl
->ac
);
158 cd
->cd_NextVolumeLeft
= ((volume
>> 1) * ((0x10000 - abs(pan
)) >> 1)) >> (16 - 2);
159 cd
->cd_NextVolumeRight
= ((volume
>> 1) * (pan
>> 1)) >> (16 - 2);
161 SelectAddRoutine( cd
->cd_NextVolumeLeft
,
162 cd
->cd_NextVolumeRight
,
165 &cd
->cd_NextScaleLeft
,
166 &cd
->cd_NextScaleRight
,
167 (ADDFUNC
**) &cd
->cd_NextAddRoutine
);
169 if(flags
& AHISF_IMM
)
171 cd
->cd_DelayedVolumeLeft
= cd
->cd_NextVolumeLeft
;
172 cd
->cd_DelayedVolumeRight
= cd
->cd_NextVolumeRight
;
174 SelectAddRoutine( cd
->cd_DelayedVolumeLeft
,
175 cd
->cd_DelayedVolumeRight
,
178 &cd
->cd_DelayedScaleLeft
,
179 &cd
->cd_DelayedScaleRight
,
180 (ADDFUNC
**) &cd
->cd_DelayedAddRoutine
);
182 /* Enable anti-click routine */
183 cd
->cd_AntiClickCount
= audioctrl
->ac
.ahiac_AntiClickSamples
;
185 if( ( flags
& AHISF_NODELAY
) ||
186 ( cd
->cd_AntiClickCount
== 0 ) ||
187 !cd
->cd_FreqOK
|| !cd
->cd_SoundOK
)
189 cd
->cd_VolumeLeft
= cd
->cd_DelayedVolumeLeft
;
190 cd
->cd_VolumeRight
= cd
->cd_DelayedVolumeRight
;
191 cd
->cd_ScaleLeft
= cd
->cd_DelayedScaleLeft
;
192 cd
->cd_ScaleRight
= cd
->cd_DelayedScaleRight
;
193 cd
->cd_AddRoutine
= cd
->cd_DelayedAddRoutine
;
195 cd
->cd_AntiClickCount
= 0;
199 cd
->cd_VolDelayed
= TRUE
;
203 AHIsub_Enable(&audioctrl
->ac
);
209 /******************************************************************************
210 ** AHI_SetFreq ****************************************************************
211 ******************************************************************************/
213 /***** ahi.device/AHI_SetFreq **********************************************
216 * AHI_SetFreq -- set frequency for a channel
219 * AHI_SetFreq( channel, freq, audioctrl, flags );
222 * void AHI_SetFreq( UWORD, ULONG, struct AHIAudioCtrl *, ULONG );
225 * Sets the playback frequency for a channel.
228 * channel - The channel to set playback frequency for.
229 * freq - The playback frequency in Hertz. Can also be AHI_MIXFREQ,
230 * which is the current mixing frequency, or 0 to temporary stop
231 * the sound (it will restart at the same point when its frequency
233 * audioctrl - A pointer to an AHIAudioCtrl structure.
234 * flags - Only one flag is defined
235 * AHISF_IMM - Set this flag if this command should take effect
236 * immediately. If this bit is not set, the command will not
237 * take effect until the current sound is finished. MUST NOT
238 * be set if called from a SoundFunc. See the programming
239 * guidelines for more information about this flag.
246 * It is safe to call this function from an interrupt.
251 * AHI_SetEffect(), AHI_SetSound(), AHI_SetVol(), AHI_LoadSound()
253 ****************************************************************************
258 _AHI_SetFreq ( UWORD channel
,
260 struct AHIPrivAudioCtrl
* audioctrl
,
262 struct AHIBase
* AHIBase
)
264 struct AHIChannelData
*cd
;
265 struct Library
*AHIsubBase
;
269 if(AHIBase
->ahib_DebugLevel
>= AHI_DEBUG_ALL
)
271 Debug_SetFreq(channel
, freq
, audioctrl
, flags
);
274 AHIsubBase
= audioctrl
->ahiac_SubLib
;
276 rc
= AHIsub_SetFreq(channel
, freq
, &audioctrl
->ac
, flags
);
278 if(audioctrl
->ac
.ahiac_Flags
& AHIACF_NOMIXING
279 || rc
!= AHIS_UNKNOWN
)
281 return 0; /* We're done! */
284 cd
= &audioctrl
->ahiac_ChannelDatas
[channel
];
288 cd
->cd_NextFreqOK
= FALSE
;
294 cd
->cd_NextFreqOK
= TRUE
;
296 if(freq
== AHI_MIXFREQ
)
310 add
= ((freq
<< 16) / audioctrl
->ac
.ahiac_MixFreq
) << shift
;
314 AHIsub_Disable(&audioctrl
->ac
);
316 cd
->cd_NextAdd
= (Fixed64
) add
<< 16;
318 if(flags
& AHISF_IMM
)
320 cd
->cd_DelayedAdd
= cd
->cd_NextAdd
;
321 cd
->cd_DelayedFreqOK
= cd
->cd_NextFreqOK
;
323 // cd->cd_Samples is also calculated when it actually happens¹...
325 cd
->cd_DelayedSamples
= CalcSamples( cd
->cd_DelayedAdd
,
327 cd
->cd_DelayedLastOffset
,
328 cd
->cd_DelayedOffset
);
330 /* Enable anti-click routine */
331 cd
->cd_AntiClickCount
= audioctrl
->ac
.ahiac_AntiClickSamples
;
333 if( ( flags
& AHISF_NODELAY
) ||
334 ( cd
->cd_AntiClickCount
== 0 ) ||
335 !cd
->cd_FreqOK
|| !cd
->cd_SoundOK
)
337 cd
->cd_Add
= cd
->cd_DelayedAdd
;
338 cd
->cd_FreqOK
= cd
->cd_DelayedFreqOK
;
340 // ¹) Unless we're not using any delay, in which case it's recalculated
343 cd
->cd_Samples
= CalcSamples( cd
->cd_Add
,
348 cd
->cd_AntiClickCount
= 0;
352 cd
->cd_FreqDelayed
= TRUE
;
356 AHIsub_Enable(&audioctrl
->ac
);
362 /******************************************************************************
363 ** AHI_SetSound ***************************************************************
364 ******************************************************************************/
366 /***** ahi.device/AHI_SetSound *********************************************
369 * AHI_SetSound -- set what sound to play for a channel
372 * AHI_SetSound( channel, sound, offset, length, audioctrl, flags );
373 * D0:16 D1:16 D2 D3 A2 D4
375 * void AHI_SetSound( UWORD, UWORD, ULONG, LONG,
376 * struct AHIAudioCtrl *, ULONG );
379 * Sets a sound to be played on a channel.
382 * channel - The channel to set sound for.
383 * sound - Sound to be played, or AHI_NOSOUND to turn the channel off.
384 * offset - Only available if the sound type is AHIST_SAMPLE or
385 * AHIST_DYNAMICSAMPLE. Must be 0 otherwise.
386 * Specifies an offset (in samples) where the playback will begin.
387 * If you wish to play the whole sound, set offset to 0.
388 * length - Only available if the sound type is AHIST_SAMPLE or
389 * AHIST_DYNAMICSAMPLE. Must be 0 otherwise.
390 * Specifies how many samples that should be played. If you
391 * wish to play the whole sound forwards, set offset to 0 and length
392 * to either 0 or the length of the sample array. You may not set
393 * length to 0 if offset is not 0! To play a sound backwards, just
394 * set length to a negative number.
395 * audioctrl - A pointer to an AHIAudioCtrl structure.
396 * flags - Only one flag is defined
397 * AHISF_IMM - Set this flag if this command should take effect
398 * immediately. If this bit is not set, the command will not
399 * take effect until the current sound is finished. MUST NOT
400 * be set if called from a SoundFunc. See the programming
401 * guidelines for more information about this flag.
408 * It is safe to call this function from an interrupt.
410 * If offset or length is not zero, make sure you do not exceed the
416 * AHI_SetEffect(), AHI_SetFreq(), AHI_SetVol(), AHI_LoadSound()
418 ****************************************************************************
423 _AHI_SetSound ( UWORD channel
,
427 struct AHIPrivAudioCtrl
* audioctrl
,
429 struct AHIBase
* AHIBase
)
431 struct AHIChannelData
*cd
;
432 struct AHISoundData
*sd
;
433 struct Library
*AHIsubBase
;
436 if(AHIBase
->ahib_DebugLevel
>= AHI_DEBUG_ALL
)
438 Debug_SetSound(channel
, sound
, offset
, length
, audioctrl
, flags
);
441 AHIsubBase
= audioctrl
->ahiac_SubLib
;
443 rc
= AHIsub_SetSound(channel
, sound
, offset
, length
, &audioctrl
->ac
, flags
);
445 if(audioctrl
->ac
.ahiac_Flags
& AHIACF_NOMIXING
446 || rc
!= AHIS_UNKNOWN
)
448 return 0; /* We're done! */
451 cd
= &audioctrl
->ahiac_ChannelDatas
[channel
];
452 sd
= &audioctrl
->ahiac_SoundDatas
[sound
];
454 AHIsub_Disable(&audioctrl
->ac
);
456 if(sound
== AHI_NOSOUND
)
458 cd
->cd_NextSoundOK
= FALSE
;
460 if(flags
& AHISF_IMM
)
462 cd
->cd_EOS
= TRUE
; /* Signal End-Of-Sample */
463 cd
->cd_SoundOK
= FALSE
;
466 else if(sd
->sd_Type
!= AHIST_NOTYPE
) /* This is a user error, shouldn't happen! */
468 if(length
== 0) length
= sd
->sd_Length
;
470 cd
->cd_NextDataStart
= sd
->sd_Addr
;
471 cd
->cd_NextType
= sd
->sd_Type
;
472 cd
->cd_NextOffset
= (Fixed64
) offset
<< 32 ;
474 cd
->cd_NextSoundOK
= TRUE
;
478 cd
->cd_NextType
|= AHIST_BW
;
479 cd
->cd_NextLastOffset
= (Fixed64
) ( offset
+ length
+ 1 ) << 32;
480 // cd->cd_NextOffset |= 0xffffffffLL;
481 *(ULONG
*) ((char*) (&cd
->cd_NextOffset
)+4) = 0xffffffffUL
;
485 #if !defined( __mc68000__ )
486 cd
->cd_NextLastOffset
= ( (Fixed64
) ( offset
+ length
- 1 ) << 32 )
487 | (Fixed64
) 0xffffffffLL
;
489 // Fix for m68k compiler bug! :-(
490 *(ULONG
*) &cd
->cd_NextLastOffset
= offset
+ length
- 1;
491 *(ULONG
*) ((char*) (&cd
->cd_NextLastOffset
)+4) = 0xffffffffUL
;
494 /* Low cd->cd_NextOffset already 0 */
497 SelectAddRoutine( cd
->cd_NextVolumeLeft
,
498 cd
->cd_NextVolumeRight
,
501 &cd
->cd_NextScaleLeft
,
502 &cd
->cd_NextScaleRight
,
503 (ADDFUNC
**) &cd
->cd_NextAddRoutine
);
505 if(flags
& AHISF_IMM
)
507 cd
->cd_DelayedOffset
= cd
->cd_NextOffset
;
508 cd
->cd_DelayedFirstOffsetI
= cd
->cd_NextOffset
>> 32; /* for linear interpol. */
509 cd
->cd_DelayedLastOffset
= cd
->cd_NextLastOffset
;
510 cd
->cd_DelayedDataStart
= cd
->cd_NextDataStart
;
511 cd
->cd_DelayedType
= cd
->cd_NextType
;
512 cd
->cd_DelayedSoundOK
= cd
->cd_NextSoundOK
;
514 SelectAddRoutine( cd
->cd_DelayedVolumeLeft
,
515 cd
->cd_DelayedVolumeRight
,
518 &cd
->cd_DelayedScaleLeft
,
519 &cd
->cd_DelayedScaleRight
,
520 (ADDFUNC
**) &cd
->cd_DelayedAddRoutine
);
522 cd
->cd_DelayedSamples
= CalcSamples( cd
->cd_DelayedAdd
,
524 cd
->cd_DelayedLastOffset
,
525 cd
->cd_DelayedOffset
);
527 /* Enable anti-click routine */
528 cd
->cd_AntiClickCount
= audioctrl
->ac
.ahiac_AntiClickSamples
;
530 if( ( flags
& AHISF_NODELAY
) ||
531 ( cd
->cd_AntiClickCount
== 0 ) ||
532 !cd
->cd_FreqOK
|| !cd
->cd_SoundOK
)
534 cd
->cd_StartPointL
= 0;
535 cd
->cd_StartPointR
= 0;
537 cd
->cd_Offset
= cd
->cd_DelayedOffset
;
538 cd
->cd_FirstOffsetI
= cd
->cd_DelayedFirstOffsetI
;
539 cd
->cd_LastOffset
= cd
->cd_DelayedLastOffset
;
540 cd
->cd_DataStart
= cd
->cd_DelayedDataStart
;
541 cd
->cd_Type
= cd
->cd_DelayedType
;
542 cd
->cd_SoundOK
= cd
->cd_DelayedSoundOK
;
543 cd
->cd_ScaleLeft
= cd
->cd_DelayedScaleLeft
;
544 cd
->cd_ScaleRight
= cd
->cd_DelayedScaleRight
;
545 cd
->cd_AddRoutine
= cd
->cd_DelayedAddRoutine
;
546 cd
->cd_Samples
= cd
->cd_DelayedSamples
;
547 cd
->cd_AntiClickCount
= 0;
551 cd
->cd_SoundDelayed
= TRUE
;
554 cd
->cd_EOS
= TRUE
; /* Signal End-Of-Sample */
558 AHIsub_Enable(&audioctrl
->ac
);
564 /******************************************************************************
565 ** AHI_SetEffect **************************************************************
566 ******************************************************************************/
568 /***** ahi.device/AHI_SetEffect ********************************************
571 * AHI_SetEffect -- set effect
574 * error = AHI_SetEffect( effect, audioctrl );
577 * ULONG AHI_SetEffect( APTR, struct AHIAudioCtrl * );
580 * Selects an effect to be used, described by a structure.
583 * effect - A pointer to an effect data structure, as defined in
584 * <devices/ahi.h>. The following effects are defined:
585 * AHIET_MASTERVOLUME - Changes the volume for all channels. Can
586 * also be used to boost volume over 100%.
587 * AHIET_OUTPUTBUFFER - Gives READ-ONLY access to the mixed output.
588 * Can be used to show nice scopes and VU-meters.
589 * AHIET_DSPMASK - Select which channels will be affected by the
591 * AHIET_DSPECHO - A DSP effects that adds (cross-)echo and delay.
593 * AHIET_CHANNELINFO - Get info about all channels. (V4)
594 * audioctrl - A pointer to an AHIAudioCtrl structure.
597 * AHIET_MASTERVOLUME - Effect is a struct AHIEffMasterVolume, with
598 * ahiemv_Volume set to the desired volume. The range is 0 to
599 * (channels/hardware channel). Assume you have 4 channels in
600 * mono mode. The range is then 0.0 to 4.0. The range is the same
601 * if the mode is stereo with panning. However, assume you have 4
602 * channels with a stereo mode *without* panning. Then you have two
603 * channels to the left and two to the right => range is 0.0 - 2.0.
604 * Setting the volume outside the range will give an unpredictable
607 * AHIET_OUTPUTBUFFER - Effect is a struct AHIEffOutputBuffer, with
608 * ahieob_Func pointing to a hook that will be called with the
609 * following parameters:
610 * A0 - (struct Hook *)
611 * A2 - (struct AHIAudioCtrl *)
612 * A1 - (struct AHIEffOutputBuffer *)
613 * The information you are looking for then is in ahieob_Type,
614 * ahieob_Buffer and ahieob_Length. Always check ahieob_Type!
615 * ahieob_Length is neither in bytes nor samples, but sample frames.
617 * AHIET_DSPMASK - Effect is a struct AHIEffDSPMask, where ahiedm_Mask
618 * is an array with ahiedm_Channels elements. Each UBYTE in the
619 * array can either make the channel 'wet' (affected by the DSP
620 * effects), by using the AHIEDM_WET constant or 'dry' (not
621 * affected by the DSP effects) by using the AHIEDM_DRY constant.
622 * The default is all channels wet. If ahiedm_Channels does not
623 * equal the current number of channels allocated, the result of
624 * this call is undefined (crash warning!). (V4)
626 * AHIET_DSPECHO - Effect is a struct AHIEffDSPEcho.
627 * ahiede_Delay is the delay in samples (and thus depends on the
630 * ahiede_Feedback is a Fixed value between 0 and 1.0, and defines
631 * how much of the delayed signal should be feed back to the delay
632 * stage. Setting this to 0 gives a delay effect, otherwise echo.
634 * ahiede_Mix tells how much of the delayed signal should be mixed
635 * with the normal signal. Setting this to 0 disables delay/echo,
636 * and setting it to 1.0 outputs only the delay/echo signal.
638 * ahiede_Cross only has effect of the current playback mode is
639 * stereo. It tells how the delayed signal should be panned to
640 * the other channel. 0 means no cross echo, 1.0 means full
643 * If the user has enabled "Fast Echo", AHI may take several short-
644 * cuts to increase the performance. This could include rounding the
645 * parameters to a power of two, or even to the extremes.
647 * If you set ahiede_Mix to 0x10000 and ahiede_Cross to 0x0, much
648 * faster mixing routines will be used, and "Fast Echo" will improve
651 * Otherwise, even with "Fast Echo" turned on, this effect will
652 * probably suck some major CPU cycles on most sound hardware. (V4)
654 * AHIET_CHANNELINFO - Effect is a struct AHIEffChannelInfo, where
655 * ahieci_Func is pointing to a hook that will be called with the
656 * following parameters:
657 * A0 - (struct Hook *)
658 * A2 - (struct AHIAudioCtrl *)
659 * A1 - (struct AHIEffChannelInfo *)
660 * ahieci_Channels must equal the current number of channels used.
661 * ahieci_Offset is an array of ULONGs, which will be filled by
662 * AHI before the hook is called (the offset is specified in sample
663 * frames). The array must have at least ahieci_Channels elements.
665 * This "effect" can be used to find out how far each channel has
666 * played. You must probably keep track of the other parameters
667 * yourself (like which sound is playing, it's volume, balance and
668 * frequency etc) in order have meaningful usage of the information.
672 * NOTE! To turn off an effect, call again with ahie_Effect OR:ed
673 * with AHIET_CANCEL. For example, it is NOT correct to disable
674 * the AHIET_MASTERVOLUME effect by setting ahiemv_Volume to 1.0!
676 * It is important that you always turn off effects before you
677 * deallocate the audio hardware. Otherwise memory may be lost.
678 * It is safe to turn off an effect that has never been turned on
679 * in the first place.
681 * Never count on that an effect will be available. For example,
682 * AHIET_OUTPUTBUFFER is impossible to implement with some sound
686 * An error code, defined in <devices/ahi.h>.
691 * Unlike the other functions whose names begin with "AHI_Set", this
692 * function may NOT be called from an interrupt (or AHI Hook).
694 * Previous to V4, this call always returned AHIE_OK.
697 * The idea of updating the source structure instead of allocating
698 * a new one that is passed the hook it pretty flawed. The reason is
699 * that AHI_SetEffect() originally could be called from interrupts,
700 * and memory allocation is not allowed from within interrupts.
703 * AHI_SetFreq(), AHI_SetSound(), AHI_SetVol(), AHI_LoadSound(),
706 ****************************************************************************
712 _AHI_SetEffect( ULONG
* effect
,
713 struct AHIPrivAudioCtrl
* audioctrl
,
714 struct AHIBase
* AHIBase
)
716 struct Library
*AHIsubBase
;
719 if(AHIBase
->ahib_DebugLevel
>= AHI_DEBUG_ALL
)
721 Debug_SetEffect(effect
, audioctrl
);
724 AHIsubBase
= audioctrl
->ahiac_SubLib
;
726 rc
= AHIsub_SetEffect(effect
, &audioctrl
->ac
);
728 if(audioctrl
->ac
.ahiac_Flags
& AHIACF_NOMIXING
729 || rc
!= AHIS_UNKNOWN
)
731 return rc
; /* We're done! */
742 case AHIET_MASTERVOLUME
:
744 struct AHIEffMasterVolume
*emv
= (struct AHIEffMasterVolume
*) effect
;
746 if(audioctrl
->ahiac_SetMasterVolume
!= emv
->ahiemv_Volume
)
748 audioctrl
->ahiac_SetMasterVolume
= emv
->ahiemv_Volume
;
749 rc
= update_MasterVolume( audioctrl
);
754 case AHIET_MASTERVOLUME
|AHIET_CANCEL
:
756 if(audioctrl
->ahiac_SetMasterVolume
!= 0x10000)
758 audioctrl
->ahiac_SetMasterVolume
= 0x10000;
759 rc
= update_MasterVolume( audioctrl
);
767 case AHIET_OUTPUTBUFFER
:
768 audioctrl
->ahiac_EffOutputBufferStruct
= (struct AHIEffOutputBuffer
*) effect
;
772 case AHIET_OUTPUTBUFFER
|AHIET_CANCEL
:
773 audioctrl
->ahiac_EffOutputBufferStruct
= NULL
;
783 rc
= update_DSPMask( (struct AHIEffDSPMask
*) effect
, audioctrl
);
786 case AHIET_DSPMASK
|AHIET_CANCEL
:
787 clear_DSPMask( audioctrl
);
797 rc
= update_DSPEcho( (struct AHIEffDSPEcho
*) effect
, audioctrl
);
800 case AHIET_DSPECHO
|AHIET_CANCEL
:
801 free_DSPEcho( audioctrl
);
810 case AHIET_CHANNELINFO
:
811 audioctrl
->ahiac_EffChannelInfoStruct
= (struct AHIEffChannelInfo
*) effect
;
815 case AHIET_CHANNELINFO
|AHIET_CANCEL
:
816 audioctrl
->ahiac_EffChannelInfoStruct
= NULL
;
825 /******************************************************************************
826 ** AHI_LoadSound **************************************************************
827 ******************************************************************************/
829 /****** ahi.device/AHI_LoadSound ********************************************
832 * AHI_LoadSound -- prepare a sound for playback
835 * error = AHI_LoadSound( sound, type, info, audioctrl );
838 * ULONG AHI_LoadSound( UWORD, ULONG, APTR, struct AHIAudioCtrl * );
841 * Defines an ID number for the sound and prepares it for playback.
844 * sound - The numeric ID to be used as a reference to this sound.
845 * The ID is a number greater or equal to 0 and less than what you
846 * specified with AHIA_Sounds when you called AHI_AllocAudioA().
847 * type - The type of the sound. Currently four types are supported:
848 * AHIST_SAMPLE - array of 8 or 16 bit samples. Note that the
849 * portion of memory where the sample is stored must NOT be
850 * altered until AHI_UnloadSound() has been called! This is
851 * because some audio drivers may wish to upload the samples
852 * to local RAM. It is OK to read, though.
854 * AHIST_DYNAMICSAMPLE - array of 8 or 16 bit samples, which can be
855 * updated dynamically. Typically used to play data that is
856 * loaded from disk or calculated realtime.
857 * Avoid using this sound type as much as possible; it will
858 * use much more CPU power than AHIST_SAMPLE on a DMA/DSP
861 * info - Depends on type:
862 * AHIST_SAMPLE - A pointer to a struct AHISampleInfo, filled with:
863 * ahisi_Type - Format of samples (four formats are supported).
864 * AHIST_M8S: Mono, 8 bit signed (BYTEs).
865 * AHIST_S8S: Stereo, 8 bit signed (2×BYTEs) (V4).
866 * AHIST_M16S: Mono, 16 bit signed (WORDs).
867 * AHIST_S16S: Stereo, 16 bit signed (2×WORDs) (V4).
868 * AHIST_M32S: Mono, 32 bit signed (LONGs). (V6)
869 * AHIST_S32S: Stereo, 32 bit signed (2×LONGs) (V6).
870 * AHIST_L7_1: 7.1, 32 bit signed (8×LONGs) (V6).
871 * ahisi_Address - Address to the sample array.
872 * ahisi_Length - The size of the array, in samples.
873 * Don't even think of setting ahisi_Address to 0 and
874 * ahisi_Length to 0xffffffff as you can do with
875 * AHIST_DYNAMICSAMPLE! Very few DMA/DSP cards have 4 GB onboard
878 * AHIST_DYNAMICSAMPLE A pointer to a struct AHISampleInfo, filled
879 * as described above (AHIST_SAMPLE).
880 * If ahisi_Address is 0 and ahisi_Length is 0xffffffff
881 * AHI_SetSound() can take the real address of an 8 bit sample
882 * to be played as offset argument. Unfortunately, this does not
883 * work for 16 bit samples.
885 * audioctrl - A pointer to an AHIAudioCtrl structure.
888 * An error code, defined in <devices/ahi.h>.
893 * There is no need to place a sample array in Chip memory, but it
894 * MUST NOT be swapped out! Allocate your sample memory with the
895 * MEMF_PUBLIC flag set.
898 * AHIST_L7_1 can only be played using 7.1 audio modes -- it will NOT
899 * be downmixed! It can't be played backwards either.
902 * AHI_UnloadSound(), AHI_SetEffect(), AHI_SetFreq(), AHI_SetSound(),
903 * AHI_SetVol(), <devices/ahi.h>
905 ****************************************************************************
910 _AHI_LoadSound( UWORD sound
,
913 struct AHIPrivAudioCtrl
* audioctrl
,
914 struct AHIBase
* AHIBase
)
917 struct Library
*AHIsubBase
;
920 if(AHIBase
->ahib_DebugLevel
>= AHI_DEBUG_LOW
)
922 Debug_LoadSound(sound
, type
, info
, audioctrl
);
925 AHIsubBase
= audioctrl
->ahiac_SubLib
;
927 rc
= AHIsub_LoadSound(sound
, type
, info
, (struct AHIAudioCtrlDrv
*) audioctrl
);
929 if((audioctrl
->ac
.ahiac_Flags
& AHIACF_NOMIXING
) || (rc
!= AHIS_UNKNOWN
))
938 case AHIST_DYNAMICSAMPLE
:
941 struct AHISampleInfo
*si
= (struct AHISampleInfo
*) info
;
943 switch(si
->ahisi_Type
)
946 if( (audioctrl
->ac
.ahiac_Flags
& AHIACF_HIFI
) == 0 )
948 rc
= AHIE_BADSAMPLETYPE
;
962 /* AHI_FreeAudio() will deallocate... */
964 audioctrl
->ahiac_SoundDatas
[sound
].sd_Type
= si
->ahisi_Type
;
965 audioctrl
->ahiac_SoundDatas
[sound
].sd_Addr
= si
->ahisi_Address
;
966 audioctrl
->ahiac_SoundDatas
[sound
].sd_Length
= si
->ahisi_Length
;
970 rc
= AHIE_BADSAMPLETYPE
;
978 rc
= AHIE_BADSOUNDTYPE
;
982 if(AHIBase
->ahib_DebugLevel
>= AHI_DEBUG_LOW
)
984 KPrintF("=>%ld\n", rc
);
990 /******************************************************************************
991 ** AHI_UnloadSound ************************************************************
992 ******************************************************************************/
994 /****** ahi.device/AHI_UnloadSound *****************************************
997 * AHI_UnloadSound -- discard a sound
1000 * AHI_UnloadSound( sound, audioctrl );
1003 * void AHI_UnloadSound( UWORD, struct AHIAudioCtrl * );
1006 * Tells 'ahi.device' that this sound will not be used anymore.
1009 * sound - The ID of the sound to unload.
1010 * audioctrl - A pointer to an AHIAudioCtrl structure.
1017 * This call will not break a Forbid() state.
1024 ****************************************************************************
1029 _AHI_UnloadSound( UWORD sound
,
1030 struct AHIPrivAudioCtrl
* audioctrl
,
1031 struct AHIBase
* AHIBase
)
1033 struct Library
*AHIsubBase
;
1036 if(AHIBase
->ahib_DebugLevel
>= AHI_DEBUG_LOW
)
1038 Debug_UnloadSound(sound
, audioctrl
);
1041 AHIsubBase
= audioctrl
->ahiac_SubLib
;
1043 rc
= AHIsub_UnloadSound(sound
, (struct AHIAudioCtrlDrv
*) audioctrl
);
1045 if((audioctrl
->ac
.ahiac_Flags
& AHIACF_NOMIXING
) || (rc
!= AHIS_UNKNOWN
))
1050 audioctrl
->ahiac_SoundDatas
[sound
].sd_Type
= AHIST_NOTYPE
;
1056 /******************************************************************************
1057 ** AHI_PlayA ******************************************************************
1058 ******************************************************************************/
1060 /****** ahi.device/AHI_PlayA ************************************************
1063 * AHI_PlayA -- Start multiple sounds in one call (V4)
1064 * AHI_Play -- varargs stub for AHI_PlayA()
1067 * AHI_PlayA( audioctrl, tags );
1070 * void AHI_PlayA( struct AHIAudioCtrl *, struct TagItem * );
1072 * AHI_Play( AudioCtrl, tag1, ...);
1074 * void AHI_Play( struct AHIAudioCtrl *, Tag, ... );
1077 * This function performs the same actions as multiple calls to
1078 * AHI_SetFreq(), AHI_SetSound() and AHI_SetVol(). The advantages
1079 * of using only one call is that simple loops can be set without
1080 * using a SoundFunc (see AHI_AllocAudioA(), tag AHIA_SoundFunc) and
1081 * that sounds on different channels can be synchronized even when the
1082 * sounds are not started from a PlayerFunc (see AHI_AllocAudioA(), tag
1083 * AHIA_PlayerFunc). The disadvantage is that this call has more
1084 * overhead than AHI_SetFreq(), AHI_SetSound() and AHI_SetVol(). It is
1085 * therefore recommended that you only use this call if you are not
1086 * calling from a SoundFunc or PlayerFunc.
1088 * The supplied tag list works like a 'program'. This means that
1089 * the order of tags matter.
1092 * audioctrl - A pointer to an AHIAudioCtrl structure.
1093 * tags - A pointer to a tag list.
1096 * AHIP_BeginChannel (UWORD) - Before you start setting attributes
1097 * for a sound to play, you have to use this tag to chose a
1098 * channel to operate on. If AHIP_BeginChannel is omitted, the
1099 * result is undefined.
1101 * AHIP_EndChannel (ULONG) - Signals the end of attributes for
1102 * the current channel. If AHIP_EndChannel is omitted, the result
1103 * is undefined. ti_Data MUST BE NULL!
1105 * AHIP_Freq (ULONG) - The playback frequency in Hertz or AHI_MIXFREQ.
1107 * AHIP_Vol (Fixed) - The desired volume. If omitted, but AHIP_Pan is
1108 * present, AHIP_Vol defaults to 0.
1110 * AHIP_Pan (sposition) - The desired panning. If omitted, but AHIP_Vol
1111 * is present, AHIP_Pan defaults to 0 (extreme left).
1113 * AHIP_Sound (UWORD) - Sound to be played, or AHI_NOSOUND.
1115 * AHIP_Offset (ULONG) - Specifies an offset (in samples) into the
1116 * sound. If this tag is present, AHIP_Length MUST be present too!
1118 * AHIP_Length (LONG) - Specifies how many samples that should be
1121 * AHIP_LoopFreq (ULONG)
1122 * AHIP_LoopVol (Fixed)
1123 * AHIP_LoopPan (sposition)
1124 * AHIP_LoopSound (UWORD)
1125 * AHIP_LoopOffset (ULONG)
1126 * AHIP_LoopLength (LONG) - These tags can be used to set simple loop
1127 * attributes. They default to their sisters. These tags must be
1128 * after the other tags.
1139 * AHI_SetFreq(), AHI_SetSound(), AHI_SetVol()
1141 ****************************************************************************
1146 _AHI_PlayA( struct AHIPrivAudioCtrl
* audioctrl
,
1147 struct TagItem
* tags
,
1148 struct AHIBase
* AHIBase
)
1150 struct TagItem
*tag
,*tstate
=tags
;
1151 struct Library
*AHIsubBase
;
1152 BOOL setfreq
= FALSE
, setvol
= FALSE
, setsound
= FALSE
,
1153 loopsetfreq
= FALSE
, loopsetvol
= FALSE
, loopsetsound
= FALSE
;
1155 freq
= 0, vol
= 0, pan
= 0, sound
= 0, offset
= 0, length
= 0;
1156 ULONG loopfreq
= 0, loopvol
= 0, looppan
= 0, loopsound
= 0,
1157 loopoffset
= 0, looplength
= 0;
1159 if(AHIBase
->ahib_DebugLevel
>= AHI_DEBUG_ALL
)
1161 Debug_PlayA(audioctrl
,tags
);
1164 AHIsubBase
= ((struct AHIPrivAudioCtrl
*)audioctrl
)->ahiac_SubLib
;
1166 AHIsub_Disable((struct AHIAudioCtrlDrv
*)audioctrl
);
1168 for( tag
= NextTagItem( &tstate
);
1170 tag
= NextTagItem( &tstate
) )
1174 case AHIP_BeginChannel
:
1175 channel
=tag
->ti_Data
;
1176 setfreq
=setvol
=setsound
=loopsetfreq
=loopsetvol
=loopsetsound
= \
1177 vol
=pan
=offset
=length
=loopvol
=looppan
=loopoffset
=looplength
=0;
1201 offset
=tag
->ti_Data
;
1205 length
=tag
->ti_Data
;
1208 loopfreq
=tag
->ti_Data
;
1212 loopvol
=tag
->ti_Data
;
1216 looppan
=tag
->ti_Data
;
1219 case AHIP_LoopSound
:
1220 loopsound
=tag
->ti_Data
;
1223 case AHIP_LoopOffset
:
1224 loopoffset
=tag
->ti_Data
;
1225 loopsetsound
=TRUE
; // AHIP_LoopSound: doesn't have to be present
1227 case AHIP_LoopLength
:
1228 looplength
=tag
->ti_Data
;
1230 case AHIP_EndChannel
:
1232 AHI_SetFreq( channel
, freq
, (struct AHIAudioCtrl
*) audioctrl
, AHISF_IMM
);
1234 AHI_SetFreq( channel
, loopfreq
, (struct AHIAudioCtrl
*) audioctrl
, AHISF_NONE
);
1236 AHI_SetVol( channel
, vol
, pan
, (struct AHIAudioCtrl
*) audioctrl
, AHISF_IMM
);
1238 AHI_SetVol( channel
, loopvol
, looppan
, (struct AHIAudioCtrl
*) audioctrl
, AHISF_NONE
);
1240 AHI_SetSound( channel
, sound
, offset
, length
, (struct AHIAudioCtrl
*) audioctrl
, AHISF_IMM
);
1242 AHI_SetSound( channel
, loopsound
, loopoffset
, looplength
, (struct AHIAudioCtrl
*) audioctrl
, AHISF_NONE
);
1247 AHIsub_Enable((struct AHIAudioCtrlDrv
*)audioctrl
);
1252 /******************************************************************************
1253 ** AHI_SampleFrameSize ********************************************************
1254 ******************************************************************************/
1256 /****** ahi.device/AHI_SampleFrameSize **************************************
1259 * AHI_SampleFrameSize -- get the size of a sample frame (V4)
1262 * size = AHI_SampleFrameSize( sampletype );
1265 * ULONG AHI_SampleFrameSize( ULONG );
1268 * Returns the size in bytes of a sample frame for a given sample type.
1271 * sampletype - The sample type to examine. See <devices/ahi.h> for
1275 * The number of bytes, or 0 for invalid types.
1282 * This function returned trash for invalid sample types
1288 ****************************************************************************
1292 static const UBYTE type2bytes
[]=
1295 2, // AHIST_M16S (1)
1297 4, // AHIST_S16S (3)
1302 4, // AHIST_M32S (8)
1304 8 // AHIST_S32S (10)
1308 _AHI_SampleFrameSize( ULONG sampletype
,
1309 struct AHIBase
* AHIBase
)
1313 if(sampletype
<= AHIST_S32S
)
1315 result
= type2bytes
[sampletype
];
1317 else if(sampletype
== AHIST_L7_1
)
1322 if(AHIBase
->ahib_DebugLevel
>= AHI_DEBUG_LOW
)
1324 Debug_SampleFrameSize(sampletype
);
1325 KPrintF("=>%ld\n",type2bytes
[sampletype
]);