grub2: bring back build of aros-side grub2 tools
[AROS.git] / workbench / devs / AHI / Device / sound.c
blob6ef935a891383d5579202ab5997d0e7c972440ab
1 /*
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,
18 MA 02139, USA.
21 #include <config.h>
23 #include <exec/memory.h>
24 #include <utility/tagitem.h>
25 #include <proto/exec.h>
26 #include <proto/utility.h>
27 #define __NOLIBBASE__
28 #define __NOGLOBALIFACE__
29 #include <proto/ahi.h>
30 #undef __NOLIBBASE__
31 #undef __NOGLOBALIFACE__
32 #include <proto/ahi_sub.h>
33 #include <stdlib.h>
35 #include "ahi_def.h"
36 #include "debug.h"
37 #include "effectinit.h"
38 #include "mixer.h"
40 #ifdef __AMIGAOS4__
41 #define IAHIsub audioctrl->ahiac_IAHIsub
42 #endif
44 /******************************************************************************
45 ** AHI_SetVol *****************************************************************
46 ******************************************************************************/
48 /***** ahi.device/AHI_SetVol ***********************************************
50 * NAME
51 * AHI_SetVol -- set volume and stereo panning for a channel
53 * SYNOPSIS
54 * AHI_SetVol( channel, volume, pan, audioctrl, flags );
55 * D0:16 D1 D2 A2 D3
57 * void AHI_SetVol( UWORD, Fixed, sposition, struct AHIAudioCtrl *,
58 * ULONG );
60 * FUNCTION
61 * Changes the volume and stereo panning for a channel.
63 * INPUTS
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
86 * pan will be used.
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.
95 * RESULT
97 * EXAMPLE
99 * NOTES
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.
107 * BUGS
109 * SEE ALSO
110 * AHI_SetEffect(), AHI_SetFreq(), AHI_SetSound(), AHI_LoadSound()
113 ****************************************************************************
117 ULONG
118 _AHI_SetVol ( UWORD channel,
119 Fixed volume,
120 sposition pan,
121 struct AHIPrivAudioCtrl* audioctrl,
122 ULONG flags,
123 struct AHIBase* AHIBase )
125 struct AHIChannelData *cd;
126 struct Library *AHIsubBase;
127 ULONG rc;
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,
163 cd->cd_NextType,
164 audioctrl,
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,
176 cd->cd_DelayedType,
177 audioctrl,
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;
197 else
199 cd->cd_VolDelayed = TRUE;
203 AHIsub_Enable(&audioctrl->ac);
204 return 0;
209 /******************************************************************************
210 ** AHI_SetFreq ****************************************************************
211 ******************************************************************************/
213 /***** ahi.device/AHI_SetFreq **********************************************
215 * NAME
216 * AHI_SetFreq -- set frequency for a channel
218 * SYNOPSIS
219 * AHI_SetFreq( channel, freq, audioctrl, flags );
220 * D0:16 D1 A2 D2
222 * void AHI_SetFreq( UWORD, ULONG, struct AHIAudioCtrl *, ULONG );
224 * FUNCTION
225 * Sets the playback frequency for a channel.
227 * INPUTS
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
232 * changed).
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.
241 * RESULT
243 * EXAMPLE
245 * NOTES
246 * It is safe to call this function from an interrupt.
248 * BUGS
250 * SEE ALSO
251 * AHI_SetEffect(), AHI_SetSound(), AHI_SetVol(), AHI_LoadSound()
253 ****************************************************************************
257 ULONG
258 _AHI_SetFreq ( UWORD channel,
259 ULONG freq,
260 struct AHIPrivAudioCtrl* audioctrl,
261 ULONG flags,
262 struct AHIBase* AHIBase )
264 struct AHIChannelData *cd;
265 struct Library *AHIsubBase;
266 ULONG rc;
267 ULONG add;
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];
286 if(freq == 0)
288 cd->cd_NextFreqOK = FALSE;
290 add = 0;
292 else
294 cd->cd_NextFreqOK = TRUE;
296 if(freq == AHI_MIXFREQ)
298 add = 0x10000;
300 else
302 int shift = 0;
304 while(freq >= 65536)
306 shift++;
307 freq >>= 1;
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,
326 cd->cd_DelayedType,
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
341 // here instead.
343 cd->cd_Samples = CalcSamples( cd->cd_Add,
344 cd->cd_Type,
345 cd->cd_LastOffset,
346 cd->cd_Offset );
348 cd->cd_AntiClickCount = 0;
350 else
352 cd->cd_FreqDelayed = TRUE;
356 AHIsub_Enable(&audioctrl->ac);
358 return 0;
362 /******************************************************************************
363 ** AHI_SetSound ***************************************************************
364 ******************************************************************************/
366 /***** ahi.device/AHI_SetSound *********************************************
368 * NAME
369 * AHI_SetSound -- set what sound to play for a channel
371 * SYNOPSIS
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 );
378 * FUNCTION
379 * Sets a sound to be played on a channel.
381 * INPUTS
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.
403 * RESULT
405 * EXAMPLE
407 * NOTES
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
411 * sample limits.
413 * BUGS
415 * SEE ALSO
416 * AHI_SetEffect(), AHI_SetFreq(), AHI_SetVol(), AHI_LoadSound()
418 ****************************************************************************
422 ULONG
423 _AHI_SetSound ( UWORD channel,
424 UWORD sound,
425 ULONG offset,
426 LONG length,
427 struct AHIPrivAudioCtrl* audioctrl,
428 ULONG flags,
429 struct AHIBase* AHIBase )
431 struct AHIChannelData *cd;
432 struct AHISoundData *sd;
433 struct Library *AHIsubBase;
434 ULONG rc;
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;
476 if(length < 0)
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;
483 else
485 #if !defined( __mc68000__ )
486 cd->cd_NextLastOffset = ( (Fixed64) ( offset + length - 1 ) << 32 )
487 | (Fixed64) 0xffffffffLL;
488 #else
489 // Fix for m68k compiler bug! :-(
490 *(ULONG*) &cd->cd_NextLastOffset = offset + length - 1;
491 *(ULONG*) ((char*) (&cd->cd_NextLastOffset)+4) = 0xffffffffUL;
492 #endif
494 /* Low cd->cd_NextOffset already 0 */
497 SelectAddRoutine( cd->cd_NextVolumeLeft,
498 cd->cd_NextVolumeRight,
499 cd->cd_NextType,
500 audioctrl,
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,
516 cd->cd_DelayedType,
517 audioctrl,
518 &cd->cd_DelayedScaleLeft,
519 &cd->cd_DelayedScaleRight,
520 (ADDFUNC**) &cd->cd_DelayedAddRoutine );
522 cd->cd_DelayedSamples = CalcSamples( cd->cd_DelayedAdd,
523 cd->cd_DelayedType,
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;
549 else
551 cd->cd_SoundDelayed = TRUE;
554 cd->cd_EOS = TRUE; /* Signal End-Of-Sample */
558 AHIsub_Enable(&audioctrl->ac);
560 return 0;
564 /******************************************************************************
565 ** AHI_SetEffect **************************************************************
566 ******************************************************************************/
568 /***** ahi.device/AHI_SetEffect ********************************************
570 * NAME
571 * AHI_SetEffect -- set effect
573 * SYNOPSIS
574 * error = AHI_SetEffect( effect, audioctrl );
575 * d0 A0 A2
577 * ULONG AHI_SetEffect( APTR, struct AHIAudioCtrl * );
579 * FUNCTION
580 * Selects an effect to be used, described by a structure.
582 * INPUTS
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
590 * DSP effects. (V4)
591 * AHIET_DSPECHO - A DSP effects that adds (cross-)echo and delay.
592 * (V4)
593 * AHIET_CHANNELINFO - Get info about all channels. (V4)
594 * audioctrl - A pointer to an AHIAudioCtrl structure.
596 * EFFECTS
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
605 * result!
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
628 * mixing rate).
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
641 * cross echo.
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
649 * that even more.
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.
669 * (V4)
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
683 * cards.
685 * RESULT
686 * An error code, defined in <devices/ahi.h>.
688 * EXAMPLE
690 * NOTES
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.
696 * BUGS
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.
702 * SEE ALSO
703 * AHI_SetFreq(), AHI_SetSound(), AHI_SetVol(), AHI_LoadSound(),
704 * <devices/ahi.h>
706 ****************************************************************************
711 ULONG
712 _AHI_SetEffect( ULONG* effect,
713 struct AHIPrivAudioCtrl* audioctrl,
714 struct AHIBase* AHIBase )
716 struct Library *AHIsubBase;
717 ULONG rc;
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! */
735 switch(*effect)
739 * MASTERVOLUME
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 );
751 break;
754 case AHIET_MASTERVOLUME|AHIET_CANCEL:
756 if(audioctrl->ahiac_SetMasterVolume != 0x10000)
758 audioctrl->ahiac_SetMasterVolume = 0x10000;
759 rc = update_MasterVolume( audioctrl );
761 break;
764 * OUTPUTBUFFER
767 case AHIET_OUTPUTBUFFER:
768 audioctrl->ahiac_EffOutputBufferStruct = (struct AHIEffOutputBuffer *) effect;
769 rc = AHIE_OK;
770 break;
772 case AHIET_OUTPUTBUFFER|AHIET_CANCEL:
773 audioctrl->ahiac_EffOutputBufferStruct = NULL;
774 rc = AHIE_OK;
775 break;
779 * DSPMASK
782 case AHIET_DSPMASK:
783 rc = update_DSPMask( (struct AHIEffDSPMask *) effect, audioctrl );
784 break;
786 case AHIET_DSPMASK|AHIET_CANCEL:
787 clear_DSPMask( audioctrl );
788 rc = AHIE_OK;
789 break;
793 * DSPECHO
796 case AHIET_DSPECHO:
797 rc = update_DSPEcho( (struct AHIEffDSPEcho *) effect, audioctrl );
798 break;
800 case AHIET_DSPECHO|AHIET_CANCEL:
801 free_DSPEcho( audioctrl );
802 rc = AHIE_OK;
803 break;
807 * CHANNELINFO
810 case AHIET_CHANNELINFO:
811 audioctrl->ahiac_EffChannelInfoStruct = (struct AHIEffChannelInfo *) effect;
812 rc = AHIE_OK;
813 break;
815 case AHIET_CHANNELINFO|AHIET_CANCEL:
816 audioctrl->ahiac_EffChannelInfoStruct = NULL;
817 rc = AHIE_OK;
818 break;
821 return rc;
825 /******************************************************************************
826 ** AHI_LoadSound **************************************************************
827 ******************************************************************************/
829 /****** ahi.device/AHI_LoadSound ********************************************
831 * NAME
832 * AHI_LoadSound -- prepare a sound for playback
834 * SYNOPSIS
835 * error = AHI_LoadSound( sound, type, info, audioctrl );
836 * D0 D0:16 D1 A0 A2
838 * ULONG AHI_LoadSound( UWORD, ULONG, APTR, struct AHIAudioCtrl * );
840 * FUNCTION
841 * Defines an ID number for the sound and prepares it for playback.
843 * INPUTS
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
859 * sound card.
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
876 * RAM...
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.
887 * RESULT
888 * An error code, defined in <devices/ahi.h>.
890 * EXAMPLE
892 * NOTES
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.
897 * BUGS
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.
901 * SEE ALSO
902 * AHI_UnloadSound(), AHI_SetEffect(), AHI_SetFreq(), AHI_SetSound(),
903 * AHI_SetVol(), <devices/ahi.h>
905 ****************************************************************************
909 ULONG
910 _AHI_LoadSound( UWORD sound,
911 ULONG type,
912 APTR info,
913 struct AHIPrivAudioCtrl* audioctrl,
914 struct AHIBase* AHIBase )
917 struct Library *AHIsubBase;
918 ULONG rc;
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))
931 return rc;
934 rc = AHIE_OK;
936 switch(type)
938 case AHIST_DYNAMICSAMPLE:
939 case AHIST_SAMPLE:
941 struct AHISampleInfo *si = (struct AHISampleInfo *) info;
943 switch(si->ahisi_Type)
945 case AHIST_L7_1:
946 if( (audioctrl->ac.ahiac_Flags & AHIACF_HIFI) == 0 )
948 rc = AHIE_BADSAMPLETYPE;
949 break;
951 else
953 // Fall through ...
956 case AHIST_M8S:
957 case AHIST_M16S:
958 case AHIST_S8S:
959 case AHIST_S16S:
960 case AHIST_M32S:
961 case AHIST_S32S:
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;
967 break;
969 default:
970 rc = AHIE_BADSAMPLETYPE;
971 break;
974 break;
977 default:
978 rc = AHIE_BADSOUNDTYPE;
979 break;
982 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
984 KPrintF("=>%ld\n", rc);
986 return rc;
990 /******************************************************************************
991 ** AHI_UnloadSound ************************************************************
992 ******************************************************************************/
994 /****** ahi.device/AHI_UnloadSound *****************************************
996 * NAME
997 * AHI_UnloadSound -- discard a sound
999 * SYNOPSIS
1000 * AHI_UnloadSound( sound, audioctrl );
1001 * D0:16 A2
1003 * void AHI_UnloadSound( UWORD, struct AHIAudioCtrl * );
1005 * FUNCTION
1006 * Tells 'ahi.device' that this sound will not be used anymore.
1008 * INPUTS
1009 * sound - The ID of the sound to unload.
1010 * audioctrl - A pointer to an AHIAudioCtrl structure.
1012 * RESULT
1014 * EXAMPLE
1016 * NOTES
1017 * This call will not break a Forbid() state.
1019 * BUGS
1021 * SEE ALSO
1022 * AHI_LoadSound()
1024 ****************************************************************************
1028 ULONG
1029 _AHI_UnloadSound( UWORD sound,
1030 struct AHIPrivAudioCtrl* audioctrl,
1031 struct AHIBase* AHIBase )
1033 struct Library *AHIsubBase;
1034 ULONG rc;
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))
1047 return 0;
1050 audioctrl->ahiac_SoundDatas[sound].sd_Type = AHIST_NOTYPE;
1052 return 0;
1056 /******************************************************************************
1057 ** AHI_PlayA ******************************************************************
1058 ******************************************************************************/
1060 /****** ahi.device/AHI_PlayA ************************************************
1062 * NAME
1063 * AHI_PlayA -- Start multiple sounds in one call (V4)
1064 * AHI_Play -- varargs stub for AHI_PlayA()
1066 * SYNOPSIS
1067 * AHI_PlayA( audioctrl, tags );
1068 * A2 A1
1070 * void AHI_PlayA( struct AHIAudioCtrl *, struct TagItem * );
1072 * AHI_Play( AudioCtrl, tag1, ...);
1074 * void AHI_Play( struct AHIAudioCtrl *, Tag, ... );
1076 * FUNCTION
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.
1091 * INPUTS
1092 * audioctrl - A pointer to an AHIAudioCtrl structure.
1093 * tags - A pointer to a tag list.
1095 * TAGS
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
1119 * played.
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.
1130 * RESULT
1132 * EXAMPLE
1134 * NOTES
1136 * BUGS
1138 * SEE ALSO
1139 * AHI_SetFreq(), AHI_SetSound(), AHI_SetVol()
1141 ****************************************************************************
1145 ULONG
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;
1154 ULONG channel = 0,
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 );
1169 tag != NULL;
1170 tag = NextTagItem( &tstate ) )
1172 switch(tag->ti_Tag)
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;
1178 break;
1179 case AHIP_Freq:
1180 loopfreq=
1181 freq=tag->ti_Data;
1182 setfreq=TRUE;
1183 break;
1184 case AHIP_Vol:
1185 loopvol=
1186 vol=tag->ti_Data;
1187 setvol=TRUE;
1188 break;
1189 case AHIP_Pan:
1190 looppan=
1191 pan=tag->ti_Data;
1192 setvol=TRUE;
1193 break;
1194 case AHIP_Sound:
1195 loopsound=
1196 sound=tag->ti_Data;
1197 setsound=TRUE;
1198 break;
1199 case AHIP_Offset:
1200 loopoffset=
1201 offset=tag->ti_Data;
1202 break;
1203 case AHIP_Length:
1204 looplength=
1205 length=tag->ti_Data;
1206 break;
1207 case AHIP_LoopFreq:
1208 loopfreq=tag->ti_Data;
1209 loopsetfreq=TRUE;
1210 break;
1211 case AHIP_LoopVol:
1212 loopvol=tag->ti_Data;
1213 loopsetvol=TRUE;
1214 break;
1215 case AHIP_LoopPan:
1216 looppan=tag->ti_Data;
1217 loopsetvol=TRUE;
1218 break;
1219 case AHIP_LoopSound:
1220 loopsound=tag->ti_Data;
1221 loopsetsound=TRUE;
1222 break;
1223 case AHIP_LoopOffset:
1224 loopoffset=tag->ti_Data;
1225 loopsetsound=TRUE; // AHIP_LoopSound: doesn't have to be present
1226 break;
1227 case AHIP_LoopLength:
1228 looplength=tag->ti_Data;
1229 break;
1230 case AHIP_EndChannel:
1231 if(setfreq)
1232 AHI_SetFreq( channel, freq, (struct AHIAudioCtrl*) audioctrl, AHISF_IMM );
1233 if(loopsetfreq)
1234 AHI_SetFreq( channel, loopfreq, (struct AHIAudioCtrl*) audioctrl, AHISF_NONE );
1235 if(setvol)
1236 AHI_SetVol( channel, vol, pan, (struct AHIAudioCtrl*) audioctrl, AHISF_IMM );
1237 if(loopsetvol)
1238 AHI_SetVol( channel, loopvol, looppan, (struct AHIAudioCtrl*) audioctrl, AHISF_NONE );
1239 if(setsound)
1240 AHI_SetSound( channel, sound, offset, length, (struct AHIAudioCtrl*) audioctrl, AHISF_IMM );
1241 if(loopsetsound)
1242 AHI_SetSound( channel, loopsound, loopoffset, looplength, (struct AHIAudioCtrl*) audioctrl, AHISF_NONE);
1243 break;
1247 AHIsub_Enable((struct AHIAudioCtrlDrv *)audioctrl);
1248 return 0;
1252 /******************************************************************************
1253 ** AHI_SampleFrameSize ********************************************************
1254 ******************************************************************************/
1256 /****** ahi.device/AHI_SampleFrameSize **************************************
1258 * NAME
1259 * AHI_SampleFrameSize -- get the size of a sample frame (V4)
1261 * SYNOPSIS
1262 * size = AHI_SampleFrameSize( sampletype );
1263 * D0 D0
1265 * ULONG AHI_SampleFrameSize( ULONG );
1267 * FUNCTION
1268 * Returns the size in bytes of a sample frame for a given sample type.
1270 * INPUTS
1271 * sampletype - The sample type to examine. See <devices/ahi.h> for
1272 * possible types.
1274 * RESULT
1275 * The number of bytes, or 0 for invalid types.
1277 * EXAMPLE
1279 * NOTES
1281 * BUGS
1282 * This function returned trash for invalid sample types
1283 * before V6.
1285 * SEE ALSO
1286 * <devices/ahi.h>
1288 ****************************************************************************
1292 static const UBYTE type2bytes[]=
1294 1, // AHIST_M8S (0)
1295 2, // AHIST_M16S (1)
1296 2, // AHIST_S8S (2)
1297 4, // AHIST_S16S (3)
1298 1, // AHIST_M8U (4)
1302 4, // AHIST_M32S (8)
1304 8 // AHIST_S32S (10)
1307 ULONG
1308 _AHI_SampleFrameSize( ULONG sampletype,
1309 struct AHIBase* AHIBase )
1311 ULONG result = 0;
1313 if(sampletype <= AHIST_S32S )
1315 result = type2bytes[sampletype];
1317 else if(sampletype == AHIST_L7_1)
1319 result = 32;
1322 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
1324 Debug_SampleFrameSize(sampletype);
1325 KPrintF("=>%ld\n",type2bytes[sampletype]);
1328 return result;