7 * The sampler routines are just
for fun
. Since interrupts must
not be disabled
,
8 * there are lots
of clicks
.
31 EXEC_MACROS_I SET
1 ; Fake a bit to avoid exec
/macros
.i problems
40 *************************************************************************
42 PRINTF MACRO
; level
,<string>,...
49 PUSHCOUNT SET PUSHCOUNT
+4
54 PUSHCOUNT SET PUSHCOUNT
+4
59 PUSHCOUNT SET PUSHCOUNT
+4
64 PUSHCOUNT SET PUSHCOUNT
+4
69 PUSHCOUNT SET PUSHCOUNT
+4
74 PUSHCOUNT SET PUSHCOUNT
+4
79 PUSHCOUNT SET PUSHCOUNT
+4
90 IFEQ
(\1&1) ;If even
, add CR
/LF par
...
96 lea
.l PUSHCOUNT
(sp
),sp
97 ENDC
;IFGE DEBUG_DETAIL
-\1
102 include hardware
/cia
.i
103 include hardware
/custom
.i
104 include hardware
/intbits
.i
105 include hardware
/dmabits
.i
108 include devices
/audio
.i
109 include devices
/timer
.i
111 include dos
/dostags
.i
113 include graphics
/gfxbase
.i
114 include intuition
/intuitionbase
.i
115 include intuition
/screens
.i
116 include resources
/misc
.i
117 include resources
/card
.i
118 include utility
/utility
.i
119 include utility
/hooks
.i
121 include lvo
/cardres_lib
.i
122 include lvo
/dos_lib
.i
123 include lvo
/exec_lib
.i
124 include lvo
/graphics_lib
.i
125 include lvo
/intuition_lib
.i
126 include lvo
/timer_lib
.i
127 include lvo
/utility_lib
.i
129 include devices
/ahi
.i
130 include libraries
/ahi_sub
.i
131 include lvo
/ahi_sub_lib
.i
144 std equrl d2
-d7
/a2
-a6
157 AUD0LC EQU aud0
+ac_ptr
158 AUD0LEN EQU aud0
+ac_len
159 AUD0PER EQU aud0
+ac_per
160 AUD0VOL EQU aud0
+ac_vol
161 AUD0DAT EQU aud0
+ac_dat
163 AUD1LC EQU aud1
+ac_ptr
164 AUD1LEN EQU aud1
+ac_len
165 AUD1PER EQU aud1
+ac_per
166 AUD1VOL EQU aud1
+ac_vol
167 AUD1DAT EQU aud1
+ac_dat
169 AUD2LC EQU aud2
+ac_ptr
170 AUD2LEN EQU aud2
+ac_len
171 AUD2PER EQU aud2
+ac_per
172 AUD2VOL EQU aud2
+ac_vol
173 AUD2DAT EQU aud2
+ac_dat
175 AUD3LC EQU aud3
+ac_ptr
176 AUD3LEN EQU aud3
+ac_len
177 AUD3PER EQU aud3
+ac_per
178 AUD3VOL EQU aud3
+ac_vol
179 AUD3DAT EQU aud3
+ac_dat
200 INTF_AUDIO EQU INTF_AUD3|INTF_AUD2|INTF_AUD1|INTF_AUD0
207 DMABUFFSAMPLES EQU
512 ; 8 of these will be allocated
!
208 RECORDSAMPLES EQU
1024
211 EXTRABUFFSIZE EQU EXTRASAMPLES
*8 ; 4 samples
of max size
( 2×
32 bit
: hifi stereo
)
213 * paula
.audio extra tags
214 AHIDB_Paula14Bit EQU AHIDB_UserBase
+0 * Boolean
215 AHIDB_PaulaTable EQU AHIDB_UserBase
+1 * Boolean
216 AHIDB_PaulaDMA EQU AHIDB_UserBase
+2 * Boolean
218 * paulaBase
(private)
219 STRUCTURE paulaBase
,LIB_SIZE
232 ULONG pb_AudioFreq
;PAL
/NTSC clock
constant
234 LABEL paulaBase_SIZEOF
236 * channel
(private) used
in DMA mode
239 UWORD ch_IntMask
;This channels interrupt bit
240 UWORD ch_DMAMask
;This channels DMA bit
241 UWORD ch_Stereo
;0 = Left
, 1 = Right
243 UBYTE ch_EndOfSample
;Flag
244 UBYTE ch_NoInt
;SetFreq
() must
not cause interrupt
246 APTR ch_RegBase
;This channels hardware register base
248 ULONG ch_Cleared
;Samples already cleared
249 ULONG ch_Cleared2
;Samples already cleared
251 ULONG ch_Count
;How mant samples played?
(In samples
)
253 APTR ch_Address
;Current sample address
254 APTR ch_NextAddress
;Next sample address
256 ULONG ch_Offset
;Where are we playing?
(In samples
)
257 ULONG ch_NextOffset
;Next
...
259 ULONG ch_Length
;Current sample length
(In samples
)
260 ULONG ch_NextLength
;Next sample length
262 ULONG ch_Type
;Current sample
type
263 ULONG ch_NextType
;Next sample
type
266 UWORD ch_Period
;Current period
(0 = stopped
)
267 UWORD ch_Volume
;Current volume
(scaled
)
269 UWORD ch_NextPeriod
;Next period
270 UWORD ch_NextVolume
;Next volume
(scaled
)
275 UWORD ch_NextVolumeNorm
277 UWORD ch_Scale
;Current frequency scale
(2^ch_Scale
)
278 UWORD ch_NextScale
;Next frequency scale
280 STRUCT ch_SndMsg
,AHISoundMessage_SIZEOF
284 * sound
(private) used
in DMA mode
292 * paula
(private) ahiac_DriverData points to this structure
.
295 UBYTE p_Parallel
;TRUE if parport allocated
296 UBYTE p_Filter
;TRUE if filter was on
when alocating
298 UWORD p_DisableCount
;AHIsub_Enable
/AHIsub_Disable cnt
301 APTR p_PaulaBase
;Pointer to library base
(DMA only
)
302 APTR p_AudioCtrl
;Backpointer to AudioCtrl struct
.
304 UBYTE p_SwapChannels
;TRUE if left
/right should be swapped
305 UBYTE p_ScreenIsDouble
;TRUE if screen mode allows
>28kHz
311 ULONG p_MinBufferLength
;Minimum length
of chipmem playbuffer
312 APTR p_CalibrationTable
;Pointer to
14 bit conversion tables
314 APTR p_DMAbuffer
;Chipmem play buffer
315 ULONG p_DoubleBufferOffset
;Buffer flag
317 LABEL p_AudPtrs
; Pointers to chipmem play buffer
327 APTR p_audioport
;For audio
.device
328 APTR p_audioreq
;For audio
.device
329 UBYTE p_audiodev
;For audio
.device
332 APTR p_ParBitsUser
;Parallel port locking
333 APTR p_ParPortUser
;Parallel port locking
334 APTR p_SerBitsUser
;Serial port locking
335 APTR p_CardHandle
;Aura PCMCIA card handle
337 STRUCT p_PlayInt
,IS_SIZE
;Player hardware interrupt
338 STRUCT p_PlaySoftInt
,IS_SIZE
;Player software interrupt
(mixing only
)
339 STRUCT p_RecInt
,IS_SIZE
;Recorder hardware interrupt
(mixing only
)
340 STRUCT p_RecSoftInt
,IS_SIZE
;Recorder software interrupt
(mixing only
)
342 UWORD p_AudPer
;Playback period
(mixing only
)
343 UWORD p_OutputVolume
;Hardware volume
(mixing only
)
344 UWORD p_MonitorVolume
;Monitor volume
(mixing only
)
345 UWORD p_Input
;Input
select (mixing only
)
348 ULONG p_LoopLeftovers
;(mixing only
)
349 ULONG p_SampleFrameShift
;Size
of sample fram
is 2^x
(mixing only
)
351 ULONG p_LoopTimes
;(mixing only
)
354 LABEL p_PlayerHookRegs
;PlayerHook
357 FPTR p_PlayerEntry
;p_PlayerHook
->h_Entry
359 LABEL p_MixHookRegs
;MixingHook
(mixing only
)
362 FPTR p_MixEntry
;p_MixHook
->h_Entry
364 LABEL p_RecIntDataAura
;Record data structure
for Aura sampl
.
365 APTR p_AuraAddress
;DO NOT CHANGE ORDER
!
366 LABEL p_RecIntData
;Record data structure
374 LABEL p_RecordMessage
;Message used
with SamplerFunc
()
379 ULONG p_EClock
;System E clock freq
. (DMA only
)
380 ULONG p_EPeriod
;PlayerFunc
() E clk period
(DMA only
)
381 STRUCT p_EAlarm
,EV_SIZE
;E Clock to wait
for (DMA only
)
382 STRUCT p_TimerPort
,MP_SIZE
;(DMA only
)
383 STRUCT p_TimerInt
,IS_SIZE
;(DMA only
)
384 APTR p_TimerReq
;Used to drive PlayerFunc
() (DMA only
)
385 UBYTE p_TimerDev
;(DMA only
)
387 UWORD p_TimerCommFlag
;Used to
end timer
(DMA only
)
389 ULONG p_MasterVolume
;Effect parameter
(DMA only
)
390 APTR p_ChannelInfo
;Effect structure
(DMA only
)
393 STRUCT p_Channels
,channel_SIZEOF
*4 ;DMA playback channel info
395 STRUCT p_CalibrationArray
,256 ;14 bit calibration prefs
402 PB_STEREO EQU AHIACB_STEREO
;=2
403 PF_STEREO EQU AHIACF_STEREO
415 DC
.B VERSION
;version
422 LibName
: dc
.b
"paula.audio",0
424 gfxName
: GRAPHICSNAME
425 utilName
: UTILITYNAME
427 intuiName
: dc
.b
"intuition.library",0
428 timerName
: dc
.b
"timer.device",0
430 cardName
: dc
.b
"card.resource",0
431 mosName
: dc
.b
"MorphOS",0
432 filterVar
: dc
.b
"AHIpaulaFilterFreq",0
433 screenVar
: dc
.b
"AHIpaulaSampleLimit",0
434 bufferVar
: dc
.b
"AHIpaulaBufferLength",0
435 swapVar
: dc
.b
"AHIpaulaSwapChannels",0
436 fakefreqVar
: dc
.b
"AHIpaulaFakeMixFreq",0
437 taskVar
: dc
.b
"AHIpaulaMixTaskPri",0
441 DC
.L paulaBase_SIZEOF
452 dc
.l AHIsub_AllocAudio
453 dc
.l AHIsub_FreeAudio
462 dc
.l AHIsub_SetEffect
463 dc
.l AHIsub_LoadSound
464 dc
.l AHIsub_UnloadSound
466 dc
.l AHIsub_HardwareControl
470 INITBYTE LN_TYPE
,NT_LIBRARY
471 INITLONG LN_NAME
,LibName
472 INITBYTE LIB_FLAGS
,LIBF_SUMUSED|LIBF_CHANGED
473 INITWORD LIB_VERSION
,VERSION
474 INITWORD LIB_REVISION
,REVISION
475 INITLONG LIB_IDSTRING
,IDString
479 movem
.l d1
/a0
/a1
/a5
/a6
,-(sp
)
482 move
.l a6
,pb_SysLib
(a5
)
483 move
.l a0
,pb_SegList
(a5
)
488 move
.l d0
,pb_GfxLib
(a5
)
490 ALERT AG_OpenLib|AO_GraphicsLib
496 move
.l d0
,pb_UtilLib
(a5
)
498 ALERT AG_OpenLib|AO_UtilityLib
504 move
.l d0
,pb_DosLib
(a5
)
506 ALERT AG_OpenLib|AO_DOSLib
512 move
.l d0
,pb_IntuiLib
(a5
)
514 ALERT AG_OpenLib|AO_Intuition
519 move
.l d0
,pb_MiscResource
(a5
)
521 ALERT AG_OpenRes|AO_MiscRsrc
526 move
.l d0
,pb_CardResource
(a5
) ;Don
't fail on error
528 move
.l #PALFREQ
,d1
;PAL
529 move
.l pb_GfxLib
(a5
),a0
530 move
.w gb_DisplayFlags
(a0
),d0
533 move
.l #NTSCFREQ
,d1
;NTSC
535 move
.l d1
,pb_AudioFreq
(a5
)
539 movem
.l
(sp
)+,d1
/a0
/a1
/a5
/a6
543 move
.l pb_IntuiLib
(a5
),a1
546 move
.l pb_DosLib
(a5
),a1
549 move
.l pb_UtilLib
(a5
),a1
552 move
.l pb_GfxLib
(a5
),a1
557 move
.w LIB_NEGSIZE
(a5
),d0
559 add
.w LIB_POSSIZE
(a5
),d0
566 addq
.w #
1,LIB_OPENCNT
(a6
)
567 bclr
.b #LIBB_DELEXP
,pb_Flags
(a6
)
573 subq
.w #
1,LIB_OPENCNT
(a6
)
575 btst
.b #LIBB_DELEXP
,pb_Flags
(a6
)
582 movem
.l d1
/d2
/a0
/a1
/a5
/a6
,-(sp
)
584 move
.l pb_SysLib
(a5
),a6
585 tst
.w LIB_OPENCNT
(a5
)
587 bset
.b #LIBB_DELEXP
,pb_Flags
(a5
)
591 move
.l pb_IntuiLib
(a5
),a1
594 move
.l pb_DosLib
(a5
),a1
597 move
.l pb_UtilLib
(a5
),a1
600 move
.l pb_GfxLib
(a5
),a1
606 move
.l pb_SegList
(a5
),d2
610 move
.w LIB_NEGSIZE
(a5
),d0
612 add
.w LIB_POSSIZE
(a5
),d0
617 movem
.l
(sp
)+,d1
/d2
/a0
/a1
/a5
/a6
624 * BeginIO
(ioRequest
)(a1
) (From amiga
.lib
)
626 ;move
.l a1
,a0
;probably
not necessary
628 move
.l IO_DEVICE
(a1
),a6
635 * a0 Environment variable to get
640 move
.l d0
,d5
;Default
642 move
.l pb_DosLib
(a5
),a6
643 subq
.l #
8,sp
;local label
644 move
.w #
("0"<<8)|
0,(sp
) ;Initialize as
"0"
652 addq
.l #
1,d0
;cmp
.l #
-1,d0
662 ; d5
is now the
integer value
667 ****** [driver
].audio
/--background-- ****************************************
671 * GENERAL PROGRAMMING GUIDLINES
673 * The driver must be able to be OpenLibrary
()'ed even
if the
674 * hardware
is not present
. If a library the driver uses fails
675 * to open
, it
is ok to fail
at the library init routine
, but please
676 * avoid it
if possible
.
678 * Please note that this document could be much better
, but since
not
679 * many will ever need to read it
, it will probably stay this way
.
680 * Don
't hesitate to contact Martin Blom
when you
're writing a driver
!
684 * The lowest supported driver version
is 2. If you
use any feature
685 * introduced
in later versions
of AHI
, you should set the driver
686 * version to the same version as the features were introduced
with.
687 * Example
: You
use PreTimer
() and PostTimer
(), and since these
688 * calls were added
in V4
of ahi
.device
, your driver
's version should
691 * Note that AHI version
4 will
not open V6 drivers
, for obvious
696 * Just some notes about selecting ID numbers
for different modes
:
697 * It
is up to the driver programmer to chose which modes should be
698 * available to the user
. Take care
when selecting
.
700 * The upper word
is the hardware ID
, and can only be allocated by
701 * Martin Blom
<lcs@lysator
.liu
.se
>. The lower word
is free
, but
in
702 * order to allow enhancements
, please only
use bit
0 to
4 for modes
!
703 * If your driver supports multiple sound cards
, use bit
12-15 to
704 * select card
(first one
is 0). If your sound card has multiple
705 * AD
/DA converters
, you can
use bit
8-11 to
select them
(the first
708 * Set the remaining bits to zero
.
710 * Use AHI
:Developer
/Support
/ScanAudioModes to have a look
at the modes
711 * currently available
. Use AHI
:Developer
/Support
/sift to make sure your
712 * mode descriptor file
is a legal IFF file
.
714 * I
do reserve the right to change the rules
if I find them incorrect
!
716 *****************************************************************************
721 ****** [driver
].audio
/AHIsub_AllocAudio
*************************************
724 * AHIsub_AllocAudio
-- Allocates and initializes the audio hardware.
727 * result
= AHIsub_AllocAudio
( tags
, audioctrl
);
730 * ULONG AHIsub_AllocAudio
( struct TagItem
*, struct AHIAudioCtrlDrv
* );
733 * Allocate
and initialize the audio hardware
. Decide
if and how you
734 * wish to
use the mixing routines provided by
'ahi.device', by looking
735 * in the AHIAudioCtrlDrv structure
and parsing the tag list
for tags
738 * 1) Use mixing routines
with timing
:
739 * You will need to be able to play any number
of samples from
740 * about
80 up to
65535 with low overhead
.
741 * · Update AudioCtrl
->ahiac_MixFreq to nearest value that your
743 * ·
Return AHISF_MIXING|AHISF_TIMING
.
745 * 2) Use mixing routines without timing
:
746 * If the hardware can
't play samples
with any length
, use this
747 * alternative
and provide timing yourself
. The buffer must
748 * take less than about
20 ms to play
, preferable less than
10!
749 * · Update AudioCtrl
->ahiac_MixFreq to nearest value that your
751 * · Store the number
of samples to mix each pass
in
752 * AudioCtrl
->ahiac_BuffSamples
.
753 * ·
Return AHISF_MIXING
754 * Alternatively
, you can
use the first method
and call the
755 * mixing hook several times
in a row to fill up a buffer
.
756 * In that
case, AHIsub_GetAttr
(AHIDB_MaxPlaySamples
) should
757 * return the size
of the buffer plus AudioCtrl
->ahiac_MaxBuffSamples
.
758 * If the buffer
is so large that it takes more than
(approx
.) 10 ms to
759 * play it
for high sample frequencies
, AHIsub_GetAttr
(AHIDB_Realtime
)
760 * should
return FALSE.
762 * 3) Don
't use mixing routines
:
763 * If your hardware can handle everything without using the CPU to
764 * mix the channels
, you tell
'ahi.device' this by
not setting
765 * either the AHISB_MIXING
or the AHISB_TIMING bit
.
767 * If you can handle stereo output from the mixing routines
, also set
768 * bit AHISB_KNOWSTEREO
.
770 * If you can handle hifi
(32 bit
) output from the mixing routines
,
771 * set bit AHISB_KNOWHIFI
.
773 * If this driver can be used to
record samples
, set bit AHISB_CANRECORD
,
774 * too
(regardless
if you
use the mixing routines
in AHI
or not).
776 * If the sound card has hardware to
do DSP effects
, you can set the
777 * AHISB_CANPOSTPROCESS bit
. The output from the mixing routines will
778 * then be two
separate buffers
, one wet
and one dry
. You should
then
779 * apply the Fx on the wet buffer
, and post
-mix the two buffers before
780 * you send the samples to the DAC
. (V4
)
783 * tags
- pointer to a taglist
.
784 * audioctrl
- pointer to an AHIAudioCtrlDrv structure
.
787 * The tags are from the audio database
(AHIDB_#?
in <devices
/ahi
.h
>),
788 * NOT the tag list the user called ahi
.device
/AHI_AllocAudio
() with.
791 * Flags
, defined
in <libraries
/ahi_sub
.h
>.
796 * You don
't have to clean up on failure
, AHIsub_FreeAudio
() will
802 * AHIsub_FreeAudio
(), AHIsub_Start
()
804 *****************************************************************************
809 PRINTF
2,"\e[0;0H\e[J"
810 PRINTF
2,"AHIsub_AllocAudio()"
818 * Allocate the
'paula' structure
(our variables
)
819 move
.l pb_SysLib
(a5
),a6
820 move
.l #paula_SIZEOF
,d0
821 move
.l #MEMF_PUBLIC|MEMF_CLEAR
,d1
823 move
.l d0
,ahiac_DriverData
(a2
)
827 * Initialize some fields
...
830 move
.l #
-1,p_ParBitsUser
(a3
)
831 move
.l #
-1,p_ParPortUser
(a3
)
832 move
.l #
-1,p_SerBitsUser
(a3
)
833 move
.l a5
,p_PaulaBase
(a3
)
834 move
.l a2
,p_AudioCtrl
(a3
)
835 lea p_RecSoftInt
(a3
),a0
836 move
.l a0
,p_RecSoftIntPtr
(a3
)
837 move
.l #AHIST_S16S
,p_rmType
(a3
)
838 move
.l #RECORDSAMPLES
,p_rmLength
(a3
)
839 move
.w #
64,p_OutputVolume
(a3
)
840 move
.l #$
10000,p_MasterVolume
(a3
)
842 * Translate tags to flags
843 move
.l pb_UtilLib
(a5
),a6
845 move
.l ahiac_Flags
(a2
),d2
846 and.b #PF_STEREO
,d2
;same as AHIACF_STEREO
848 move
.l #AHIDB_Paula14Bit
,d0
850 move
.l d3
,a0
;tag list
856 move
.l #AHIDB_HiFi
,d0
858 move
.l d3
,a0
;tag list
864 move
.l #AHIDB_PaulaDMA
,d0
866 move
.l d3
,a0
;tag list
873 move
.b p_Flags
(a3
),d1
874 and.b #~
(PF_STEREO|PF_14BIT|PF_HIFI|PF_DMA
),d1
876 move
.b d1
,p_Flags
(a3
)
879 move
.b d0
,p_ScreenIsDouble
(a3
)
881 * Check
if a table should be used
(14 bit calibration
)
882 move
.l #AHIDB_PaulaTable
,d0
884 move
.l d3
,a0
;tag list
889 * Load
'ENV:CyberSound/SoundDrivers/14Bit_Calibration', allocate
890 * and initialize the table
.
891 * FIXIT
: The calibration file should move to a special chunk
in
892 * 'DEVS:AudioModes/PAULA'.
893 move
.l pb_DosLib
(a5
),a6
894 lea
.calibname
(pc
),a0
896 move
.l #MODE_OLDFILE
,d2
901 lea p_CalibrationArray
(a3
),a0
909 lea p_CalibrationArray
(a3
),a0
920 move
.l pb_SysLib
(a5
),a6
922 move
.l #MEMF_PUBLIC
,d1
924 move
.l d0
,p_CalibrationTable
(a3
)
927 lea p_CalibrationArray
(a3
),a1
931 * Get the minimum chip buffer size
935 move
.l d0
,p_MinBufferLength
(a3
)
937 * Check
if we should swap left
& right channels
941 move
.b d0
,p_SwapChannels
(a3
)
943 * Check
if we should
use a
task instead
of a software interrupt
944 move
.l #
128,d0
;Default
(softint
)
947 move
.w d0
,p_MixTaskPri
(a3
)
950 move
.l pb_SysLib
(a5
),a6
956 * If MorphOS
, check internal lock
958 move
.l pb_Lock
(a5
),d0
960 move
.l a3
,pb_Lock
(a5
)
967 * allocate audio
.device
969 move
.l pb_SysLib
(a5
),a6
971 move
.l d0
,p_audioport
(a3
)
974 move
.l #MEMF_PUBLIC|MEMF_CLEAR
,d1
976 move
.l d0
,p_audioreq
(a3
)
979 move
.l p_audioport
(a3
),MN_REPLYPORT
(a0
)
980 clr
.w ioa_AllocKey
(a0
)
981 move
.b #
127,LN_PRI
(a0
) ;steal it
!
982 lea
.audiochannelarray
(pc
),a1
983 move
.l a1
,ioa_Data
(a0
)
984 move
.l #
1,ioa_Length
(a0
)
985 lea
.audioname
(pc
),a0
987 move
.l p_audioreq
(a3
),a1
990 move
.b d0
,p_audiodev
(a3
)
991 bne
.error_noaudiodev
;somebody already owns the hardware
(could be us
!)
992 move
.l p_audioreq
(a3
),a1
993 move
.w #CMD_RESET
,IO_COMMAND
(a1
)
994 bsr
.w BeginIO
;clear attach
, stop sound
.
995 move
.l p_audioport
(a3
),a0
997 move
.l p_audioport
(a3
),a0
1000 move
.l pb_DosLib
(a5
),a6
1006 * Set dummy interrupt handler
1007 move
.l pb_SysLib
(a5
),a6
1008 move
.l #Interrupt_Dummy
,IS_CODE
+p_PlayInt
(a3
)
1010 lea p_PlayInt
(a3
),a1
1013 lea p_PlayInt
(a3
),a1
1016 lea p_PlayInt
(a3
),a1
1019 lea p_PlayInt
(a3
),a1
1023 * test
if mode supports recording
1024 move
.b p_Flags
(a3
),d0
1025 and.b #PF_14BIT|PF_DMA
,d0
1026 bne
.dontgetsampler
;no
record if 14 bit
and DMA modes
1028 * try to allocate parallel port
1029 clr
.b p_Parallel
(a3
)
1030 move
.l pb_MiscResource
(a5
),a6
1031 moveq #MR_PARALLELBITS
,d0
1033 jsr MR_ALLOCMISCRESOURCE
(a6
)
1034 move
.l d0
,p_ParBitsUser
(a3
)
1036 moveq #MR_PARALLELPORT
,d0
1038 jsr MR_ALLOCMISCRESOURCE
(a6
)
1039 move
.l d0
,p_ParPortUser
(a3
)
1042 move
.b #
TRUE,p_Parallel
(a3
)
1043 move
.b #
0,_ciaa
+ciaddrb
;make PB0
-PB7 inputs
1046 * allocate Aura sampler
1047 clr
.l p_AuraAddress
(a3
)
1048 move
.l pb_CardResource
(a5
),d0
1055 move
.l cmm_IOMemory
(a0
),d2
1058 move
.l pb_SysLib
(a5
),a6
1059 moveq #CardHandle_SIZEOF
,d0
1060 move
.l #MEMF_PUBLIC|MEMF_CLEAR
,d1
1062 move
.l d0
,p_CardHandle
(a3
)
1065 move
.l pb_CardResource
(a5
),a6
1067 move
.l #IDString
,LN_NAME
(a1
)
1068 move
.b #CARDF_RESETREMOVE|CARDF_IFAVAILABLE
,cah_CardFlags
(a1
)
1073 move
.l p_CardHandle
(a3
),a1
1074 call BeginCardAccess
1076 move
.l d2
,p_AuraAddress
(a3
)
1082 * initialize interrupts
(Only dummy
function pointers
at this time
)
1084 * p_PlayInt
(the main playback interrupt
)
1085 move
.b #NT_INTERRUPT
,LN_TYPE
+p_PlayInt
(a3
)
1086 move
.l #LibName
,LN_NAME
+p_PlayInt
(a3
)
1087 move
.l #Interrupt_Dummy
,IS_CODE
+p_PlayInt
(a3
)
1088 move
.l a3
,IS_DATA
+p_PlayInt
(a3
)
1090 * p_PlaySoftInt
(caused by p_PlayInt
, here are the mixing
and conversion done
)
1091 move
.b #NT_INTERRUPT
,LN_TYPE
+p_PlaySoftInt
(a3
)
1092 move
.l #LibName
,LN_NAME
+p_PlaySoftInt
(a3
)
1093 move
.l #SoftInt_Dummy
,IS_CODE
+p_PlaySoftInt
(a3
)
1094 move
.l a3
,IS_DATA
+p_PlaySoftInt
(a3
)
1096 * p_RecInt
(the interrupt used
for recording
)
1097 move
.b #NT_INTERRUPT
,LN_TYPE
+p_RecInt
(a3
)
1098 move
.l #LibName
,LN_NAME
+p_RecInt
(a3
)
1099 move
.l #Interrupt_Dummy
,IS_CODE
+p_RecInt
(a3
)
1100 clr
.l IS_DATA
+p_RecInt
(a3
)
1102 * p_RecSoftInt
(caused by p_RecInt
when the
record buffer has been filled
)
1103 move
.b #
32,LN_PRI
+p_RecSoftInt
(a3
)
1104 move
.b #NT_INTERRUPT
,LN_TYPE
+p_RecSoftInt
(a3
)
1105 move
.l #LibName
,LN_NAME
+p_RecSoftInt
(a3
)
1106 move
.l #RecordSoftInt
,IS_CODE
+p_RecSoftInt
(a3
)
1107 move
.l a3
,IS_DATA
+p_RecSoftInt
(a3
)
1109 * Make sure no interrupts occur
until AHIsub_Start
() is called
1110 move
.w #INTF_AUDIO
,custom
+INTENA
1111 move
.w #INTF_SETCLR
,p_IRQMask
(a3
)
1113 * Update ahiac_MixFreq to what the mixing
/sampling frequency really
is
1114 moveq #
0,d0
;Default
1115 lea fakefreqVar
(pc
),a0
1119 move
.l ahiac_MixFreq
(a2
),d0
1121 move
.l d0
,ahiac_MixFreq
(a2
) ;store actual freq
1124 * Save the filter state
1128 * Check the AHIpaulaFilterFreq variable
.
1129 * If the mixing frequency
is higher than this one
, set disable the filter
,
1131 moveq #
0,d0
;Default freq
1132 lea filterVar
(pc
),a0
1134 cmp
.l ahiac_MixFreq
(a2
),d0
1136 bclr #
1,$bfe001
;turn audio filter on
1139 bset #
1,$bfe001
;turn audio filter off
1142 btst
.b #PB_DMA
,p_Flags
(a3
)
1145 cmp
.w #
4,ahiac_Channels
(a2
)
1148 move
.l pb_AudioFreq
(a5
),ahiac_MixFreq
(a2
) ;store actual freq
1150 move
.l #AHIST_NOTYPE
,p_Channels
+channel_SIZEOF
*0+ch_Type
(a3
)
1151 move
.l #AHIST_NOTYPE
,p_Channels
+channel_SIZEOF
*1+ch_Type
(a3
)
1152 move
.l #AHIST_NOTYPE
,p_Channels
+channel_SIZEOF
*2+ch_Type
(a3
)
1153 move
.l #AHIST_NOTYPE
,p_Channels
+channel_SIZEOF
*3+ch_Type
(a3
)
1154 move
.l #AHIST_NOTYPE
,p_Channels
+channel_SIZEOF
*0+ch_NextType
(a3
)
1155 move
.l #AHIST_NOTYPE
,p_Channels
+channel_SIZEOF
*1+ch_NextType
(a3
)
1156 move
.l #AHIST_NOTYPE
,p_Channels
+channel_SIZEOF
*2+ch_NextType
(a3
)
1157 move
.l #AHIST_NOTYPE
,p_Channels
+channel_SIZEOF
*3+ch_NextType
(a3
)
1158 move
.w #
0,p_Channels
+channel_SIZEOF
*0+ch_SndMsg
+ahism_Channel
(a3
)
1159 move
.w #
1,p_Channels
+channel_SIZEOF
*1+ch_SndMsg
+ahism_Channel
(a3
)
1160 move
.w #
2,p_Channels
+channel_SIZEOF
*2+ch_SndMsg
+ahism_Channel
(a3
)
1161 move
.w #
3,p_Channels
+channel_SIZEOF
*3+ch_SndMsg
+ahism_Channel
(a3
)
1163 move
.l pb_SysLib
(a5
),a6
1164 move
.w ahiac_Sounds
(a2
),d0
1165 mulu
.w #sound_SIZEOF
,d0
1166 move
.l #MEMF_PUBLIC|MEMF_CLEAR
,d1
1168 move
.l d0
,p_Sounds
(a3
)
1169 beq
.error_nosoundmem
1172 move
.w ahiac_Sounds
(a2
),d0
1175 move
.l #AHIST_NOTYPE
,so_Type
(a0
)
1176 add
.w #sound_SIZEOF
,a0
1179 tst
.b p_SwapChannels
(a3
)
1181 move
.l #custom
+AUD1
,p_Channels
+channel_SIZEOF
*0+ch_RegBase
(a3
)
1182 move
.l #custom
+AUD0
,p_Channels
+channel_SIZEOF
*1+ch_RegBase
(a3
)
1183 move
.l #custom
+AUD2
,p_Channels
+channel_SIZEOF
*2+ch_RegBase
(a3
)
1184 move
.l #custom
+AUD3
,p_Channels
+channel_SIZEOF
*3+ch_RegBase
(a3
)
1185 move
.w #DMAF_AUD1
,p_Channels
+channel_SIZEOF
*0+ch_DMAMask
(a3
)
1186 move
.w #DMAF_AUD0
,p_Channels
+channel_SIZEOF
*1+ch_DMAMask
(a3
)
1187 move
.w #DMAF_AUD2
,p_Channels
+channel_SIZEOF
*2+ch_DMAMask
(a3
)
1188 move
.w #DMAF_AUD3
,p_Channels
+channel_SIZEOF
*3+ch_DMAMask
(a3
)
1189 move
.w #INTF_AUD1
,p_Channels
+channel_SIZEOF
*0+ch_IntMask
(a3
)
1190 move
.w #INTF_AUD0
,p_Channels
+channel_SIZEOF
*1+ch_IntMask
(a3
)
1191 move
.w #INTF_AUD2
,p_Channels
+channel_SIZEOF
*2+ch_IntMask
(a3
)
1192 move
.w #INTF_AUD3
,p_Channels
+channel_SIZEOF
*3+ch_IntMask
(a3
)
1193 move
.w #
0,p_Channels
+channel_SIZEOF
*0+ch_Stereo
(a3
)
1194 move
.w #
1,p_Channels
+channel_SIZEOF
*1+ch_Stereo
(a3
)
1195 move
.w #
1,p_Channels
+channel_SIZEOF
*2+ch_Stereo
(a3
)
1196 move
.w #
0,p_Channels
+channel_SIZEOF
*3+ch_Stereo
(a3
)
1199 move
.l #custom
+AUD0
,p_Channels
+channel_SIZEOF
*0+ch_RegBase
(a3
)
1200 move
.l #custom
+AUD1
,p_Channels
+channel_SIZEOF
*1+ch_RegBase
(a3
)
1201 move
.l #custom
+AUD3
,p_Channels
+channel_SIZEOF
*2+ch_RegBase
(a3
)
1202 move
.l #custom
+AUD2
,p_Channels
+channel_SIZEOF
*3+ch_RegBase
(a3
)
1203 move
.w #DMAF_AUD0
,p_Channels
+channel_SIZEOF
*0+ch_DMAMask
(a3
)
1204 move
.w #DMAF_AUD1
,p_Channels
+channel_SIZEOF
*1+ch_DMAMask
(a3
)
1205 move
.w #DMAF_AUD3
,p_Channels
+channel_SIZEOF
*2+ch_DMAMask
(a3
)
1206 move
.w #DMAF_AUD2
,p_Channels
+channel_SIZEOF
*3+ch_DMAMask
(a3
)
1207 move
.w #INTF_AUD0
,p_Channels
+channel_SIZEOF
*0+ch_IntMask
(a3
)
1208 move
.w #INTF_AUD1
,p_Channels
+channel_SIZEOF
*1+ch_IntMask
(a3
)
1209 move
.w #INTF_AUD3
,p_Channels
+channel_SIZEOF
*2+ch_IntMask
(a3
)
1210 move
.w #INTF_AUD2
,p_Channels
+channel_SIZEOF
*3+ch_IntMask
(a3
)
1211 move
.w #
1,p_Channels
+channel_SIZEOF
*0+ch_Stereo
(a3
)
1212 move
.w #
0,p_Channels
+channel_SIZEOF
*1+ch_Stereo
(a3
)
1213 move
.w #
0,p_Channels
+channel_SIZEOF
*2+ch_Stereo
(a3
)
1214 move
.w #
1,p_Channels
+channel_SIZEOF
*3+ch_Stereo
(a3
)
1222 moveq #AHISF_KNOWSTEREO|AHISF_KNOWHIFI|AHISF_CANRECORD|AHISF_MIXING|AHISF_TIMING
,d0
1235 moveq #AHISF_ERROR
,d0
1243 dc
.b
"ENV:CyberSound/SoundDrivers/14Bit_Calibration",0
1246 dc
.l
0,0 ;ln_Succ
, ln_Pred
1249 dc
.l IDString
;ln_Name
1250 dc
.l
0,0,0 ;cah_CardRemoved
, cah_CardInserted
, cah_CardStatus
1251 dc
.b
(CARDF_RESETREMOVE|CARDF_IFAVAILABLE
)
1261 * Calculate
and return the best period
and the actual frequency
.
1263 PRINTF
2,"calcperiod()"
1266 move
.l pb_AudioFreq
(a5
),d2
1269 move
.l pb_UtilLib
(a5
),a1
1270 jsr _LVOUDivMod32
(a1
)
1277 * d4
is now period
. Check
if is it a valid one
, depending on current display mode
1292 move
.l pb_UtilLib
(a5
),a1
1293 jsr _LVOUDivMod32
(a1
)
1306 * d0
TRUE if current mode
is double
1308 * Checks
if the current screen mode
is doublescan
.
1309 * This routine
is a bit ugly
, but it does get the job
1310 * done
, even
if a graphic card
is used
.
1312 PRINTF
2,"checkvideo"
1316 * Check the AHIpaulaSampleLimit variable
.
1317 * If 1, allow
> 28 kHz frequencies
, if 0, don
't. If not present
,
1318 * check the screen mode
.
1321 lea screenVar
(pc
),a0
1323 addq
.l #
1,d0
; cmp
.l #
-1,d0
1326 subq
.l #
1,d0
; cmp
.l #
0,d0
1328 subq
.l #
1,d0
; cmp
.l #
1,d0
1333 ; Chip revision test
1335 move
.l pb_GfxLib
(a5
),a0
1336 move
.b gb_ChipRevBits0
(a0
),d0
1337 and.b #GFXF_HR_DENISE|GFXF_AA_LISA
,d0
1338 beq
.no31k
; OCS
: No
31 kHz modes
1340 ; Native screen test
1343 move
.l pb_IntuiLib
(a5
),a6
1346 move
.l ib_FirstScreen
(a6
),a0
1347 lea sc_ViewPort
(a0
),a0
1348 move
.l pb_GfxLib
(a5
),a6
1352 move
.l pb_IntuiLib
(a5
),a6
1355 ; "Check" if native screen
1361 sub
.w #mtr_SIZEOF
,sp
;local storage
1364 move
.l #mtr_SIZEOF
,d0
1365 move
.l #DTAG_MNTR
,d1
1366 move
.l pb_GfxLib
(a5
),a6
1367 call GetDisplayInfoData
1370 add
.w mtr_TotalRows
(sp
),d1
1371 sub
.w mtr_MinRow
(sp
),d1
1372 move
.w mtr_TotalColorClocks
(sp
),d2
1373 mulu
.w mtr_TotalRows
(sp
),d2
1375 add
.w #mtr_SIZEOF
,sp
;restore stack
1378 ; Calculate TotalColorClocks
*TotalRows
/(2*(TotalRows
-MinRow
+1)
1382 cmp
.w #
64,d2
; 64 is an round nice number
, no?
1390 move.l pb_SysLib(a5),a6
1391 lea .picasso96(pc),a1
1392 call Forbid ; Not required, it's just to...
1394 call Permit ; ...make PatchWork happy.
1396 beq .cgfx ; Not P96, assume CyberGraphX
1398 move.l pb_DosLib(a5),a6
1399 clr.l -(sp) ;Initialize local data
1400 lea .p96amigavideo(pc),a0
1416 move.l pb_GfxLib(a5),a0
1417 cmp.w #39,LIB_VERSION(a0)
1419 cmp.w #40,LIB_VERSION(a0)
1423 move.l gb_copinit(a0),a0
1424 cmp.w #$01FC,copinit_fm0(a0) ;Security check (test if really FMODE)
1425 bne .is31k ;Probably an ECS machine.
1426 ;Assume the user is clever enough
1427 ;to use "AddAudioModes DBLSCAN"....
1428 move.w copinit_fm0+2(a0),d0
1429 and.w #$c000,d0 ;Mask sprite and bitplane double bit
1442 dc.b "Picasso96/AmigaVideo",0
1448 * d0 Closest frequency
1478 dc.l 8000 ; µ- and A-Law, DAT/6
1486 dc.l 19200 ; DAT/2.5
1490 FREQUENCIES_OCS EQU (*-freqlist)>>2
1492 dc.l 32000 ; DAT/1.5
1497 FREQUENCIES EQU (*-freqlist)>>2
1500 * _CreateTable directly stolen from Christian Buchner's CyberSound
1501 * audio sub system (with permission).
1503 * _CreateTable **************************************************************
1507 ; a0 = Table address
1508 ; (MUST have enough space for 65536 UWORDS)
1509 ; a1 = Additive Array
1512 ; the table is organized as follows:
1513 ; 32768 UWORDS positive range, ascending order
1514 ; 32768 UWORDS negative range, ascending order
1515 ; access: (a0,d0.l*2)
1516 ; where d0.w is signed word sample data
1517 ; and the upper word of d0.l is *cleared!*
1520 _CreateTable movem.l a2/d2-d6,-(sp)
1524 move.l a2,a1 ; count the number of steps
1525 moveq #128-1,d0 ; in the positive range
1527 .countpositive move.b (a1)+,d1
1531 dbra d0,.countpositive ; d5=number of steps
1532 move.l #32768,d6 ; reset stretch counter
1534 move.l a2,a1 ; middle value in calibdata
1535 move.w #32768-1,d0 ; number of positive values -1
1536 moveq #0,d1 ; HI value
1537 moveq #0,d2 ; LO value
1538 moveq #0,d3 ; counter
1539 .fetchnext2 move.b (a1)+,d4 ; add calibtable to counter
1542 .outerloop2 tst.w d3
1544 .negative2 addq.w #1,d1 ; increment HI value
1545 sub.w d4,d2 ; reset LO value
1547 .positive2 move.b d1,(a0)+ ; store HI and LO value
1549 sub.l d5,d6 ; stretch the table
1550 bpl.s .repeat2 ; to 32768 entries
1552 addq.w #1,d2 ; increment LO value
1553 subq.w #1,d3 ; decrement counter
1554 .repeat2 dbra d0,.outerloop2
1556 move.l a2,a1 ; count the number of steps
1557 moveq #128-1,d0 ; in the negative range
1559 .countnegative move.b -(a1),d1
1563 dbra d0,.countnegative ; d5=number of steps
1564 move.l #32768,d6 ; reset stretch counter
1566 add.l #2*32768,a0 ; place at the end of the table
1567 move.l a2,a1 ; middle value in calibdata
1568 move.w #32768-1,d0 ; number of negative values -1
1569 moveq #-1,d1 ; HI value
1570 moveq #-1,d2 ; LO value
1571 moveq #0,d3 ; counter
1572 .fetchnext1 move.b -(a1),d4 ; add calibtable to counter
1575 add.w d4,d2 ; maximize LO value
1576 .outerloop1 tst.w d3
1578 .negative1 subq.w #1,d1
1580 .positive1 move.b d2,-(a0) ; store LO and HI value
1582 sub.l d5,d6 ; stretch the table
1583 bpl.s .repeat1 ; to 32768 entries
1585 subq.w #1,d2 ; decrement lo value
1586 subq.w #1,d3 ; decrement counter
1587 .repeat1 dbra d0,.outerloop1
1589 movem.l (sp)+,a2/d2-d6
1593 ****** [driver].audio/AHIsub_FreeAudio **************************************
1596 * AHIsub_FreeAudio -- Deallocates the audio hardware.
1599 * AHIsub_FreeAudio( audioctrl );
1602 * void AHIsub_FreeAudio( struct AHIAudioCtrlDrv * );
1605 * Deallocate the audio hardware and other resources allocated in
1606 * AHIsub_AllocAudio(). AHIsub_Stop() will always be called by
1607 * 'ahi
.device
' before this call is made.
1610 * audioctrl - pointer to an AHIAudioCtrlDrv structure.
1613 * It must be safe to call this routine even if AHIsub_AllocAudio()
1614 * was never called, failed or called more than once.
1617 * AHIsub_AllocAudio()
1619 *****************************************************************************
1624 PRINTF 2,"AHIsub_FreeAudio()"
1628 move.l pb_SysLib(a5),a6
1630 move.l ahiac_DriverData(a2),d0
1634 move.l p_Sounds(a3),d0
1640 move.l p_CalibrationTable(a3),d0
1648 bclr #1,$bfe001 ;turn audio filter on
1651 bset #1,$bfe001 ;turn audio filter off
1655 tst.b p_audiodev(a3)
1658 move.l p_audioreq(a3),a1
1659 move.w #CMD_RESET,IO_COMMAND(a1) ;Restore audio interrupts
1661 move.l p_audioport(a3),a0
1663 move.l p_audioport(a3),a0
1665 move.l p_audioreq(a3),a1
1668 move.l p_audioreq(a3),d0
1673 move.l p_audioport(a3),d0
1680 cmp.l pb_Lock(a5),a3
1686 tst.l p_AuraAddress(a3)
1688 move.l pb_CardResource(a5),d0
1691 move.l p_CardHandle(a3),d0
1695 move.l p_CardHandle(a3),a1
1696 moveq #CARDF_REMOVEHANDLE,d0
1699 move.l pb_SysLib(a5),a6
1700 move.l p_CardHandle(a3),d0
1705 move.l pb_MiscResource(a5),a6
1706 tst.l p_ParPortUser(a3)
1708 moveq #MR_PARALLELPORT,d0
1709 jsr MR_FREEMISCRESOURCE(a6)
1711 tst.l p_ParBitsUser(a3)
1713 moveq #MR_PARALLELBITS,d0
1714 jsr MR_FREEMISCRESOURCE(a6)
1716 tst.l p_SerBitsUser(a3)
1718 moveq #MR_SERIALBITS,d0
1719 jsr MR_FREEMISCRESOURCE(a6)
1721 move.l pb_SysLib(a5),a6
1723 clr.l ahiac_DriverData(a2)
1726 ;moveq #0,d0 ; void function, no returncode needed
1731 ****** [driver].audio/AHIsub_Disable ****************************************
1734 * AHIsub_Disable -- Temporary turn off audio interrupt/task
1737 * AHIsub_Disable( audioctrl );
1740 * void AHIsub_Disable( struct AHIAudioCtrlDrv * );
1743 * If you are lazy, then call exec.library/Disable().
1744 * If you are smart, only disable your own interrupt or task.
1747 * audioctrl - pointer to an AHIAudioCtrlDrv structure.
1750 * This call should be guaranteed to preserve all registers.
1751 * V6 drivers do NOT have to preserve all registers.
1755 * AHIsub_Enable(), exec.library/Disable()
1757 *****************************************************************************
1763 PRINTF 6,"AHIsub_Disable()"
1765 move.l ahiac_DriverData(a2),a3
1766 move.l p_PaulaBase(a3),a6
1767 move.l pb_SysLib(a6),a6
1769 move.w #INTF_AUDIO,custom+INTENA ; Turn off ALL audio interrupts
1770 addq.w #1,p_DisableCount(a3)
1771 ; PRINTF 0,"Disable: Wrote $%04lx to intena",#INTF_AUDIO
1772 ; PRINTF 0,"Count: %d",p_DisableCount(a3)
1778 ****** [driver].audio/AHIsub_Enable *****************************************
1781 * AHIsub_Enable -- Turn on audio interrupt/task
1784 * AHIsub_Enable( audioctrl );
1787 * void AHIsub_Enable( struct AHIAudioCtrlDrv * );
1790 * If you are lazy, then call exec.library/Enable().
1791 * If you are smart, only enable your own interrupt or task.
1794 * audioctrl - pointer to an AHIAudioCtrlDrv structure.
1797 * This call should be guaranteed to preserve all registers.
1798 * V6 drivers do NOT have to preserve all registers.
1802 * AHIsub_Disable(), exec.library/Enable()
1804 *****************************************************************************
1810 PRINTF 6,"AHIsub_Enable()"
1812 move.l ahiac_DriverData(a2),a3
1813 move.l p_PaulaBase(a3),a6
1814 move.l pb_SysLib(a6),a6
1816 subq.w #1,p_DisableCount(a3)
1818 move.w p_IRQMask(a3),custom+INTENA
1819 ; PRINTF 0,"Enable: Wrote $%04x to intena",p_IRQMask(a3)
1821 ; PRINTF 0,"Count: %d",p_DisableCount(a3)
1827 ****** [driver].audio/AHIsub_Start ******************************************
1830 * AHIsub_Start -- Starts playback or recording
1833 * error = AHIsub_Start( flags, audioctrl );
1836 * ULONG AHIsub_Start(ULONG, struct AHIAudioCtrlDrv * );
1839 * What to do depends what you returned in AHIsub_AllocAudio().
1841 * * First, assume bit AHISB_PLAY in flags is set. This means that you
1842 * should begin playback.
1844 * - AHIsub_AllocAudio() returned AHISF_MIXING|AHISF_TIMING:
1846 * A) Allocate a mixing buffer of ahiac_BuffSize bytes. The buffer must
1848 * B) Create/start an interrupt or task that will do 1-6 over and over
1849 * again until AHIsub_Stop() is called. Note that it is not a good
1850 * idea to do the actual mixing and conversion in a real hardware
1851 * interrupt. Signal a task or create a Software Interrupt to do
1852 * the number crunching.
1854 * 1) Call the user Hook ahiac_PlayerFunc with the following parameters:
1855 * A0 - (struct Hook *)
1856 * A2 - (struct AHIAudioCtrlDrv *)
1859 * 2) [Call the ahiac_PreTimer function. If it returns TRUE (Z will be
1860 * cleared so you don't have to test d0), skip step 3 and 4. This
1861 * is used to avoid overloading the CPU. This step is optional.
1862 * A2 is assumed to point to struct AHIAudioCtrlDrv. All registers
1863 * except d0 are preserved. (V4)
1865 * Starting with V6, you can also call the pre-timer Hook
1866 * (ahiac_PreTimerFunc) with the following parameters:
1867 * A0 - (struct Hook *) - The Hook itself
1868 * A2 - (struct AHIAudioCtrlDrv *)
1870 * The Hook is not guaranteed to preserve all registers and
1871 * you must check the return value and not rely on the Z flag. (V6)
1873 * This step, 2, is optional.]
1875 * 3) Call the mixing Hook (ahiac_MixerFunc) with the following
1877 * A0 - (struct Hook *) - The Hook itself
1878 * A2 - (struct AHIAudioCtrlDrv *)
1879 * A1 - (WORD *[]) - The mixing buffer.
1880 * Note that ahiac_MixerFunc preserves ALL registers.
1881 * The user Hook ahiac_SoundFunc will be called by the mixing
1882 * routine when a sample have been processed, so you don't have to
1884 * How the buffer will be filled is indicated by ahiac_Flags.
1885 * It is always filled with signed 16-bit (32 bit if AHIACB_HIFI in
1886 * in ahiac_Flags is set) words, even if playback is 8 bit. If
1887 * AHIDBB_STEREO is set (in ahiac_Flags), data for left and right
1888 * channel are interleaved:
1889 * 1st sample left channel,
1890 * 1st sample right channel,
1891 * 2nd sample left channel,
1893 * ahiac_BuffSamples:th sample left channel,
1894 * ahiac_BuffSamples:th sample right channel.
1895 * If AHIDBB_STEREO is cleared, the mono data is stored:
1899 * ahiac_BuffSamples:th sample.
1900 * Note that neither AHIACB_STEREO nor AHIACB_HIFI will be set if
1901 * you didn't report that you understand these flags when
1902 * AHI_AllocAudio() was called.
1904 * For AHI V2, the type of buffer is also available in ahiac_BuffType.
1905 * It is suggested that you use this value instead. ahiac_BuffType
1906 * can be one of AHIST_M16S, AHIST_S16S, AHIST_M32S and AHIST_S32S.
1908 * 4) Convert the buffer if needed and feed it to the audio hardware.
1909 * Note that you may have to clear CPU caches if you are using DMA
1910 * to play the buffer, and the buffer is not allocated in non-
1911 * cachable RAM (which is not a good idea anyway, for performace
1914 * 5) [Call the ahiac_PostTimer function. A2 is assumed to point to
1915 * struct AHIAudioCtrlDrv. All registers are preserved. (V4)
1917 * Starting with V6, you can also call the post-timer Hook
1918 * (ahiac_PostTimerFunc) with the following parameters:
1919 * A0 - (struct Hook *) - The Hook itself
1920 * A2 - (struct AHIAudioCtrlDrv *)
1922 * The Hook is not guaranteed to preserve all registers. (V6)
1924 * This step, 5, is optional.]
1926 * 6) Wait until the whole buffer has been played, then repeat.
1928 * Use double buffering if possible!
1930 * You may DECREASE ahiac_BuffSamples slightly, for example to force an
1931 * even number of samples to be mixed. By doing this you will make
1932 * ahiac_PlayerFunc to be called at wrong frequency so be careful!
1933 * Even if ahiac_BuffSamples is defined ULONG, it will never be greater
1936 * ahiac_BuffSize is the largest size of the mixing buffer that will be
1937 * needed until AHIsub_Stop() is called.
1939 * ahiac_MaxBuffSamples is the maximum number of samples that will be
1940 * mixed (until AHIsub_Stop() is called). You can use this value if you
1941 * need to allocate DMA buffers.
1943 * ahiac_MinBuffSamples is the minimum number of samples that will be
1944 * mixed. Most drivers will ignore it.
1946 * If AHIsub_AllocAudio() returned with the AHISB_CANPOSTPROCESS bit set,
1947 * ahiac_BuffSize is large enough to hold two buffers. The mixing buffer
1948 * will be filled with the wet buffer first, immediately followed by the
1949 * dry buffer. I.e., ahiac_BuffSamples sample frames wet data, then
1950 * ahiac_BuffSamples sample frames dry data. The DSP fx should only be
1951 * applied to the wet buffer, and the two buffers should then be added
1954 * - If AHIsub_AllocAudio() returned AHISF_MIXING, do as described above,
1955 * except calling ahiac_PlayerFunc. ahiac_PlayerFunc should be called
1956 * ahiac_PlayerFreq times per second, clocked by timers on your sound
1957 * card or by using 'timer
.device
' or 'realtime
.library
'. No other Amiga
1958 * resources may be used for timing (like direct CIA timers).
1959 * ahiac_MinBuffSamples and ahiac_MaxBuffSamples are undefined if
1960 * AHIsub_AllocAudio() returned AHISF_MIXING (AHISB_TIMING bit not set).
1962 * - If AHIsub_AllocAudio() returned with neither the AHISB_MIXING nor
1963 * the AHISB_TIMING bit set, then just start playback. Don't forget to
1964 * call ahiac_PlayerFunc ahiac_PlayerFreq times per second. Only your
1965 * own timing hardware, 'timer
.device
' or 'realtime
.library
' may be
1966 * used. Note that ahiac_MixerFunc, ahiac_BuffSamples,
1967 * ahiac_MinBuffSamples, ahiac_MaxBuffSamples and ahiac_BuffSize are
1968 * undefined. ahiac_MixFreq is the frequency the user wants to use for
1969 * recording, if you support that.
1971 * * Second, assume bit AHISB_RECORD in flags is set. This means that you
1972 * should start to sample. Create a interrupt or task that does the
1975 * Allocate a buffer (you chose size, but try to keep it reasonable
1976 * small to avoid delays - it is suggested that RecordFunc is called
1977 * at least 4 times/second for the lowers sampling rate, and more often
1978 * for higher rates), and fill it with the sampled data. The buffer must
1979 * be long aligned, and it's size must be evenly divisible by four.
1980 * The format should always be AHIST_S16S (even with 8 bit mono samplers),
1982 * 1st sample left channel,
1983 * 1st sample right channel (same as prev. if mono),
1984 * 2nd sample left channel,
1986 * Each sample is a signed word (WORD). The sample rate should be equal
1987 * to the mixing rate.
1989 * Call the ahiac_SamplerFunc Hook with the following parameters:
1990 * A0 - (struct Hook *) - The Hook itself
1991 * A2 - (struct AHIAudioCtrlDrv *)
1992 * A1 - (struct AHIRecordMessage *)
1993 * The message should be filled as follows:
1994 * ahirm_Type - Set to AHIST_S16S.
1995 * ahirm_Buffer - A pointer to the filled buffer.
1996 * ahirm_Samples - How many sample frames stored.
1997 * You must not destroy the buffer until next time the Hook is called.
1999 * Repeat until AHIsub_Stop() is called.
2001 * * Note that both bits may be set when this function is called.
2004 * flags - See <libraries/ahi_sub.h>.
2005 * audioctrl - pointer to an AHIAudioCtrlDrv structure.
2008 * Returns AHIE_OK if successful, else an error code as defined
2009 * in <devices/ahi.h>. AHIsub_Stop() will always be called, even
2010 * if this call failed.
2013 * The driver must be able to handle multiple calls to this routine
2014 * without preceding calls to AHIsub_Stop().
2017 * AHIsub_Update(), AHIsub_Stop()
2019 *****************************************************************************
2025 PRINTF 2,"AHIsub_Start()"
2031 move.l ahiac_DriverData(a2),a3
2039 moveq #AHISF_PLAY,d0
2040 call AHIsub_Stop ;Stop current playback if any.
2041 call AHIsub_Update ;fill variables
2044 move.l pb_SysLib(a5),a6
2046 btst #PB_DMA,p_Flags(a3)
2052 move.l ahiac_BuffSize(a2),d0
2053 add.l #EXTRABUFFSIZE,d0 ;Add space for 4 sample frames
2054 move.l #MEMF_PUBLIC|MEMF_CLEAR,d1
2056 move.l d0,p_Mixbuffer(a3)
2059 move.l ahiac_MixFreq(a2),d0
2061 move.w d1,p_AudPer(a3)
2063 * The init*bit? routines allocates p_DMAbuffer, sets up
2064 * p_AudPtr, sets the volume, stores the correct interrupt routines in
2065 * p_PlayInt's and p_PlaySoftInt's IS_CODE.
2068 move.b p_Flags(a3),d0
2069 and.b #PF_STEREO|PF_14BIT,d0
2083 move.w p_MixTaskPri(a3),d0
2087 move.l sp,d2 ;Save sp
2088 move.l #TAG_DONE,-(sp)
2090 move.l #NP_Entry,-(sp)
2092 move.l #NP_Name,-(sp)
2094 move.l #NP_Priority,-(sp)
2095 move.l pb_SysLib(a5),a6
2098 move.l pb_DosLib(a5),a6
2100 move.l d2,sp ;Restore sp
2101 move.l d0,p_MixTask(a3)
2104 move.l a3,TC_Userdata(a0) ;Send struct as argument
2106 move.l pb_SysLib(a5),a6
2109 ; If it worked, it worked. If not, softints will still be used.
2113 * Install play interrupt
2114 lea p_PlayInt(a3),a1
2118 or.w #INTF_SETCLR|INTF_AUD0,p_IRQMask(a3)
2121 tst.w p_DisableCount(a3)
2123 move.w #INTF_SETCLR|INTF_AUD0,INTENA(a4) ;enable
2125 move.w #INTF_SETCLR|INTF_AUD0,INTREQ(a4) ;start
2132 btst #AHISB_RECORD,d7
2138 move.b p_Flags(a3),d0 ;Sanity check...
2139 and.b #PF_14BIT|PF_DMA,d0
2142 moveq #AHISF_RECORD,d0
2143 call AHIsub_Stop ;Stop current recording if any.
2146 move.l pb_SysLib(a5),a6
2148 move.l #RECORDSAMPLES*4,d0
2149 move.l #MEMF_PUBLIC,d1
2151 move.l d0,p_RecBuffer1(a3)
2154 move.l d0,p_RecFillPtr(a3)
2155 move.w #RECORDSAMPLES,p_RecFillCount(a3)
2157 move.l #RECORDSAMPLES*4,d0
2158 move.l #MEMF_PUBLIC,d1
2160 move.l d0,p_RecBuffer2(a3)
2163 move.l ahiac_MixFreq(a2),d0
2165 lsr.w #1,d1 ;Period/2 => Frequency·2
2166 move.w d1,AUD2PER(a4)
2167 move.w d1,AUD3PER(a4)
2168 move.w p_MonitorVolume(a3),d0
2169 move.w d0,AUD2VOL(a4)
2170 move.w d0,AUD3VOL(a4)
2172 * Install record interrupt
2173 move.w p_Input(a3),d0
2182 tst.b p_Parallel(a3) ;Parrallel port allocated?
2184 lea p_RecIntData(a3),a1
2185 move.l a1,IS_DATA+p_RecInt(a3)
2186 move.l #RecordInterrupt,IS_CODE+p_RecInt(a3)
2188 move.b #$ff,_ciab+ciaddrb ; Set parallel port to output
2193 tst.b p_Parallel(a3) ;Parrallel port allocated?
2196 move.l pb_MiscResource(a5),a6
2197 move.l #MR_SERIALBITS,d0 ; allocate serial port control lines
2199 jsr MR_ALLOCMISCRESOURCE(a6)
2200 move.l d0,p_SerBitsUser(a3)
2203 lea p_RecIntData(a3),a1
2204 move.l a1,IS_DATA+p_RecInt(a3)
2205 move.l #RecordInterruptClarity,IS_CODE+p_RecInt(a3)
2207 ; Set DTR, PRTBUSY and PRTRPOUT to outputs
2208 or.b #CIAF_COMDTR!CIAF_PRTRBUSY!CIAF_PRTRPOUT,_ciab+ciaddra
2209 move.b #$ff,_ciab+ciaddrb ; Set parallel port to output
2211 move.b #CIAF_PRTRBUSY!CIAF_PRTRPOUT,_ciab+ciapra
2212 move.b #CIAF_PRTRPOUT,_ciab+ciapra
2213 move.b #CIAF_PRTRBUSY!CIAF_PRTRPOUT,_ciab+ciapra
2214 ; Clarity is now in stereo record mode
2219 tst.l p_AuraAddress(a3) ;Aura sampler allocated?
2221 lea p_RecIntDataAura(a3),a1
2222 move.l a1,IS_DATA+p_RecInt(a3)
2223 move.l #RecordInterruptAura,IS_CODE+p_RecInt(a3)
2227 move.l pb_SysLib(a5),a6
2232 move.w #DMAF_AUD2|DMAF_AUD3,DMACON(a4) ;disable DMA
2233 or.w #INTF_SETCLR|INTF_AUD3,p_IRQMask(a3)
2234 move.w #INTF_SETCLR|INTF_AUD3,INTENA(a4) ;enable
2235 move.w #INTF_SETCLR|INTF_AUD3,INTREQ(a4) ;start
2244 moveq #AHIE_NOMEM,d0
2247 moveq #AHIE_UNKNOWN,d0
2258 PRINTF 2,"init8bitM()"
2259 move.l #AudioInterrupt2,IS_CODE+p_PlayInt(a3)
2260 move.l #SoftInt_8bitM,IS_CODE+p_PlaySoftInt(a3)
2262 move.l #1,p_SampleFrameShift(a3) ;log2( sizeof( AHIST_M16S ) )
2264 move.b p_Flags(a3),d0
2267 move.l #SoftInt_8bitMH,IS_CODE+p_PlaySoftInt(a3)
2269 move.l #2,p_SampleFrameShift(a3) ;log2( sizeof( AHIST_M32S ) )
2273 move.l p_MinBufferLength(a3),d0
2274 add.l ahiac_MaxBuffSamples(a2),d0 ;Max. # of 8 bit samples
2275 addq.l #EXTRASAMPLES,d0
2277 and.b #~3,d0 ;make it a multiple of 4
2278 move.l d0,d2 ;d2 = channel size
2280 lsl.l #1,d0 ;Double buffer
2281 move.l #MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR,d1
2283 move.l d0,p_DMAbuffer(a3)
2286 move.l d0,p_AudPtr1A(a3)
2287 move.l d0,p_AudPtr2A(a3)
2289 move.l d0,p_AudPtr1B(a3)
2290 move.l d0,p_AudPtr2B(a3)
2292 ; move.w #64,AUD0VOL(a4)
2293 ; move.w #64,AUD1VOL(a4)
2298 moveq #AHIE_NOMEM,d0
2307 PRINTF 2,"init8bitS()"
2308 move.l #AudioInterrupt2,IS_CODE+p_PlayInt(a3)
2309 move.l #SoftInt_8bitS,IS_CODE+p_PlaySoftInt(a3)
2311 move.l #2,p_SampleFrameShift(a3) ;log2( sizeof( AHIST_S16S ) )
2313 move.b p_Flags(a3),d0
2316 move.l #SoftInt_8bitSH,IS_CODE+p_PlaySoftInt(a3)
2318 move.l #3,p_SampleFrameShift(a3) ;log2( sizeof( AHIST_S32S ) )
2322 move.l p_MinBufferLength(a3),d0
2323 add.l ahiac_MaxBuffSamples(a2),d0 ;Max. # of 8 bit samples
2324 addq.l #EXTRASAMPLES,d0
2326 and.b #~3,d0 ;make it a multiple of 4
2327 move.l d0,d2 ;d2 = channel size
2329 lsl.l #2,d0 ;Double buffer + Stereo
2330 move.l #MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR,d1
2332 move.l d0,p_DMAbuffer(a3)
2335 move.l d0,p_AudPtr1A(a3)
2337 move.l d0,p_AudPtr2A(a3)
2339 move.l d0,p_AudPtr1B(a3)
2341 move.l d0,p_AudPtr2B(a3)
2343 ; move.w #64,AUD0VOL(a4)
2344 ; move.w #64,AUD1VOL(a4)
2349 moveq #AHIE_NOMEM,d0
2358 PRINTF 2,"init14bitM()"
2359 move.l #AudioInterrupt4,IS_CODE+p_PlayInt(a3)
2360 lea SoftInt_14bitM(pc),a0
2362 move.l #1,p_SampleFrameShift(a3) ;log2( sizeof( AHIST_M16S ) )
2364 move.b p_Flags(a3),d0
2367 lea SoftInt_14bitMH(pc),a0
2369 move.l #2,p_SampleFrameShift(a3) ;log2( sizeof( AHIST_M32S ) )
2372 tst.l p_CalibrationTable(a3)
2374 lea SoftInt_14CbitM(pc),a0
2375 move.b p_Flags(a3),d0
2378 lea SoftInt_14CbitMH(pc),a0
2381 move.l a0,IS_CODE+p_PlaySoftInt(a3)
2383 move.l p_MinBufferLength(a3),d0
2384 add.l ahiac_MaxBuffSamples(a2),d0 ;Max. # of 16 bit samples
2385 addq.l #EXTRASAMPLES,d0
2387 and.b #~3,d0 ;make it a multiple of 4
2388 move.l d0,d2 ;d2 = channel size
2390 lsl.l #2,d0 ;Double buffer + 2×8 bit
2391 move.l #MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR,d1
2393 move.l d0,p_DMAbuffer(a3)
2396 move.l d0,p_AudPtr1A(a3)
2397 move.l d0,p_AudPtr2A(a3)
2399 move.l d0,p_AudPtr4A(a3)
2400 move.l d0,p_AudPtr3A(a3)
2402 move.l d0,p_AudPtr1B(a3)
2403 move.l d0,p_AudPtr2B(a3)
2405 move.l d0,p_AudPtr4B(a3)
2406 move.l d0,p_AudPtr3B(a3)
2408 ; move.w #64,AUD0VOL(a4)
2409 ; move.w #64,AUD1VOL(a4)
2410 ; move.w #1,AUD2VOL(a4)
2411 ; move.w #1,AUD3VOL(a4)
2416 moveq #AHIE_NOMEM,d0
2425 PRINTF 2,"init14bitS()"
2426 move.l #AudioInterrupt4,IS_CODE+p_PlayInt(a3)
2427 lea SoftInt_14bitS(pc),a0
2429 move.l #2,p_SampleFrameShift(a3) ;log2( sizeof( AHIST_S16S ) )
2431 move.b p_Flags(a3),d0
2434 lea SoftInt_14bitSH(pc),a0
2436 move.l #3,p_SampleFrameShift(a3) ;log2( sizeof( AHIST_S32S ) )
2439 tst.l p_CalibrationTable(a3)
2441 lea SoftInt_14CbitS(pc),a0
2442 move.b p_Flags(a3),d0
2445 lea SoftInt_14CbitSH(pc),a0
2448 move.l a0,IS_CODE+p_PlaySoftInt(a3)
2450 move.l p_MinBufferLength(a3),d0
2451 add.l ahiac_MaxBuffSamples(a2),d0 ;Max. # of 16 bit samples
2452 addq.l #EXTRASAMPLES,d0
2454 and.b #~3,d0 ;make it a multiple of 4
2455 move.l d0,d2 ;d2 = channel size
2457 lsl.l #3,d0 ;Double buffer + 2×8 bit + Stereo
2458 move.l #MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR,d1
2460 move.l d0,p_DMAbuffer(a3)
2463 move.l d0,p_AudPtr1A(a3)
2465 move.l d0,p_AudPtr2A(a3)
2467 move.l d0,p_AudPtr3A(a3)
2469 move.l d0,p_AudPtr4A(a3)
2471 move.l d0,p_AudPtr1B(a3)
2473 move.l d0,p_AudPtr2B(a3)
2475 move.l d0,p_AudPtr3B(a3)
2477 move.l d0,p_AudPtr4B(a3)
2479 ; move.w #64,AUD0VOL(a4)
2480 ; move.w #64,AUD1VOL(a4)
2481 ; move.w #1,AUD2VOL(a4)
2482 ; move.w #1,AUD3VOL(a4)
2487 moveq #AHIE_NOMEM,d0
2491 ****** [driver].audio/AHIsub_Update *****************************************
2494 * AHIsub_Update -- Update some variables
2497 * AHIsub_Update( flags, audioctrl );
2500 * void AHIsub_Update(ULONG, struct AHIAudioCtrlDrv * );
2503 * All you have to do is to reread some variables:
2505 * * Mixing & timing: ahiac_PlayerFunc, ahiac_MixerFunc, ahiac_SamplerFunc,
2506 * ahiac_BuffSamples (and perhaps ahiac_PlayerFreq if you use it).
2508 * * Mixing only: ahiac_PlayerFunc, ahiac_MixerFunc, ahiac_SamplerFunc and
2511 * * Nothing: ahiac_PlayerFunc, ahiac_SamplerFunc and ahiac_PlayerFreq.
2514 * flags - Currently no flags defined.
2515 * audioctrl - pointer to an AHIAudioCtrlDrv structure.
2520 * This call must be safe from interrupts.
2525 *****************************************************************************
2531 PRINTF 2,"AHIsub_Update()"
2534 call AHIsub_Disable ;make sure we don't get an interrupt
2535 ;while updating our local variables
2536 move.l ahiac_DriverData(a2),a3
2538 move.l ahiac_PlayerFunc(a2),a0
2539 move.l a0,p_PlayerHook(a3)
2540 move.l h_Entry(a0),p_PlayerEntry(a3)
2542 btst #PB_DMA,p_Flags(a3)
2549 move.l ahiac_BuffSamples(a2),d1
2550 and.b #~3,d1 ;make it a multiple of 4
2551 move.l d1,ahiac_BuffSamples(a2)
2555 move.l d0,p_LoopTimes(a3) ;See softints. (Unrolled)
2558 PRINTF 4, "ahiac_BuffSamples is %ld", ahiac_BuffSamples(a2)
2560 move.l ahiac_MixerFunc(a2),a0
2561 move.l a0,p_MixHook(a3)
2562 move.l h_Entry(a0),p_MixEntry(a3)
2566 ;moveq #0,d0 ; void function, no returncode needed
2571 ****** [driver].audio/AHIsub_Stop *******************************************
2574 * AHIsub_Stop -- Stops playback.
2577 * AHIsub_Stop( flags, audioctrl );
2580 * void AHIsub_Stop( ULONG, struct AHIAudioCtrlDrv * );
2583 * Stop playback and/or recording, remove all resources allocated by
2587 * flags - See <libraries/ahi_sub.h>.
2588 * audioctrl - pointer to an AHIAudioCtrlDrv structure.
2591 * It must be safe to call this routine even if AHIsub_Start() was never
2592 * called, failed or called more than once.
2597 *****************************************************************************
2602 PRINTF 2,"AHIsub_Stop()"
2607 move.l pb_SysLib(a5),a6
2608 move.l ahiac_DriverData(a2),a3
2618 btst #PB_DMA,p_Flags(a3)
2624 move.w #DMAF_AUDIO,DMACON(a4) ;disable audio DMA
2626 and.w #~INTF_AUD0,p_IRQMask(a3)
2627 move.w #INTF_AUD0,INTENA(a4)
2628 move.w #INTF_AUD0,INTREQ(a4) ;Clear any waiting interrupts
2629 move.l #Interrupt_Dummy,IS_CODE+p_PlayInt(a3)
2630 lea p_PlayInt(a3),a1
2635 move.w d0,AUD0VOL(a4)
2636 move.w d0,AUD1VOL(a4)
2637 move.w d0,AUD2VOL(a4)
2638 move.w d0,AUD3VOL(a4)
2645 move.l d0,p_ReplyTask(a3)
2647 move.l #SIGF_SINGLE,d1 ;Clear SINGLE signal
2649 move.l p_MixTask(a3),a1
2650 move.l #SIGBREAKF_CTRL_C,d0 ;Kill child
2652 move.l #SIGF_SINGLE,d0
2653 call Wait ;Wait until child is dead
2656 move.l p_DMAbuffer(a3),d0
2659 clr.l p_DMAbuffer(a3)
2662 move.l p_Mixbuffer(a3),d0
2665 clr.l p_Mixbuffer(a3)
2672 btst #AHISB_RECORD,d0
2678 btst #PB_14BIT,p_Flags(a3) ;Sanity check...
2681 and.w #~INTF_AUD3,p_IRQMask(a3)
2682 move.w #INTF_AUD3,INTENA(a4)
2683 move.w #INTF_AUD3,INTREQ(a4) ;Clear any waiting interrupts
2685 move.l #Interrupt_Dummy,IS_CODE+p_RecInt(a3)
2690 move.w #0,AUD2VOL(a4)
2691 move.w #0,AUD3VOL(a4)
2693 move.l p_RecBuffer1(a3),d0
2696 clr.l p_RecBuffer1(a3)
2699 move.l p_RecBuffer2(a3),d0
2702 clr.l p_RecBuffer2(a3)
2707 ;moveq #0,d0 ; void function, no returncode needed
2712 ****** [driver].audio/AHIsub_GetAttr ****************************************
2715 * AHIsub_GetAttr -- Returns information about audio modes or driver
2718 * AHIsub_GetAttr( attribute, argument, default, taglist, audioctrl );
2721 * LONG AHIsub_GetAttr( ULONG, LONG, LONG, struct TagItem *,
2722 * struct AHIAudioCtrlDrv * );
2725 * Return the attribute based on a tag list and an AHIAudioCtrlDrv
2726 * structure, which are the same that will be passed to
2727 * AHIsub_AllocAudio() by 'ahi
.device
'. If the attribute is
2728 * unknown to you, return the default.
2731 * attribute - Is really a Tag and can be one of the following:
2733 * AHIDB_Bits - Return how many output bits the tag list will
2736 * AHIDB_MaxChannels - Return the maximum number of channels.
2738 * AHIDB_Frequencies - Return how many mixing/sampling frequencies
2741 * AHIDB_Frequency - Return the argument:th frequency
2742 * Example: You support 3 frequencies; 32, 44.1 and 48 kHz.
2743 * If argument is 1, return 44100.
2745 * AHIDB_Index - Return the index which gives the frequency closest
2747 * Example: You support 3 frequencies; 32, 44.1 and 48 kHz.
2748 * If argument is 40000, return 1 (=> 44100).
2750 * AHIDB_Author - Return pointer to name of driver author:
2751 * "Martin 'Leviticus
' Blom"
2753 * AHIDB_Copyright - Return pointer to copyright notice, including
2754 * the '©
' character: "© 1996 Martin Blom" or "Public Domain"
2756 * AHIDB_Version - Return pointer version string, normal Amiga
2757 * format: "paula 1.5 (18.2.96)\r\n"
2759 * AHIDB_Annotation - Return pointer to an annotation string, which
2760 * can be several lines.
2762 * AHIDB_Record - Are you a sampler, too? Return TRUE or FALSE.
2764 * AHIDB_FullDuplex - Return TRUE or FALSE.
2766 * AHIDB_Realtime - Return TRUE or FALSE.
2768 * AHIDB_MaxPlaySamples - Normally, return the default. See
2769 * AHIsub_AllocAudio(), section 2.
2771 * AHIDB_MaxRecordSamples - Return the size of the buffer you fill
2774 * The following are associated with AHIsub_HardwareControl() and are
2777 * AHIDB_MinMonitorVolume
2778 * AHIDB_MaxMonitorVolume - Return the lower/upper limit for
2779 * AHIC_MonitorVolume. If unsupported but always 1.0, return
2782 * AHIDB_MinInputGain
2783 * AHIDB_MaxInputGain - Return the lower/upper limit for
2784 * AHIC_InputGain. If unsupported but always 1.0, return 1.0 for
2787 * AHIDB_MinOutputVolume
2788 * AHIDB_MaxOutputVolume - Return the lower/upper limit for
2789 * AHIC_OutputVolume.
2791 * AHIDB_Inputs - Return how many inputs you have.
2792 * AHIDB_Input - Return a short string describing the argument:th
2793 * input. Number 0 should be the default one. Example strings
2794 * can be "Line 1", "Mic", "Optical" or whatever.
2796 * AHIDB_Outputs - Return how many outputs you have.
2797 * AHIDB_Output - Return a short string describing the argument:th
2798 * output. Number 0 should be the default one. Example strings
2799 * can be "Line 1", "Headphone", "Optical" or whatever.
2801 * argument - extra info for some attributes.
2802 * default - What you should return for unknown attributes.
2803 * taglist - Pointer to a tag list that eventually will be fed to
2804 * AHIsub_AllocAudio(), or NULL.
2805 * audioctrl - Pointer to an AHIAudioCtrlDrv structure that eventually
2806 * will be fed to AHIsub_AllocAudio(), or NULL.
2811 * AHIsub_AllocAudio(), AHIsub_HardwareControl(),
2812 * ahi.device/AHI_GetAudioAttrsA()
2814 *****************************************************************************
2819 PRINTF 2,"AHIsub_GetAttr()"
2823 move.l pb_UtilLib(a5),a6
2826 moveq #FALSE,d3 ; 14 bit flag
2827 moveq #FALSE,d4 ; DMA flag
2835 move.l #AHIDB_Paula14Bit,d0
2841 move.l #AHIDB_PaulaDMA,d0
2850 and.l #~(AHI_TagBaseR),d0
2851 cmp.l #AHIDB_Data & ~(AHI_TagBaseR),d0
2855 move.w .jt(pc,d0.w),d0
2868 dc.w 0 ; AHIDB_AudioID
2869 dc.w 0 ; AHIDB_Driver
2870 dc.w 0 ; AHIDB_Flags
2871 dc.w ga_Volume-.jt ; AHIDB_Volume
2872 dc.w ga_Panning-.jt ; AHIDB_Panning
2873 dc.w ga_Stereo-.jt ; AHIDB_Stereo
2874 dc.w ga_HiFi-.jt ; AHIDB_HiFi
2875 dc.w ga_PingPong-.jt ; AHIDB_PingPong
2876 dc.w 0 ; AHIDB_MultTable
2878 dc.w ga_Bits-.jt ; AHIDB_Bits
2879 dc.w ga_MaxChannels-.jt ; AHIDB_MaxChannels
2880 dc.w 0 ; AHIDB_MinMixFreq
2881 dc.w 0 ; AHIDB_MaxMixFreq
2882 dc.w ga_Record-.jt ; AHIDB_Record
2883 dc.w ga_Frequencies-.jt ; AHIDB_Frequencies
2884 dc.w 0 ; AHIDB_FrequencyArg
2885 dc.w ga_Frequency-.jt ; AHIDB_Frequency
2886 dc.w ga_Author-.jt ; AHIDB_Author
2887 dc.w ga_Copyright-.jt ; AHIDB_Copyright
2888 dc.w ga_Version-.jt ; AHIDB_Version
2889 dc.w ga_Annotation-.jt ; AHIDB_Annotation
2890 dc.w 0 ; AHIDB_BufferLen
2891 dc.w 0 ; AHIDB_IndexArg
2892 dc.w ga_Index-.jt ; AHIDB_Index
2893 dc.w ga_Realtime-.jt ; AHIDB_Realtime
2894 dc.w 0 ; AHIDB_MaxPlaySamples
2895 dc.w ga_MaxRecordSamples-.jt ; AHIDB_MaxRecordSample
2897 dc.w ga_FullDuplex-.jt ; AHIDB_FullDuplex
2898 dc.w ga_MinMonitorVolume-.jt ; AHIDB_MinMonitorVolum
2899 dc.w ga_MaxMonitorVolume-.jt ; AHIDB_MaxMonitorVolum
2900 dc.w ga_MinInputGain-.jt ; AHIDB_MinInputGain
2901 dc.w ga_MaxInputGain-.jt ; AHIDB_MaxInputGain
2902 dc.w ga_MinOutputVolume-.jt ; AHIDB_MinOutputVolume
2903 dc.w ga_MaxOutputVolume-.jt ; AHIDB_MaxOutputVolume
2904 dc.w ga_Inputs-.jt ; AHIDB_Inputs
2905 dc.w 0 ; AHIDB_InputArg
2906 dc.w ga_Input-.jt ; AHIDB_Input
2907 dc.w ga_Outputs-.jt ; AHIDB_Outputs
2908 dc.w 0 ; AHIDB_OutputArg
2909 dc.w ga_Output-.jt ; AHIDB_Output
2913 *** The tags AHIDB_Volume, AHIDB_Panning, AHIDB_Stereo and AHIDB_HiFi are
2914 *** parameters to the mixing routine when mixing, but attributes in DMA mode.
2989 moveq #FREQUENCIES,d0
2993 moveq #FREQUENCIES_OCS,d0
2999 move.l #PALFREQ,d2 ;PAL
3000 move.l pb_GfxLib(a5),a0
3001 move.w gb_DisplayFlags(a0),d0
3002 btst #REALLY_PALn,d0
3004 move.l #NTSCFREQ,d2 ;NTSC
3013 ; moveq #0,d0 ;Default
3014 ; lea fakefreqVar(pc),a0
3017 ; bne .skipfrequpdate
3029 .author dc.b "Martin 'Leviticus
' Blom",0
3033 lea .copyright(pc),a0
3036 .copyright dc.b "Public Domain",0
3048 .anno dc.b "14 bit routines by Christian Buchner.",0
3062 ga_MaxRecordSamples:
3063 move.l #RECORDSAMPLES,d0
3077 ga_MinMonitorVolume:
3081 ga_MaxMonitorVolume:
3126 move.l .inputs(pc,d1.w),d0
3128 .inputs dc.l .input0
3132 .input0 dc.b "Parallel port sampler",0
3133 .input1 dc.b "Aura sampler",0
3134 .input2 dc.b "Clarity sampler",0
3145 .output dc.b "Line",0
3149 ****** [driver].audio/AHIsub_HardwareControl ********************************
3152 * AHIsub_HardwareControl -- Modify sound card settings
3155 * AHIsub_HardwareControl( attribute, argument, audioctrl );
3158 * LONG AHIsub_HardwareControl( ULONG, LONG, struct AHIAudioCtrlDrv * );
3161 * Set or return the state of a particular hardware component. AHI uses
3162 * AHIsub_GetAttr() to supply the user with limits and what tags are
3166 * attribute - Is really a Tag and can be one of the following:
3168 * AHIC_MonitorVolume - Set the input monitor volume to argument.
3169 * AHIC_MonitorVolume_Query - Return the current input monitor
3170 * volume (argument is ignored).
3172 * AHIC_InputGain - Set the input gain to argument. (V2)
3173 * AHIC_InputGain_Query (V2)
3175 * AHIC_OutputVolume - Set the output volume to argument. (V2)
3176 * AHIC_OutputVolume_Query (V2)
3178 * AHIC_Input - Use the argument:th input source (default is 0). (V2)
3179 * AHIC_Input_Query (V2)
3181 * AHIC_Output - Use the argument:th output destination (default
3183 * AHIC_Output_Query (V2)
3185 * argument - What value attribute should be set to.
3186 * audioctrl - Pointer to an AHIAudioCtrlDrv structure.
3189 * Return the state of selected attribute. If you were asked to set
3190 * something, return TRUE. If attribute is unknown to you or unsupported,
3194 * This call must be safe from interrupts.
3197 * ahi.device/AHI_ControlAudioA(), AHIsub_GetAttr()
3199 *****************************************************************************
3203 AHIsub_HardwareControl:
3204 PRINTF 2,"AHIsub_HardwareControl()"
3205 cmp.l #AHIC_MonitorVolume,d0
3206 bne.b .dontsetmonvol
3207 move.l ahiac_DriverData(a2),a1
3210 move.w d1,p_MonitorVolume(a1)
3213 cmp.l #AHIC_MonitorVolume_Query,d0
3214 bne.b .dontgetmonvol
3215 move.l ahiac_DriverData(a2),a1
3217 move.w p_MonitorVolume(a1),d0
3222 cmp.l #AHIC_OutputVolume,d0
3223 bne.b .dontsetoutvol
3224 move.l ahiac_DriverData(a2),a1
3227 move.w d1,p_OutputVolume(a1)
3230 cmp.l #AHIC_OutputVolume_Query,d0
3231 bne.b .dontgetoutvol
3232 move.l ahiac_DriverData(a2),a1
3234 move.w p_OutputVolume(a1),d0
3239 cmp.l #AHIC_Input,d0
3241 move.l ahiac_DriverData(a2),a1
3242 move.w d1,p_Input(a1)
3245 cmp.l #AHIC_Input_Query,d0
3247 move.l ahiac_DriverData(a2),a1
3249 move.w p_Input(a1),d0
3265 *******************************************************************************
3266 ***** Interrupt routines ******************************************************
3267 *******************************************************************************
3274 move.l TC_Userdata(a0),a3
3275 move.l p_PaulaBase(a3),a5
3278 move.l #SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D,d0
3281 btst #SIGBREAKB_CTRL_C,d0
3284 btst #SIGBREAKB_CTRL_D,d0
3288 move.l p_PlaySoftInt+IS_CODE(a3),a5
3289 move.l p_PlaySoftInt+IS_DATA(a3),a1
3297 move.l p_ReplyTask(a3),d0
3300 move.l #SIGF_SINGLE,d0
3305 ; Multitasking will resume when we're dead
3310 move.w #INTF_AUDIO,INTREQ(a0)
3316 * d1 INTENAR & INTREQR
3318 * a1 &(paula->p_RecIntData)
3319 * a5 &RecordInterrupt
3323 * This function will be executed up to 28000 times per second - that's once per
3324 * rasterline! It has to be as fast as possible.
3326 move.w #INTF_AUD2|INTF_AUD3,INTREQ(a0) ;Clear the interrupt flags
3328 move.b _ciaa+ciaprb,d0 ;read parallel port
3330 move.l convtable(pc,d0.w*4),d0 ;1 unsigned byte -> 2 signed words
3334 move.l convtable(pc,d0.w),d0
3336 move.w d0,AUD2DAT(a0) ;left
3337 move.w d0,AUD3DAT(a0) ;right
3339 move.l (a1),a5 ;p_RecFillPtr
3340 move.l d0,(a5)+ ;store sample in buffer
3341 move.l a5,(a1)+ ;update pointer
3342 subq.w #1,(a1) ;p_ReqFillCount
3343 beq ri_Filled ;branch if buffer filled
3349 dc.b CNT-128,CNT-128,CNT-128,CNT-128
3355 * d1 INTENAR & INTREQR
3357 * a1 &(paula->p_RecIntData)
3358 * a5 &RecordInterrupt
3360 RecordInterruptClarity:
3362 * This function will be executed up to 28000 times per second - that's once per
3363 * rasterline! It has to be as fast as possible.
3365 move.w #INTF_AUD2|INTF_AUD3,INTREQ(a0) ;Clear the interrupt flags
3367 lea _ciab+ciatahi,a5
3369 move.b _ciaa+ciaprb,d0 ;left lsb
3370 ror.l #8,d0 ;d0: L0xxxxxx
3371 tst.b (a5) ;3x700 kHz wait states
3375 move.b _ciaa+ciaprb,d0 ;left msb
3376 ror.l #8,d0 ;d0: L1L0xxxx
3377 tst.b (a5) ;3x700 kHz wait states
3381 move.b _ciaa+ciaprb,d0 ;right lsb
3382 lsl.w #8,d0 ;d0: L1L0R0xx
3383 tst.b (a5) ;3x700 kHz wait states
3387 move.b _ciaa+ciaprb,d0 ;right msb
3388 ror.w #8,d0 ;d0: L1L0R1R0
3390 move.l (a1),a5 ;p_RecFillPtr
3391 move.l d0,(a5)+ ;store sample in buffer
3392 move.l a5,(a1)+ ;update pointer
3398 move.w d1,AUD2DAT(a0) ;right
3399 move.w d1,AUD3DAT(a0) ;left
3401 subq.w #1,(a1) ;p_ReqFillCount
3402 beq ri_Filled ;branch if buffer filled
3407 * d1 INTENAR & INTREQR
3409 * a1 &(paula->p_RecIntDataAura)
3410 * a5 &RecordInterrupt
3412 RecordInterruptAura:
3414 * This function will be executed up to 28000 times per second - that's once per
3415 * rasterline! It has to be as fast as possible.
3417 move.w #INTF_AUD2|INTF_AUD3,INTREQ(a0) ;Clear the interrupt flags
3419 move.l (a5),d0 ;read aura sampler
3421 move.l (a1),a5 ;p_RecFillPtr
3422 move.l d0,(a5)+ ;store sample in buffer
3423 move.l a5,(a1)+ ;update pointer
3429 move.w d1,AUD2DAT(a0) ;left
3430 move.w d1,AUD3DAT(a0) ;right
3432 subq.w #1,(a1) ;p_ReqFillCount
3433 beq ri_Filled ;branch if buffer filled
3436 *******************************************************************************
3440 * This part is only executed every RECORDSAMPLES:th time... No need to hurry.
3442 move.l 8(a1),d0 ;p_RecBuffer2->
3443 move.l 4(a1),8(a1) ;p_RecBuffer1->p_RecBuffer2
3444 move.l d0,4(a1) ; ->p_RecBuffer1
3445 move.l d0,-4(a1) ;p_RecFillPtr
3446 move.w #RECORDSAMPLES,(a1) ;p_ReqFillCount
3447 move.l 12(a1),a1 ;p_RecSoftIntPtr
3459 * This function is not executed many times per second and is therefore not
3460 * fully optimized... ;)
3462 move.w p_MonitorVolume(a1),d0
3463 move.w d0,custom+AUD2VOL
3464 move.w d0,custom+AUD3VOL
3465 move.l p_RecBuffer2(a1),p_rmBuffer(a1)
3466 move.l p_AudioCtrl(a1),a2
3467 lea p_RecordMessage(a1),a1
3468 move.l ahiac_SamplerFunc(a2),a0
3469 move.l h_Entry(a0),a5
3474 *******************************************************************************
3475 *******************************************************************************
3479 * d1 INTENAR & INTREQR
3482 * a5 &AudioInterrupt
3485 AudioInterrupt2: ;Two hardware channels used
3486 ; move.l p_AudLenPer(a1),d0
3487 ; move.l d0,AUD0LEN(a0)
3488 ; move.l d0,AUD1LEN(a0)
3489 move.w p_AudPer(a1),d0
3490 move.w d0,AUD0PER(a0)
3491 move.w d0,AUD1PER(a0)
3492 move.w p_OutputVolume(a1),AUD0VOL(a0)
3493 move.w p_OutputVolume(a1),AUD1VOL(a0)
3495 move.l p_DoubleBufferOffset(a1),d0
3497 move.l d0,p_DoubleBufferOffset(a1)
3499 lea p_AudPtrs(a1,d0.l),a5
3500 tst.b p_SwapChannels(a1)
3502 move.l (a5)+,AUD0LC(a0)
3503 move.l (a5)+,AUD1LC(a0)
3506 move.l (a5)+,AUD1LC(a0)
3507 move.l (a5)+,AUD0LC(a0)
3509 move.w #INTF_AUD0,INTREQ(a0) ;Clear the interrupt
3510 move.l p_MixTask(a1),d0
3512 lea p_PlaySoftInt(a1),a1
3513 jmp _LVOCause(a6) ;start PlaySoftInt
3516 move.l #SIGBREAKF_CTRL_D,d0
3520 AudioInterrupt4: ;Four hardware channels used
3521 ; move.l p_AudLenPer(a1),d0
3522 ; move.l d0,AUD0LEN(a0)
3523 ; move.l d0,AUD1LEN(a0)
3524 ; move.l d0,AUD2LEN(a0)
3525 ; move.l d0,AUD3LEN(a0)
3526 move.w p_AudPer(a1),d0
3527 move.w d0,AUD0PER(a0)
3528 move.w d0,AUD1PER(a0)
3529 move.w d0,AUD2PER(a0)
3530 move.w d0,AUD3PER(a0)
3531 move.w #64,AUD0VOL(a0)
3532 move.w #64,AUD1VOL(a0)
3533 move.w #1,AUD2VOL(a0)
3534 move.w #1,AUD3VOL(a0)
3536 move.l p_DoubleBufferOffset(a1),d0
3538 move.l d0,p_DoubleBufferOffset(a1)
3540 lea p_AudPtrs(a1,d0.l),a5
3541 tst.b p_SwapChannels(a1)
3543 move.l (a5)+,AUD0LC(a0)
3544 move.l (a5)+,AUD1LC(a0)
3545 move.l (a5)+,AUD2LC(a0)
3546 move.l (a5)+,AUD3LC(a0)
3549 move.l (a5)+,AUD1LC(a0)
3550 move.l (a5)+,AUD0LC(a0)
3551 move.l (a5)+,AUD3LC(a0)
3552 move.l (a5)+,AUD2LC(a0)
3554 move.w #INTF_AUD0,INTREQ(a0) ;Clear the interrupt
3555 move.l p_MixTask(a1),d0
3557 lea p_PlaySoftInt(a1),a1
3558 jmp _LVOCause(a6) ;start PlaySoftInt
3561 move.l #SIGBREAKF_CTRL_D,d0
3566 *******************************************************************************
3578 move.l p_AudioCtrl(a6),a2
3579 move.l ahiac_PreTimer(a2),a0
3580 PRINTF 8,"Calling PreTimer: %08lx", a2
3584 move.l p_DoubleBufferOffset(a6),d0
3585 lea p_AudPtrs(a6,d0.l),a0
3586 movem.l (a0)+,d2/d3/d4/d5 ;get all 4 buffer pointers
3589 PRINTF 3,"Leftovers: %ld", p_LoopLeftovers(a6)
3594 movem.l p_PlayerHookRegs(a6),a0/a1/a3
3595 PRINTF 8,"Calling PlayerHook: %08lx, %08lx, %08lx", a0, a2, a1
3596 jsr (a3) ;call Player Hook
3599 add.l ahiac_BuffSamples(a2),d6 ;Faked # of mixed samples
3603 movem.l p_MixHookRegs(a6),a0/a1/a3
3605 move.l p_LoopLeftovers(a6),d0
3606 move.l p_SampleFrameShift(a6),d1
3608 PRINTF 3," adding %ld", d0
3609 add.l d0,a1 ;don't overwrite the leftovers
3610 ;(the mixbuffer is large enough,
3611 ;search for EXTRABUFFSIZE!)
3613 PRINTF 8,"Calling MixerHook: %08lx, %08lx, %08lx", a0, a2, a1
3614 jsr (a3) ;call Mixer Hook
3617 move.l ahiac_BuffSamples(a2),d0
3618 add.l p_LoopLeftovers(a6),d0
3622 move.l d1,p_LoopLeftovers(a6)
3623 add.l d0,d6 ;Count actual number of played samples
3624 PRINTF 4," Playing %ld, %ld missing", d0, d1
3627 move.l p_Mixbuffer(a6),a1 ;a1 was modified above, remember?
3629 move.l p_LoopTimes(a6),d0
3634 ; Conversion code here!
3638 ; d2-d5 buffer pointers
3639 ; d6 (sample counter/4)
3640 ; d7 (pretimer flag)
3642 ; a1 source buffer (must be updated)
3647 ; Conversion code here!
3653 ; Transfer the leftovers to the beginning of the mixbuffer
3654 ; It's easy: just transfer p_LoopLeftovers samples from (a1) to
3657 move.l p_Mixbuffer(a6),a0
3658 move.l p_LoopLeftovers(a6),d0
3659 PRINTF 3,"Tranfering %ld samples",d0
3660 move.l p_SampleFrameShift(a6),d1
3662 PRINTF 3,", that is %ld bytes",d0
3666 PRINTF 4," or %ld iterations.",d0
3676 add.l ahiac_BuffSamples(a2),d6
3678 cmp.l p_MinBufferLength(a6),d6
3680 move.l ahiac_PostTimer(a2),a0
3681 PRINTF 8,"Calling PostTimer: %08lx", a2
3684 PRINTF 4,"I have played %ld samples", d0
3690 ; d0 Samples in buffer
3693 *******************************************************************************
3699 move.l d2,a0 ;get buffer ptr
3711 move.l a0,d2 ;save buffer ptr
3716 move.w d0,AUD0LEN(a0)
3717 move.w d0,AUD1LEN(a0)
3718 move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1,DMACON(a0)
3721 *******************************************************************************
3726 move.l d2,a0 ;get buffer ptr
3738 move.l a0,d2 ;save buffer ptr
3743 move.w d0,AUD0LEN(a0)
3744 move.w d0,AUD1LEN(a0)
3745 move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1,DMACON(a0)
3748 *******************************************************************************
3753 move.l d2,a0 ;get buffer ptr
3754 move.l d3,a3 ;get buffer ptr
3779 move.l a0,d2 ;save buffer ptr
3780 move.l a3,d3 ;save buffer ptr
3785 move.w d0,AUD0LEN(a0)
3786 move.w d0,AUD1LEN(a0)
3787 move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1,DMACON(a0)
3790 *******************************************************************************
3795 move.l d2,a0 ;get buffer ptr
3796 move.l d3,a3 ;get buffer ptr
3821 move.l a0,d2 ;save buffer ptr
3822 move.l a3,d3 ;save buffer ptr
3827 move.w d0,AUD0LEN(a0)
3828 move.w d0,AUD1LEN(a0)
3829 move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1,DMACON(a0)
3832 *******************************************************************************
3837 move.l d2,a0 ;get buffer ptr
3838 move.l d5,a5 ;get buffer ptr
3867 move.l a0,d2 ;save buffer ptr
3868 move.l a5,d5 ;save buffer ptr
3873 move.w d0,AUD0LEN(a0)
3874 move.w d0,AUD1LEN(a0)
3875 move.w d0,AUD2LEN(a0)
3876 move.w d0,AUD3LEN(a0)
3877 move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
3880 *******************************************************************************
3886 move.l d2,a0 ;get buffer ptr
3887 move.l d5,a5 ;get buffer ptr
3916 move.l a0,d2 ;save buffer ptr
3917 move.l a5,d5 ;save buffer ptr
3922 move.w d0,AUD0LEN(a0)
3923 move.w d0,AUD1LEN(a0)
3924 move.w d0,AUD2LEN(a0)
3925 move.w d0,AUD3LEN(a0)
3926 move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
3929 *******************************************************************************
3934 move.l d2,a0 ;get buffer ptr
3935 move.l d5,a5 ;get buffer ptr
3936 move.l p_CalibrationTable(a6),a3
3942 move.w (a3,d3.l*2),d3
3950 lsl.l #8,d1 ;xxxxAAxx
3952 lsl.l #8,d2 ;xxaaxxxx
3955 move.w (a3,d3.l*2),d3
3963 lsl.l #8,d1 ;xxAABBxx
3965 lsl.l #8,d2 ;aabbxxxx
3968 move.w (a3,d3.l*2),d3
3976 lsl.l #8,d1 ;AABBCCxx
3977 move.w d3,d2 ;aabbccxx
3981 move.w (a3,d3.l*2),d3
3988 move.b d3,d1 ;AABBCCDD
3990 move.b d3,d2 ;aabbccdd
3996 move.l a0,d2 ;save buffer ptr
3997 move.l a5,d5 ;save buffer ptr
4002 move.w d0,AUD0LEN(a0)
4003 move.w d0,AUD1LEN(a0)
4004 move.w d0,AUD2LEN(a0)
4005 move.w d0,AUD3LEN(a0)
4006 move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
4009 *******************************************************************************
4014 move.l d2,a0 ;get buffer ptr
4015 move.l d5,a5 ;get buffer ptr
4016 move.l p_CalibrationTable(a6),a3
4022 move.w (a3,d3.l*2),d3
4030 lsl.l #8,d1 ;xxxxAAxx
4032 lsl.l #8,d2 ;xxaaxxxx
4035 move.w (a3,d3.l*2),d3
4043 lsl.l #8,d1 ;xxAABBxx
4045 lsl.l #8,d2 ;aabbxxxx
4048 move.w (a3,d3.l*2),d3
4056 lsl.l #8,d1 ;AABBCCxx
4057 move.w d3,d2 ;aabbccxx
4061 move.w (a3,d3.l*2),d3
4068 move.b d3,d1 ;AABBCCDD
4070 move.b d3,d2 ;aabbccdd
4077 move.l a0,d2 ;save buffer ptr
4078 move.l a5,d5 ;save buffer ptr
4083 move.w d0,AUD0LEN(a0)
4084 move.w d0,AUD1LEN(a0)
4085 move.w d0,AUD2LEN(a0)
4086 move.w d0,AUD3LEN(a0)
4087 move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
4091 *******************************************************************************
4096 move.l d2,a0 ;get buffer ptr
4097 move.l d3,a3 ;get buffer ptr
4098 move.l d4,a4 ;get buffer ptr
4099 move.l d5,a5 ;get buffer ptr
4152 move.l a0,d2 ;save buffer ptr
4153 move.l a3,d3 ;save buffer ptr
4154 move.l a4,d4 ;save buffer ptr
4155 move.l a5,d5 ;save buffer ptr
4160 move.w d0,AUD0LEN(a0)
4161 move.w d0,AUD1LEN(a0)
4162 move.w d0,AUD2LEN(a0)
4163 move.w d0,AUD3LEN(a0)
4164 move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
4167 *******************************************************************************
4172 move.l d2,a0 ;get buffer ptr
4173 move.l d3,a3 ;get buffer ptr
4174 move.l d4,a4 ;get buffer ptr
4175 move.l d5,a5 ;get buffer ptr
4228 move.l a0,d2 ;save buffer ptr
4229 move.l a3,d3 ;save buffer ptr
4230 move.l a4,d4 ;save buffer ptr
4231 move.l a5,d5 ;save buffer ptr
4236 move.w d0,AUD0LEN(a0)
4237 move.w d0,AUD1LEN(a0)
4238 move.w d0,AUD2LEN(a0)
4239 move.w d0,AUD3LEN(a0)
4240 move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
4244 *******************************************************************************
4249 move.l d2,a0 ;get buffer ptr
4250 move.l d3,a3 ;get buffer ptr
4251 move.l d4,a4 ;get buffer ptr
4252 move.l d5,a5 ;get buffer ptr
4254 move.l p_CalibrationTable(a6),a6
4261 move.w (a6,d3.l*2),d3
4269 lsl.l #8,d1 ;xxxxAAxx
4271 lsl.l #8,d2 ;xxaaxxxx
4274 move.w (a6,d3.l*2),d3
4282 lsl.l #8,d1 ;xxAABBxx
4284 lsl.l #8,d2 ;aabbxxxx
4287 move.w (a6,d3.l*2),d3
4295 lsl.l #8,d1 ;AABBCCxx
4296 move.w d3,d2 ;aabbccxx
4300 move.w (a6,d3.l*2),d3
4307 move.b d3,d1 ;AABBCCDD
4309 move.b d3,d2 ;aabbccdd
4317 move.w (a6,d3.l*2),d3
4325 lsl.l #8,d1 ;xxxxAAxx
4327 lsl.l #8,d2 ;xxaaxxxx
4330 move.w (a6,d3.l*2),d3
4338 lsl.l #8,d1 ;xxAABBxx
4340 lsl.l #8,d2 ;aabbxxxx
4343 move.w (a6,d3.l*2),d3
4351 lsl.l #8,d1 ;AABBCCxx
4352 move.w d3,d2 ;aabbccxx
4356 move.w (a6,d3.l*2),d3
4363 move.b d3,d1 ;AABBCCDD
4365 move.b d3,d2 ;aabbccdd
4373 move.l a0,d2 ;save buffer ptr
4374 move.l a3,d3 ;save buffer ptr
4375 move.l a4,d4 ;save buffer ptr
4376 move.l a5,d5 ;save buffer ptr
4381 move.w d0,AUD0LEN(a0)
4382 move.w d0,AUD1LEN(a0)
4383 move.w d0,AUD2LEN(a0)
4384 move.w d0,AUD3LEN(a0)
4385 move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
4389 *******************************************************************************
4394 move.l d2,a0 ;get buffer ptr
4395 move.l d3,a3 ;get buffer ptr
4396 move.l d4,a4 ;get buffer ptr
4397 move.l d5,a5 ;get buffer ptr
4399 move.l p_CalibrationTable(a6),a6
4406 move.w (a6,d3.l*2),d3
4414 lsl.l #8,d1 ;xxxxAAxx
4416 lsl.l #8,d2 ;xxaaxxxx
4419 move.w (a6,d3.l*2),d3
4427 lsl.l #8,d1 ;xxAABBxx
4429 lsl.l #8,d2 ;aabbxxxx
4432 move.w (a6,d3.l*2),d3
4440 lsl.l #8,d1 ;AABBCCxx
4441 move.w d3,d2 ;aabbccxx
4445 move.w (a6,d3.l*2),d3
4452 move.b d3,d1 ;AABBCCDD
4454 move.b d3,d2 ;aabbccdd
4462 move.w (a6,d3.l*2),d3
4470 lsl.l #8,d1 ;xxxxAAxx
4472 lsl.l #8,d2 ;xxaaxxxx
4475 move.w (a6,d3.l*2),d3
4483 lsl.l #8,d1 ;xxAABBxx
4485 lsl.l #8,d2 ;aabbxxxx
4488 move.w (a6,d3.l*2),d3
4496 lsl.l #8,d1 ;AABBCCxx
4497 move.w d3,d2 ;aabbccxx
4501 move.w (a6,d3.l*2),d3
4508 move.b d3,d1 ;AABBCCDD
4510 move.b d3,d2 ;aabbccdd
4518 move.l a0,d2 ;save buffer ptr
4519 move.l a3,d3 ;save buffer ptr
4520 move.l a4,d4 ;save buffer ptr
4521 move.l a5,d5 ;save buffer ptr
4526 move.w d0,AUD0LEN(a0)
4527 move.w d0,AUD1LEN(a0)
4528 move.w d0,AUD2LEN(a0)
4529 move.w d0,AUD3LEN(a0)
4530 move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
4539 *******************************************************************************
4540 ***** DMA playback routines ***************************************************
4541 *******************************************************************************
4550 * d0 AHIsub_Start return code
4553 PRINTF 2,"DMA_Start()"
4555 * Allocate DMA buffers
4556 move.l #DMABUFFSAMPLES*8,d0 ; 4 channels, double buffers
4557 move.l #MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR,d1
4559 move.l d0,p_DMAbuffer(a3)
4562 move.l #DMABUFFSAMPLES,d1
4563 move.l d0,p_AudPtr1A(a3)
4565 move.l d0,p_AudPtr1B(a3)
4567 move.l d0,p_AudPtr2A(a3)
4569 move.l d0,p_AudPtr2B(a3)
4571 move.l d0,p_AudPtr3A(a3)
4573 move.l d0,p_AudPtr3B(a3)
4575 move.l d0,p_AudPtr4A(a3)
4577 move.l d0,p_AudPtr4B(a3)
4579 * Set up audio hardware interrupts
4580 move.l #AudioInterruptDMA,IS_CODE+p_PlayInt(a3)
4581 move.l a3,IS_DATA+p_PlayInt(a3)
4583 lea p_PlayInt(a3),a1
4586 lea p_PlayInt(a3),a1
4589 lea p_PlayInt(a3),a1
4592 lea p_PlayInt(a3),a1
4596 * Use timer.device to clock the PlayerFunc() using a software interrupt/msg port
4598 lea p_TimerPort+MP_MSGLIST(a3),a0
4601 lea p_TimerPort(a3),a0
4602 move.b #NT_MSGPORT,LN_TYPE(a0)
4603 move.b #PA_SOFTINT,MP_FLAGS(a0)
4604 lea p_TimerInt(a3),a1
4605 move.l a1,MP_SIGTASK(a0)
4607 move.b #32,p_TimerInt+LN_PRI(a3) ; Highest priority to keep it steady
4608 lea PlayerFunc(pc),a0
4609 move.l a0,p_TimerInt+IS_CODE(a3)
4610 move.l a3,p_TimerInt+IS_DATA(a3)
4612 lea p_TimerPort(a3),a0
4614 call CreateIORequest
4615 move.l d0,p_TimerReq(a3)
4618 lea timerName(pc),a0
4619 moveq #UNIT_ECLOCK,d0
4620 move.l p_TimerReq(a3),a1
4623 move.b d0,p_TimerDev(a3)
4626 move.l p_TimerReq(a3),a0
4627 move.l IO_DEVICE(a0),pb_TimerLib(a5)
4631 bsr DMA_Update ;Calc p_EClock/p_EPeriod
4632 pop a6 ;and p_EAlarm
4634 ; Add p_EPeriod to the alarm time
4635 move.l p_EAlarm+EV_LO(a3),d0
4636 move.l p_EAlarm+EV_HI(a3),d1
4637 move.l p_EPeriod(a3),d2
4641 move.l d2,p_EAlarm+EV_LO(a3)
4642 move.l d3,p_EAlarm+EV_HI(a3)
4644 clr.w p_TimerCommFlag(a3)
4646 move.l p_TimerReq(a3),a1
4647 move.w #TR_ADDREQUEST,IO_COMMAND(a1)
4648 move.l p_EPeriod(a3),IOTV_TIME+EV_LO(a1)
4649 clr.l IOTV_TIME+EV_HI(a1)
4653 or.w #INTF_SETCLR|INTF_AUDIO,p_IRQMask(a3)
4654 tst.w p_DisableCount(a3)
4656 move.w #INTF_SETCLR|INTF_AUDIO,INTENA(a4) ;enable all
4658 move.w #INTF_SETCLR|INTF_AUDIO,INTREQ(a4) ;start all
4666 moveq #AHIE_UNKNOWN,d0
4670 moveq #AHIE_NOMEM,d0
4680 PRINTF 2,"DMA_Update()"
4681 move.l pb_TimerLib(a6),d0
4687 move.l d0,p_EClock(a3)
4691 move.l ahiac_PlayerFreq(a2),d1
4698 move.l pb_UtilLib(a6),a0
4699 jsr _LVOUDivMod32(a0)
4701 move.l d0,p_EPeriod(a3)
4706 move.l #709379/50,p_EPeriod(a3) ;Approx 50 Hz
4718 PRINTF 2,"DMA_Stop()"
4720 and.w #INTF_AUDIO,p_IRQMask(a3)
4721 move.w #INTF_AUDIO,INTENA(a4)
4722 move.w #DMAF_AUDIO,DMACON(a4) ;Disable DMA
4723 move.w #INTF_AUDIO,INTREQ(a4) ;Clear any waiting interrupts
4725 tst.b p_TimerDev(a3)
4729 * Ask timer softint to stop
4731 addq.w #1,p_TimerCommFlag(a3)
4733 tst.w p_TimerCommFlag(a3)
4735 move.l pb_DosLib(a5),a6
4741 clr.l pb_TimerLib(a5)
4743 move.l pb_SysLib(a5),a6
4744 move.l p_TimerReq(a3),a1
4747 move.l p_TimerReq(a3),a0
4748 clr.l p_TimerReq(a3)
4749 call DeleteIORequest
4751 move.l #Interrupt_Dummy,IS_CODE+p_PlayInt(a3)
4753 lea p_PlayInt(a3),a1
4756 lea p_PlayInt(a3),a1
4759 lea p_PlayInt(a3),a1
4762 lea p_PlayInt(a3),a1
4766 move.l p_DMAbuffer(a3),a1
4767 clr.l p_DMAbuffer(a3)
4773 ****** [driver].audio/AHIsub_#? *********************************************
4776 * AHIsub_SetEffect -- Set effect.
4777 * AHIsub_SetFreq -- Set frequency.
4778 * AHIsub_SetSound -- Set sound.
4779 * AHIsub_SetVol -- Set volume and stereo panning.
4780 * AHIsub_LoadSound -- Prepare a sound for playback.
4781 * AHIsub_UnloadSound -- Discard a sound.
4784 * See functions in 'ahi
.device
'.
4787 * If AHIsub_AllocAudio() did not return with bit AHISB_MIXING set,
4788 * all user calls to these function will be routed to the driver.
4790 * If AHIsub_AllocAudio() did return with bit AHISB_MIXING set, the
4791 * calls will first be routed to the driver, and only handled by
4792 * 'ahi
.device
' if the driver returned AHIS_UNKNOWN. This way it is
4793 * possible to add effects that the sound card handles on its own, like
4794 * filter and echo effects.
4796 * For what each function does, see the autodocs for 'ahi
.device
'.
4799 * See functions in 'ahi
.device
'.
4802 * See functions in 'ahi
.device
'.
4805 * ahi.device/AHI_SetEffect(), ahi.device/AHI_SetFreq(),
4806 * ahi.device/AHI_SetSound(), ahi.device/AHI_SetVol(),
4807 * ahi.device/AHI_LoadSound(), ahi.device/AHI_UnloadSound()
4810 *****************************************************************************
4815 *****************************************************************************
4816 * Panning is ignored, and negative volume is not supported.
4820 move.l ahiac_DriverData(a2),a3
4821 btst.b #PB_DMA,p_Flags(a3)
4824 mulu.w #channel_SIZEOF,d0
4825 lea p_Channels(a3),a0
4834 * Store volume and scale according to the master volume
4835 move.w d1,ch_NextVolumeNorm(a0)
4836 move.l p_MasterVolume(a3),d0
4845 move.w d0,ch_NextVolume(a0)
4849 move.w d1,ch_VolumeNorm(a0)
4850 move.l p_MasterVolume(a3),d0
4859 move.w d0,ch_Volume(a0)
4860 ; move.l ch_PerVol(a0),ch_AudPerVol(a0)
4861 move.l ch_RegBase(a0),a1
4862 move.w d0,AUDVOL(a1)
4867 moveq #0,d0 ; Return NULL!
4872 *****************************************************************************
4873 * If the frequency is higher than the audio DMA can handle, the samples will
4874 * be decimated before they are played. The frequency will only take effect
4875 * immediately if the decimate factor didn't change, or the new frequency
4876 * was zero. Otherwise, the frequency will change when the current DMA
4877 * block is finished.
4881 move.l ahiac_DriverData(a2),a3
4882 btst.b #PB_DMA,p_Flags(a3)
4885 PRINTF 2,"AHIsub_SetFreq()"
4887 mulu.w #channel_SIZEOF,d0
4888 lea p_Channels(a3),a0
4891 cmp.l #AHI_MIXFREQ,d1
4893 move.l ahiac_MixFreq(a2),d1
4897 tst.b p_ScreenIsDouble(a3)
4901 moveq #0,d3 ; Decimate/scale (log)
4912 moveq #0,d0 ;VVVeeerrryyyy ssslllooowww!!!
4917 move.l pb_AudioFreq(a6),d0
4922 move.l pb_UtilLib(a6),a1
4923 jsr _LVOUDivMod32(a1)
4930 move.w d0,ch_NextPeriod(a0)
4931 move.w d3,ch_NextScale(a0)
4936 ; We must not change the frequency if the scale has changed! (Unless it's 0)
4939 cmp.w ch_Scale(a0),d3
4942 ; move.l ch_PerVol(a0),ch_AudPerVol(a0)
4943 move.l ch_RegBase(a0),a1
4944 move.w d0,AUDPER(a1)
4947 ; Force an interrupt if the channel was paused
4953 move.w ch_IntMask(a0),d1
4954 or.w #INTF_SETCLR,d1
4955 move.w d1,INTREQ(a1)
4959 move.w d0,ch_Period(a0)
4960 move.w d3,ch_Scale(a0)
4966 moveq #0,d0 ; Return NULL!
4972 *****************************************************************************
4976 move.l ahiac_DriverData(a2),a3
4977 btst.b #PB_DMA,p_Flags(a3)
4980 PRINTF 2,"AHIsub_SetSound()"
4983 mulu.w #channel_SIZEOF,d0
4984 lea p_Channels(a3),a0
4987 cmp.w #AHI_NOSOUND,d1
4991 moveq #AHIST_NOTYPE,d5
4995 mulu.w #sound_SIZEOF,d1
4996 move.l p_Sounds(a3),a1
5001 move.l so_Length(a1),d3
5003 move.l so_Type(a1),d5
5008 bpl .positive_length
5009 neg.l d3 ; Make positive
5010 or.l #AHIST_BW,d5 ; Mark type as backward-playing
5013 ; PRINTF 0,"New sample! %08lx, %ld, %08lx", d2,d3,d5
5017 move.l so_Address(a1),ch_NextAddress(a0)
5018 move.l d2,ch_NextOffset(a0)
5019 move.l d3,ch_NextLength(a0)
5020 move.l d5,ch_NextType(a0)
5026 move.l so_Address(a1),ch_Address(a0)
5027 move.l d2,ch_Offset(a0)
5028 move.l d3,ch_Length(a0)
5029 move.l d5,ch_Type(a0)
5031 st.b ch_EndOfSample(a0) ; Call SoundFunc()
5035 ; Clear pending interrupt (if there was one)
5037 move.w ch_IntMask(a0),INTREQ(a1)
5040 move.w ch_DMAMask(a0),DMACON(a1)
5042 ; Wait for Agnus/Alice to understand
5044 move.l pb_SysLib(a6),a6
5047 move.b VHPOSR(a1),d0
5052 cmp.b #20,VHPOSR+1(a1)
5058 ; When the period reaches 0, Paula will invoke our interrupt routine!
5060 ; Now just make sure that we receive no more than 1 interrupt.
5061 move.l ch_RegBase(a0),a1
5062 move.w #1,AUDPER(a1)
5067 moveq #0,d0 ; Return NULL!
5073 *****************************************************************************
5077 move.l ahiac_DriverData(a2),a3
5078 btst.b #PB_DMA,p_Flags(a3)
5081 PRINTF 2,"AHIsub_SetEffect()"
5082 move.l ahie_Effect(a0),d0
5083 cmp.l #AHIET_MASTERVOLUME,d0
5085 cmp.l #AHIET_CANCEL|AHIET_MASTERVOLUME,d0
5086 beq .mastervolume_off
5087 cmp.l #AHIET_CHANNELINFO,d0
5089 cmp.l #AHIET_CANCEL|AHIET_CHANNELINFO,d0
5090 beq .channelinfo_off
5092 moveq #AHIE_UNKNOWN,d0 ; Return error code!
5098 move.l ahiemv_Volume(a0),d0
5099 .mastervolume_update
5100 move.l d0,p_MasterVolume(a3)
5102 lea p_Channels(a3),a0
5105 move.l p_MasterVolume(a3),d0
5107 blo .mastervolume_scale1
5108 move.w ch_NextVolumeNorm(a0),d0
5109 bra .mastervolume_store1
5110 .mastervolume_scale1
5111 mulu.w ch_NextVolumeNorm(a0),d0
5113 .mastervolume_store1
5114 move.w d0,ch_NextVolume(a0)
5115 move.l p_MasterVolume(a3),d0
5117 blo .mastervolume_scale2
5118 move.w ch_VolumeNorm(a0),d0
5119 bra .mastervolume_store2
5120 .mastervolume_scale2
5121 mulu.w ch_VolumeNorm(a0),d0
5123 .mastervolume_store2
5124 move.w d0,ch_Volume(a0)
5125 ; move.l ch_PerVol(a0),ch_AudPerVol(a0)
5126 move.l ch_RegBase(a0),a1
5127 move.w d0,AUDVOL(a1)
5129 add.w #channel_SIZEOF,a0
5130 dbf d1,.mastervolume_loop
5137 bra .mastervolume_update
5141 move.l a0,p_ChannelInfo(a3)
5146 clr.l p_ChannelInfo(a3)
5151 *****************************************************************************
5155 move.l ahiac_DriverData(a2),a3
5156 btst.b #PB_DMA,p_Flags(a3)
5159 PRINTF 2,"AHIsub_LoadSound()"
5160 cmp.l #AHIST_SAMPLE,d1
5162 cmp.l #AHIST_DYNAMICSAMPLE,d1
5165 mulu.w #sound_SIZEOF,d0
5166 move.l p_Sounds(a3),a1
5169 move.l ahisi_Type(a0),d0
5172 cmp.l #AHIST_M16S,d0
5176 cmp.l #AHIST_S16S,d0
5179 move.l d0,so_Type(a1)
5180 move.l ahisi_Address(a0),so_Address(a1)
5181 move.l ahisi_Length(a0),so_Length(a1)
5190 moveq #AHIE_BADSOUNDTYPE,d0
5193 moveq #AHIE_BADSAMPLETYPE,d0
5196 *****************************************************************************
5200 move.l ahiac_DriverData(a2),a3
5201 btst.b #PB_DMA,p_Flags(a3)
5204 PRINTF 2,"AHIsub_UnloadSound()"
5205 mulu.w #sound_SIZEOF,d0
5206 move.l p_Sounds(a3),a1
5208 move.l #AHIST_NOTYPE,so_Type(a1)
5209 clr.l so_Address(a1)
5212 moveq #0,d0 ; Return NULL!
5217 *****************************************************************************
5220 moveq #AHIS_UNKNOWN,d0 ; Return AHIS_UNKNOWN!
5224 *****************************************************************************
5233 move.l p_AudioCtrl(a3),a2
5235 move.l p_PaulaBase(a3),a6
5236 move.l pb_SysLib(a6),a6
5237 lea p_TimerPort(a3),a0
5238 call GetMsg ; Remove message
5240 tst.w p_TimerCommFlag(a3)
5243 clr.w p_TimerCommFlag(a3)
5247 ; Add p_EPeriod to the alarm time
5248 move.l p_EAlarm+EV_LO(a3),d0
5249 move.l p_EAlarm+EV_HI(a3),d1
5250 move.l p_EPeriod(a3),d2
5254 move.l d2,p_EAlarm+EV_LO(a3)
5255 move.l d3,p_EAlarm+EV_HI(a3)
5259 move.l p_PaulaBase(a3),a0
5260 move.l pb_TimerLib(a0),a6
5264 move.l EV_LO(sp),d0 ; Current time
5266 sub.l d0,d2 ; Calculate difference (Alarm - Current)
5274 moveq #0,d3 ; Rather small delay...
5277 ; PRINTF 0,"Delay: %08ld%08ld",d3,d2
5278 move.l p_TimerReq(a3),a1
5279 move.w #TR_ADDREQUEST,IO_COMMAND(a1)
5280 move.l d2,IOTV_TIME+EV_LO(a1)
5281 move.l d3,IOTV_TIME+EV_HI(a1)
5284 move.l p_PaulaBase(a3),a6
5287 ; Handle the ChannelInfo effect
5289 move.l p_ChannelInfo(a3),d0
5292 lea ahieci_Offset(a0),a1
5293 move.w ahieci_Channels(a0),d0
5296 lea p_Channels(a3),a4
5298 move.l ch_Offset(a4),(a1)+
5299 add.w #channel_SIZEOF,a4
5302 move.l p_ChannelInfo(a3),a1
5303 move.l ahieci_Func(a1),d0
5306 move.l h_Entry(a0),a4
5309 ; lea p_Channels(a3),a4
5310 ; PRINTF 0,"CI: %ld, %ld, %ld, %ld",ch_Offset(a4),ch_Offset+channel_SIZEOF(a4),ch_Offset+channel_SIZEOF*2(a4),ch_Offset+channel_SIZEOF*3(a4)
5313 ; Call the PlayerFunc()
5315 move.l ahiac_PlayerFunc(a2),d0
5318 sub.l a1,a1 ; IMPORTANT!
5319 move.l h_Entry(a0),a4
5320 PRINTF 8,"Calling PlayerFunc(%08lx,%08lx,%08lx)",a0,a2,a1
5331 *****************************************************************************
5335 * d1.w INTENAR & INTREQR
5338 * a5 &AudioInterruptDMA
5345 PRINTF 6,"AudioInterruptDMA"
5347 move.l p_AudioCtrl(a1),a4
5348 lea p_Channels(a1),a5
5349 lea p_AudPtr1A(a1),a6
5352 move.w ch_IntMask(a5),d0
5356 move.l ch_RegBase(a5),a0
5357 move.l ch_PerVol(a5),AUDPERVOL(a0)
5358 ; move.l ch_AudPerVol(a5),AUDPERVOL(a0)
5359 ; move.l ch_PerVol(a5),ch_AudPerVol(a5)
5363 move.w ch_IntMask(a5),custom+INTREQ ; Clear the interrupt
5364 move.l ch_RegBase(a5),a0
5365 move.l (a6),AUDLC(a0)
5366 move.w ch_DMALength(a5),AUDLEN(a0)
5371 add.w #channel_SIZEOF,a5
5374 move.w ch_IntMask(a5),d0
5378 move.l ch_RegBase(a5),a0
5379 move.l ch_PerVol(a5),AUDPERVOL(a0)
5380 ; move.l ch_AudPerVol(a5),AUDPERVOL(a0)
5381 ; move.l ch_PerVol(a5),ch_AudPerVol(a5)
5385 move.w ch_IntMask(a5),custom+INTREQ ; Clear the interrupt
5386 move.l ch_RegBase(a5),a0
5387 move.l (a6),AUDLC(a0)
5388 move.w ch_DMALength(a5),AUDLEN(a0)
5393 add.w #channel_SIZEOF,a5
5396 move.w ch_IntMask(a5),d0
5400 move.l ch_RegBase(a5),a0
5401 move.l ch_PerVol(a5),AUDPERVOL(a0)
5402 ; move.l ch_AudPerVol(a5),AUDPERVOL(a0)
5403 ; move.l ch_PerVol(a5),ch_AudPerVol(a5)
5407 move.w ch_IntMask(a5),custom+INTREQ ; Clear the interrupt
5408 move.l ch_RegBase(a5),a0
5409 move.l (a6),AUDLC(a0)
5410 move.w ch_DMALength(a5),AUDLEN(a0)
5415 add.w #channel_SIZEOF,a5
5418 move.w ch_IntMask(a5),d0
5422 move.l ch_RegBase(a5),a0
5423 move.l ch_PerVol(a5),AUDPERVOL(a0)
5424 ; move.l ch_AudPerVol(a5),AUDPERVOL(a0)
5425 ; move.l ch_PerVol(a5),ch_AudPerVol(a5)
5429 move.w ch_IntMask(a5),custom+INTREQ ; Clear the interrupt
5430 move.l ch_RegBase(a5),a0
5431 move.l (a6),AUDLC(a0)
5432 move.w ch_DMALength(a5),AUDLEN(a0)
5439 move.w #DMAF_SETCLR|DMAF_AUDIO,DMACON(a0) ; Enable DMA
5440 ; move.w #INTF_AUDIO,INTREQ(a0) ; Clear the interrupts
5446 * a4 AHIAudioCtrlDrv
5447 * a5 struct channel *
5448 * a6 BYTE **buffer[2]
5451 * Check if the next set of parameters should be fetced
5453 cmp.l #AHIST_NOTYPE,ch_Type(a5)
5455 tst.b ch_EndOfSample(a5) ; Already set?
5457 move.l ch_Count(a5),d0
5459 move.l ch_Length(a5),d1
5460 and.l #~1,d1 ; Force even
5465 move.l ch_NextAddress(a5),ch_Address(a5)
5466 move.l ch_NextLength(a5),ch_Length(a5)
5467 move.l ch_NextType(a5),ch_Type(a5)
5468 move.l ch_NextPerVol(a5),ch_PerVol(a5)
5469 move.w ch_NextScale(a5),ch_Scale(a5)
5470 move.l ch_NextOffset(a5),ch_Offset(a5)
5473 PRINTF 4,"New sound! %08lx, Length: %ld, Type: %08lx, PerVol: %08lx",ch_Address(a5),ch_Length(a5),ch_Type(a5),ch_PerVol(a5)
5475 ; Signal that SoundFunc() should be called
5476 st.b ch_EndOfSample(a5)
5479 * Check if SoundFunc() should be called
5481 tst.b ch_EndOfSample(a5)
5483 clr.b ch_EndOfSample(a5) ; Clear signal
5485 ; Call the SoundFunc()
5486 move.l ahiac_SoundFunc(a4),d0
5489 lea ch_SndMsg(a5),a1
5491 move.l h_Entry(a0),a3
5493 move.w ahism_Channel(a1),d0
5494 PRINTF 4,"Calling SoundFunc(%08lx,%08lx,%ld)",a0,a2,d0
5499 * Swap chipmem buffers
5503 * Swap cleared indicators
5504 move.l ch_Cleared2(a5),d0
5505 move.l ch_Cleared(a5),ch_Cleared2(a5)
5506 move.l d0,ch_Cleared(a5)
5508 move.l ch_Address(a5),a2
5510 move.w ch_Scale(a5),d2
5512 move.l ch_Length(a5),d0
5513 move.l ch_Count(a5),d1
5515 * Calculate the number of samples to transfer (this is source samples, which is
5516 * a multiple of the destination samples if ch_Scale != 0.
5519 ble .endofsample ; <= 0 ?
5523 * We have either already reached the end of the sample, or it's paused.
5524 * Set the length to DMABUFFSAMPLES and scale to 0. (I.e., clear the whole
5525 * chipmem buffer.) Do NOT increase ch_Offset/ch_Count!
5526 move.l #DMABUFFSAMPLES,d0
5531 ; samples = max(samples, DMABUFFSAMPLES*(2^scale))
5532 move.l #DMABUFFSAMPLES,d3
5538 add.l d0,ch_Count(a5)
5540 * Get current ch_Offset
5541 move.l ch_Offset(a5),d1
5543 * Update the ch_Offset
5544 move.l ch_Type(a5),d3
5547 sub.l d0,ch_Offset(a5)
5550 add.l d0,ch_Offset(a5)
5553 lsr.l d2,d0 ; Calc. destination samples
5555 lsr.l #1,d3 ; # of words, round to lower
5556 move.w d3,ch_DMALength(a5)
5558 move.l d2,d3 ;Convert ²log scale...
5560 bset d3,d2 ;...to linear
5562 move.l ch_Type(a5),d3
5564 * If the period is 0, this sample is paused => clear the buffer
5565 * If type == AHIST_NOTYPE, clear the buffer
5568 cmp.l #AHIST_NOTYPE,d3
5573 * Alright, we should play silence. But before the dma buffer is filled with
5574 * zeroes, check if we already have cleared it. In that case, there is no need
5575 * to do that again (chipmem accesses are expensive!).
5576 cmp.l ch_Cleared(a5),d0
5577 bls .filled ; Skip it!
5578 move.l d0,ch_Cleared(a5)
5579 lea ClearSample(pc),a3
5583 * It was a normal sample. Figure out which transfer routine to use etc.
5584 clr.l ch_Cleared(a5) ; Mark buffer as un-cleared
5590 and.l #~AHIST_BW,d3 ; Mask fwd/bwd bit
5591 cmp.l #AHIST_S16S,d3
5592 bhi .error ; Sanity check!
5594 move.l jmpt(pc,d3.l),a3
5601 * This should never happen...
5603 PRINTF 2,"Illegal type! %08lx",d3
5613 * d0 Samples to copy
5615 * d2 Decimate/Scale (not log, but linear, can be negative)
5621 PRINTF 6,"ClearSample %08lx, %ld, %ld",a1,d0,d1
5623 lsr.l #2,d0 ;Unrolled
5634 PRINTF 6,"CopySampleM8S %08lx, %ld, %ld",a1,d0,d1
5636 lsr.l #2,d0 ;Unrolled
5645 PRINTF 6,"CopySampleM16S %08lx, %ld, %ld",a1,d0,d1
5646 lsl.l #1,d1 ; 16 bits/sample
5647 lsl.l #1,d2 ; 16 bits/sample
5649 lsr.l #2,d0 ;Unrolled
5658 PRINTF 6,"CopySampleS8S %08lx, %ld, %ld",a1,d0,d1
5659 lsl.l #1,d1 ; 16 bits/sample frame
5660 lsl.l #1,d2 ; 16 bits/sample frame
5662 lsr.l #2,d0 ;Unrolled
5668 add.w ch_Stereo(a5),a2
5672 PRINTF 6,"CopySampleS16S %08lx, %ld, %ld",a1,d0,d1
5673 lsl.l #2,d1 ; 32 bits/sample frame
5674 lsl.l #2,d2 ; 32 bits/sample frame
5676 lsr.l #2,d0 ;Unrolled
5682 add.w ch_Stereo(a5),a2
5683 add.w ch_Stereo(a5),a2
5690 PRINTF 2,"CopySampleError"
5693 * Collect 4 samples and write a full longword to the chipmem buffer