w.i.p - correctly remap ColorModel_TrueColor images.
[AROS.git] / workbench / devs / AHI / Device / sound.c
blob923c2abdd340af15c839924aaccb6683fab2eb74
1 /*
2 AHI - Hardware independent audio subsystem
3 Copyright (C) 2017 The AROS Dev Team
4 Copyright (C) 1996-2005 Martin Blom <martin@blom.org>
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with this library; if not, write to the
18 Free Software Foundation, Inc., 59 Temple Place - Suite 330, Cambridge,
19 MA 02139, USA.
22 #include <config.h>
24 #include <exec/memory.h>
25 #include <utility/tagitem.h>
26 #include <proto/exec.h>
27 #include <proto/utility.h>
28 #define __NOLIBBASE__
29 #define __NOGLOBALIFACE__
30 #include <proto/ahi.h>
31 #undef __NOLIBBASE__
32 #undef __NOGLOBALIFACE__
33 #include <proto/ahi_sub.h>
34 #include <stdlib.h>
36 #include "ahi_def.h"
37 #include "debug.h"
38 #include "effectinit.h"
39 #include "mixer.h"
41 #ifdef __AMIGAOS4__
42 #define IAHIsub audioctrl->ahiac_IAHIsub
43 #endif
45 /******************************************************************************
46 ** AHI_SetVol *****************************************************************
47 ******************************************************************************/
49 /***** ahi.device/AHI_SetVol ***********************************************
51 * NAME
52 * AHI_SetVol -- set volume and stereo panning for a channel
54 * SYNOPSIS
55 * AHI_SetVol( channel, volume, pan, audioctrl, flags );
56 * D0:16 D1 D2 A2 D3
58 * void AHI_SetVol( UWORD, Fixed, sposition, struct AHIAudioCtrl *,
59 * ULONG );
61 * FUNCTION
62 * Changes the volume and stereo panning for a channel.
64 * INPUTS
65 * channel - The channel to set volume for.
66 * volume - The desired volume. Fixed is a LONG fixed-point value with
67 * 16 bits to the left of the point and 16 to the right
68 * (typedef LONG Fixed; from IFF-8SVX docs).
69 * Maximum volume is 1.0 (0x10000L) and 0.0 (0x0L) will turn off
70 * this channel. Note: The sound will continue to play, but you
71 * wont hear it. To stop a sound completely, use AHI_SetSound().
72 * Starting with V4 volume can also be negative, which tells AHI
73 * to invert the samples before playing. Note that all drivers
74 * may not be able to handle negative volume. In that case the
75 * absolute volume will be used.
76 * pan - The desired panning. sposition is the same as Fixed
77 * (typedef Fixed sposition; from IFF-8SVX.PAN docs).
78 * 1.0 (0x10000L) means that the sound is panned all the way to
79 * the right, 0.5 (0x8000L) means the sound is centered and 0.0
80 * (0x0L) means that the sound is panned all the way to the left.
81 * Try to set Pan to the 'correct' value even if you know it has no
82 * effect. For example, if you know you use a mono mode, set pan to
83 * 0.5 even if it does not matter.
84 * Starting with V4 pan can also be negative, which tells AHI to
85 * use the surround speaker for this channel. Note that all drivers
86 * may not be able to handle negative pan. In that case the absolute
87 * pan will be used.
88 * audioctrl - A pointer to an AHIAudioCtrl structure.
89 * flags - Only one flag is defined
90 * AHISF_IMM - Set this flag if this command should take effect
91 * immediately. If this bit is not set, the command will not
92 * take effect until the current sound is finished. MUST NOT
93 * be set if called from a SoundFunc. See the programming
94 * guidelines for more information about this flag.
96 * RESULT
98 * EXAMPLE
100 * NOTES
101 * It is safe to call this function from an interrupt.
103 * Negative volume or negative pan may use more CPU time than positive.
105 * Using both negative volume and negative pan will play the inverted
106 * sound on the surround speaker.
108 * BUGS
110 * SEE ALSO
111 * AHI_SetEffect(), AHI_SetFreq(), AHI_SetSound(), AHI_LoadSound()
114 ****************************************************************************
118 ULONG
119 _AHI_SetVol ( UWORD channel,
120 Fixed volume,
121 sposition pan,
122 struct AHIPrivAudioCtrl* audioctrl,
123 ULONG flags,
124 struct AHIBase* AHIBase )
126 struct AHIChannelData *cd;
127 struct Library *AHIsubBase;
128 ULONG rc;
130 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_ALL)
132 Debug_SetVol(channel, volume, pan, audioctrl, flags);
135 AHIsubBase = audioctrl->ahiac_SubLib;
137 rc = AHIsub_SetVol(channel, volume, pan, &audioctrl->ac, flags);
139 if(audioctrl->ac.ahiac_Flags & AHIACF_NOMIXING
140 || rc != AHIS_UNKNOWN)
142 return 0; /* We're done! */
145 cd = &audioctrl->ahiac_ChannelDatas[channel];
147 if((audioctrl->ac.ahiac_Flags & AHIACF_VOL) == 0)
149 volume = volume & 0x10000; /* |volume|=0 or 0x10000 */
152 if((audioctrl->ac.ahiac_Flags & AHIACF_PAN) == 0)
154 pan = (channel & 1) << 16; /* pan = 0 or 0x10000 */
157 AHIsub_Disable(&audioctrl->ac);
159 cd->cd_NextVolumeLeft = ((volume >> 1) * ((0x10000 - abs(pan)) >> 1)) >> (16 - 2);
160 cd->cd_NextVolumeRight = ((volume >> 1) * (pan >> 1)) >> (16 - 2);
162 SelectAddRoutine( cd->cd_NextVolumeLeft,
163 cd->cd_NextVolumeRight,
164 cd->cd_NextType,
165 audioctrl,
166 &cd->cd_NextScaleLeft,
167 &cd->cd_NextScaleRight,
168 (ADDFUNC**) &cd->cd_NextAddRoutine );
170 if(flags & AHISF_IMM)
172 cd->cd_DelayedVolumeLeft = cd->cd_NextVolumeLeft;
173 cd->cd_DelayedVolumeRight = cd->cd_NextVolumeRight;
175 SelectAddRoutine( cd->cd_DelayedVolumeLeft,
176 cd->cd_DelayedVolumeRight,
177 cd->cd_DelayedType,
178 audioctrl,
179 &cd->cd_DelayedScaleLeft,
180 &cd->cd_DelayedScaleRight,
181 (ADDFUNC**) &cd->cd_DelayedAddRoutine );
183 /* Enable anti-click routine */
184 cd->cd_AntiClickCount = audioctrl->ac.ahiac_AntiClickSamples;
186 if( ( flags & AHISF_NODELAY ) ||
187 ( cd->cd_AntiClickCount == 0 ) ||
188 !cd->cd_FreqOK || !cd->cd_SoundOK )
190 cd->cd_VolumeLeft = cd->cd_DelayedVolumeLeft;
191 cd->cd_VolumeRight = cd->cd_DelayedVolumeRight;
192 cd->cd_ScaleLeft = cd->cd_DelayedScaleLeft;
193 cd->cd_ScaleRight = cd->cd_DelayedScaleRight;
194 cd->cd_AddRoutine = cd->cd_DelayedAddRoutine;
196 cd->cd_AntiClickCount = 0;
198 else
200 cd->cd_VolDelayed = TRUE;
204 AHIsub_Enable(&audioctrl->ac);
205 return 0;
210 /******************************************************************************
211 ** AHI_SetFreq ****************************************************************
212 ******************************************************************************/
214 /***** ahi.device/AHI_SetFreq **********************************************
216 * NAME
217 * AHI_SetFreq -- set frequency for a channel
219 * SYNOPSIS
220 * AHI_SetFreq( channel, freq, audioctrl, flags );
221 * D0:16 D1 A2 D2
223 * void AHI_SetFreq( UWORD, ULONG, struct AHIAudioCtrl *, ULONG );
225 * FUNCTION
226 * Sets the playback frequency for a channel.
228 * INPUTS
229 * channel - The channel to set playback frequency for.
230 * freq - The playback frequency in Hertz. Can also be AHI_MIXFREQ,
231 * which is the current mixing frequency, or 0 to temporary stop
232 * the sound (it will restart at the same point when its frequency
233 * changed).
234 * audioctrl - A pointer to an AHIAudioCtrl structure.
235 * flags - Only one flag is defined
236 * AHISF_IMM - Set this flag if this command should take effect
237 * immediately. If this bit is not set, the command will not
238 * take effect until the current sound is finished. MUST NOT
239 * be set if called from a SoundFunc. See the programming
240 * guidelines for more information about this flag.
242 * RESULT
244 * EXAMPLE
246 * NOTES
247 * It is safe to call this function from an interrupt.
249 * BUGS
251 * SEE ALSO
252 * AHI_SetEffect(), AHI_SetSound(), AHI_SetVol(), AHI_LoadSound()
254 ****************************************************************************
258 ULONG
259 _AHI_SetFreq ( UWORD channel,
260 ULONG freq,
261 struct AHIPrivAudioCtrl* audioctrl,
262 ULONG flags,
263 struct AHIBase* AHIBase )
265 struct AHIChannelData *cd;
266 struct Library *AHIsubBase;
267 ULONG rc;
268 ULONG add;
270 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_ALL)
272 Debug_SetFreq(channel, freq, audioctrl, flags);
275 AHIsubBase = audioctrl->ahiac_SubLib;
277 rc = AHIsub_SetFreq(channel, freq, &audioctrl->ac, flags);
279 if(audioctrl->ac.ahiac_Flags & AHIACF_NOMIXING
280 || rc != AHIS_UNKNOWN)
282 return 0; /* We're done! */
285 cd = &audioctrl->ahiac_ChannelDatas[channel];
287 if(freq == 0)
289 cd->cd_NextFreqOK = FALSE;
291 add = 0;
293 else
295 cd->cd_NextFreqOK = TRUE;
297 if(freq == AHI_MIXFREQ)
299 add = 0x10000;
301 else
303 int shift = 0;
305 while(freq >= 65536)
307 shift++;
308 freq >>= 1;
311 add = ((freq << 16) / audioctrl->ac.ahiac_MixFreq) << shift;
315 AHIsub_Disable(&audioctrl->ac);
317 cd->cd_NextAdd = (Fixed64) add << 16;
319 if(flags & AHISF_IMM)
321 cd->cd_DelayedAdd = cd->cd_NextAdd;
322 cd->cd_DelayedFreqOK = cd->cd_NextFreqOK;
324 // cd->cd_Samples is also calculated when it actually happens¹...
326 cd->cd_DelayedSamples = CalcSamples( cd->cd_DelayedAdd,
327 cd->cd_DelayedType,
328 cd->cd_DelayedLastOffset,
329 cd->cd_DelayedOffset );
331 /* Enable anti-click routine */
332 cd->cd_AntiClickCount = audioctrl->ac.ahiac_AntiClickSamples;
334 if( ( flags & AHISF_NODELAY ) ||
335 ( cd->cd_AntiClickCount == 0 ) ||
336 !cd->cd_FreqOK || !cd->cd_SoundOK )
338 cd->cd_Add = cd->cd_DelayedAdd;
339 cd->cd_FreqOK = cd->cd_DelayedFreqOK;
341 // ¹) Unless we're not using any delay, in which case it's recalculated
342 // here instead.
344 cd->cd_Samples = CalcSamples( cd->cd_Add,
345 cd->cd_Type,
346 cd->cd_LastOffset,
347 cd->cd_Offset );
349 cd->cd_AntiClickCount = 0;
351 else
353 cd->cd_FreqDelayed = TRUE;
357 AHIsub_Enable(&audioctrl->ac);
359 return 0;
363 /******************************************************************************
364 ** AHI_SetSound ***************************************************************
365 ******************************************************************************/
367 /***** ahi.device/AHI_SetSound *********************************************
369 * NAME
370 * AHI_SetSound -- set what sound to play for a channel
372 * SYNOPSIS
373 * AHI_SetSound( channel, sound, offset, length, audioctrl, flags );
374 * D0:16 D1:16 D2 D3 A2 D4
376 * void AHI_SetSound( UWORD, UWORD, ULONG, LONG,
377 * struct AHIAudioCtrl *, ULONG );
379 * FUNCTION
380 * Sets a sound to be played on a channel.
382 * INPUTS
383 * channel - The channel to set sound for.
384 * sound - Sound to be played, or AHI_NOSOUND to turn the channel off.
385 * offset - Only available if the sound type is AHIST_SAMPLE or
386 * AHIST_DYNAMICSAMPLE. Must be 0 otherwise.
387 * Specifies an offset (in samples) where the playback will begin.
388 * If you wish to play the whole sound, set offset to 0.
389 * length - Only available if the sound type is AHIST_SAMPLE or
390 * AHIST_DYNAMICSAMPLE. Must be 0 otherwise.
391 * Specifies how many samples that should be played. If you
392 * wish to play the whole sound forwards, set offset to 0 and length
393 * to either 0 or the length of the sample array. You may not set
394 * length to 0 if offset is not 0! To play a sound backwards, just
395 * set length to a negative number.
396 * audioctrl - A pointer to an AHIAudioCtrl structure.
397 * flags - Only one flag is defined
398 * AHISF_IMM - Set this flag if this command should take effect
399 * immediately. If this bit is not set, the command will not
400 * take effect until the current sound is finished. MUST NOT
401 * be set if called from a SoundFunc. See the programming
402 * guidelines for more information about this flag.
404 * RESULT
406 * EXAMPLE
408 * NOTES
409 * It is safe to call this function from an interrupt.
411 * If offset or length is not zero, make sure you do not exceed the
412 * sample limits.
414 * BUGS
416 * SEE ALSO
417 * AHI_SetEffect(), AHI_SetFreq(), AHI_SetVol(), AHI_LoadSound()
419 ****************************************************************************
423 ULONG
424 _AHI_SetSound ( UWORD channel,
425 UWORD sound,
426 ULONG offset,
427 LONG length,
428 struct AHIPrivAudioCtrl* audioctrl,
429 ULONG flags,
430 struct AHIBase* AHIBase )
432 struct AHIChannelData *cd;
433 struct AHISoundData *sd;
434 struct Library *AHIsubBase;
435 ULONG rc;
437 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_ALL)
439 Debug_SetSound(channel, sound, offset, length, audioctrl, flags);
442 AHIsubBase = audioctrl->ahiac_SubLib;
444 rc = AHIsub_SetSound(channel, sound, offset, length, &audioctrl->ac, flags);
446 if(audioctrl->ac.ahiac_Flags & AHIACF_NOMIXING
447 || rc != AHIS_UNKNOWN)
449 return 0; /* We're done! */
452 cd = &audioctrl->ahiac_ChannelDatas[channel];
453 sd = &audioctrl->ahiac_SoundDatas[sound];
455 AHIsub_Disable(&audioctrl->ac);
457 if(sound == AHI_NOSOUND)
459 cd->cd_NextSoundOK = FALSE;
461 if(flags & AHISF_IMM)
463 cd->cd_EOS = TRUE; /* Signal End-Of-Sample */
464 cd->cd_SoundOK = FALSE;
467 else if(sd->sd_Type != AHIST_NOTYPE) /* This is a user error, shouldn't happen! */
469 if(length == 0) length = sd->sd_Length;
471 cd->cd_NextDataStart = sd->sd_Addr;
472 cd->cd_NextType = sd->sd_Type;
473 cd->cd_NextOffset = (Fixed64) offset << 32 ;
475 cd->cd_NextSoundOK = TRUE;
477 if(length < 0)
479 cd->cd_NextType |= AHIST_BW;
480 cd->cd_NextLastOffset = (Fixed64) ( offset + length + 1 ) << 32;
481 // cd->cd_NextOffset |= 0xffffffffLL;
482 *(ULONG*) ((char*) (&cd->cd_NextOffset)+4) = 0xffffffffUL;
484 else
486 #if !defined( __mc68000__ )
487 cd->cd_NextLastOffset = ( (Fixed64) ( offset + length - 1 ) << 32 )
488 | (Fixed64) 0xffffffffLL;
489 #else
490 // Fix for m68k compiler bug! :-(
491 *(ULONG*) &cd->cd_NextLastOffset = offset + length - 1;
492 *(ULONG*) ((char*) (&cd->cd_NextLastOffset)+4) = 0xffffffffUL;
493 #endif
495 /* Low cd->cd_NextOffset already 0 */
498 SelectAddRoutine( cd->cd_NextVolumeLeft,
499 cd->cd_NextVolumeRight,
500 cd->cd_NextType,
501 audioctrl,
502 &cd->cd_NextScaleLeft,
503 &cd->cd_NextScaleRight,
504 (ADDFUNC**) &cd->cd_NextAddRoutine );
506 if(flags & AHISF_IMM)
508 cd->cd_DelayedOffset = cd->cd_NextOffset;
509 cd->cd_DelayedFirstOffsetI = cd->cd_NextOffset >> 32; /* for linear interpol. */
510 cd->cd_DelayedLastOffset = cd->cd_NextLastOffset;
511 cd->cd_DelayedDataStart = cd->cd_NextDataStart;
512 cd->cd_DelayedType = cd->cd_NextType;
513 cd->cd_DelayedSoundOK = cd->cd_NextSoundOK;
515 SelectAddRoutine( cd->cd_DelayedVolumeLeft,
516 cd->cd_DelayedVolumeRight,
517 cd->cd_DelayedType,
518 audioctrl,
519 &cd->cd_DelayedScaleLeft,
520 &cd->cd_DelayedScaleRight,
521 (ADDFUNC**) &cd->cd_DelayedAddRoutine );
523 cd->cd_DelayedSamples = CalcSamples( cd->cd_DelayedAdd,
524 cd->cd_DelayedType,
525 cd->cd_DelayedLastOffset,
526 cd->cd_DelayedOffset );
528 /* Enable anti-click routine */
529 cd->cd_AntiClickCount = audioctrl->ac.ahiac_AntiClickSamples;
531 if( ( flags & AHISF_NODELAY ) ||
532 ( cd->cd_AntiClickCount == 0 ) ||
533 !cd->cd_FreqOK || !cd->cd_SoundOK )
535 cd->cd_StartPointL = 0;
536 cd->cd_StartPointR = 0;
538 cd->cd_Offset = cd->cd_DelayedOffset;
539 cd->cd_FirstOffsetI = cd->cd_DelayedFirstOffsetI;
540 cd->cd_LastOffset = cd->cd_DelayedLastOffset;
541 cd->cd_DataStart = cd->cd_DelayedDataStart;
542 cd->cd_Type = cd->cd_DelayedType;
543 cd->cd_SoundOK = cd->cd_DelayedSoundOK;
544 cd->cd_ScaleLeft = cd->cd_DelayedScaleLeft;
545 cd->cd_ScaleRight = cd->cd_DelayedScaleRight;
546 cd->cd_AddRoutine = cd->cd_DelayedAddRoutine;
547 cd->cd_Samples = cd->cd_DelayedSamples;
548 cd->cd_AntiClickCount = 0;
550 else
552 cd->cd_SoundDelayed = TRUE;
555 cd->cd_EOS = TRUE; /* Signal End-Of-Sample */
559 AHIsub_Enable(&audioctrl->ac);
561 return 0;
565 /******************************************************************************
566 ** AHI_SetEffect **************************************************************
567 ******************************************************************************/
569 /***** ahi.device/AHI_SetEffect ********************************************
571 * NAME
572 * AHI_SetEffect -- set effect
574 * SYNOPSIS
575 * error = AHI_SetEffect( effect, audioctrl );
576 * d0 A0 A2
578 * ULONG AHI_SetEffect( APTR, struct AHIAudioCtrl * );
580 * FUNCTION
581 * Selects an effect to be used, described by a structure.
583 * INPUTS
584 * effect - A pointer to an effect data structure, as defined in
585 * <devices/ahi.h>. The following effects are defined:
586 * AHIET_MASTERVOLUME - Changes the volume for all channels. Can
587 * also be used to boost volume over 100%.
588 * AHIET_OUTPUTBUFFER - Gives READ-ONLY access to the mixed output.
589 * Can be used to show nice scopes and VU-meters.
590 * AHIET_DSPMASK - Select which channels will be affected by the
591 * DSP effects. (V4)
592 * AHIET_DSPECHO - A DSP effects that adds (cross-)echo and delay.
593 * (V4)
594 * AHIET_CHANNELINFO - Get info about all channels. (V4)
595 * audioctrl - A pointer to an AHIAudioCtrl structure.
597 * EFFECTS
598 * AHIET_MASTERVOLUME - Effect is a struct AHIEffMasterVolume, with
599 * ahiemv_Volume set to the desired volume. The range is 0 to
600 * (channels/hardware channel). Assume you have 4 channels in
601 * mono mode. The range is then 0.0 to 4.0. The range is the same
602 * if the mode is stereo with panning. However, assume you have 4
603 * channels with a stereo mode *without* panning. Then you have two
604 * channels to the left and two to the right => range is 0.0 - 2.0.
605 * Setting the volume outside the range will give an unpredictable
606 * result!
608 * AHIET_OUTPUTBUFFER - Effect is a struct AHIEffOutputBuffer, with
609 * ahieob_Func pointing to a hook that will be called with the
610 * following parameters:
611 * A0 - (struct Hook *)
612 * A2 - (struct AHIAudioCtrl *)
613 * A1 - (struct AHIEffOutputBuffer *)
614 * The information you are looking for then is in ahieob_Type,
615 * ahieob_Buffer and ahieob_Length. Always check ahieob_Type!
616 * ahieob_Length is neither in bytes nor samples, but sample frames.
618 * AHIET_DSPMASK - Effect is a struct AHIEffDSPMask, where ahiedm_Mask
619 * is an array with ahiedm_Channels elements. Each UBYTE in the
620 * array can either make the channel 'wet' (affected by the DSP
621 * effects), by using the AHIEDM_WET constant or 'dry' (not
622 * affected by the DSP effects) by using the AHIEDM_DRY constant.
623 * The default is all channels wet. If ahiedm_Channels does not
624 * equal the current number of channels allocated, the result of
625 * this call is undefined (crash warning!). (V4)
627 * AHIET_DSPECHO - Effect is a struct AHIEffDSPEcho.
628 * ahiede_Delay is the delay in samples (and thus depends on the
629 * mixing rate).
631 * ahiede_Feedback is a Fixed value between 0 and 1.0, and defines
632 * how much of the delayed signal should be feed back to the delay
633 * stage. Setting this to 0 gives a delay effect, otherwise echo.
635 * ahiede_Mix tells how much of the delayed signal should be mixed
636 * with the normal signal. Setting this to 0 disables delay/echo,
637 * and setting it to 1.0 outputs only the delay/echo signal.
639 * ahiede_Cross only has effect of the current playback mode is
640 * stereo. It tells how the delayed signal should be panned to
641 * the other channel. 0 means no cross echo, 1.0 means full
642 * cross echo.
644 * If the user has enabled "Fast Echo", AHI may take several short-
645 * cuts to increase the performance. This could include rounding the
646 * parameters to a power of two, or even to the extremes.
648 * If you set ahiede_Mix to 0x10000 and ahiede_Cross to 0x0, much
649 * faster mixing routines will be used, and "Fast Echo" will improve
650 * that even more.
652 * Otherwise, even with "Fast Echo" turned on, this effect will
653 * probably suck some major CPU cycles on most sound hardware. (V4)
655 * AHIET_CHANNELINFO - Effect is a struct AHIEffChannelInfo, where
656 * ahieci_Func is pointing to a hook that will be called with the
657 * following parameters:
658 * A0 - (struct Hook *)
659 * A2 - (struct AHIAudioCtrl *)
660 * A1 - (struct AHIEffChannelInfo *)
661 * ahieci_Channels must equal the current number of channels used.
662 * ahieci_Offset is an array of ULONGs, which will be filled by
663 * AHI before the hook is called (the offset is specified in sample
664 * frames). The array must have at least ahieci_Channels elements.
666 * This "effect" can be used to find out how far each channel has
667 * played. You must probably keep track of the other parameters
668 * yourself (like which sound is playing, it's volume, balance and
669 * frequency etc) in order have meaningful usage of the information.
670 * (V4)
673 * NOTE! To turn off an effect, call again with ahie_Effect OR:ed
674 * with AHIET_CANCEL. For example, it is NOT correct to disable
675 * the AHIET_MASTERVOLUME effect by setting ahiemv_Volume to 1.0!
677 * It is important that you always turn off effects before you
678 * deallocate the audio hardware. Otherwise memory may be lost.
679 * It is safe to turn off an effect that has never been turned on
680 * in the first place.
682 * Never count on that an effect will be available. For example,
683 * AHIET_OUTPUTBUFFER is impossible to implement with some sound
684 * cards.
686 * RESULT
687 * An error code, defined in <devices/ahi.h>.
689 * EXAMPLE
691 * NOTES
692 * Unlike the other functions whose names begin with "AHI_Set", this
693 * function may NOT be called from an interrupt (or AHI Hook).
695 * Previous to V4, this call always returned AHIE_OK.
697 * BUGS
698 * The idea of updating the source structure instead of allocating
699 * a new one that is passed the hook it pretty flawed. The reason is
700 * that AHI_SetEffect() originally could be called from interrupts,
701 * and memory allocation is not allowed from within interrupts.
703 * SEE ALSO
704 * AHI_SetFreq(), AHI_SetSound(), AHI_SetVol(), AHI_LoadSound(),
705 * <devices/ahi.h>
707 ****************************************************************************
712 ULONG
713 _AHI_SetEffect( IPTR* effect,
714 struct AHIPrivAudioCtrl* audioctrl,
715 struct AHIBase* AHIBase )
717 struct Library *AHIsubBase;
718 ULONG rc;
720 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_ALL)
722 Debug_SetEffect(effect, audioctrl);
725 AHIsubBase = audioctrl->ahiac_SubLib;
727 rc = AHIsub_SetEffect(effect, &audioctrl->ac);
729 if(audioctrl->ac.ahiac_Flags & AHIACF_NOMIXING
730 || rc != AHIS_UNKNOWN)
732 return rc; /* We're done! */
736 switch(*effect)
740 * MASTERVOLUME
743 case AHIET_MASTERVOLUME:
745 struct AHIEffMasterVolume *emv = (struct AHIEffMasterVolume *) effect;
747 if(audioctrl->ahiac_SetMasterVolume != emv->ahiemv_Volume)
749 audioctrl->ahiac_SetMasterVolume = emv->ahiemv_Volume;
750 rc = update_MasterVolume( audioctrl );
752 break;
755 case AHIET_MASTERVOLUME|AHIET_CANCEL:
757 if(audioctrl->ahiac_SetMasterVolume != 0x10000)
759 audioctrl->ahiac_SetMasterVolume = 0x10000;
760 rc = update_MasterVolume( audioctrl );
762 break;
765 * OUTPUTBUFFER
768 case AHIET_OUTPUTBUFFER:
769 audioctrl->ahiac_EffOutputBufferStruct = (struct AHIEffOutputBuffer *) effect;
770 rc = AHIE_OK;
771 break;
773 case AHIET_OUTPUTBUFFER|AHIET_CANCEL:
774 audioctrl->ahiac_EffOutputBufferStruct = NULL;
775 rc = AHIE_OK;
776 break;
780 * DSPMASK
783 case AHIET_DSPMASK:
784 rc = update_DSPMask( (struct AHIEffDSPMask *) effect, audioctrl );
785 break;
787 case AHIET_DSPMASK|AHIET_CANCEL:
788 clear_DSPMask( audioctrl );
789 rc = AHIE_OK;
790 break;
794 * DSPECHO
797 case AHIET_DSPECHO:
798 rc = update_DSPEcho( (struct AHIEffDSPEcho *) effect, audioctrl );
799 break;
801 case AHIET_DSPECHO|AHIET_CANCEL:
802 free_DSPEcho( audioctrl );
803 rc = AHIE_OK;
804 break;
808 * CHANNELINFO
811 case AHIET_CHANNELINFO:
812 audioctrl->ahiac_EffChannelInfoStruct = (struct AHIEffChannelInfo *) effect;
813 rc = AHIE_OK;
814 break;
816 case AHIET_CHANNELINFO|AHIET_CANCEL:
817 audioctrl->ahiac_EffChannelInfoStruct = NULL;
818 rc = AHIE_OK;
819 break;
822 return rc;
826 /******************************************************************************
827 ** AHI_LoadSound **************************************************************
828 ******************************************************************************/
830 /****** ahi.device/AHI_LoadSound ********************************************
832 * NAME
833 * AHI_LoadSound -- prepare a sound for playback
835 * SYNOPSIS
836 * error = AHI_LoadSound( sound, type, info, audioctrl );
837 * D0 D0:16 D1 A0 A2
839 * ULONG AHI_LoadSound( UWORD, ULONG, APTR, struct AHIAudioCtrl * );
841 * FUNCTION
842 * Defines an ID number for the sound and prepares it for playback.
844 * INPUTS
845 * sound - The numeric ID to be used as a reference to this sound.
846 * The ID is a number greater or equal to 0 and less than what you
847 * specified with AHIA_Sounds when you called AHI_AllocAudioA().
848 * type - The type of the sound. Currently four types are supported:
849 * AHIST_SAMPLE - array of 8 or 16 bit samples. Note that the
850 * portion of memory where the sample is stored must NOT be
851 * altered until AHI_UnloadSound() has been called! This is
852 * because some audio drivers may wish to upload the samples
853 * to local RAM. It is OK to read, though.
855 * AHIST_DYNAMICSAMPLE - array of 8 or 16 bit samples, which can be
856 * updated dynamically. Typically used to play data that is
857 * loaded from disk or calculated realtime.
858 * Avoid using this sound type as much as possible; it will
859 * use much more CPU power than AHIST_SAMPLE on a DMA/DSP
860 * sound card.
862 * info - Depends on type:
863 * AHIST_SAMPLE - A pointer to a struct AHISampleInfo, filled with:
864 * ahisi_Type - Format of samples (four formats are supported).
865 * AHIST_M8S: Mono, 8 bit signed (BYTEs).
866 * AHIST_S8S: Stereo, 8 bit signed (2×BYTEs) (V4).
867 * AHIST_M16S: Mono, 16 bit signed (WORDs).
868 * AHIST_S16S: Stereo, 16 bit signed (2×WORDs) (V4).
869 * AHIST_M32S: Mono, 32 bit signed (LONGs). (V6)
870 * AHIST_S32S: Stereo, 32 bit signed (2×LONGs) (V6).
871 * AHIST_L7_1: 7.1, 32 bit signed (8×LONGs) (V6).
872 * ahisi_Address - Address to the sample array.
873 * ahisi_Length - The size of the array, in samples.
874 * Don't even think of setting ahisi_Address to 0 and
875 * ahisi_Length to 0xffffffff as you can do with
876 * AHIST_DYNAMICSAMPLE! Very few DMA/DSP cards have 4 GB onboard
877 * RAM...
879 * AHIST_DYNAMICSAMPLE A pointer to a struct AHISampleInfo, filled
880 * as described above (AHIST_SAMPLE).
881 * If ahisi_Address is 0 and ahisi_Length is 0xffffffff
882 * AHI_SetSound() can take the real address of an 8 bit sample
883 * to be played as offset argument. Unfortunately, this does not
884 * work for 16 bit samples.
886 * audioctrl - A pointer to an AHIAudioCtrl structure.
888 * RESULT
889 * An error code, defined in <devices/ahi.h>.
891 * EXAMPLE
893 * NOTES
894 * There is no need to place a sample array in Chip memory, but it
895 * MUST NOT be swapped out! Allocate your sample memory with the
896 * MEMF_PUBLIC flag set.
898 * BUGS
899 * AHIST_L7_1 can only be played using 7.1 audio modes -- it will NOT
900 * be downmixed! It can't be played backwards either.
902 * SEE ALSO
903 * AHI_UnloadSound(), AHI_SetEffect(), AHI_SetFreq(), AHI_SetSound(),
904 * AHI_SetVol(), <devices/ahi.h>
906 ****************************************************************************
910 ULONG
911 _AHI_LoadSound( UWORD sound,
912 ULONG type,
913 APTR info,
914 struct AHIPrivAudioCtrl* audioctrl,
915 struct AHIBase* AHIBase )
918 struct Library *AHIsubBase;
919 ULONG rc;
921 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
923 Debug_LoadSound(sound, type, info, audioctrl);
926 AHIsubBase = audioctrl->ahiac_SubLib;
928 rc = AHIsub_LoadSound(sound, type, info, (struct AHIAudioCtrlDrv *) audioctrl);
930 if((audioctrl->ac.ahiac_Flags & AHIACF_NOMIXING) || (rc != AHIS_UNKNOWN))
932 return rc;
935 rc = AHIE_OK;
937 switch(type)
939 case AHIST_DYNAMICSAMPLE:
940 case AHIST_SAMPLE:
942 struct AHISampleInfo *si = (struct AHISampleInfo *) info;
944 switch(si->ahisi_Type)
946 case AHIST_L7_1:
947 if( (audioctrl->ac.ahiac_Flags & AHIACF_HIFI) == 0 )
949 rc = AHIE_BADSAMPLETYPE;
950 break;
952 else
954 // Fall through ...
957 case AHIST_M8S:
958 case AHIST_M16S:
959 case AHIST_S8S:
960 case AHIST_S16S:
961 case AHIST_M32S:
962 case AHIST_S32S:
963 /* AHI_FreeAudio() will deallocate... */
965 audioctrl->ahiac_SoundDatas[sound].sd_Type = si->ahisi_Type;
966 audioctrl->ahiac_SoundDatas[sound].sd_Addr = si->ahisi_Address;
967 audioctrl->ahiac_SoundDatas[sound].sd_Length = si->ahisi_Length;
968 break;
970 default:
971 rc = AHIE_BADSAMPLETYPE;
972 break;
975 break;
978 default:
979 rc = AHIE_BADSOUNDTYPE;
980 break;
983 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
985 KPrintF("=>%ld\n", rc);
987 return rc;
991 /******************************************************************************
992 ** AHI_UnloadSound ************************************************************
993 ******************************************************************************/
995 /****** ahi.device/AHI_UnloadSound *****************************************
997 * NAME
998 * AHI_UnloadSound -- discard a sound
1000 * SYNOPSIS
1001 * AHI_UnloadSound( sound, audioctrl );
1002 * D0:16 A2
1004 * void AHI_UnloadSound( UWORD, struct AHIAudioCtrl * );
1006 * FUNCTION
1007 * Tells 'ahi.device' that this sound will not be used anymore.
1009 * INPUTS
1010 * sound - The ID of the sound to unload.
1011 * audioctrl - A pointer to an AHIAudioCtrl structure.
1013 * RESULT
1015 * EXAMPLE
1017 * NOTES
1018 * This call will not break a Forbid() state.
1020 * BUGS
1022 * SEE ALSO
1023 * AHI_LoadSound()
1025 ****************************************************************************
1029 ULONG
1030 _AHI_UnloadSound( UWORD sound,
1031 struct AHIPrivAudioCtrl* audioctrl,
1032 struct AHIBase* AHIBase )
1034 struct Library *AHIsubBase;
1035 ULONG rc;
1037 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
1039 Debug_UnloadSound(sound, audioctrl);
1042 AHIsubBase = audioctrl->ahiac_SubLib;
1044 rc = AHIsub_UnloadSound(sound, (struct AHIAudioCtrlDrv *) audioctrl);
1046 if((audioctrl->ac.ahiac_Flags & AHIACF_NOMIXING) || (rc != AHIS_UNKNOWN))
1048 return 0;
1051 audioctrl->ahiac_SoundDatas[sound].sd_Type = AHIST_NOTYPE;
1053 return 0;
1057 /******************************************************************************
1058 ** AHI_PlayA ******************************************************************
1059 ******************************************************************************/
1061 /****** ahi.device/AHI_PlayA ************************************************
1063 * NAME
1064 * AHI_PlayA -- Start multiple sounds in one call (V4)
1065 * AHI_Play -- varargs stub for AHI_PlayA()
1067 * SYNOPSIS
1068 * AHI_PlayA( audioctrl, tags );
1069 * A2 A1
1071 * void AHI_PlayA( struct AHIAudioCtrl *, struct TagItem * );
1073 * AHI_Play( AudioCtrl, tag1, ...);
1075 * void AHI_Play( struct AHIAudioCtrl *, Tag, ... );
1077 * FUNCTION
1078 * This function performs the same actions as multiple calls to
1079 * AHI_SetFreq(), AHI_SetSound() and AHI_SetVol(). The advantages
1080 * of using only one call is that simple loops can be set without
1081 * using a SoundFunc (see AHI_AllocAudioA(), tag AHIA_SoundFunc) and
1082 * that sounds on different channels can be synchronized even when the
1083 * sounds are not started from a PlayerFunc (see AHI_AllocAudioA(), tag
1084 * AHIA_PlayerFunc). The disadvantage is that this call has more
1085 * overhead than AHI_SetFreq(), AHI_SetSound() and AHI_SetVol(). It is
1086 * therefore recommended that you only use this call if you are not
1087 * calling from a SoundFunc or PlayerFunc.
1089 * The supplied tag list works like a 'program'. This means that
1090 * the order of tags matter.
1092 * INPUTS
1093 * audioctrl - A pointer to an AHIAudioCtrl structure.
1094 * tags - A pointer to a tag list.
1096 * TAGS
1097 * AHIP_BeginChannel (UWORD) - Before you start setting attributes
1098 * for a sound to play, you have to use this tag to chose a
1099 * channel to operate on. If AHIP_BeginChannel is omitted, the
1100 * result is undefined.
1102 * AHIP_EndChannel (ULONG) - Signals the end of attributes for
1103 * the current channel. If AHIP_EndChannel is omitted, the result
1104 * is undefined. ti_Data MUST BE NULL!
1106 * AHIP_Freq (ULONG) - The playback frequency in Hertz or AHI_MIXFREQ.
1108 * AHIP_Vol (Fixed) - The desired volume. If omitted, but AHIP_Pan is
1109 * present, AHIP_Vol defaults to 0.
1111 * AHIP_Pan (sposition) - The desired panning. If omitted, but AHIP_Vol
1112 * is present, AHIP_Pan defaults to 0 (extreme left).
1114 * AHIP_Sound (UWORD) - Sound to be played, or AHI_NOSOUND.
1116 * AHIP_Offset (ULONG) - Specifies an offset (in samples) into the
1117 * sound. If this tag is present, AHIP_Length MUST be present too!
1119 * AHIP_Length (LONG) - Specifies how many samples that should be
1120 * played.
1122 * AHIP_LoopFreq (ULONG)
1123 * AHIP_LoopVol (Fixed)
1124 * AHIP_LoopPan (sposition)
1125 * AHIP_LoopSound (UWORD)
1126 * AHIP_LoopOffset (ULONG)
1127 * AHIP_LoopLength (LONG) - These tags can be used to set simple loop
1128 * attributes. They default to their sisters. These tags must be
1129 * after the other tags.
1131 * RESULT
1133 * EXAMPLE
1135 * NOTES
1137 * BUGS
1139 * SEE ALSO
1140 * AHI_SetFreq(), AHI_SetSound(), AHI_SetVol()
1142 ****************************************************************************
1146 ULONG
1147 _AHI_PlayA( struct AHIPrivAudioCtrl* audioctrl,
1148 struct TagItem* tags,
1149 struct AHIBase* AHIBase )
1151 struct TagItem *tag,*tstate=tags;
1152 struct Library *AHIsubBase;
1153 BOOL setfreq = FALSE, setvol = FALSE, setsound = FALSE,
1154 loopsetfreq = FALSE, loopsetvol = FALSE, loopsetsound = FALSE;
1155 ULONG channel = 0,
1156 freq = 0, vol = 0, pan = 0, sound = 0, offset = 0, length = 0;
1157 ULONG loopfreq = 0, loopvol = 0, looppan = 0, loopsound = 0,
1158 loopoffset = 0, looplength = 0;
1160 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_ALL)
1162 Debug_PlayA(audioctrl,tags);
1165 AHIsubBase = ((struct AHIPrivAudioCtrl *)audioctrl)->ahiac_SubLib;
1167 AHIsub_Disable((struct AHIAudioCtrlDrv *)audioctrl);
1169 for( tag = NextTagItem( &tstate );
1170 tag != NULL;
1171 tag = NextTagItem( &tstate ) )
1173 switch(tag->ti_Tag)
1175 case AHIP_BeginChannel:
1176 channel=tag->ti_Data;
1177 setfreq=setvol=setsound=loopsetfreq=loopsetvol=loopsetsound= \
1178 vol=pan=offset=length=loopvol=looppan=loopoffset=looplength=0;
1179 break;
1180 case AHIP_Freq:
1181 loopfreq=
1182 freq=tag->ti_Data;
1183 setfreq=TRUE;
1184 break;
1185 case AHIP_Vol:
1186 loopvol=
1187 vol=tag->ti_Data;
1188 setvol=TRUE;
1189 break;
1190 case AHIP_Pan:
1191 looppan=
1192 pan=tag->ti_Data;
1193 setvol=TRUE;
1194 break;
1195 case AHIP_Sound:
1196 loopsound=
1197 sound=tag->ti_Data;
1198 setsound=TRUE;
1199 break;
1200 case AHIP_Offset:
1201 loopoffset=
1202 offset=tag->ti_Data;
1203 break;
1204 case AHIP_Length:
1205 looplength=
1206 length=tag->ti_Data;
1207 break;
1208 case AHIP_LoopFreq:
1209 loopfreq=tag->ti_Data;
1210 loopsetfreq=TRUE;
1211 break;
1212 case AHIP_LoopVol:
1213 loopvol=tag->ti_Data;
1214 loopsetvol=TRUE;
1215 break;
1216 case AHIP_LoopPan:
1217 looppan=tag->ti_Data;
1218 loopsetvol=TRUE;
1219 break;
1220 case AHIP_LoopSound:
1221 loopsound=tag->ti_Data;
1222 loopsetsound=TRUE;
1223 break;
1224 case AHIP_LoopOffset:
1225 loopoffset=tag->ti_Data;
1226 loopsetsound=TRUE; // AHIP_LoopSound: doesn't have to be present
1227 break;
1228 case AHIP_LoopLength:
1229 looplength=tag->ti_Data;
1230 break;
1231 case AHIP_EndChannel:
1232 if(setfreq)
1233 AHI_SetFreq( channel, freq, (struct AHIAudioCtrl*) audioctrl, AHISF_IMM );
1234 if(loopsetfreq)
1235 AHI_SetFreq( channel, loopfreq, (struct AHIAudioCtrl*) audioctrl, AHISF_NONE );
1236 if(setvol)
1237 AHI_SetVol( channel, vol, pan, (struct AHIAudioCtrl*) audioctrl, AHISF_IMM );
1238 if(loopsetvol)
1239 AHI_SetVol( channel, loopvol, looppan, (struct AHIAudioCtrl*) audioctrl, AHISF_NONE );
1240 if(setsound)
1241 AHI_SetSound( channel, sound, offset, length, (struct AHIAudioCtrl*) audioctrl, AHISF_IMM );
1242 if(loopsetsound)
1243 AHI_SetSound( channel, loopsound, loopoffset, looplength, (struct AHIAudioCtrl*) audioctrl, AHISF_NONE);
1244 break;
1248 AHIsub_Enable((struct AHIAudioCtrlDrv *)audioctrl);
1249 return 0;
1253 /******************************************************************************
1254 ** AHI_SampleFrameSize ********************************************************
1255 ******************************************************************************/
1257 /****** ahi.device/AHI_SampleFrameSize **************************************
1259 * NAME
1260 * AHI_SampleFrameSize -- get the size of a sample frame (V4)
1262 * SYNOPSIS
1263 * size = AHI_SampleFrameSize( sampletype );
1264 * D0 D0
1266 * ULONG AHI_SampleFrameSize( ULONG );
1268 * FUNCTION
1269 * Returns the size in bytes of a sample frame for a given sample type.
1271 * INPUTS
1272 * sampletype - The sample type to examine. See <devices/ahi.h> for
1273 * possible types.
1275 * RESULT
1276 * The number of bytes, or 0 for invalid types.
1278 * EXAMPLE
1280 * NOTES
1282 * BUGS
1283 * This function returned trash for invalid sample types
1284 * before V6.
1286 * SEE ALSO
1287 * <devices/ahi.h>
1289 ****************************************************************************
1293 static const UBYTE type2bytes[]=
1295 1, // AHIST_M8S (0)
1296 2, // AHIST_M16S (1)
1297 2, // AHIST_S8S (2)
1298 4, // AHIST_S16S (3)
1299 1, // AHIST_M8U (4)
1303 4, // AHIST_M32S (8)
1305 8 // AHIST_S32S (10)
1308 ULONG
1309 _AHI_SampleFrameSize( ULONG sampletype,
1310 struct AHIBase* AHIBase )
1312 ULONG result = 0;
1314 if(sampletype <= AHIST_S32S )
1316 result = type2bytes[sampletype];
1318 else if(sampletype == AHIST_L7_1)
1320 result = 32;
1323 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
1325 Debug_SampleFrameSize(sampletype);
1326 KPrintF("=>%ld\n",type2bytes[sampletype]);
1329 return result;