|
|
1.1 root 1: ;*** ScR *** *** NOTESff ***
2:
3: ;* There is still room For improvements in the softint's. For example,
4: ;* try If reducing Chip memory accesses increases speed. NOT high priority, though.
5: ;* This driver should probably have a DMA play mode For 1-4 stereo channels.
6: ;*
7: ;* The sampler routines are just For fun. Since interrupts must NOT be disabled,
8: ;* there are lots of clicks. But still, I have tried To sample at 22kHz While down-
9: ;* loading files from a BBS On my A4000/040, AND it worked without any serial errors.
10: MC68020
11: ;------------
12:
13: VERSION EQU 4
14: REVISION EQU 2
15: DATE Macro
16: Dc.b "17.4.97"
17: ENDM
18: VERS Macro
19: Dc.b "uae 4.2"
20: ENDM
21: VSTRING Macro
22: VERS
23: Dc.b " ("
24: DATE
25: Dc.b ")",13,10,0
26: ENDM
27: VERSTAG Macro
28: Dc.b 0,"$VER: "
29: VERS
30: Dc.b " ("
31: DATE
32: Dc.b ")",0
33: ENDM
34:
35: incdir include:
36:
37: include hardware/all.i
38:
39: include exec/initializers.i
40: include exec/resident.i
41: include exec/alerts.i
42: include exec/memory.i
43: include graphics/gfxbase.i
44: include utility/utility.i
45: include utility/hooks.i
46: include devices/audio.i
47: include dos/dos.i
48:
49:
50: include lvos/exec_lib.i
51: include lvos/utility_lib.i
52: include lvos/dos_lib.i
53: include lvos/cardres_lib.i
54:
55: include devices/ahi.i
56: include libraries/ahi_sub.i
57: include lvos/ahi_sub_lib.i
58:
59: include resources/misc.i
60: include resources/card.i
61: include macros.i
62:
63: _ciaa EQU $bfe001
64: _ciab EQU $bfd000
65:
66: PALFREQ EQU 3546895
67: NTSCFREQ EQU 3579545
68: MINPER EQU 62
69:
70: RECORDSAMPLES EQU 1024
71:
72:
73:
74: ;* paula.audio extra tags
75: AHIDB_Paula14Bit EQU AHIDB_UserBase+0 * Boolean
76: AHIDB_PaulaTable EQU AHIDB_UserBase+1 * Boolean
77:
78: ;* paulaBase (private)
79: STRUCTURE paulaBase,LIB_SIZE
80: UBYTE pb_Flags
81: UBYTE pb_Pad1
82: UWORD pb_Pad2
83: APTR pb_SysLib
84: ULONG pb_SegList
85: APTR pb_GfxLib
86: APTR pb_UtilLib
87: APTR pb_DosLib
88: APTR pb_MiscResource
89: APTR pb_CardResource
90: LABEL paulaBase_SIZEOF
91:
92: ;* paula (private) ahiac_DriverData points to this structure.
93: STRUCTURE paula,0
94: UBYTE p_Flags
95: UBYTE p_Parallel ;TRUE if pport allocated
96: UWORD p_DisableCount
97: APTR p_audioport
98: APTR p_audioreq
99: ULONG p_audiodev
100: APTR p_DMAbuffer
101: APTR p_ParBitsUser
102: APTR p_ParPortUser
103: APTR p_CardHandle
104:
105: STRUCT p_PlayInt,IS_SIZE
106: STRUCT p_PlaySoftInt,IS_SIZE
107: STRUCT p_RecInt,IS_SIZE
108: STRUCT p_RecSoftInt,IS_SIZE
109:
110: UWORD p_MonitorVolume
111: UWORD p_Input
112:
113: ;*** IS_DATA for Play Interrupt (do not change order!)
114: LABEL p_PlayIntData
115: APTR p_PlaySoftIntPtr
116: UWORD p_AudLen ;don't change order
117: ULONG p_AudPer ;
118: UWORD p_DoubleBufferFlag
119: APTR p_AudPtr1A
120: APTR p_AudPtr2A
121: APTR p_AudPtr3A
122: APTR p_AudPtr4A
123: APTR p_AudPtr1B
124: APTR p_AudPtr2B
125: APTR p_AudPtr3B
126: APTR p_AudPtr4B
127:
128: ;*** IS_DATA for Play Software Interrupt (do not change order!)
129: LABEL p_PlaySoftIntData
130: APTR p_PlayerHook
131: ULONG p_Reserved
132: APTR p_AudioCtrlP
133: FPTR p_PlayerEntry ;p_PlayerHook->h_Entry
134: FPTR p_PreTimer
135: FPTR p_PostTimer
136: ULONG p_LoopTimes
137: APTR p_MixHook
138: APTR p_Mixbuffer
139: APTR p_AudioCtrlM
140: FPTR p_MixEntry ;p_MixHook->h_Entry
141: APTR p_AudPtrs
142: APTR p_CalibrationTable
143:
144: ;*** IS_DATA for Aura Record Interrupt (do not change order!)
145: LABEL p_RecIntDataAura
146: APTR p_AuraAddress
147: ;*** IS_DATA for Paula Record Interrupt (do not change order!)
148: LABEL p_RecIntData
149: APTR p_RecFillPtr
150: UWORD p_RecFillCount
151: UWORD p_Pad3
152: APTR p_RecBuffer1
153: APTR p_RecBuffer2
154: APTR p_RecSoftIntPtr
155:
156: LABEL p_RecordMessage
157: ULONG p_rmType
158: APTR p_rmBuffer
159: ULONG p_rmLength
160:
161: STRUCT p_CalibrationArray,256
162: LABEL paula_SIZEOF
163:
164: ;* p_Flags
165: BITDEF P,14BIT,0
166: PB_STEREO EQU AHIACB_STEREO ;=2
167: PF_STEREO EQU AHIACF_STEREO
168:
169: Start:
170: MOVEQ #-1,d0
171: RTS
172:
173: RomTag:
174: Dc.W RTC_MATCHWORD
175: Dc.L RomTag
176: Dc.L EndCode
177: Dc.B RTF_AUTOINIT
178: Dc.B VERSION ;version
179: Dc.B NT_LIBRARY
180: Dc.B 0 ;pri
181: Dc.L LibName
182: Dc.L IDString
183: Dc.L InitTable
184:
185: LibName: Dc.b "uae.audio",0
186: IDString: VSTRING
187: gfxName: GRAPHICSNAME
188: utilName: UTILITYNAME
189: dosName: DOSNAME
190: miscName: MISCNAME
191: cardName: Dc.b "card.resource",0
192: envVar: Dc.b "AHIpaulaFilterFreq",0
193: cnop 0,2
194:
195: InitTable:
196: Dc.L paulaBase_SIZEOF
197: Dc.L funcTable
198: Dc.L dataTable
199: Dc.L initRoutine
200:
201: funcTable:
202: Dc.l Open
203: Dc.l Close
204: Dc.l Expunge
205: Dc.l Null
206: ;*
207: Dc.l AHIsub_AllocAudio
208: Dc.l AHIsub_FreeAudio
209: Dc.l AHIsub_Disable
210: Dc.l AHIsub_Enable
211: Dc.l AHIsub_Start
212: Dc.l AHIsub_Update
213: Dc.l AHIsub_Stop
214: Dc.l AHIsub_SetVol
215: Dc.l AHIsub_SetFreq
216: Dc.l AHIsub_SetSound
217: Dc.l AHIsub_SetEffect
218: Dc.l AHIsub_LoadSound
219: Dc.l AHIsub_UnloadSound
220: Dc.l AHIsub_GetAttr
221: Dc.l AHIsub_HardwareControl
222: Dc.l -1
223:
224: dataTable:
225: INITBYTE LN_TYPE,NT_LIBRARY
226: INITLONG LN_NAME,LibName
227: INITBYTE LIB_FLAGS,LIBF_SUMUSED!LIBF_CHANGED
228: INITWORD LIB_VERSION,VERSION
229: INITWORD LIB_REVISION,REVISION
230: INITLONG LIB_IDSTRING,IDString
231: Dc.L 0
232:
233: initRoutine:
234: MOVEM.l d1/a0/a1/a5/a6,-(sp)
235: MOVE.l d0,a5
236: MOVE.l a6,pb_SysLib(a5)
237: MOVE.l a0,pb_SegList(a5)
238: LEA gfxName(pc),a1
239: MOVEQ #0,d0
240: call OpenLibrary
241: MOVE.l d0,pb_GfxLib(a5)
242: BNE.b .gfxOK
243: ALERT AG_OpenLib!AO_GraphicsLib
244: MOVEQ #0,d0
245: BRA .exit
246: .gfxOK
247: LEA utilName(pc),a1
248: MOVEQ #0,d0
249: call OpenLibrary
250: MOVE.l d0,pb_UtilLib(a5)
251: BNE.b .utilOK
252: ALERT AG_OpenLib!AO_UtilityLib
253: MOVEQ #0,d0
254: BRA .exit
255: .utilOK
256: LEA dosName(pc),a1
257: MOVEQ #0,d0
258: call OpenLibrary
259: MOVE.l d0,pb_DosLib(a5)
260: BNE.b .dosOK
261: ALERT AG_OpenLib!AO_DOSLib
262: MOVEQ #0,d0
263: BRA .exit
264: .dosOK
265: LEA miscName(pc),a1
266: call OpenResource
267: MOVE.l d0,pb_MiscResource(a5)
268: BNE.b .miscOK
269: ALERT AG_OpenRes!AO_MiscRsrc
270: MOVEQ #0,d0
271: BRA .exit
272: .miscOK
273: LEA cardName(pc),a1
274: call OpenResource
275: MOVE.l d0,pb_CardResource(a5) ;Don't fail on error
276:
277: MOVE.l a5,d0
278: .exit
279: MOVEM.l (sp)+,d1/a0/a1/a5/a6
280: RTS
281:
282: Open:
283: MOVEQ #0,d0
284: ADDQ.w #1,LIB_OPENCNT(a6)
285: BCLR.b #LIBB_DELEXP,pb_Flags(a6)
286: MOVE.l a6,d0
287: .exit
288: RTS
289:
290: Close:
291: MOVEQ #0,d0
292: SUBQ.w #1,LIB_OPENCNT(a6)
293: BNE.b .exit
294: BTST.b #LIBB_DELEXP,pb_Flags(a6)
295: BEQ.b .exit
296: BSR Expunge
297: .exit
298: RTS
299:
300: Expunge:
301: MOVEM.l d1/d2/a0/a1/a5/a6,-(sp)
302: MOVE.l a6,a5
303: MOVE.l pb_SysLib(a5),a6
304: TST.w LIB_OPENCNT(a5)
305: BEQ.b .notopen
306: BSET.b #LIBB_DELEXP,pb_Flags(a5)
307: MOVEQ #0,d0
308: BRA.b .Expunge_end
309: .notopen
310: MOVE.l pb_GfxLib(a5),a1
311: call CloseLibrary
312:
313: MOVE.l pb_UtilLib(a5),a1
314: call CloseLibrary
315:
316: MOVE.l pb_DosLib(a5),a1
317: call CloseLibrary
318:
319: MOVE.l pb_SegList(a5),d2
320: MOVE.l a5,a1
321: call Remove
322:
323: MOVEQ #0,d0
324: MOVE.l a5,a1
325: MOVE.w LIB_NEGSIZE(a5),d0
326: SUB.l d0,a1
327: ADD.w LIB_POSSIZE(a5),d0
328: call FreeMem
329: MOVE.l d2,d0
330: .Expunge_end
331: MOVEM.l (sp)+,d1/d2/a0/a1/a5/a6
332: RTS
333:
334: Null:
335: MOVEQ #0,d0
336: RTS
337:
338: ;* BeginIO(ioRequest)(a1) (From amiga.lib)
339: BeginIO:
340: MOVE.l a1,a0 ;probably not neccesary
341: push a6
342: MOVE.l IO_DEVICE(a1),a6
343: JSR -30(a6)
344: pop a6
345: RTS
346:
347: ;****** [driver].audio/--background-- ****************************************
348: ;*
349: ;* OVERVIEW
350: ;*
351: ;* AUDIO ID NUMBERS
352: ;*
353: ;* Just some notes about selecting ID numbers for different modes:
354: ;* It is up to the driver programmer to chose which modes should be
355: ;* available to the user. Take care when selecting.
356: ;* The upper word is the hardware ID, and can only be allocated by
357: ;* Martin Blom <[email protected]>. The lower word is free, but in
358: ;* order to allow enhancements, please only use bit 0 to 3 for modes!
359: ;* Set the remaining bits to zero.
360: ;* The ID is currently used by AHI_BestAudioIDA() to select a mode.
361: ;* In order for this to work, you have to follow some rules.
362: ;* 7 Modes using tables should have higher IDs than modes that uses more
363: ;* CPU power.
364: ;* 7 Mono modes should have higher IDs than stereo modes
365: ;* 7 Stereo modes should have higher IDs than stereo modes with panning.
366: ;* Use AHI:Developer/Support/ScanAudioModes to have a look at the modes
367: ;* currently available.
368: ;*
369: ;* I do reserve the right to change the rules if I find them incorrect!
370: ;*
371: ;*****************************************************************************
372: ;*
373: ;*
374:
375: ;****** [driver].audio/AHIsub_AllocAudio *************************************
376: ;*
377: ;* NAME
378: ;* AHIsub_AllocAudio -- Allocates and initializes the audio hardware.
379: ;*
380: ;* SYNOPSIS
381: ;* result = AHIsub_AllocAudio( tags, audioctrl);
382: ;* D0 A1 A2
383: ;*
384: ;* ULONG AHIsub_AllocAudio( struct TagItem *, struct AHIAudioCtrlDrv * );
385: ;*
386: ;* IMPLEMENTATION
387: ;* Allocate and initialize the audio hardware. Decide if and how you
388: ;* wish to use the mixing routines provided by 'ahi.device', by looking
389: ;* in the AHIAudioCtrlDrv structure and parsing the tag list for tags
390: ;* you support.
391: ;*
392: ;* 1) Use mixing routines with timing:
393: ;* You will need to be able to play any number of samples from
394: ;* about 80 up to 65535 with low overhead.
395: ;* 7 Update AudioCtrl->ahiac_MixFreq to nearest value that your
396: ;* hardware supports.
397: ;* 7 Return AHISF_MIXING|AHISF_TIMING.
398: ;* 2) Use mixing routines without timing:
399: ;* If the hardware can't play samples with any length, use this
400: ;* alternative and provide timing yourself. The buffer must
401: ;* take less than about 20 ms to play, preferable less than 10!
402: ;* 7 Update AudioCtrl->ahiac_MixFreq to nearest value that your
403: ;* hardware supports.
404: ;* 7 Store the number of samples to mix each pass in
405: ;* AudioCtrl->ahiac_BuffSamples.
406: ;* 7 Return AHISF_MIXING
407: ;* Alternatively, you can use the first method and call the
408: ;* mixing hook several times in a row to fill up a buffer.
409: ;* In that case, AHIsub_GetAttr(AHIDB_MaxPlaySamples) should
410: ;* return the size of the buffer plus AudioCtrl->ahiac_MaxBuffSamples.
411: ;* If the buffer is so large that it takes more than (approx.) 10 ms to
412: ;* play it for high sample frequencies, AHIsub_GetAttr(AHIDB_Realtime)
413: ;* should return FALSE.
414: ;* 3) Don't use mixing routines:
415: ;* If your hardware can handle everything without using the CPU to
416: ;* mix the channels, you tell 'ahi.device' this by not setting
417: ;* neither the AHISB_MIXING nor the AHISB_TIMING bit.
418: ;*
419: ;* If you can handle stereo output from the mixing routines, also set
420: ;* bit AHISB_KNOWSTEREO.
421: ;*
422: ;* If you can handle hifi (32 bit) output from the mixing routines,
423: ;* set bit AHISB_KNOWHIFI.
424: ;*
425: ;* If this driver can be used to record samples, set bit AHISB_CANRECORD,
426: ;* too (regardless if you use the mixing routines in AHI or not).
427: ;*
428: ;* If the sound card has hardware to do DSP effects, you can set the
429: ;* AHISB_CANPOSTPROCESS bit. The output from the mixing routines will
430: ;* then be two separate buffers, one wet and one dry. You should then
431: ;* apply the Fx on the wet buffer, and post-mix the two buffers before
432: ;* you send the samples to the DAC. (V4)
433: ;*
434: ;* INPUTS
435: ;* tags - pointer to a taglist.
436: ;* audioctrl - pointer to an AHIAudioCtrlDrv structure.
437: ;*
438: ;* TAGS
439: ;* The tags are from the audio database (AHIDB_#? in <devices/ahi.h>),
440: ;* NOT the tag list the user called ahi.device/AHI_AllocAudio() with.
441: ;*
442: ;* RESULT
443: ;* Flags, defined in <libraries/ahi_sub.h>.
444: ;*
445: ;* EXAMPLE
446: ;*
447: ;* NOTES
448: ;* You don't have to clean up on failure, AHIsub_FreeAudio() will
449: ;* always be called.
450: ;*
451: ;* BUGS
452: ;*
453: ;* SEE ALSO
454: ;* AHIsub_FreeAudio(), AHIsub_Start()
455: ;*
456: ;*****************************************************************************
457: ;*
458: ;*
459:
460: AHIsub_AllocAudio:
461: pushm d2-d7/a2-a6
462: MOVE.l a6,a5
463:
464: MOVE.l a1,d3
465:
466: * Allocate the 'paula' structure (our variables)
467: MOVE.l pb_SysLib(a5),a6
468: MOVE.l #paula_SIZEOF,d0
469: MOVE.l #MEMF_PUBLIC|MEMF_CLEAR,d1
470: call AllocVec
471: MOVE.l d0,ahiac_DriverData(a2)
472: BEQ .error_nopaula
473: MOVE.l d0,a3
474:
475: * Initialize some Fields...
476: MOVE.l #-1,p_audiodev(a3)
477: MOVE.l #-1,p_ParBitsUser(a3)
478: MOVE.l #-1,p_ParPortUser(a3)
479: MOVE.l a2,p_AudioCtrlP(a3) ;player Hook
480: MOVE.l a2,p_AudioCtrlM(a3) ;mixer Hook
481: LEA p_PlaySoftInt(a3),a0
482: MOVE.l a0,p_PlaySoftIntPtr(a3)
483: LEA p_RecSoftInt(a3),a0
484: MOVE.l a0,p_RecSoftIntPtr(a3)
485: MOVE.l #AHIST_S16S,p_rmType(a3)
486: MOVE.l #RECORDSAMPLES,p_rmLength(a3)
487:
488: * Translate Tags To flags
489: MOVEQ #0,d2
490: MOVE.l pb_UtilLib(a5),a6
491: MOVE.l #AHIDB_Paula14Bit,d0
492: MOVEQ #0,d1
493: MOVE.l d3,a0 ;tag list
494: call GetTagData
495: TST.l d0
496: BEQ.b .no14bit
497: MOVEQ #PF_14BIT,d2
498: .no14bit
499: MOVE.l ahiac_Flags(a2),d0
500: AND.b #PF_STEREO,d0 ;same as AHIACF_STEREO
501: OR.b d2,d0
502: MOVE.b p_Flags(a3),d1
503: AND.b #~(PF_STEREO|PF_14BIT),d1
504: OR.b d0,d1
505: MOVE.b d1,p_Flags(a3)
506:
507: * Check If a table should be Used (14 bit calibration)
508: MOVE.l #AHIDB_PaulaTable,d0
509: MOVEQ #0,d1
510: MOVE.l d3,a0 ;tag list
511: call GetTagData
512: TST.l d0
513: BEQ .notable
514:
515: * Load 'ENV:CyberSound/SoundDrivers/14Bit_Calibration', allocate
516: * AND initialize the table.
517: * FIXIT: The calibration File should MOVE To a special chunk in
518: * 'DEVS:AudioModes/PAULA'.
519: MOVE.l pb_DosLib(a5),a6
520: LEA .calibname(pc),a0
521: MOVE.l a0,d1
522: MOVE.l #MODE_OLDFILE,d2
523: call Open
524: MOVE.l d0,d4
525: BEQ .nocalib
526: MOVE.l d0,d1
527: LEA p_CalibrationArray(a3),a0
528: MOVE.l a0,d2
529: MOVE.l #256,d3
530: call Read
531: CMP.l d0,d3
532: BEQ .tableloaded
533: .nocalib
534: ; Fill defaults
535: LEA p_CalibrationArray(a3),a0
536: MOVE.w #254-1,d0
537: .initcalib
538: MOVE.b #$55,(a0)+
539: DBF d0,.initcalib
540: MOVE.b #$7f,(a0)+
541: .tableloaded
542: MOVE.l d4,d1
543: BEQ.b .nofile
544: call Close
545: .nofile
546: MOVE.l pb_SysLib(a5),a6
547: MOVE.l #65536*2,d0
548: MOVE.l #MEMF_PUBLIC,d1
549: call AllocVec
550: MOVE.l d0,p_CalibrationTable(a3)
551: BEQ.b .notable
552: MOVE.l d0,a0 ;table
553: LEA p_CalibrationArray(a3),a1
554: BSR.w _CreateTable
555: .notable
556:
557:
558: * allocate audio.device
559: MOVE.l pb_SysLib(a5),a6
560: call CreateMsgPort
561: MOVE.l d0,p_audioport(a3)
562: BEQ .error_noport
563: MOVEQ #ioa_SIZEOF,d0
564: MOVE.l #MEMF_PUBLIC!MEMF_CLEAR,d1
565: call AllocVec
566: MOVE.l d0,p_audioreq(a3)
567: BEQ .error_noreqmem
568: MOVE.l d0,a0
569: MOVE.l p_audioport(a3),MN_REPLYPORT(a0)
570: CLR.w ioa_AllocKey(a0)
571: MOVE.b #127,LN_PRI(a0) ;steal it!
572: LEA .audiochannelarray(pc),a1
573: MOVE.l a1,ioa_Data(a0)
574: MOVE.l #1,ioa_Length(a0)
575: LEA .audioname(pc),a0
576: MOVEQ #0,d0
577: MOVE.l p_audioreq(a3),a1
578: MOVEQ #0,d1
579: call OpenDevice
580: MOVE.l d0,p_audiodev(a3)
581: BNE .error_noaudiodev ;somebody already owns the hardware (could be us!)
582: MOVE.l p_audioreq(a3),a1 ;bernd#1
583: MOVE.w #CMD_RESET,IO_COMMAND(a1)
584: BSR.w BeginIO ;clear attach, stop sound.
585: MOVE.l p_audioport(a3),a0
586: call WaitPort
587: MOVE.l p_audioport(a3),a0
588: call GetMsg
589:
590: MOVE.l pb_DosLib(a5),a6
591: MOVEQ #1,d1
592: call Delay
593:
594: * test If mode supports recording
595: BTST #PB_14BIT,p_Flags(a3)
596: BNE .dontgetsampler ;no record if 14 bit mode
597:
598: * try To allocate parallel port
599: CLR.b p_Parallel(a3)
600: MOVE.l pb_MiscResource(a5),a6
601: MOVEQ #MR_PARALLELBITS,d0
602: LEA IDString(pc),a1
603: JSR MR_ALLOCMISCRESOURCE(a6)
604: MOVE.l d0,p_ParBitsUser(a3)
605: BNE .no_parrallel
606: MOVEQ #MR_PARALLELPORT,d0
607: LEA IDString(pc),a1
608: JSR MR_ALLOCMISCRESOURCE(a6)
609: MOVE.l d0,p_ParPortUser(a3)
610: BNE .no_parrallel
611:
612: MOVE.b #TRUE,p_Parallel(a3)
613: ;move.b #0,_ciaa+ciaddrb ;make PB0-PB7 inputs
614: .no_parrallel
615:
616: ;* allocate Aura sampler
617: CLR.l p_AuraAddress(a3)
618: MOVE.l pb_CardResource(a5),d0
619: BEQ .no_aura
620: MOVE.l d0,a6
621: call GetCardMap
622: TST.l d0
623: BEQ .no_aura
624: MOVE.l d0,a0
625: MOVE.l cmm_IOMemory(a0),d2
626: BEQ .no_aura
627:
628: base exec
629: MOVEQ #CardHandle_SIZEOF,d0
630: MOVE.l #MEMF_PUBLIC|MEMF_CLEAR,d1
631: call AllocVec
632: MOVE.l d0,p_CardHandle(a3)
633: BEQ .no_aura
634:
635: MOVE.l pb_CardResource(a5),a6
636: MOVE.l d0,a1
637: MOVE.l #IDString,LN_NAME(a1)
638: MOVE.b #CARDF_RESETREMOVE|CARDF_IFAVAILABLE,cah_CardFlags(a1)
639: call OwnCard
640: TST.l d0
641: BNE .no_aura
642:
643: MOVE.l p_CardHandle(a3),a1
644: call BeginCardAccess
645: TST.l d0
646: BEQ .no_aura
647:
648: MOVE.l d2,p_AuraAddress(a3)
649: .no_aura
650: .dontgetsampler
651:
652:
653: ;* initialize interrupts (Only dummy function pointers at this time)
654:
655: ;* p_PlayInt (the main playback interrupt)
656: MOVE.b #NT_INTERRUPT,LN_TYPE+p_PlayInt(a3)
657: MOVE.l #LibName,LN_NAME+p_PlayInt(a3)
658: MOVE.l #Interrupt_Dummy,IS_CODE+p_PlayInt(a3)
659: LEA p_PlayIntData(a3),a1
660: MOVE.l a1,IS_DATA+p_PlayInt(a3)
661:
662: ;* p_PlaySoftInt (caused by p_PlayInt, here are the mixing and conversion done)
663: MOVE.b #NT_INTERRUPT,LN_TYPE+p_PlaySoftInt(a3)
664: MOVE.l #LibName,LN_NAME+p_PlaySoftInt(a3)
665: MOVE.l #SoftInt_Dummy,IS_CODE+p_PlaySoftInt(a3)
666: LEA p_PlaySoftIntData(a3),a1
667: MOVE.l a1,IS_DATA+p_PlaySoftInt(a3)
668:
669: ;* p_RecInt (the interrupt used for recording)
670: MOVE.b #NT_INTERRUPT,LN_TYPE+p_RecInt(a3)
671: MOVE.l #LibName,LN_NAME+p_RecInt(a3)
672: MOVE.l #Interrupt_Dummy,IS_CODE+p_RecInt(a3)
673: CLR.l IS_DATA+p_RecInt(a3)
674:
675: ;* p_RecSoftInt (caused by p_RecInt when the record buffer has been filled)
676: MOVE.b #32,LN_PRI+p_RecSoftInt(a3)
677: MOVE.b #NT_INTERRUPT,LN_TYPE+p_RecSoftInt(a3)
678: MOVE.l #LibName,LN_NAME+p_RecSoftInt(a3)
679: MOVE.l #RecordSoftInt,IS_CODE+p_RecSoftInt(a3)
680: MOVE.l a3,IS_DATA+p_RecSoftInt(a3)
681:
682: ;* Make sure no interrupts occur until AHIsub_Start() is called
683: MOVE.w #INTF_AUD0!INTF_AUD1!INTF_AUD2!INTF_AUD3,CUSTOM+INTENA
684:
685: ;* Update ahiac_MixFreq to what the mixing/sampling frequency really is
686: MOVE.l ahiac_MixFreq(a2),d1
687: BSR calcperiod
688: MOVE.l d0,ahiac_MixFreq(a2) ;store actual freq
689:
690: MOVEQ #AHISB_KNOWHIFI|AHISF_KNOWSTEREO|AHISF_CANRECORD|AHISF_MIXING|AHISF_TIMING,d0
691: .exit
692: popm d2-d7/a2-a6
693: RTS
694:
695: .error_noaudiodev
696: .error_noreqmem
697: .error_noport
698: .error_nopaula
699: MOVEQ #AHISF_ERROR,d0
700: BRA.b .exit
701:
702: .audiochannelarray
703: Dc.b 1+2+4+8
704: .audioname
705: AUDIONAME
706: .calibname
707: Dc.b "ENV:CyberSound/SoundDrivers/14Bit_Calibration",0
708: Even
709: .cardhandle:
710: Dc.l 0,0 ;ln_Succ, ln_Pred
711: Dc.b 0 ;ln_Type
712: Dc.b 0 ;ln_Pri
713: Dc.l IDString ;ln_Name
714: Dc.l 0,0,0 ;cah_CardRemoved, cah_CardInserted, cah_CardStatus
715: Dc.b (CARDF_RESETREMOVE|CARDF_IFAVAILABLE)
716: Even
717:
718: ;in:
719: ;* d1 MixFreq
720: ;* a5 paulaBase
721: ;out:
722: ;* d0 New MixFreq
723: ;* d1.w Period
724: ;description:
725: ;* Calculate and return the best period and the actual frequency.
726: calcperiod:
727: pushm d2-d5
728: move.l d1,d5
729: MOVE.l #0,d0
730: jsr $F0FFB0
731: MOVE.l d0,d1
732: MOVE.l #1,d0
733: jsr $F0FFB0
734: ; now, d0 contains the divisor UAE uses for its output frequency.
735: ; d1 contains the nominal output frequency of UAE.
736: ; Multiply the two and divide by desired frequency (which we'll
737: ; assume to be 44100 Hz), and we get the necessary divider
738: MOVE.l pb_UtilLib(a5),a1
739: jsr _LVOUMult32(a1)
740: MOVE.l #44100,d5 ; @@@ potentially change this
741: MOVE.l d5,d1
742: jsr _LVOUDivMod32(a1)
743: MOVE.l d0,d1
744: MOVE.l d5,d0
745: popm d2-d5
746: RTS
747:
748: ;in:
749: * d0 Frequency
750: ;out:
751: * d0 Closest frequency
752: * d1 Index
753: findfreq:
754: LEA uae(pc),a0
755: CMP.l (a0),d0
756: BLS.b .2
757: .findfreq
758: CMP.l (a0)+,d0
759: BHI.b .findfreq
760: MOVE.l -4(a0),d1
761: SUB.l d0,d1
762: SUB.l -8(a0),d0
763: CMP.l d1,d0
764: bhs.b .1
765: SUBQ.l #4,a0
766: .1
767: SUBQ.l #4,a0
768: .2
769: MOVE.l (a0),d0
770: MOVE.l a0,d1
771: SUB.l #uae,d1
772: LSR.l #2,d1
773: RTS
774:
775: freqlist:
776: Dc.l 4410 ; CD/10
777: Dc.l 4800 ; DAT/10
778: Dc.l 5513 ; CD/8
779: Dc.l 6000 ; DAT/8
780: Dc.l 7350 ; CD/6
781: Dc.l 8000 ; 5- and A-Law, DAT/6
782: Dc.l 9600 ; DAT/5
783: Dc.l 11025 ; CD/4
784: Dc.l 12000 ; DAT/4
785: Dc.l 14700 ; CD/3
786: Dc.l 16000 ; DAT/3
787: Dc.l 17640 ; CD/2.5
788: Dc.l 18900
789: Dc.l 19200 ; DAT/2.5
790: Dc.l 22050 ; CD/2
791: Dc.l 24000 ; DAT/2
792: Dc.l 27429
793: FREQUENCIES_OCS EQU (*-freqlist)
794: Dc.l 29400 ; CD/1.5
795: uae Dc.l 32000 ; DAT/1.5
796: ;dc.l 33075
797: ;dc.l 37800
798: Dc.l 44100 ; CD
799: ;dc.l 48000 ; DAT
800: FREQUENCIES EQU (*-uae)
801: Dc.l -1
802:
803: * _CreateTable directly stolen from Christian Buchner's CyberSound
804: * audio SUB system (with permission).
805:
806: * _CreateTable **************************************************************
807:
808: ; Parameters
809:
810: ; a0 = Table address
811: ; (MUST have enough space for 65536 UWORDS)
812: ; a1 = Additive Array
813: ; 256 UBYTEs
814: ;
815: ; the table is organized as follows:
816: ; 32768 UWORDS positive range, ascending order
817: ; 32768 UWORDS negative range, ascending order
818: ; access: (a0,d0.l*2)
819: ; where d0.w is signed word sample data
820: ; and the upper word of d0.l is *cleared!*
821:
822:
823: _CreateTable MOVEM.l a2/d2-d6,-(sp)
824:
825: LEA 128(a1),a2
826:
827: MOVE.l a2,a1 ; count the number of steps
828: MOVEQ #128-1,d0 ; in the positive range
829: MOVEQ #0,d5
830: .countpositive MOVE.b (a1)+,d1
831: EXT.w d1
832: EXT.l d1
833: ADD.l d1,d5
834: DBRA d0,.countpositive ; d5=number of steps
835: MOVE.l #32768,d6 ; reset stretch counter
836:
837: MOVE.l a2,a1 ; middle value in calibdata
838: MOVE.w #32768-1,d0 ; number of positive values -1
839: MOVEQ #0,d1 ; HI value
840: MOVEQ #0,d2 ; LO value
841: MOVEQ #0,d3 ; counter
842: .fetchnext2 MOVE.b (a1)+,d4 ; add calibtable to counter
843: EXT.w d4
844: ADD.w d4,d3
845: .outerloop2 TST.w d3
846: BGT.s .positive2
847: .negative2 ADDQ.w #1,d1 ; increment HI value
848: SUB.w d4,d2 ; reset LO value
849: BRA.s .fetchnext2
850: .positive2 MOVE.b d1,(a0)+ ; store HI and LO value
851: MOVE.b d2,(a0)+
852: SUB.l d5,d6 ; stretch the table
853: BPL.s .repeat2 ; to 32768 entries
854: ADD.l #32768,d6
855: ADDQ.w #1,d2 ; increment LO value
856: SUBQ.w #1,d3 ; decrement counter
857: .repeat2 DBRA d0,.outerloop2
858:
859: MOVE.l a2,a1 ; count the number of steps
860: MOVEQ #128-1,d0 ; in the negative range
861: MOVEQ #0,d5
862: .countnegative MOVE.b -(a1),d1
863: EXT.w d1
864: EXT.l d1
865: ADD.l d1,d5
866: DBRA d0,.countnegative ; d5=number of steps
867: MOVE.l #32768,d6 ; reset stretch counter
868:
869: ADD.l #2*32768,a0 ; place at the end of the table
870: MOVE.l a2,a1 ; middle value in calibdata
871: MOVE.w #32768-1,d0 ; number of negative values -1
872: MOVEQ #-1,d1 ; HI value
873: MOVEQ #-1,d2 ; LO value
874: MOVEQ #0,d3 ; counter
875: .fetchnext1 MOVE.b -(a1),d4 ; add calibtable to counter
876: EXT.w d4
877: ADD.w d4,d3
878: ADD.w d4,d2 ; maximize LO value
879: .outerloop1 TST.w d3
880: BGT.s .positive1
881: .negative1 SUBQ.w #1,d1
882: BRA.s .fetchnext1
883: .positive1 MOVE.b d2,-(a0) ; store LO and HI value
884: MOVE.b d1,-(a0)
885: SUB.l d5,d6 ; stretch the table
886: BPL.s .repeat1 ; to 32768 entries
887: ADD.l #32768,d6
888: SUBQ.w #1,d2 ; decrement lo value
889: SUBQ.w #1,d3 ; decrement counter
890: .repeat1 DBRA d0,.outerloop1
891:
892: MOVEM.l (sp)+,a2/d2-d6
893: RTS
894:
895:
896: ****** [driver].audio/AHIsub_FreeAudio **************************************
897: *
898: * NAME
899: * AHIsub_FreeAudio -- Deallocates the audio hardware.
900: *
901: * SYNOPSIS
902: * AHIsub_FreeAudio( audioctrl );
903: * A2
904: *
905: * void AHIsub_FreeAudio( struct AHIAudioCtrlDrv * );
906: *
907: * IMPLEMENTATION
908: * Deallocate the audio hardware AND other resources allocated in
909: * AHIsub_AllocAudio(). AHIsub_Stop() will always be called by
910: * 'ahi.device' before this Call is made.
911: *
912: * INPUTS
913: * audioctrl - Pointer To an AHIAudioCtrlDrv structure.
914: *
915: * NOTES
916: * It must be safe To Call this routine Even If AHIsub_AllocAudio()
917: * was never called, failed OR called more than once.
918: *
919: * SEE ALSO
920: * AHIsub_AllocAudio()
921: *
922: *****************************************************************************
923: *
924: *
925:
926: AHIsub_FreeAudio:
927: pushm d2-d7/a2-a6
928:
929: MOVE.l a6,a5
930: MOVE.l pb_SysLib(a5),a6
931:
932: MOVE.l ahiac_DriverData(a2),d0
933: BEQ .nopaula
934: MOVE.l d0,a3
935:
936: MOVE.l p_CalibrationTable(a3),d0
937: BEQ.b .notable
938: MOVE.l d0,a1
939: call FreeVec
940: .notable
941: TST.l p_audiodev(a3)
942: BNE.b .noaudiodev
943: MOVE.l p_audioreq(a3),a1 ;bernd#1
944: MOVE.w #CMD_RESET,IO_COMMAND(a1) ;Restore audio interrupts
945: BSR.w BeginIO
946: MOVE.l p_audioport(a3),a0
947: call WaitPort
948: MOVE.l p_audioport(a3),a0
949: call GetMsg
950: MOVE.l p_audioreq(a3),a1
951: SUBQ.l #1,p_audiodev(a3)
952: call CloseDevice
953: .noaudiodev
954: MOVE.l p_audioreq(a3),d0
955: BEQ.b .noaudioreq
956: MOVE.l d0,a1
957: call FreeVec
958: .noaudioreq
959: MOVE.l p_audioport(a3),d0
960: BEQ.b .noaudioport
961: MOVE.l d0,a0
962: call DeleteMsgPort
963: .noaudioport
964: MOVE.l pb_CardResource(a5),d0
965: BEQ .noaura
966: MOVE.l d0,a6
967: MOVE.l p_CardHandle(a3),d0
968: BEQ .noaura
969: MOVE.l d0,a1
970: call EndCardAccess
971: MOVE.l p_CardHandle(a3),a1
972: MOVEQ #CARDF_REMOVEHANDLE,d0
973: call ReleaseCard
974: .noaura
975: MOVE.l pb_SysLib(a5),a6
976: MOVE.l p_CardHandle(a3),d0
977: BEQ .nocardhandle
978: MOVE.l d0,a1
979: call FreeVec
980: .nocardhandle
981: MOVE.l pb_MiscResource(a5),a6
982: TST.l p_ParPortUser(a3)
983: BNE.b .noparport
984: MOVEQ #MR_PARALLELPORT,d0
985: JSR MR_FREEMISCRESOURCE(a6)
986: .noparport
987: TST.l p_ParBitsUser(a3)
988: BNE.b .noparbits
989: MOVEQ #MR_PARALLELBITS,d0
990: JSR MR_FREEMISCRESOURCE(a6)
991: .noparbits
992: MOVE.l pb_SysLib(a5),a6
993: MOVE.l a3,a1
994: CLR.l ahiac_DriverData(a2)
995: call FreeVec
996: .nopaula
997: MOVEQ #0,d0
998: popm d2-d7/a2-a6
999: RTS
1000:
1001:
1002: ****** [driver].audio/AHIsub_Disable ****************************************
1003: *
1004: * NAME
1005: * AHIsub_Disable -- Temporary turn Off audio interrupt/task
1006: *
1007: * SYNOPSIS
1008: * AHIsub_Disable( audioctrl );
1009: * A2
1010: *
1011: * void AHIsub_Disable( struct AHIAudioCtrlDrv * );
1012: *
1013: * IMPLEMENTATION
1014: * If you are lazy, Then Call exec.library/Disable().
1015: * If you are smart, only Disable your own interrupt OR task.
1016: *
1017: * INPUTS
1018: * audioctrl - Pointer To an AHIAudioCtrlDrv structure.
1019: *
1020: * NOTES
1021: * This Call should be guaranteed To preserve all registers.
1022: * This Call nests.
1023: *
1024: * SEE ALSO
1025: * AHIsub_Enable(), exec.library/Disable()
1026: *
1027: *****************************************************************************
1028: *
1029: *
1030:
1031: AHIsub_Disable:
1032: push a3
1033: MOVE.l ahiac_DriverData(a2),a3
1034: ADDQ.w #1,p_DisableCount(a3)
1035: MOVE.w #INTF_AUD0,CUSTOM+INTENA
1036: ; moveq #2,d0
1037: ; moveq #0,d1
1038: ; jsr.l $f0ffb0
1039: pop a3
1040: RTS
1041:
1042: ****** [driver].audio/AHIsub_Enable *****************************************
1043: *
1044: * NAME
1045: * AHIsub_Enable -- Turn On audio interrupt/task
1046: *
1047: * SYNOPSIS
1048: * AHIsub_Enable( audioctrl );
1049: * A2
1050: *
1051: * void AHIsub_Enable( struct AHIAudioCtrlDrv * );
1052: *
1053: * IMPLEMENTATION
1054: * If you are lazy, Then Call exec.library/Enable().
1055: * If you are smart, only Enable your own interrupt OR task.
1056: *
1057: * INPUTS
1058: * audioctrl - Pointer To an AHIAudioCtrlDrv structure.
1059: *
1060: * NOTES
1061: * This Call should be guaranteed To preserve all registers.
1062: * This Call nests.
1063: *
1064: * SEE ALSO
1065: * AHIsub_Disable(), exec.library/Enable()
1066: *
1067: *****************************************************************************
1068: *
1069: *
1070:
1071: AHIsub_Enable:
1072: push a3
1073: MOVE.l ahiac_DriverData(a2),a3
1074: SUBQ.w #1,p_DisableCount(a3)
1075: BNE.b .exit
1076: MOVE.w #INTF_SETCLR!INTF_AUD0,CUSTOM+INTENA
1077: ; moveq #2,d0
1078: ; moveq #1,d1
1079: ; jsr.l $f0ffb0
1080: .exit
1081: pop a3
1082: RTS
1083:
1084: ****** [driver].audio/AHIsub_Start ******************************************
1085: *
1086: * NAME
1087: * AHIsub_Start -- Starts PlayBack OR recording
1088: *
1089: * SYNOPSIS
1090: * error = AHIsub_Start( flags, audioctrl );
1091: * D0 D0 A2
1092: *
1093: * ULONG AHIsub_Start(ULONG, struct AHIAudioCtrlDrv * );
1094: *
1095: * IMPLEMENTATION
1096: * What To do depends what you returned in AHIsub_AllocAudio().
1097: *
1098: * * First, assume bit AHISB_PLAY in flags is set. This means that you
1099: * should begin PlayBack.
1100: *
1101: * - AHIsub_AllocAudio() returned AHISF_MIXING|AHISF_TIMING:
1102: *
1103: * A) Allocate a mixing Buffer of ahiac_BuffSize bytes. The Buffer must
1104: * be long aligned!
1105: * B) Create/Start an interrupt OR task that will do 1-6 over AND over
1106: * again Until AHIsub_Stop() is called. Note that it is NOT a good
1107: * idea To do the actual mixing AND conversion in a real hardware
1108: * interrupt. Signal a task OR create a Software Interrupt To do
1109: * the number crunching.
1110: *
1111: * 1) Call the user Hook ahiac_PlayerFunc with the following parameters:
1112: * A0 - (struct Hook *)
1113: * A2 - (struct AHIAudioCtrlDrv *)
1114: * A1 - Set To Null.
1115: *
1116: * 2) [Call the ahiac_PreTimer Function. If it returns True (Z will be
1117: * cleared so you don't have To test d0), skip Step 3 AND 4. This
1118: * is Used To avoid overloading the CPU. This Step is optional.
1119: * A2 is assumed To Point To struct AHIAudioCtrlDrv. All registers
1120: * except d0 are preserved. (V4)]
1121: *
1122: * 3) Call the mixing Hook (ahiac_MixerFunc) with the following
1123: * parameters:
1124: * A0 - (struct Hook *) - The Hook itself
1125: * A2 - (struct AHIAudioCtrlDrv *)
1126: * A1 - (WORD *[]) - The mixing Buffer.
1127: * Note that ahiac_MixerFunc preserves ALL registers.
1128: * The user Hook ahiac_SoundFunc will be called by the mixing
1129: * routine when a sample have been processed, so you don't have To
1130: * worry about that.
1131: * How the Buffer will be filled is indicated by ahiac_Flags.
1132: * It is always filled with signed 16-bit (32 bit If AHIDBB_HIFI in
1133: * in ahiac_Flags is set) words, Even If PlayBack is 8 bit. If
1134: * AHIDBB_STEREO is set (in ahiac_Flags), Data For left AND right
1135: * channel are interleaved:
1136: * 1st sample left channel,
1137: * 1st sample right channel,
1138: * 2nd sample left channel,
1139: * ...,
1140: * ahiac_BuffSamples:th sample left channel,
1141: * ahiac_BuffSamples:th sample right channel.
1142: * If AHIDBB_STEREO is cleared, the mono Data is stored:
1143: * 1st sample,
1144: * 2nd sample,
1145: * ...,
1146: * ahiac_BuffSamples:th sample.
1147: * Note that neither AHIDBB_STEREO nor AHIDBB_HIFI will be set If
1148: * you didn't report that you understand these flags when
1149: * AHI_AllocAudio() was called.
1150: *
1151: * For AHI V2, the Type of Buffer is also available in ahiac_BuffType.
1152: * It is suggested that you Use this value instead. ahiac_BuffType
1153: * can be one of AHIST_M16S, AHIST_S16S, AHIST_M32S AND AHIST_S32S.
1154: *
1155: * 4) Convert the Buffer If needed AND feed it To the audio hardware.
1156: * Note that you may have To clear CPU caches If you are using DMA
1157: * To play the Buffer, AND the Buffer is NOT allocated in non-
1158: * cachable RAM.
1159: *
1160: * 5) [Call the ahiac_PostTimer Function. A2 is assumed To Point To
1161: * struct AHIAudioCtrlDrv. All registers are preserved. (V4)]
1162: *
1163: * 6) Wait Until the whole Buffer has been played, Then Repeat.
1164: *
1165: * Use double buffering If possible!
1166: *
1167: * You may DECREASE ahiac_BuffSamples slightly, For example To force an
1168: * Even number of samples To be mixed. By doing this you will make
1169: * ahiac_PlayerFunc To be called at wrong frequency so be careful!
1170: * Even If ahiac_BuffSamples is defined ULONG, it will never be greater
1171: * than 65535.
1172: *
1173: * ahiac_BuffSize is the Largest size of the mixing Buffer that will be
1174: * needed Until AHIsub_Stop() is called.
1175: *
1176: * ahiac_MaxBuffSamples is the Maximum number of samples that will be
1177: * mixed (Until AHIsub_Stop() is called). You can Use this value If you
1178: * need To allocate DMA buffers.
1179: *
1180: * ahiac_MinBuffSamples is the minimum number of samples that will be
1181: * mixed. Most drivers will ignore it.
1182: *
1183: * If AHIsub_AllocAudio() returned with the AHISB_CANPOSTPROCESS bit set,
1184: * ahiac_BuffSize is large enough To hold two buffers. The mixing Buffer
1185: * will be filled with the wet Buffer first, immediately followed by the
1186: * dry Buffer. I.e., ahiac_BuffSamples sample Frames wet Data, Then
1187: * ahiac_BuffSamples sample Frames dry Data. The DSP fx should only be
1188: * applied To the wet Buffer, AND the two buffers should Then be added
1189: * together. (V4)
1190: *
1191: * - If AHIsub_AllocAudio() returned AHISF_MIXING, do as described above,
1192: * except calling ahiac_PlayerFunc. ahiac_PlayerFunc should be called
1193: * ahiac_PlayerFreq times per second, clocked by timers On your Sound
1194: * card OR by using 'realtime.library'. No other AMIGA resources may
1195: * be Used For timing (like direct CIA timers).
1196: * ahiac_MinBuffSamples AND ahiac_MaxBuffSamples are undefined If
1197: * AHIsub_AllocAudio() returned AHISF_MIXING (AHISB_TIMING bit NOT set).
1198: *
1199: * - If AHIsub_AllocAudio() returned with neither the AHISB_MIXING nor
1200: * the AHISB_TIMING bit set, Then just Start PlayBack. Don't forget To
1201: * Call ahiac_PlayerFunc ahiac_PlayerFreq times per second. Only your
1202: * own timing hardware OR 'realtime.library' may be Used. Note that
1203: * ahiac_MixerFunc, ahiac_BuffSamples, ahiac_MinBuffSamples,
1204: * ahiac_MaxBuffSamples AND ahiac_BuffSize are undefined. ahiac_MixFreq
1205: * is the frequency the user wants To Use For recording, If you support
1206: * that.
1207: *
1208: * * Second, assume bit AHISB_RECORD in flags is set. This means that you
1209: * should Start To sample. Create a interrupt OR task that does the
1210: * following:
1211: *
1212: * Allocate a Buffer (you chose size, but try To keep it reasonable
1213: * small To avoid delays - it is suggested that RecordFunc is called
1214: * at least 4 times/second For the lowers sampling rate, AND more often
1215: * For higher rates), AND fill it with the sampled Data. The Buffer must
1216: * be long aligned, AND it's size must be evenly divisible by four.
1217: * The Format should always be AHIST_S16S (Even with 8 bit mono samplers),
1218: * which means:
1219: * 1st sample left channel,
1220: * 1st sample right channel (same as prev. If mono),
1221: * 2nd sample left channel,
1222: * ... etc.
1223: * Each sample is a signed word (WORD). The sample rate should be equal
1224: * To the mixing rate.
1225: *
1226: * Call the ahiac_SamplerFunc Hook with the following parameters:
1227: * A0 - (struct Hook *) - The Hook itself
1228: * A2 - (struct AHIAudioCtrlDrv *)
1229: * A1 - (struct AHIRecordMessage *)
1230: * The message should be filled as follows:
1231: * ahirm_Type - Set To AHIST_S16S.
1232: * ahirm_Buffer - A Pointer To the filled Buffer.
1233: * ahirm_Samples - How many sample Frames stored.
1234: * You must NOT destroy the Buffer Until Next time the Hook is called.
1235: *
1236: * Repeat Until AHIsub_Stop() is called.
1237: *
1238: * * Note that both bits may be set when this Function is called.
1239: *
1240: * INPUTS
1241: * flags - See <libraries/ahi_sub.h>.
1242: * audioctrl - Pointer To an AHIAudioCtrlDrv structure.
1243: *
1244: * RESULT
1245: * Returns AHIE_OK If successful, Else an error code as defined
1246: * in <devices/ahi.h>. AHIsub_Stop() will always be called, Even
1247: * If this Call failed.
1248: *
1249: * NOTES
1250: * The driver must be able To Handle multiple calls To this routine
1251: * without preceding calls To AHIsub_Stop().
1252: *
1253: * SEE ALSO
1254: * AHIsub_Update(), AHIsub_Stop()
1255: *
1256: *****************************************************************************
1257: *
1258: *
1259: *
1260:
1261: AHIsub_Start:
1262: pushm d2-d7/a2-a6
1263:
1264: MOVE.l d0,d7
1265: LEA CUSTOM,a4
1266: MOVE.l ahiac_DriverData(a2),a3
1267:
1268: BTST #AHISB_PLAY,d0
1269: BEQ .dont_play
1270:
1271: **
1272: *** AHISB_PLAY
1273: **
1274: MOVEQ #AHISF_PLAY,d0
1275: call AHIsub_Stop ;Stop current playback if any.
1276: call AHIsub_Update ;fill variables
1277:
1278: MOVE.l a6,a5
1279: MOVE.l pb_SysLib(a5),a6
1280:
1281: MOVE.l ahiac_BuffSize(a2),d0
1282: MOVE.l #MEMF_PUBLIC|MEMF_CLEAR,d1
1283: call AllocVec
1284: MOVE.l d0,p_Mixbuffer(a3)
1285: BEQ .error_nomem
1286:
1287: MOVE.l ahiac_MixFreq(a2),d1
1288: BSR.w calcperiod
1289: MOVE.l d1,p_AudPer(a3)
1290: MOVE.l #0,flag
1291: CMP.w #$7f,d1 ;use old routines
1292: BGE .10
1293: MOVE.l #1,flag
1294: .10
1295: * The init*bit? routines allocates p_DMAbuffer, sets up p_AudPtr, sets the Volume,
1296: * stores the correct interrupt routines in p_PlayInt's AND p_PlaySoftInt's IS_CODE.
1297:
1298: PEA .1(pc)
1299: MOVE.b p_Flags(a3),d0
1300: AND.b #PF_STEREO!PF_14BIT,d0
1301: BEQ.w init16bitM
1302: CMP.b #PF_STEREO,d0
1303: BEQ.w init16bitS
1304: CMP.b #PF_14BIT,d0
1305: BEQ.w init14bitM
1306: BRA.w init14bitS
1307: .1
1308: TST.l d0
1309: BNE .exit
1310:
1311: * Install play interrupt
1312: LEA p_PlayInt(a3),a1
1313: MOVEQ #INTB_AUD0,d0
1314: call SetIntVector
1315: CLR.w p_DisableCount(a3)
1316:
1317: MOVE.w #INTF_SETCLR!INTF_AUD0,INTENA(a4) ;enable
1318: MOVE.w #INTF_SETCLR!INTF_AUD0,INTREQ(a4) ;start
1319: MOVE.l a5,a6
1320:
1321:
1322: .dont_play
1323: BTST #AHISB_RECORD,d7
1324: BEQ .dont_record
1325: **
1326: *** AHISB_RECORD
1327: **
1328: BTST #PB_14BIT,p_Flags(a3) ;Sanity check...
1329: BNE .error_unknown
1330:
1331: MOVEQ #AHISF_RECORD,d0
1332: call AHIsub_Stop ;Stop current recording if any.
1333:
1334: MOVE.l a6,a5
1335: MOVE.l pb_SysLib(a5),a6
1336:
1337: MOVE.l #RECORDSAMPLES*4,d0
1338: MOVE.l #MEMF_PUBLIC,d1
1339: call AllocVec
1340: MOVE.l d0,p_RecBuffer1(a3)
1341: BEQ .error_nomem
1342:
1343: MOVE.l d0,p_RecFillPtr(a3)
1344: MOVE.w #RECORDSAMPLES,p_RecFillCount(a3)
1345:
1346: MOVE.l #RECORDSAMPLES*4,d0
1347: MOVE.l #MEMF_PUBLIC,d1
1348: call AllocVec
1349: MOVE.l d0,p_RecBuffer2(a3)
1350: BEQ .error_nomem
1351:
1352: MOVE.l ahiac_MixFreq(a2),d1
1353: BSR.w calcperiod
1354: LSR.w #1,d1 ;Period/2 => Frequency72
1355: MOVE.w d1,AUD2PER(a4)
1356: MOVE.w d1,AUD3PER(a4)
1357: MOVE.w p_MonitorVolume(a3),AUD2VOL(a4)
1358: MOVE.w p_MonitorVolume(a3),AUD3VOL(a4)
1359:
1360: * Install Record interrupt
1361: MOVE.w p_Input(a3),d0
1362: BEQ .parsampler
1363: CMP.w #1,d0
1364: BEQ .aurasampler
1365: BRA .error_unknown
1366: .parsampler
1367: TST.b p_Parallel(a3) ;Parrallel port allocated?
1368: BEQ .error_unknown
1369: LEA p_RecIntData(a3),a1
1370: MOVE.l a1,IS_DATA+p_RecInt(a3)
1371: MOVE.l #RecordInterrupt,IS_CODE+p_RecInt(a3)
1372: BRA .setrecint
1373: .aurasampler
1374: TST.l p_AuraAddress(a3) ;Aura sampler allocated?
1375: BEQ .error_unknown
1376: LEA p_RecIntDataAura(a3),a1
1377: MOVE.l a1,IS_DATA+p_RecInt(a3)
1378: MOVE.l #RecordInterruptAura,IS_CODE+p_RecInt(a3)
1379: .setrecint
1380: LEA p_RecInt(a3),a1
1381: MOVEQ #INTB_AUD3,d0
1382: call SetIntVector
1383:
1384: MOVE.w #DMAF_AUD2!DMAF_AUD3,DMACON(a4) ;disable DMA
1385: MOVE.w #INTF_SETCLR!INTF_AUD3,INTENA(a4) ;enable
1386: MOVE.w #INTF_SETCLR!INTF_AUD3,INTREQ(a4) ;start
1387:
1388: .dont_record
1389: .return
1390:
1391:
1392: MOVEQ #AHIE_OK,d0
1393: .exit
1394: popm d2-d7/a2-a6
1395: RTS
1396: .error_nomem
1397: MOVEQ #AHIE_NOMEM,d0
1398: BRA.b .exit
1399: .error_unknown
1400: MOVEQ #AHIE_UNKNOWN,d0
1401: BRA.b .exit
1402:
1403:
1404: ;in:
1405: * a2 AudioCtrl
1406: * a3 paula
1407: * a4 CUSTOM
1408: * a5 paulaBase
1409: * a6 ExecBase
1410:
1411: init16bitM:
1412: MOVE.l #AudioInterrupt2,IS_CODE+p_PlayInt(a3)
1413: MOVE.l #SoftInt_16bitM,IS_CODE+p_PlaySoftInt(a3)
1414:
1415: MOVE.l ahiac_MaxBuffSamples(a2),d0 ;Max. # of 8 bit samples
1416:
1417: ADDQ.l #1,d0
1418: BCLR #0,d0 ;force even
1419: MOVE.l d0,d2 ;d2 = channel size
1420: LSL #1,d2
1421: ; move.l d0,ahiac_BuffSamples(a2)
1422: LSL.l #1,d0 ;Double buffer
1423: LSL.l #1,d0 ;it's actually 16 bits
1424: MOVE.l #MEMF_CHIP!MEMF_PUBLIC|MEMF_CLEAR,d1
1425: call AllocVec
1426: MOVE.l d0,p_DMAbuffer(a3)
1427: BEQ .nomem
1428:
1429: MOVE.l d0,p_AudPtr1A(a3)
1430: MOVE.l d0,p_AudPtr2A(a3)
1431: ADD.l d2,d0
1432: MOVE.l d0,p_AudPtr1B(a3)
1433: MOVE.l d0,p_AudPtr2B(a3)
1434:
1435: MOVEQ #0,d0
1436: RTS
1437: .nomem
1438: MOVEQ #AHIE_NOMEM,d0
1439: RTS
1440:
1441: ;in:
1442: * a2 AudioCtrl
1443: * a3 paula
1444: * a5 paulaBase
1445: * a6 ExecBase
1446: init16bitS:
1447: MOVE.l #AudioInterrupt2,IS_CODE+p_PlayInt(a3)
1448: MOVE.l #SoftInt_16bitS,IS_CODE+p_PlaySoftInt(a3)
1449:
1450: MOVE.l ahiac_MaxBuffSamples(a2),d0 ;Max. # of 8 bit samples
1451: ADDQ.l #1,d0
1452: BCLR #0,d0 ;force even
1453: MOVE.l d0,d2 ;d2 = channel size
1454: LSL #1,d2
1455: ; move.l d0,ahiac_BuffSamples(a2)
1456:
1457: LSL.l #2,d0 ;Double buffer + Stereo
1458: LSL.l #1,d0 ;it's actually 16 bits
1459: MOVE.l #MEMF_CHIP!MEMF_PUBLIC|MEMF_CLEAR,d1
1460: call AllocVec
1461: MOVE.l d0,p_DMAbuffer(a3)
1462: BEQ .nomem
1463:
1464: MOVE.l d0,p_AudPtr1A(a3)
1465: ADD.l d2,d0
1466: MOVE.l d0,p_AudPtr2A(a3)
1467: ADD.l d2,d0
1468: MOVE.l d0,p_AudPtr1B(a3)
1469: ADD.l d2,d0
1470: MOVE.l d0,p_AudPtr2B(a3)
1471:
1472: MOVEQ #0,d0
1473: RTS
1474: .nomem
1475: MOVEQ #AHIE_NOMEM,d0
1476: RTS
1477:
1478: ;in:
1479: * a2 AudioCtrl
1480: * a3 paula
1481: * a5 paulaBase
1482: * a6 ExecBase
1483: init14bitM:
1484: MOVE.l #AudioInterrupt4,IS_CODE+p_PlayInt(a3)
1485: LEA SoftInt_14bitM(pc),a0
1486: TST.l p_CalibrationTable(a3)
1487: BEQ.b .nocalib
1488: LEA SoftInt_14CbitM(pc),a0
1489: .nocalib
1490: MOVE.l a0,IS_CODE+p_PlaySoftInt(a3)
1491:
1492: MOVE.l ahiac_MaxBuffSamples(a2),d0 ;Max. # of 16 bit samples
1493: ADDQ.l #1,d0
1494: BCLR #0,d0 ;force even
1495: MOVE.l d0,d2 ;d2 = channel size
1496:
1497: LSL.l #2,d0 ;Double buffer + 2W8 bit
1498: MOVE.l #MEMF_CHIP!MEMF_PUBLIC|MEMF_CLEAR,d1
1499: call AllocVec
1500: MOVE.l d0,p_DMAbuffer(a3)
1501: BEQ .nomem
1502:
1503: MOVE.l d0,p_AudPtr1A(a3)
1504: MOVE.l d0,p_AudPtr2A(a3)
1505: ADD.l d2,d0
1506: MOVE.l d0,p_AudPtr4A(a3)
1507: MOVE.l d0,p_AudPtr3A(a3)
1508: ADD.l d2,d0
1509: MOVE.l d0,p_AudPtr1B(a3)
1510: MOVE.l d0,p_AudPtr2B(a3)
1511: ADD.l d2,d0
1512: MOVE.l d0,p_AudPtr4B(a3)
1513: MOVE.l d0,p_AudPtr3B(a3)
1514:
1515: MOVE.w #64,AUD0VOL(a4)
1516: MOVE.w #64,AUD1VOL(a4)
1517: MOVE.w #1,AUD2VOL(a4)
1518: MOVE.w #1,AUD3VOL(a4)
1519:
1520: MOVEQ #0,d0
1521: RTS
1522: .nomem
1523: MOVEQ #AHIE_NOMEM,d0
1524: RTS
1525:
1526: ;in:
1527: * a2 AudioCtrl
1528: * a3 paula
1529: * a5 paulaBase
1530: * a6 ExecBase
1531: init14bitS:
1532: MOVE.l #AudioInterrupt4,IS_CODE+p_PlayInt(a3)
1533: LEA SoftInt_14bitS(pc),a0
1534: TST.l p_CalibrationTable(a3)
1535: BEQ .nocalib
1536: ;lea SoftInt_14CbitS(pc),a0 changed for uae
1537: .nocalib
1538: MOVE.l a0,IS_CODE+p_PlaySoftInt(a3)
1539:
1540:
1541: MOVE.l ahiac_MaxBuffSamples(a2),d0 ;Max. # of 16 bit samples
1542: ASL.l #2,d0
1543: MOVE.l d0,ahiac_MaxBuffSamples(a2)
1544: ADDQ.l #1,d0
1545: BCLR #0,d0 ;force even
1546: MOVE.l d0,d2 ;d2 = channel size
1547:
1548: LSL.l #3,d0 ;Double buffer + 2W8 bit + Stereo
1549: MOVE.l #MEMF_CHIP!MEMF_PUBLIC|MEMF_CLEAR,d1
1550: call AllocVec
1551: MOVE.l d0,p_DMAbuffer(a3)
1552: BEQ .nomem
1553:
1554: MOVE.l d0,p_AudPtr1A(a3)
1555: ADD.l d2,d0
1556: MOVE.l d0,p_AudPtr2A(a3)
1557: ADD.l d2,d0
1558: MOVE.l d0,p_AudPtr3A(a3)
1559: ADD.l d2,d0
1560: MOVE.l d0,p_AudPtr4A(a3)
1561: ADD.l d2,d0
1562: MOVE.l d0,p_AudPtr1B(a3)
1563: ADD.l d2,d0
1564: MOVE.l d0,p_AudPtr2B(a3)
1565: ADD.l d2,d0
1566: MOVE.l d0,p_AudPtr3B(a3)
1567: ADD.l d2,d0
1568: MOVE.l d0,p_AudPtr4B(a3)
1569:
1570: MOVE.w #$4849,AUD0VOL(a4) ;changed for uae
1571: MOVE.w #64,AUD1VOL(a4)
1572: MOVE.w #1,AUD2VOL(a4)
1573: MOVE.w #1,AUD3VOL(a4)
1574:
1575: MOVEQ #0,d0
1576: RTS
1577: .nomem
1578: MOVEQ #AHIE_NOMEM,d0
1579: RTS
1580:
1581: ****** [driver].audio/AHIsub_Update *****************************************
1582: *
1583: * NAME
1584: * AHIsub_Update -- Update some variables
1585: *
1586: * SYNOPSIS
1587: * AHIsub_Update( flags, audioctrl );
1588: * D0 A2
1589: *
1590: * void AHIsub_Update(ULONG, struct AHIAudioCtrlDrv * );
1591: *
1592: * IMPLEMENTATION
1593: * All you have To do is To update some variables:
1594: * Mixing & timing: ahiac_PlayerFunc, ahiac_MixerFunc, ahiac_SamplerFunc,
1595: * ahiac_BuffSamples (AND perhaps ahiac_PlayerFreq If you Use it).
1596: * Mixing only: ahiac_PlayerFunc, ahiac_MixerFunc, ahiac_SamplerFunc AND
1597: * ahiac_PlayerFreq.
1598: * Nothing: ahiac_PlayerFunc, ahiac_SamplerFunc AND ahiac_PlayerFreq.
1599: *
1600: * INPUTS
1601: * flags - Currently no flags defined.
1602: * audioctrl - Pointer To an AHIAudioCtrlDrv structure.
1603: *
1604: * RESULT
1605: *
1606: * NOTES
1607: * This Call must be safe from interrupts.
1608: *
1609: * SEE ALSO
1610: * AHIsub_Start()
1611: *
1612: *****************************************************************************
1613: *
1614: *
1615: *
1616:
1617: AHIsub_Update:
1618: pushm d2-d7/a2-a6
1619:
1620: call AHIsub_Disable ;make sure we don't get an interrupt
1621: ;while updating our local variables
1622: MOVE.l ahiac_DriverData(a2),a3
1623:
1624: MOVE.l ahiac_PlayerFunc(a2),a0
1625: MOVE.l a0,p_PlayerHook(a3)
1626: MOVE.l h_Entry(a0),p_PlayerEntry(a3)
1627:
1628: MOVE.l ahiac_BuffSamples(a2),d0
1629: MOVE.w d0,p_AudLen(a3)
1630: SUBQ.l #1,d0
1631: MOVE.l d0,p_LoopTimes(a3) ;See softints. (Unrolled)
1632:
1633: MOVE.l ahiac_MixerFunc(a2),a0
1634: MOVE.l a0,p_MixHook(a3)
1635: MOVE.l h_Entry(a0),p_MixEntry(a3)
1636:
1637: MOVE.l ahiac_PreTimer(a2),p_PreTimer(a3)
1638: MOVE.l ahiac_PostTimer(a2),p_PostTimer(a3)
1639:
1640: call AHIsub_Enable
1641: MOVEQ #0,d0
1642: popm d2-d7/a2-a6
1643: RTS
1644:
1645:
1646: ****** [driver].audio/AHIsub_Stop *******************************************
1647: *
1648: * NAME
1649: * AHIsub_Stop -- Stops PlayBack.
1650: *
1651: * SYNOPSIS
1652: * AHIsub_Stop( flags, audioctrl );
1653: * D0 A2
1654: *
1655: * void AHIsub_Stop( ULONG, struct AHIAudioCtrlDrv * );
1656: *
1657: * IMPLEMENTATION
1658: * Stop PlayBack AND/OR recording, remove all resources allocated by
1659: * AHIsub_Start().
1660: *
1661: * INPUTS
1662: * flags - See <libraries/ahi_sub.h>.
1663: * audioctrl - Pointer To an AHIAudioCtrlDrv structure.
1664: *
1665: * NOTES
1666: * It must be safe To Call this routine Even If AHIsub_Start() was never
1667: * called, failed OR called more than once.
1668: *
1669: * SEE ALSO
1670: * AHIsub_Start()
1671: *
1672: *****************************************************************************
1673: *
1674: *
1675:
1676: AHIsub_Stop:
1677: pushm d2-d7/a2-a6
1678:
1679: LEA CUSTOM,a4
1680: MOVE.l a6,a5
1681: MOVE.l pb_SysLib(a5),a6
1682: MOVE.l ahiac_DriverData(a2),a3
1683:
1684: push d0
1685: BTST #AHISB_PLAY,d0
1686: BEQ .dontplay
1687:
1688: **
1689: *** AHISB_PLAY
1690: **
1691: MOVEQ #2,d0
1692: MOVEQ #0,d1
1693: jsr.l $F0FFB0
1694: MOVEQ #3,d0
1695: MOVEQ #0,d3
1696: jsr.l $F0FFB0
1697: MOVEQ #4,d0
1698: MOVEQ #0,d3
1699: jsr.l $F0FFB0
1700:
1701: MOVEQ #0,d0
1702: MOVE.w d0,AUD0VOL(a4)
1703: MOVE.w d0,AUD1VOL(a4)
1704: MOVE.w d0,AUD2VOL(a4)
1705: MOVE.w d0,AUD3VOL(a4)
1706: MOVE.w #DMAF_AUDIO,DMACON(a4) ;disable audio DMA
1707:
1708: MOVE.w #INTF_AUD0,INTENA(a4)
1709: MOVE.w #INTF_AUD0,INTREQ(a4) ;Clear any waiting interrupts
1710: MOVE.l #Interrupt_Dummy,IS_CODE+p_PlayInt(a3)
1711: LEA p_PlayInt(a3),a1
1712: MOVEQ #INTB_AUD0,d0
1713: call SetIntVector
1714:
1715: MOVE.l p_DMAbuffer(a3),d0
1716: BEQ.b .nodmamem
1717: MOVE.l d0,a1
1718: CLR.l p_DMAbuffer(a3)
1719: call FreeVec
1720: .nodmamem
1721: MOVE.l p_Mixbuffer(a3),d0
1722: BEQ.b .nomixmem
1723: MOVE.l d0,a1
1724: CLR.l p_Mixbuffer(a3)
1725: call FreeVec
1726: .nomixmem
1727:
1728: .dontplay
1729: pop d0
1730: BTST #AHISB_RECORD,d0
1731: BEQ .dontrecord
1732:
1733: **
1734: *** AHISB_RECORD
1735: **
1736: BTST #PB_14BIT,p_Flags(a3) ;Sanity check...
1737: BNE .dontrecord
1738:
1739: MOVE.w #INTF_AUD3,INTENA(a4)
1740: MOVE.w #INTF_AUD3,INTREQ(a4) ;Clear any waiting interrupts
1741:
1742: MOVE.l #Interrupt_Dummy,IS_CODE+p_RecInt(a3)
1743: LEA p_RecInt(a3),a1
1744: MOVEQ #INTB_AUD3,d0
1745: call SetIntVector
1746:
1747: MOVE.w #0,AUD2VOL(a4)
1748: MOVE.w #0,AUD3VOL(a4)
1749:
1750: MOVE.l p_RecBuffer1(a3),d0
1751: BEQ.b .norecmem1
1752: MOVE.l d0,a1
1753: CLR.l p_RecBuffer1(a3)
1754: call FreeVec
1755: .norecmem1
1756: MOVE.l p_RecBuffer2(a3),d0
1757: BEQ.b .norecmem2
1758: MOVE.l d0,a1
1759: CLR.l p_RecBuffer2(a3)
1760: call FreeVec
1761: .norecmem2
1762: .dontrecord
1763: .return
1764: MOVEQ #0,d0
1765: popm d2-d7/a2-a6
1766: RTS
1767:
1768: ****** [driver].audio/AHIsub_#? *********************************************
1769: *
1770: * NAME
1771: * AHIsub_SetEffect -- Set effect.
1772: * AHIsub_SetFreq -- Set frequency.
1773: * AHIsub_SetSound -- Set Sound.
1774: * AHIsub_SetVol -- Set Volume AND stereo panning.
1775: * AHIsub_LoadSound -- Prepare a Sound For PlayBack.
1776: * AHIsub_UnloadSound -- Discard a Sound.
1777: *
1778: * SYNOPSIS
1779: * See functions in 'ahi.device'.
1780: *
1781: * IMPLEMENTATION
1782: * If AHIsub_AllocAudio() did NOT Return with bit AHISB_MIXING set,
1783: * all user calls To these Function will be routed To the driver.
1784: *
1785: * If AHIsub_AllocAudio() did Return with bit AHISB_MIXING set, the
1786: * calls will first be routed To the driver, AND only handled by
1787: * 'ahi.device' If the driver returned AHIS_UNKNOWN. This way it is
1788: * possible To ADD effects that the Sound card handles On its own, like
1789: * Filter AND echo effects.
1790: *
1791: * For what each Function does, see the autodocs For 'ahi.device'.
1792: *
1793: * INPUTS
1794: * See functions in 'ahi.device'.
1795: *
1796: * NOTES
1797: * See functions in 'ahi.device'.
1798: *
1799: * SEE ALSO
1800: * ahi.device/AHI_SetEffect(), ahi.device/AHI_SetFreq(),
1801: * ahi.device/AHI_SetSound(), ahi.device/AHI_SetVol(),
1802: * ahi.device/AHI_LoadSound(), ahi.device/AHI_UnloadSound()
1803: *
1804: *
1805: *****************************************************************************
1806: *
1807: *
1808:
1809: AHIsub_SetVol:
1810: AHIsub_SetFreq:
1811: AHIsub_SetSound:
1812: AHIsub_SetEffect:
1813: AHIsub_LoadSound:
1814: AHIsub_UnloadSound:
1815: MOVEQ #AHIS_UNKNOWN,d0
1816: RTS
1817:
1818: ****** [driver].audio/AHIsub_GetAttr ****************************************
1819: *
1820: * NAME
1821: * AHIsub_GetAttr -- Returns information about audio modes OR driver
1822: *
1823: * SYNOPSIS
1824: * AHIsub_GetAttr( attribute, argument, Default, taglist, audioctrl );
1825: * D0 D0 D1 D2 A1 A2
1826: *
1827: * LONG AHIsub_GetAttr( ULONG, LONG, LONG, struct TagItem *,
1828: * struct AHIAudioCtrlDrv * );
1829: *
1830: * IMPLEMENTATION
1831: * Return the attribute based On a tag List AND an AHIAudioCtrlDrv
1832: * structure, which are the same that will be passed To
1833: * AHIsub_AllocAudio() by 'ahi.device'. If the attribute is
1834: * unknown To you, Return the Default.
1835: *
1836: * INPUTS
1837: * attribute - Is really a Tag AND can be one of the following:
1838: * AHIDB_Bits - Return how many output bits the tag List will
1839: * result in.
1840: * AHIDB_MaxChannels - Return the resulting number of channels.
1841: * AHIDB_Frequencies - Return how many mixing/sampling frequencies
1842: * you support
1843: * AHIDB_Frequency - Return the argument:th frequency
1844: * Example: You support 3 frequencies 32, 44.1 AND 48 kHz.
1845: * If argument is 1, Return 44100.
1846: * AHIDB_Index - Return the Index which gives the frequency closest
1847: * To argument.
1848: * Example: You support 3 frequencies 32, 44.1 AND 48 kHz.
1849: * If argument is 40000, Return 1 (=> 44100).
1850: * AHIDB_Author - Return Pointer To name of driver author:
1851: * "Martin 'Leviticus' Blom"
1852: * AHIDB_Copyright - Return Pointer To copyright notice, including
1853: * the ')' character: "?????1996 Martin Blom" OR "Public Domain"
1854: * AHIDB_Version - Return Pointer version string, normal AMIGA
1855: * Format: "paula 1.5 (18.2.96)\r\n"
1856: * AHIDB_Annotation - Return Pointer To an annotation string, which
1857: * can be several lines.
1858: * AHIDB_Record - Are you a sampler, too? Return True OR False.
1859: * AHIDB_FullDuplex - Return True OR False.
1860: * AHIDB_Realtime - Return True OR False.
1861: * AHIDB_MaxPlaySamples - Normally, Return the Default. See
1862: * AHIsub_AllocAudio(), section 2.
1863: * AHIDB_MaxRecordSamples - Return the size of the Buffer you fill
1864: * when recording.
1865: *
1866: * The following are associated with AHIsub_HardwareControl() AND are
1867: * new For V2.
1868: * AHIDB_MinMonitorVolume
1869: * AHIDB_MaxMonitorVolume - Return the lower/upper limit For
1870: * AHIC_MonitorVolume. If unsupported but always 1.0, Return
1871: * 1.0 For both.
1872: * AHIDB_MinInputGain
1873: * AHIDB_MaxInputGain - Return the lower/upper limit For
1874: * AHIC_InputGain. If unsupported but always 1.0, Return 1.0 For
1875: * both.
1876: * AHIDB_MinOutputVolume
1877: * AHIDB_MaxOutputVolume - Return the lower/upper limit For
1878: * AHIC_OutputVolume.
1879: * AHIDB_Inputs - Return how many inputs you have.
1880: * AHIDB_Input - Return a short string describing the argument:th
1881: * input. Number 0 should be the Default one. Example strings
1882: * can be "Line 1", "Mic", "Optical" OR whatever.
1883: * AHIDB_Outputs - Return how many outputs you have.
1884: * AHIDB_Output - Return a short string describing the argument:th
1885: * output. Number 0 should be the Default one. Example strings
1886: * can be "Line 1", "Headphone", "Optical" OR whatever.
1887: * argument - extra info For some attributes.
1888: * Default - What you should Return For unknown attributes.
1889: * taglist - Pointer To a tag List that eventually will be fed To
1890: * AHIsub_AllocAudio(), OR Null.
1891: * audioctrl - Pointer To an AHIAudioCtrlDrv structure that eventually
1892: * will be fed To AHIsub_AllocAudio(), OR Null.
1893: *
1894: * NOTES
1895: *
1896: * SEE ALSO
1897: * AHIsub_AllocAudio(), AHIsub_HardwareControl(),
1898: * ahi.device/AHI_GetAudioAttrsA()
1899: *
1900: *****************************************************************************
1901: *
1902: *
1903:
1904: AHIsub_GetAttr:
1905: pushm a3/a5-a6
1906: MOVE.l a6,a5
1907: MOVE.l pb_UtilLib(a5),a6
1908:
1909: IFD MC020
1910: TST.l a1
1911: Else
1912: CMP.l #0,a1
1913: ENDC
1914: BEQ .notaglist ;no tag list!
1915:
1916: MOVE.l a1,a3
1917:
1918: pushm d0-d1
1919:
1920: MOVE.l #AHIDB_Paula14Bit,d0
1921: MOVEQ #FALSE,d1
1922: MOVE.l a3,a0
1923: call GetTagData
1924: TST.l d0
1925: BNE .2
1926:
1927: * Only For AHIDB_Paula14Bit False (== recording available)
1928: popm d0-d1
1929:
1930: CMP.l #AHIDB_Record,d0
1931: BNE.b .not_record1
1932: MOVEQ #TRUE,d0
1933: BRA .exit
1934: .not_record1
1935: CMP.l #AHIDB_FullDuplex,d0
1936: BNE.b .not_fullduplex1
1937: MOVEQ #TRUE,d0
1938: BRA .exit
1939: .not_fullduplex1
1940: CMP.l #AHIDB_MaxRecordSamples,d0
1941: BNE.b .not_mrs1
1942: MOVE.l #RECORDSAMPLES,d0
1943: BRA .exit
1944: .not_mrs1
1945: CMP.l #AHIDB_MinMonitorVolume,d0
1946: BNE.b .not_minmonvol1
1947: MOVEQ #0,d0
1948: BRA .exit
1949: .not_minmonvol1
1950: CMP.l #AHIDB_MaxMonitorVolume,d0
1951: BNE.b .not_maxmonvol1
1952: MOVE.l #$10000,d0
1953: BRA .exit
1954: .not_maxmonvol1
1955: CMP.l #AHIDB_MinInputGain,d0
1956: BNE.b .not_mingain1
1957: MOVE.l #$10000,d0
1958: BRA .exit
1959: .not_mingain1
1960: CMP.l #AHIDB_MaxInputGain,d0
1961: BNE.b .not_maxgain1
1962: MOVE.l #$10000,d0
1963: BRA .exit
1964: .not_maxgain1
1965: CMP.l #AHIDB_Inputs,d0
1966: BNE.b .not_inputs
1967: MOVEQ #2,d0
1968: BRA .exit
1969: .not_inputs
1970: CMP.l #AHIDB_Input,d0
1971: BNE.b .not_input
1972: LSL.l #2,d1
1973: MOVE.l .inputs(pc,d1.w),d0
1974: BRA .exit
1975: .not_input
1976: BRA .3
1977: .inputs:
1978: Dc.l .input0
1979: Dc.l .input1
1980:
1981: .2
1982: * Only For AHIDB_Paula14Bit True (== no recording)
1983: popm d0-d1
1984: CMP.l #AHIDB_Record,d0
1985: BNE.b .not_record2
1986: MOVEQ #FALSE,d0
1987: BRA .exit
1988: .not_record2
1989: CMP.l #AHIDB_FullDuplex,d0
1990: BNE.b .not_fullduplex2
1991: MOVEQ #FALSE,d0
1992: BRA .exit
1993: .not_fullduplex2
1994:
1995: .3
1996: * Common Tags (AHIDB_14bit)
1997:
1998: CMP.l #AHIDB_Bits,d0
1999: BNE.b .not_bits
2000: MOVE.l #AHIDB_Paula14Bit,d0
2001: MOVEQ #FALSE,d1
2002: MOVE.l a3,a0
2003: call GetTagData
2004: TST.l d0
2005: BEQ.b .no14bit
2006: MOVEQ #14,d0
2007: skipw
2008: .no14bit
2009: MOVEQ #8,d0
2010: BRA .exit
2011: .not_bits
2012: .notaglist
2013: CMP.l #AHIDB_Frequencies,d0
2014: BNE.b .not_freqs
2015: MOVE.l #FREQUENCIES,d0
2016: lsr.l #2,d0
2017: BRA .exit
2018: .not_freqs
2019:
2020: CMP.l #AHIDB_Frequency,d0
2021: BNE.b .not_freq
2022: ADD.w d1,d1
2023: ADD.w d1,d1
2024: LEA uae(pc),a0
2025: ; move.l (a0,d1.w),d1
2026: ; bsr calcperiod
2027: MOVE.l (a0,d1.w),d0
2028: BRA .exit
2029: .not_freq
2030: CMP.l #AHIDB_Index,d0
2031: BNE.b .not_index
2032: MOVE.l d1,d0
2033: BSR findfreq
2034: MOVE.l d1,d0
2035: BRA .exit
2036: .not_index
2037: CMP.l #AHIDB_Author,d0
2038: BNE.b .not_author
2039: LEA .author(pc),a0
2040: MOVE.l a0,d0
2041: BRA .exit
2042: .not_author
2043: CMP.l #AHIDB_Copyright,d0
2044: BNE.b .not_copyright
2045: LEA .copyright(pc),a0
2046: MOVE.l a0,d0
2047: BRA .exit
2048: .not_copyright
2049: CMP.l #AHIDB_Version,d0
2050: BNE.b .not_version
2051: LEA IDString(pc),a0
2052: MOVE.l a0,d0
2053: BRA .exit
2054: .not_version
2055: CMP.l #AHIDB_Annotation,d0
2056: BNE.b .not_anno
2057: LEA .anno(pc),a0
2058: MOVE.l a0,d0
2059: BRA .exit
2060: .not_anno
2061: CMP.l #AHIDB_Realtime,d0
2062: BNE.b .not_realtime
2063: MOVEQ #TRUE,d0
2064: BRA .exit
2065: .not_realtime
2066: CMP.l #AHIDB_Outputs,d0
2067: BNE.b .not_outputs
2068: MOVEQ #1,d0
2069: BRA .exit
2070: .not_outputs
2071: CMP.l #AHIDB_Output,d0
2072: BNE.b .not_output
2073: LEA .output(pc),a0
2074: MOVE.l a0,d0
2075: BRA .exit
2076: .not_output
2077:
2078: * Unknown attribute, Return Default.
2079: MOVE.l d2,d0
2080: .exit
2081: popm a3/a5-a6
2082: RTS
2083: .author Dc.b "Martin 'Leviticus' Blom",0
2084: .copyright Dc.b "Public Domain",0
2085: .anno Dc.b "14 bit routines by Christian Buchner.",0
2086: .input0 Dc.b "Parallel port sampler",0
2087: .input1 Dc.b "Aura sampler",0
2088: .output Dc.b "Line",0
2089: Even
2090:
2091:
2092: ****** [driver].audio/AHIsub_HardwareControl ********************************
2093: *
2094: * NAME
2095: * AHIsub_HardwareControl -- Modify Sound card settings
2096: *
2097: * SYNOPSIS
2098: * AHIsub_HardwareControl( attribute, argument, audioctrl );
2099: * D0 D0 D1 A2
2100: *
2101: * LONG AHIsub_HardwareControl( ULONG, LONG, struct AHIAudioCtrlDrv * );
2102: *
2103: * IMPLEMENTATION
2104: * Set OR Return the state of a particular hardware component. AHI uses
2105: * AHIsub_GetAttr() To supply the user with limits AND what Tags are
2106: * available.
2107: *
2108: * INPUTS
2109: * attribute - Is really a Tag AND can be one of the following:
2110: * AHIC_MonitorVolume - Set the input monitor Volume To argument.
2111: * AHIC_MonitorVolume_Query - Return the current input monitor
2112: * Volume (argument is ignored).
2113: *
2114: * AHIC_InputGain - Set the input gain To argument. (V2)
2115: * AHIC_InputGain_Query (V2)
2116: *
2117: * AHIC_OutputVolume - Set the output Volume To argument. (V2)
2118: * AHIC_OutputVolume_Query (V2)
2119: *
2120: * AHIC_Input - Use the argument:th input source (Default is 0). (V2)
2121: * AHIC_Input_Query (V2)
2122: *
2123: * AHIC_Output - Use the argument:th output destination (Default
2124: * is 0). (V2)
2125: * AHIC_Output_Query (V2)
2126: *
2127: * argument - What value attribute should be set To.
2128: * audioctrl - Pointer To an AHIAudioCtrlDrv structure.
2129: *
2130: * RESULT
2131: * Return the state of selected attribute. If you were asked To set
2132: * something, Return True. If attribute is unknown To you OR unsupported,
2133: * Return False.
2134: *
2135: * NOTES
2136: * This Call must be safe from interrupts.
2137: *
2138: * SEE ALSO
2139: * ahi.device/AHI_ControlAudioA(), AHIsub_GetAttr()
2140: *
2141: *****************************************************************************
2142: *
2143: *
2144:
2145: AHIsub_HardwareControl:
2146: CMP.l #AHIC_MonitorVolume,d0
2147: BNE.b .dontsetmonvol
2148: MOVE.l ahiac_DriverData(a2),a1
2149: LSR.l #8,d1
2150: LSR.l #2,d1
2151: MOVE.w d1,p_MonitorVolume(a1)
2152: BRA.b .exit
2153: .dontsetmonvol
2154: CMP.l #AHIC_MonitorVolume_Query,d0
2155: BNE.b .dontgetmonvol
2156: MOVE.l ahiac_DriverData(a2),a1
2157: MOVEQ #0,d0
2158: MOVE.w p_MonitorVolume(a1),d0
2159: LSL.l #8,d0
2160: LSL.l #2,d0
2161: BRA.b .quit
2162: .dontgetmonvol
2163: CMP.l #AHIC_Input,d0
2164: BNE.b .dontsetinput
2165: MOVE.l ahiac_DriverData(a2),a1
2166: MOVE.w d1,p_Input(a1)
2167: BRA.b .exit
2168: .dontsetinput
2169: CMP.l #AHIC_Input_Query,d0
2170: BNE.b .dontgetinput
2171: MOVE.l ahiac_DriverData(a2),a1
2172: MOVEQ #0,d0
2173: MOVE.w p_Input(a1),d0
2174: BRA.b .quit
2175: .dontgetinput
2176: MOVEQ #FALSE,d0
2177: .quit
2178: RTS
2179: .exit
2180: MOVEQ #TRUE,d0
2181: RTS
2182:
2183:
2184:
2185:
2186:
2187:
2188:
2189: ;----------------------------------------------------------------------------
2190:
2191: Interrupt_Dummy:
2192: MOVE.w #INTF_AUD0!INTF_AUD1!INTF_AUD2!INTF_AUD3,INTREQ(a0)
2193: SoftInt_Dummy:
2194: RTS
2195:
2196: ;in:
2197: * d0 scratch
2198: * d1 INTENAR && INTREQR
2199: * a0 CUSTOM
2200: * a1 &(paulaBase->p_RecIntData)
2201: * a5 &RecordInterrupt
2202: * a6 ExecBase
2203: RecordInterrupt:
2204:
2205: * This Function will be executed up To 28000 times per second - that's once per
2206: * rasterline! It has To be as fast as possible.
2207:
2208: MOVE.w #INTF_AUD2!INTF_AUD3,INTREQ(a0) ;Clear the interrupt flags
2209: MOVEQ #0,d0
2210: ;move.b _ciaa+ciaprb,d0 ;read parallel port
2211: IFD MC020
2212: ;move.l convtable(pc,d0.w*4),d0 ;1 unsigned byte -> 2 signed words
2213: Else
2214: ADD.w d0,d0
2215: ADD.w d0,d0
2216: ;move.l convtable(pc,d0.w),d0
2217: ENDC
2218: MOVE.w d0,AUD2DAT(a0) ;right
2219: MOVE.w d0,AUD3DAT(a0) ;left
2220:
2221: MOVE.l (a1),a5 ;p_RecFillPtr
2222: MOVE.l d0,(a5)+ ;store sample in buffer
2223: MOVE.l a5,(a1)+ ;update pointer
2224: SUBQ.w #1,(a1) ;p_ReqFillCount
2225: BEQ ri_Filled ;branch if buffer filled
2226: RTS
2227:
2228: ;convtable
2229: ;CNT SET 0
2230: ; REPT 256
2231: ; dc.b CNT-128,CNT-128,CNT-128,CNT-128
2232: ; SET CNT+1
2233: ; ENDR
2234:
2235: ;in:
2236: * d0 scratch
2237: * d1 INTENAR && INTREQR
2238: * a0 CUSTOM
2239: * a1 &(paulaBase->p_RecIntDataAura)
2240: * a5 &RecordInterrupt
2241: * a6 ExecBase
2242: RecordInterruptAura:
2243: MOVE.w #INTF_AUD2!INTF_AUD3,INTREQ(a0) ;Clear the interrupt flags
2244: MOVE.l (a1)+,a5
2245: MOVE.l (a5),d0 ;read aura sampler
2246: EOR.l #$80008000,d0
2247: MOVE.l (a1),a5 ;p_RecFillPtr
2248: MOVE.l d0,(a5)+ ;store sample in buffer
2249: MOVE.l a5,(a1)+ ;update pointer
2250:
2251: MOVE.w d0,d1
2252: LSR.w #8,d0
2253: MOVE.b d0,d1
2254:
2255: MOVE.w d1,AUD2DAT(a0) ;right
2256: MOVE.w d1,AUD3DAT(a0) ;left
2257:
2258: SUBQ.w #1,(a1) ;p_ReqFillCount
2259: BEQ ri_Filled ;branch if buffer filled
2260: RTS
2261:
2262: ri_Filled:
2263:
2264: * This part is only executed every RECORDSAMPLES:th time... No need To hurry.
2265:
2266: MOVE.l 8(a1),d0 ;p_RecBuffer2->
2267: MOVE.l 4(a1),8(a1) ;p_RecBuffer1->p_RecBuffer2
2268: MOVE.l d0,4(a1) ; ->p_RecBuffer1
2269: MOVE.l d0,-4(a1) ;p_RecFillPtr
2270: MOVE.w #RECORDSAMPLES,(a1) ;p_ReqFillCount
2271: MOVE.l 12(a1),a1 ;p_RecSoftIntPtr
2272: JMP _LVOCause(a6)
2273:
2274:
2275: ;in:
2276: * d0 scratch
2277: * d1 scratch
2278: * a0 scratch
2279: * a1 paulaBase
2280: * a5 scratch
2281: RecordSoftInt:
2282:
2283: * This Function is NOT executed many times per second AND is therefore NOT
2284: * fully optimized... ;)
2285: push a2
2286: MOVE.w p_MonitorVolume(a1),CUSTOM+AUD2VOL
2287: MOVE.w p_MonitorVolume(a1),CUSTOM+AUD3VOL
2288: MOVE.l p_RecBuffer2(a1),p_rmBuffer(a1)
2289: MOVE.l p_AudioCtrlP(a1),a2
2290: LEA p_RecordMessage(a1),a1
2291: MOVE.l ahiac_SamplerFunc(a2),a0
2292: MOVE.l h_Entry(a0),a5
2293: JSR (a5)
2294: pop a2
2295: RTS
2296:
2297: ;in:
2298: * d0 scratch
2299: * d1 INTENAR && INTREQR
2300: * a0 CUSTOM
2301: * a1 &(paulaBase->p_PlayIntData)
2302: * a5 &AudioInterrupt
2303: * a6 ExecBase
2304:
2305: AudioInterrupt2: ;Two hardware channels used
2306: MOVEM.l a2/d2/d3,-(sp)
2307: MOVEQ #1,d3 ; Enable UAE-side AHI
2308: moveq #0,d2
2309: MOVE.w 4(a1),d2 ; Length
2310: MOVE.l 6(a1),d1 ; Period
2311: LEA.l 12(a1),a2
2312: NOT.w 10(a1) ;double buffering
2313: BEQ.b .1
2314: ADD.w #4*4,a2
2315: .1
2316: LEA p_AudPtrs-p_PlaySoftIntPtr(a1),a5;
2317:
2318: MOVE.l a2,(a5)
2319: MOVE.l (a2)+,a0
2320: MOVEQ #3,d0
2321: jsr $F0FFB0 ; Left channel
2322: MOVE.l (a2)+,a0
2323: MOVEQ #4,d0
2324: jsr $F0FFB0 ; Right channel
2325:
2326: moveq #2,d0
2327: moveq #1,d1
2328: jsr $F0FFB0 ; Enable AHI.
2329:
2330: MOVE.l (a1),a1 ;p_PlaySoftInt
2331: MOVEM.l (sp)+,a2/d2/d3
2332: MOVE.w #INTF_AUD0,$DFF09C ;Clear the interrupt
2333: JMP _LVOCause(a6) ;start PlaySoftInt
2334:
2335: AudioInterrupt4: ;Four hardware channels used
2336:
2337: MOVEM.l (a1)+,d0/d1 ;p_PlaySoftIntPtr,p_AudLen/p_AudPer
2338:
2339:
2340:
2341: MOVE.l d1,AUD1LEN(a0)
2342: MOVE.l d1,AUD2LEN(a0)
2343: MOVE.l d1,AUD3LEN(a0)
2344:
2345: MOVE.l d1,AUD0LEN(a0)
2346: NOT.l (a1)+ ;double buffering
2347:
2348: LEA p_AudPtrs-p_AudPtr1A(a1),a5
2349: BEQ.b .1
2350:
2351: ADD.w #4*4,a1
2352:
2353: .1
2354:
2355:
2356: MOVE.l a1,(a5)
2357: MOVE.l (a1)+,AUD0LC(a0)
2358: MOVE.l (a1)+,AUD1LC(a0)
2359: MOVE.l (a1)+,AUD2LC(a0)
2360: MOVE.l (a1)+,AUD3LC(a0)
2361: MOVE.l d0,a1 ;p_PlaySoftInt
2362: MOVE.w #INTF_AUD0,INTREQ(a0) ;Clear the interrupt
2363:
2364: JMP _LVOCause(a6) ;start PlaySoftInt
2365:
2366: ;in:
2367: * d0 scratch
2368: * d1 scratch
2369: * a0 scratch
2370: * a1 &(paulaBase->p_PlaySoftIntData)
2371: * a5 scratch
2372:
2373: SoftInt_16bitM:
2374: pushm a2/a3/a4/a6
2375: MOVE.l a1,a5
2376: MOVEM.l (a5)+,a0/a1/a2/a3/a4/a6
2377: JSR (a3) ;call Player Hook
2378: JSR (a4) ;call PreTimer
2379: BNE .exit
2380: MOVEM.l (a5),d0/a0/a1/a2/a3/a5
2381: JSR (a3) ;call Mixer Hook
2382:
2383: * convert AND transfer Buffer
2384: MOVE.l (a5),a0
2385: .loop
2386: MOVE.w (a1)+,(a0)+
2387:
2388: ; MOVE.w (a1)+,(a0)+
2389: DBF d0,.loop
2390: .exit
2391: JSR (a6) ;call PostTimer, a2 ok
2392: popm a2/a3/a4/a6
2393: MOVE.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1,CUSTOM+DMACON
2394: RTS
2395:
2396: ;in:
2397: * d0 scratch
2398: * d1 scratch
2399: * a0 scratch
2400: * a1 &(paulaBase->p_PlaySoftIntData)
2401: * a5 scratch
2402:
2403: SoftInt_16bitS:
2404: pushm a2/a3/a4/a6
2405: MOVE.l a1,a5
2406: MOVEM.l (a5)+,a0/a1/a2/a3/a4/a6
2407: JSR (a3) ;call Player Hook
2408: JSR (a4) ;call PreTimer
2409: BNE .exit
2410: MOVEM.l (a5),d0/a0/a1/a2/a3/a5
2411: JSR (a3) ;call Mixer Hook
2412:
2413: * convert AND transfer Buffer
2414: MOVEM.l (a5),a0/a3
2415: .loop
2416: ; REPT 2
2417: ;left
2418: MOVE.w (a1)+,(a3)+
2419: ;right
2420: MOVE.w (a1)+,(a0)+
2421: ; ENDR
2422: DBF d0,.loop
2423: .exit
2424: JSR (a6) ;call PostTimer, a2 ok
2425: popm a2/a3/a4/a6
2426: MOVE.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1,CUSTOM+DMACON
2427: RTS
2428:
2429: ;in:
2430: * d0 scratch
2431: * d1 scratch
2432: * a0 scratch
2433: * a1 &(paulaBase->p_PlaySoftIntData)
2434: * a5 scratch
2435:
2436: SoftInt_14bitM:
2437: pushm a2/a3/a4/a6
2438: MOVE.l a1,a5
2439: MOVEM.l (a5)+,a0/a1/a2/a3/a4/a6
2440: JSR (a3) ;call Player Hook
2441: JSR (a4) ;call PreTimer
2442: BNE .exit
2443: MOVEM.l (a5),d0/a0/a1/a2/a3/a5
2444: JSR (a3) ;call Mixer Hook
2445:
2446: * convert AND transfer Buffer
2447: MOVEM.l (a5),a0/a3/a4/a5 ;a3/a4 unused
2448: .loop
2449: REPT 2
2450: MOVE.b (a1)+,(a0)+
2451: MOVE.b (a1)+,d1
2452: LSR.b #2,d1
2453: MOVE.b d1,(a5)+
2454: ENDR
2455: DBF d0,.loop
2456: .exit
2457: JSR (a6) ;call PostTimer, a2 ok
2458: popm a2/a3/a4/a6
2459: MOVE.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,CUSTOM+DMACON
2460: RTS
2461:
2462: ;in:
2463: * d0 scratch
2464: * d1 scratch
2465: * a0 scratch
2466: * a1 &(paulaBase->p_PlaySoftIntData)
2467: * a5 scratch
2468:
2469: SoftInt_14CbitM:
2470: pushm a2/a3/a4/a6
2471: MOVE.l a1,a5
2472: MOVEM.l (a5)+,a0/a1/a2/a3/a4/a6
2473: JSR (a3) ;call Player Hook
2474: JSR (a4) ;call PreTimer
2475: BNE .exit
2476: MOVEM.l (a5),d0/a0/a1/a2/a3/a4/a5
2477: JSR (a3) ;call Mixer Hook
2478:
2479: * convert AND transfer Buffer, using the table
2480: MOVE.l (a4),a0
2481: MOVE.l 12(a4),a4
2482: MOVEQ #0,d1
2483: .loop
2484:
2485: REPT 2
2486: IFD MC020
2487: MOVE.w (a1)+,d1 ;fetch 16 bit sample
2488: MOVE.w (a5,d1.l*2),d1
2489: Else
2490: MOVEQ #0,d1
2491: MOVE.w (a1)+,d1 ;fetch 16 bit sample
2492: ADD.w d1,d1
2493: MOVE.w (a5,d1.l),d1
2494: ENDC
2495: MOVE.b d1,(a4)+ ;low byte
2496: LSR.w #8,d1
2497: MOVE.b d1,(a0)+ ;high byte
2498: ENDR
2499: DBF d0,.loop
2500: .exit
2501: JSR (a6) ;call PostTimer, a2 ok
2502: popm a2/a3/a4/a6
2503: MOVE.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,CUSTOM+DMACON
2504: RTS
2505:
2506: ;in:
2507: * d0 scratch
2508: * d1 scratch
2509: * a0 scratch
2510: * a1 &(paulaBase->p_PlaySoftIntData)
2511: * a5 scratch
2512:
2513: SoftInt_14bitS:
2514: pushm a2/a3/a4/a6
2515: MOVE.l a1,a5
2516:
2517: MOVEM.l (a5)+,a0/a1/a2/a3/a4/a6
2518: JSR (a3) ;call Player Hook
2519: JSR (a4) ;call PreTimer
2520: BNE .exit
2521: MOVEM.l (a5),d0/a0/a1/a2/a3/a5
2522: JSR (a3) ;call Mixer Hook
2523: push a2
2524: * convert AND transfer Buffer
2525: * TODO: Use a table!
2526:
2527: MOVEM.l (a5),a0/a2/a3/a5
2528: ;move.l d2,-(a7)
2529:
2530: .loop
2531: REPT 2
2532: ;left
2533:
2534: ;add.b #1,check
2535: MOVE.b (a1)+,(a2)+ ;used for uae
2536: MOVE.b (a1)+,(a3)+
2537: ;move.b check,(a2)+
2538: ;right
2539: MOVE.b (a1)+,(a0)+
2540: MOVE.b (a1)+,(a5)+
2541: ENDR
2542: DBF d0,.loop
2543: ;movem.l (a7)+,d2
2544: pop a2
2545: .exit
2546: JSR (a6) ;call PostTimer, a2 ok
2547: popm a2/a3/a4/a6
2548: ;move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,CUSTOM+DMACON
2549: RTS
2550:
2551: ;in:
2552: * d0 scratch
2553: * d1 scratch
2554: * a0 scratch
2555: * a1 &(paulaBase->p_PlaySoftIntData)
2556: * a5 scratch
2557:
2558: SoftInt_14CbitS:
2559: pushm a2/a3/a4/a6
2560: MOVE.l a1,a5
2561: MOVEM.l (a5)+,a0/a1/a2/a3/a4/a6
2562: JSR (a3) ;call Player Hook
2563: JSR (a4) ;call PreTimer
2564: BNE .exit
2565: MOVEM.l (a5),d0/a0/a1/a2/a3/a4/a5
2566: JSR (a3) ;call Mixer Hook
2567: push a2
2568: * convert AND transfer Buffer, using the table
2569: MOVEM.l (a4),a0/a2/a3/a4
2570: MOVEQ #0,d1
2571: .loop
2572: REPT 2
2573:
2574: ;left
2575: IFD MC020
2576: MOVE.w (a1)+,d1 ;fetch 16 bit sample
2577: MOVE.w (a5,d1.l*2),d1
2578: Else
2579: MOVEQ #0,d1
2580: MOVE.w (a1)+,d1 ;fetch 16 bit sample
2581: ADD.w d1,d1
2582: MOVE.w (a5,d1.l),d1
2583: ENDC
2584: MOVE.b d1,(a3)+ ;low byte
2585: LSR.w #8,d1
2586: MOVE.b d1,(a2)+ ;high byte
2587:
2588: ;right
2589: IFD MC020
2590: MOVE.w (a1)+,d1 ;fetch 16 bit sample
2591: MOVE.w (a5,d1.l*2),d1
2592: Else
2593: MOVEQ #0,d1
2594: MOVE.w (a1)+,d1 ;fetch 16 bit sample
2595: ADD.w d1,d1
2596: MOVE.w (a5,d1.l),d1
2597: ENDC
2598: MOVE.b d1,(a4)+ ;low byte
2599: LSR.w #8,d1
2600: MOVE.b d1,(a0)+ ;high byte
2601: ENDR
2602:
2603: DBF d0,.loop
2604: pop a2
2605: .exit
2606: JSR (a6) ;call PostTimer
2607: popm a2/a3/a4/a6
2608: ;move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,CUSTOM+DMACON
2609: RTS
2610: flag Dc.l 0
2611: EndCode:
2612: check Dc.b 0
2613: END
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.