Dr.Godfried-Willem RAES

Kursus Experimentele Muziek: Boekdeel 1: Algoritmische Kompositie

Hogeschool Gent : Departement Muziek & Drama


<Terug naar inhoudstafel kursus>    

1164

Het weergeven van WAV bestanden vanuit Basic

via een Soundblaster kaart

Het hiernavolgend voorbeeldprogramma (twee versies) toont hoe je een wave-bestand binnen basic programmas kan weergeven. De voorbeeld kode spreekt rechtstreeks de hardware aan van de soundblaster kaart en maakt geen gebruik van externe libraries zoals beschikbaar voor Soundblaster kaarten. Om deze reden kunnen we kompatibiliteit met latere klankkaarten van Soundblaster, en zeker met andere klonen, niet garanderen.

Sedert 2000 is deze aanpak achterhaald en kunnen we de studenten beter verwijzen naar de door ons ontwikkelde kode zoals die deel uitmaakt van onze GMT programmeertaal voor kompositie.


' ***********************************

' * Voorbeeldprogramma 'QBWAVE.BAS' *

' ***********************************

'Original found at http://www.fys.ruu.nl/~bergmann/basic.html
'converted to PowerBASIC by Dave Navarro, Jr.
'additional work by unknown author on CompuServe, and by Godfried-Willem Raes
' this version runs on the Microsoft BC7 PDS platform.

' This SHOULD work on everything that is higher than an XT. An 386-16 won't
' keep up with this in the environment but runs most 8 bit waves fine from
' the compiled program. I also added the environ string stuff to detect a
' non-standard SB port, if BLASTER= is set.
DECLARE SUB SetVoice (OnOff%)
DEFINT A-Z

MaxTicks& = 1193180
SHARED WritePort%, MaxTicks&

'-Div.Init (maybe you get the filename from command line?
CLS
FILES ("*.WAV")
INPUT "Select Wave File"; VocFile$
VocFile% = FREEFILE

'-open the voc-file
OPEN VocFile$ FOR BINARY AS #VocFile%

TestPort$ = ENVIRON$("BLASTER")
IF TestPort$ > "" THEN
  PortAddress$ = "&H" + MID$(TestPort$, 2, 3)
  PortAddress = VAL(PortAddress$)
  WritePort = PortAddress + 12
ELSE
  WritePort = &H22C
END IF

'-parameters for copy-to-soundblaster
Bytes& = LOF(VocFile%)                 'number of bytes
X$ = SPACE$(40) 'riff file header stuff
GET #VocFile, , X$
Speed = ASC(MID$(X$, 26, 1)) * 256 OR ASC(MID$(X$, 25, 1))

'Playrate in Bytes per second.
'We are assuming an 8 bit *.Wav File Here
' And my 386-16 will hang in there at 11025 BPS under DOS
Clocks = MaxTicks& \ Speed 'using an integer divide. Close enough
                           'and doesn't pull in floating point math pack
                           'Maxticks are for the "normal" PC Clock at
                           '18.206 + ticks per second.
                           'We'll use this to time the play rate.
Bytes& = Bytes& - 40
BytesRemaining& = Bytes&               'number of remaining bytes
BufferMax% = &H3F00                    'largest buffer
Buffer$ = SPACE$(BufferMax%)           'create buffer
SetVoice 1                             'Soundblaster on

'-read {BufferMax%} bytes from disc, output on SB
DO
  BytesRemaining& = BytesRemaining& - BufferLen%
  IF BytesRemaining& = 0 THEN EXIT DO  'nothing left over?
  IF BytesRemaining& > BufferMax% THEN 'how many bytes?
    BufferLen% = BufferMax%
  ELSE
    BufferLen% = BytesRemaining&       'remaining (<BufferMax%)..
    Buffer$ = SPACE$(BufferLen%)       '..throw it into SB :-)
  END IF

  GET #VocFile%, , Buffer$             'read buffeer
  T = 0
  DEF SEG = STRSEG(Buffer$)
  K = STRPTR(Buffer$)
  OUT &H43, &H34 'PIT Timer select one shot then we can let the
  OUT &H40, 0  'clock keep up.
  OUT &H40, 0  ' set the clock to 0 and start the count down
  Rate& = 65536 - Clocks 'First count down stopping value
                         ' "zero" - Rate
  DO             'output od {bufferlen%}
     Char = PEEK(K + T)
     WAIT WritePort, &H80, &HFF             'wait for data-ready
     OUT WritePort, &H10
     WAIT WritePort, &H80, &HFF
     OUT WritePort, Char 'Direct DAC method
     T = T + 1
     DO
      C& = (INP(&H40) + INP(&H40) * 256&) 'check the ticker
    LOOP UNTIL C& <= Rate& 'end if it's at or below the ticks we alloted
    Rate& = Rate& - Clocks
    IF Rate& < 0 THEN
        OUT &H40, 0  'reset the ticker to 0
        OUT &H40, 0  'both bytes
        Rate& = 65536 - Clocks  'Reset the Rate& value
    END IF
  LOOP UNTIL T = BufferLen 'This is faster than a for next loop
  OUT &H43, 4
LOOP UNTIL Forever
SetVoice 0                             'SB off
CLOSE #VocFile%                        'close file
END                                    '.. good bye :-)

' Turns Speaker on and off
SUB SetVoice (OnOff%)
  IF OnOff% THEN
    WAIT WritePort%, &H80, &HFF             'wait for data-ready on SB
    OUT WritePort%, &HD1 'ON
  ELSE
    WAIT WritePort%, &H80, &HFF
    OUT WritePort%, &HD3 'OFF
  END IF
END SUB

'***********************************************

'* PB-WAVE.BAS PowerBasic Version *

'***********************************************

'Original found at http://www.fys.ruu.nl/~bergmann/basic.html
'converted to PowerBASIC by Dave Navarro, Jr.

'-Div.Init (maybe you get the filename from commandline?
VocFile$ = "MAKEITSO.WAV"              'input-file
VocFile% = FREEFILE                    '.
xDelay%  = 120                         'value for delay

'-open the voc-file
OPEN VocFile$ FOR BINARY AS #VocFile%

'-parameters for copy-to-soundblaster
Bytes& = LOF( VocFile% )               'number of bytes

BytesRemaining& = Bytes&               'number of remaining bytes
BufferMax% = &H7F00                    'largest buffer
Buffer$ = SPACE$( BufferMax% )         'create buffer

SetVoice 1                             'Soundblaster on

'-read {BufferMax%} bytes from disc, output on SB
DO
  BytesRemaining& = BytesRemaining& - BufferLen%
  IF BytesRemaining& = 0 THEN EXIT DO  'nothing left over?
  IF BytesRemaining& > BufferMax% THEN 'how many bytes?
    BufferLen% = BufferMax%
  ELSE
    BufferLen% = BytesRemaining&       'remaining (<BufferMax%)..
    Buffer$ = SPACE$( BufferLen% )     '..throw it into SB :-)
  END IF

  GET #VocFile%,, Buffer$              'read buffer
  DEF SEG = STRSEG( Buffer$ )          'get address of buffer
  VOff% = STRPTR( Buffer$ )            '.

  FOR t% = 1 TO BufferLen%             'output od {bufferlen%}
    FOR qq% = 1 TO xDelay: NEXT qq%    ' delay
    WAIT &H22C, &H80, &HFF             'wait for data-ready
    OUT &H22C, &H10
    WAIT &H22C, &H80, &HFF
    OUT &H22C, PEEK( VOff% )
    VOff% = VOff% + 1
  NEXT t%

LOOP WHILE INKEY$ = ""

SetVoice 0                             'SB off
CLOSE #VocFile%                        'close file
END                                    '.. good bye :-)

SUB SetVoice( OnOff% )
  IF OnOff% THEN
    WAIT &H22C, &H80, &HFF             'wait for data-ready on SB
    OUT &H22C, &HD1 'ON
  ELSE
    WAIT &H22C, &H80, &HFF
    OUT &H22C, &HD3 'OFF
  END IF
END SUB

Enkele extra links naar bronnen voor het werken met geluid in BASIC:

http://www.snafu.de/~pbsound

http://comt.to/pbdos


Filedate: 98-09-07

Terug naar inhoudstafel kursus: <Index Kursus> Naar homepage dr.Godfried-Willem RAES