home *** CD-ROM | disk | FTP | other *** search
/ The Best of Mecomp Multimedia 1 / Mecomp-CD.iso / amiga / player / ahi / developer / drivers / paula / paula_audio.a next >
Text File  |  1996-11-01  |  62KB  |  2,586 lines

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