home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 19 / CD_ASCQ_19_010295.iso / dos / prg / midas / vu.asm < prev    next >
Assembly Source File  |  1994-08-06  |  11KB  |  446 lines

  1. ;*    VU.ASM
  2. ;*
  3. ;* Real VU meter routines
  4. ;*
  5. ;* Copyright 1994 Petteri Kangaslampi and Jarno Paananen
  6. ;*
  7. ;* This file is part of the MIDAS Sound System, and may only be
  8. ;* used, modified and distributed under the terms of the MIDAS
  9. ;* Sound System license, LICENSE.TXT. By continuing to use,
  10. ;* modify or distribute this file you indicate that you have
  11. ;* read the license and understand and accept it fully.
  12. ;*
  13.  
  14.  
  15. IDEAL
  16. P386
  17. JUMPS
  18.  
  19. INCLUDE "lang.inc"
  20. INCLUDE "errors.inc"
  21. INCLUDE "vu.inc"
  22. INCLUDE "mmem.inc"
  23. INCLUDE "sdevice.inc"
  24.  
  25.  
  26. VUBLOCK = 128                ; VU calculation block size
  27. VUBSHIFT = 7                ; shr value to convert from bytes to
  28.                     ; blocks
  29.  
  30.  
  31.  
  32. DATASEG
  33.  
  34. vuInsts     DD    ?        ; pointer to instrument info table
  35.  
  36.  
  37.  
  38. CODESEG
  39.  
  40.  
  41. ;/***************************************************************************\
  42. ;*
  43. ;* Function:     int vuInit(void);
  44. ;*
  45. ;* Description:  Initializes VU-meters, allocating room for MAXINSTS
  46. ;*               instruments.
  47. ;*
  48. ;* Returns:      MIDAS error code
  49. ;*
  50. ;\***************************************************************************/
  51.  
  52. PROC    vuInit        FAR
  53. USES    di
  54.  
  55.         ; Allocate memory for instrument information structures:
  56.         call    memAlloc LANG, MAXINSTS * SIZE vuInstrument, \
  57.                 seg vuInsts offset vuInsts
  58.         test    ax,ax
  59.         jnz     @@err
  60.  
  61.         les     di,[vuInsts]
  62.         xor     al,al                            ; initialize instrument
  63.         mov     cx,MAXINSTS * SIZE vuInstrument  ; information to all zeros
  64.     rep    stosb
  65.  
  66.         xor     ax,ax                   ; success
  67.         jmp     @@done
  68.  
  69. @@err:  ERROR   ID_vuInit
  70.  
  71. @@done:
  72.     ret
  73. ENDP
  74.  
  75.  
  76.  
  77.  
  78. ;/***************************************************************************\
  79. ;*
  80. ;* Function:     int vuClose(void);
  81. ;*
  82. ;* Description:  Uninitializes VU-meters
  83. ;*
  84. ;* Returns:      MIDAS error code
  85. ;*
  86. ;\***************************************************************************/
  87.  
  88. PROC    vuClose     FAR
  89. USES    si,di
  90.  
  91.         les     si,[vuInsts]            ; point es:bx to first instrument
  92.         mov     di,MAXINSTS
  93.  
  94. @@ilp:  cmp     [es:si+vuInstrument.vuInfo],0   ; allocated VU information?
  95.     je    @@iok
  96.         push    es
  97.         call    memFree LANG, [es:si+vuInstrument.vuInfo]       ; deallocate
  98.         pop     es
  99.         test    ax,ax
  100.         jnz     @@err
  101.  
  102. @@iok:  add     si,size vuInstrument    ; next instrument
  103.         dec     di
  104.         jnz     @@ilp
  105.  
  106.     call    memFree LANG, [vuInsts]     ; deallocate instrument info
  107.         test    ax,ax
  108.         jnz     @@err
  109.  
  110.         xor     ax,ax
  111.         jmp     @@done
  112.  
  113. @@err:
  114.         ERROR   ID_vuClose
  115.  
  116. @@done:
  117.     ret
  118. ENDP
  119.  
  120.  
  121.  
  122.  
  123. ;/***************************************************************************\
  124. ;*
  125. ;* Function:     int vuPrepare(ushort inst, uchar *sample, ushort slength,
  126. ;*                             ushort loopStart, ushort loopEnd);
  127. ;*
  128. ;* Description:  Prepares the VU information for an instrument
  129. ;*
  130. ;* Input:        ushort inst             instrument number
  131. ;*               uchar *sample           pointer to sample data
  132. ;*               ushort slength          sample length
  133. ;*               ushort loopStart        sample loop start
  134. ;*               ushort loopEnd          sample loop end (0 if no looping)
  135. ;*
  136. ;* Returns:      MIDAS error code
  137. ;*
  138. ;\***************************************************************************/
  139.  
  140. PROC    vuPrepare    FAR    inst : word, sample : dword, slength : word,\
  141.                 loopStart : word, loopEnd : word
  142. USES    di,si
  143.  
  144.     mov    ax,[inst]
  145.         cmp     ax,MAXINSTS                    ; instrument number too large?
  146.         jb      @@iok
  147.  
  148.         mov     ax,errNoInstHandles             ; out of instrument handles
  149.         jmp     @@err
  150.  
  151. @@iok:
  152.     les    si,[vuInsts]
  153.     imul    ax,ax,size vuInstrument     ; point es:si to instrument
  154.     add    si,ax                ; information
  155.  
  156.     cmp    [es:si+vuInstrument.vuInfo],0    ; is there allocated VU info?
  157.     je    @@noi
  158.     push    es
  159.     call    memFree LANG, [es:si+vuInstrument.vuInfo]    ; deallocate
  160.     pop    es
  161.         test    ax,ax
  162.         jnz     @@err
  163.  
  164. @@noi:    mov    [es:si+vuInstrument.vuInfo],0    ; no VU information
  165.     mov    ax,[slength]
  166.     shr    ax,VUBSHIFT
  167.     inc    ax
  168.  
  169.         lea     bx,[es:si+vuInstrument.vuInfo]  ; point es:bx to VU info ptr
  170.  
  171.         ; allocate space for VU information:
  172.     push    es
  173.         call    memAlloc LANG, ax, es bx
  174.     pop    es
  175.         test    ax,ax
  176.         jnz     @@err
  177.  
  178.     mov    ax,[slength]
  179.     mov    [es:si+vuInstrument.slength],ax
  180.     mov    ax,[loopStart]
  181.     mov    [es:si+vuInstrument.loopStart],ax
  182.     mov    ax,[loopEnd]
  183.     mov    [es:si+vuInstrument.loopEnd],ax
  184.  
  185.     push    ds
  186.     les    di,[es:si+vuInstrument.vuInfo]    ; point es:di to VU info
  187.     lds    si,[sample]            ; point ds:si to sample
  188.     mov    bx,[slength]            ; sample length counter
  189.  
  190. @@vublp:
  191.     mov    cx,bx
  192.     cmp    cx,VUBLOCK        ; is more than one block left?
  193.     jbe    @@cok            ; if yes, calculate only one block's
  194.     mov    cx,VUBLOCK        ; worth of data
  195.  
  196. @@cok:    sub    bx,cx            ; decrease sample length counter
  197.     mov    dl,128            ; smallest sample value in block
  198.     mov    dh,128            ; largest sample value in block
  199.  
  200. @@blp:    lodsb                ; get byte from sample
  201.     cmp    al,dl            ; is byte smaller than smallest value?
  202.     jb    @@sm
  203.     cmp    al,dh            ; is byte larger than largest value?
  204.     ja    @@lg
  205. @@cblp:
  206.     loop    @@blp            ; next byte
  207.     jmp    @@bdone
  208.  
  209. @@sm:    mov    dl,al            ; new smallest value
  210.     jmp    @@cblp
  211.  
  212. @@lg:    mov    dh,al            ; new largest value
  213.     jmp    @@cblp
  214.  
  215. @@bdone:
  216.     mov    al,dh
  217.     sub    al,dl            ; VU value = (largest - smallest) / 4
  218.     xor    ah,ah
  219.     add    ax,2            ; round up
  220.     shr    ax,2            ; and divide - range is 0-64
  221.     stosb                ; store VU value
  222.         test    bx,bx                   ; sample data left?
  223.     jnz    @@vublp         ; if is, continue
  224.  
  225.     pop    ds
  226.  
  227.         xor     ax,ax
  228.         jmp     @@done
  229.  
  230.  
  231. @@err:  ERROR   ID_vuPrepare
  232.  
  233. @@done:
  234.     ret
  235. ENDP
  236.  
  237.  
  238.  
  239.  
  240. ;/***************************************************************************\
  241. ;*
  242. ;* Function:     int vuRemove(ushort inst);
  243. ;*
  244. ;* Description:  Removes and deallocates the VU information for an instrument
  245. ;*
  246. ;* Input:        ushort inst             instrument number
  247. ;*
  248. ;* Returns:      MIDAS error code
  249. ;*
  250. ;\***************************************************************************/
  251.  
  252. PROC    vuRemove        FAR     inst : word
  253.  
  254.     mov    ax,[inst]
  255.         cmp     ax,MAXINSTS                     ; instrument number too large?
  256.         jb      @@iok
  257.  
  258.         mov     ax,errInvalidInstHandle
  259.         jmp     @@err
  260.  
  261. @@iok:
  262.     les    bx,[vuInsts]
  263.     imul    ax,ax,size vuInstrument     ; point es:bx to instrument
  264.     add    bx,ax                ; information
  265.  
  266.     cmp    [es:bx+vuInstrument.vuInfo],0    ; VU information?
  267.         jne     @@ok2
  268.  
  269.         mov     ax,errInvalidInstHandle
  270.         jmp     @@err
  271.  
  272. @@ok2:
  273.     push    es bx
  274.     call    memFree LANG, [es:bx+vuInstrument.vuInfo]    ; deallocate
  275.     pop    bx es
  276.         test    ax,ax
  277.         jnz     @@err
  278.  
  279.     mov    [es:bx+vuInstrument.vuInfo],0    ; no VU information
  280.  
  281.         xor     ax,ax
  282.         jmp     @@done
  283.  
  284. @@err:  ERROR   ID_vuRemove
  285.  
  286. @@done:
  287.     ret
  288. ENDP
  289.  
  290.  
  291.  
  292.  
  293. ;/***************************************************************************\
  294. ;*
  295. ;* Function:     int vuMeter(ushort inst, ulong rate, ushort pos,
  296. ;*                           ushort volume, ushort *meter);
  297. ;*
  298. ;* Description:  Calculates the VU-meter value (0-64) for the next 1/50th of
  299. ;*               a second
  300. ;*
  301. ;* Input:        ushort inst             instrument that is played
  302. ;*               ulong rate              playing rate
  303. ;*               ushort pos              playing position
  304. ;*               ushort volume           playing volume (0-64)
  305. ;*               ushort *meter           pointer to VU-meter value
  306. ;*
  307. ;* Returns:      MIDAS error code.
  308. ;*               VU-meter value (0-64) is stored in *meter
  309. ;*
  310. ;\***************************************************************************/
  311.  
  312. PROC    vuMeter     FAR    inst : word, rate : dword, pos : word, \
  313.                                 volume : word, meter : dword
  314. USES    si
  315. LOCAL    bytes : word
  316.  
  317.     mov    ax,[inst]
  318.         cmp     ax,MAXINSTS                     ; instrument number too large?
  319.         jae     @@invinst
  320.  
  321.     les    bx,[vuInsts]
  322.     imul    ax,ax,size vuInstrument     ; point es:bx to instrument
  323.     add    bx,ax                ; information
  324.  
  325.     cmp    [es:bx+vuInstrument.vuInfo],0    ; VU information?
  326.         je      @@invinst
  327.  
  328.     mov    eax,[rate]
  329.     xor    edx,edx         ; eax = number of bytes in a 1/50th
  330.     mov    ecx,50            ; of a second
  331.     div    ecx
  332.  
  333.     mov    [bytes],ax
  334.  
  335.     cmp    [es:bx+vuInstrument.loopEnd],0    ; looping sample
  336.     je    @@noloop
  337.  
  338.  
  339.     ; looping sample
  340.  
  341.     xor    dl,dl            ; VU meter value
  342.  
  343. @@lp:
  344.     mov    cx,[es:bx+vuInstrument.loopEnd] ; cx = number of bytes to
  345.     sub    cx,[pos]            ; loop end
  346.     cmp    cx,[bytes]        ; more bytes to loop end than would
  347.     jbe    @@l1            ; be played?
  348.     mov    cx,[bytes]
  349.  
  350. @@l1:    sub    [bytes],cx
  351.  
  352.     lgs    si,[es:bx+vuInstrument.vuInfo]    ; point gs:si to VU info
  353.     mov    ax,[pos]
  354.     shr    ax,VUBSHIFT        ; ax = first VU block number
  355.     add    si,ax
  356.  
  357.     add    cx,VUBLOCK-1        ; number of VU blocks
  358.     shr    cx,VUBSHIFT
  359.         test    cx,cx
  360.         jz      @@lpd
  361.  
  362. @@llp:    mov    al,[gs:si]        ; get VU meter value for block
  363.     cmp    al,dl            ; greater than current meter value?
  364.     jbe    @@llp1
  365.     mov    dl,al            ; if is, set current meter value
  366. @@llp1:
  367.     inc    si            ; next VU block
  368.         loop    @@llp
  369.  
  370. @@lpd:
  371.     cmp    [bytes],0        ; more sample data left?
  372.     je    @@vuok
  373.  
  374.     mov    ax,[es:bx+vuInstrument.loopStart]
  375.     mov    [pos],ax        ; move to sample loop start
  376.  
  377.     mov    cx,[es:bx+vuInstrument.loopEnd]
  378.     sub    cx,ax            ; cx = loop length
  379.     cmp    [bytes],cx
  380.     jb    @@l2            ; do not calculate the loop more than
  381.     mov    [bytes],cx        ; once
  382.  
  383. @@l2:    jmp    @@lp
  384.  
  385.  
  386. @@noloop:
  387.     mov    cx,[es:bx+vuInstrument.slength] ; cx = number of bytes to
  388.     sub    cx,[pos]            ; sample end
  389.  
  390.     cmp    cx,ax            ; more bytes left than would be
  391.     jbe    @@nl1            ; played?
  392.     mov    cx,ax
  393.  
  394. @@nl1:    lgs    si,[es:bx+vuInstrument.vuInfo]    ; point gs:si to VU info
  395.     mov    dx,[pos]        ; sample playing position
  396.     mov    ax,dx
  397.     shr    ax,VUBSHIFT        ; ax = first VU block number
  398.     add    si,ax
  399.  
  400.     add    cx,VUBLOCK-1        ; number of VU blocks before end
  401.     shr    cx,VUBSHIFT
  402.         test    cx,cx
  403.         jz      @@nld
  404.  
  405.     xor    dl,dl            ; VU meter value
  406.  
  407. @@nll:    mov    al,[gs:si]        ; get VU meter value for block
  408.     cmp    al,dl            ; greater than current meter value?
  409.     jbe    @@nll1
  410.     mov    dl,al            ; if is, set current meter value
  411. @@nll1:
  412.     inc    si            ; next VU block
  413.     loop    @@nll
  414.  
  415. @@nld:
  416.     movzx    ax,dl            ; ax = VU meter value
  417.     jmp    @@vuok
  418.  
  419. @@vuok:
  420.         cmp     ax,64
  421.         jbe     @@vuvalok               ; make sure value is <= 64
  422.         mov     ax,64
  423.  
  424. @@vuvalok:
  425.         mul     [volume]                ; multiply value with volume
  426.     shr    ax,6            ; and divide with 64
  427.  
  428.         les     bx,[meter]              ; store VU meter value
  429.         mov     [es:bx],ax
  430.  
  431.         xor     ax,ax
  432.         jmp     @@done
  433.  
  434. @@invinst:
  435.         mov     ax,errInvalidInstHandle
  436.  
  437. @@err:  ERROR   ID_vuMeter
  438.  
  439. @@done:
  440.     ret
  441. ENDP
  442.  
  443.  
  444.  
  445. END
  446.