SOUND and ENVELOPE in assembler

by Richard Russell, March 2010

BBC BASIC for Windows provides no direct means for an assembly language program to access the SOUND or ENVELOPE statements. It can be achieved using the technique described in Calling BASIC from assembler code but an alternative approach is to use the code listed below. This makes available three subroutines: Sound, Envelope and Qstatus, the last of which allows you to discover the amount of space available in a sound queue (similar to what can be achieved using ADVAL).

The parameters and returned values are documented within the code:

        DEF PROCassemble
        LOCAL L%, P%, code%, pass%
        DIM code% 200, L% -1
        FOR pass% = 8 TO 10 STEP 2
          P% = code%
          [OPT pass%
          ; SOUND
          ;   Inputs; eax = &HSFC
          ;           ebx = amplitude/envelope
          ;           ecx = pitch
          ;           edx = duration
          ; Destroys; eax, ebx, ecx, edx, esi, edi, flags
          ;
          .Sound
          cmp dword,[^@hwo%],0
          jnz snd0
          pushad
          push 0
          push 0
          push &405
          push @hwnd%
          call "SendMessage"
          popad
          .snd0
          mov  esi,eax
          and  esi,3
          imul edi,esi,20
          add  edi,@vdu%+112
          test al,&F0
          jz   snd1
          .snd5
          mov  al,[esi+@vdu%+80]
          mov  [esi+@vdu%+76],al
          cmp  al,[esi+@vdu%+80]
          jnz  snd5
          .snd1
          mov  bh,ah
          movzx eax,byte [esi+@vdu%+76]
          mov  [edi+eax+0],dl
          mov  [edi+eax+1],cl
          mov  [edi+eax+2],bl
          mov  [edi+eax+3],bh
          add  al,4
          cmp  al,20
          jc   snd2
          xor  al,al
          .snd2
          cmp  al,[esi+@vdu%+80]
          jnz  snd3
          push 1
          call "Sleep"
          test byte [^@flags%+3],&80
          jz   snd2
          ret
          ;
          .snd3
          mov  [esi+@vdu%+76],al
          ret
          ;
          ; Sound queue status
          ;   Inputs; eax = channel number
          ;  Outputs; eax = no. of bytes free
          ; Destroys; eax, ebx, flags
          ;
          .Qstatus
          and  eax,3
          mov  ebx,eax
          mov  al,[ebx+@vdu%+80]
          sub  al,[ebx+@vdu%+76]
          jz   qstat0
          jnc  qstat1
          .qstat0
          add  al,20
          .qstat1
          sub  al,4
          ret
          ;
          ; ENVELOPE
          ;   Inputs; eax = envelope number
          ;           ebx = address of 13 byte parameter block
          ; Destroys; eax, ecx, esi, edi, flags
          ;
          .Envelope
          and  eax,15
          shl  eax,4
          mov  edi,[@vdu%-28]
          add  edi,eax
          mov  esi,ebx
          mov  ecx,13
          rep  movsb
          ret
          ]
        NEXT pass%
        ENDPROC