Playing multiple wav files simultaneously?

Hi!

I'm trying to add sound effects to a game I've programmed in Borland Pascal 7.0. I'v found the below code, which is really easy to use for playing wav files. So far so good. However, whenever I play a wav file, it cuts off the sound currently playing. Is there any way to modify this code, so that I have multiple tracks for playing wav files simultaneously? I tried just making a second unit (WavPlay2) which was just a copy of this unit with all the variables and procedures having added "2" at the end. I hoped that in that way I could call PlayWav() and then while that file was playing I could call PlayWav2() for playing another wave file simultaneously. However, this didn't work -- it just cut off the currently playing wav file just as it did before.

[CODE]
Unit WavPlay;
{***************************************************************************
** Unit to play WAV-format files from Turbo Pascal for DOS. **
** by Steven H Don **
** **
** For questions, feel free to e-mail me. **
** **
** shd@earthling.net **
** http://shd.cjb.net **
** **
***************************************************************************}

interface

{
This is used for transmitting wave-information to the calling programme
}
type WType = record
SampleRate : Word;
Resolution : Byte;
Stereo : Boolean;
Length : LongInt;
end;

{
The only 2 procedures available to the calling programme.

** Playing a Wave-file
All the calling programme has to do is :
PlayWave ('TEST.WAV');
and the appropriate file will be played through any SB-compatible card.
Is this easy or what? I don't think it comes any easier!
On second thought : read the next bit.

** Stopping the currently playing Wave-file :
StopWave;
Anyone who has trouble doing that is on the wrong news-group and
probably has an IQ below absolute 0.

}
procedure PlayWave (FileName : String);
procedure StopWave;

{Variables available to the calling programme : }
var Playing : Boolean; {True if currently playing a wave-file}
WaveError : Byte; {If an error has occurred, contains the error code}
WaveType : WType; {Contains wave-file information}

{Different error codes. Note that these are the only things
the programme checks for. Additional errors might produce
unexpected results}
const
FileNotFound = $01;
InvalidWAVE = $02;
NoCard = $03;
NoStereoCard = $04;
No16BitCard = $05;
NoMemory = $06;

implementation

{Needed for I/O}
uses Dos, Crt;

{Definition of chunk-formats}
type
HeaderChunk = record
RIFF : LongInt;
NextChunkSize : LongInt;
end;

WaveChunk = record
WAVE : LongInt;
end;

fmtHeader = record
fmt : LongInt;
fmtDataLength : LongInt;
end;

fmtChunk = record
WaveType : Word;
Channels : Word;
SampleRate : LongInt;
BytesPerSecond : LongInt;
BlockAlignment : Word;
BitResolution : Word;
end;

DataChunk = record
data : LongInt;
SoundLength : LongInt;
end;

ThirtyTwoK = array [0..32767] of Byte;

{Local variables}
var
{Pointer to old IRQ handler}
OldIRQ,
{Pointer to old exit procedure}
OldEP : pointer;
{The SB base address}
Base : Word;
{What kind of card is installed}
Card,
{The IRQ level}
IRQ,
{The DMA channel currently used}
Channel : Byte;
{One DMA channel for 8bit, the other for 16bit}
DMA8, DMA16 : Byte;

{The sound buffer itself}
SoundBuffer : ^ThirtyTwoK;

{The amount of bytes already read}
SoundRead,
{If the amount of bytes to be played is not a multiple of 16384 (most
likely, it isn't), this is used to store the difference}
OverHead : LongInt;
{Which buffer is being played}
Upper,
{Should the sound buffer be release?}
FreeBuffer : Boolean;
{A handle to the sound file}
SoundFile : File;
{The chunks that should be read from the file}
Header : HeaderChunk;
Wave : WaveChunk;
fmtH : fmtHeader;
fmt : fmtChunk;
data : DataChunk;

const
SB8 = 8; SB16 = 16;
{Constants used for programming of the DMA-controller}
DmaChannel : Array [0..7, 1..3] of Byte =
( ($87, $0, $1), ($83, $2, $3), ($81, $4, $5), ($82, $6, $7),
($8F, $C0, $C2), ($8B, $C4, $C6), ($89, $C8, $CA), ($8A, $CC, $CE));
DmaPort : Array [0..7, 1..3] of Byte =
( ($A, $B, $C), ($A, $B, $C), ($A, $B, $C), ($A, $B, $C),
($D4, $D6, $D8), ($D4, $D6, $D8), ($D4, $D6, $D8), ($D4, $D6, $D8));

{Chunk-identification values}
rId = $46464952; {RIFF}
wId = $45564157; {WAVE}
fId = $20746D66; {fmt }
dId = $61746164; {data}

{Writes a value to the DSP-chip on the SB}
procedure WriteDSP (value : byte);
begin
while Port [base + $C] And $80 <> 0 do;
Port [base + $C] := value;
end;

{Establishes the DSP<->Speaker connection, necessary for older cards.}
function SpeakerOn : byte;
begin
WriteDSP ($D1);
end;

{Discontinues the DSP<->Speaker connection, necessary for older cards.}
function SpeakerOff : byte;
begin
WriteDSP ($D3);
end;

{Stops playing the wave-file.}
procedure DMAStop;
begin
{Set general variable to indicate no sound}
Playing := false;

{Function : D0 Stop 8 bit DMA transfer}
WriteDSP ($D0);
{Function : D5 Stop 16 bit DMA transfer}
WriteDSP ($D5);

{$I-}
Close (SoundFile); {Close the soundfile}
if IOResult <> 0 then; {Clear Error flag}
{$I+}

{Free the sound buffer}
if SoundBuffer <> nil then begin
Dispose (SoundBuffer);
SoundBuffer := nil;
end;
end;

{This procedure sets up the DMA controller for DMA transfer.
Then it programs the DSP chip to receive the transfer.
Finally it initiates the transfer.}
{procedure Playback (SoundSeg, SoundOfs, size : longint);}
procedure Playback (Location : Pointer; Start, Size : Word);
var
SoundSeg, SoundOfs : Word;
page, offset : longint;

begin
{Calculate offset and segment part of the buffer}
SoundSeg := Seg (Location^);
SoundOfs := Ofs (Location^) + Start;

{Calculate Offset and Page address of Wave-data}
if fmt.BitResolution = 8 then begin
offset := SoundSeg Shl 4 + SoundOfs;
page := (SoundSeg + SoundOfs shr 4) shr 12;
end else begin
size := size shr 1;
page := (SoundSeg + SoundOfs shr 4) shr 12;
offset := (SoundSeg Shl 3 + SoundOfs shr 1) mod 65536;
end;

{Decrease size by one. This is necessary because the
DMA controller sends one byte/word more than it is told to}
{Setup DMA Controller for transfer}
Port [DMAPort [Channel, 1]] := 4 or (Channel and 3);
if fmt.BitResolution = 16 then Port [$D8] := 0;
Port [DMAPort [Channel, 3]] := 0;
Port [DMAPort [Channel, 2]] := $48 or (Channel and 3);
Port [DMAChannel [Channel, 2]] := Lo (offset);
Port [DMAChannel [Channel, 2]] := Hi (offset);
Port [DMAChannel [Channel, 1]] := page;
Port [DMAChannel [Channel, 3]] := Lo (size);
Port [DMAChannel [Channel, 3]] := Hi (size);
Port [DMAPort [Channel, 1]] := (Channel and 3);

{Set DSP}
if Card = SB8 then begin
{Set up 8-bit card, sorry no stereo SBPRO support}
WriteDSP ($14);
end else begin
{Set up 16-bit card}
if fmt.BitResolution = 8 then begin
{8-Bit file}
WriteDSP ($C0);
if fmt.Channels = 1 then WriteDSP ($00); {Mono}
if fmt.Channels = 2 then WriteDSP ($20); {Stereo}
end else begin
{16-Bit file
Perhaps this also needs to be changed}
WriteDSP ($B0);
if fmt.Channels = 1 then WriteDSP ($10); {Mono}
if fmt.Channels = 2 then WriteDSP ($30); {Stereo}
end;
end;

{Send the size of the transfer to the SB}
WriteDSP (Lo (size));
WriteDSP (Hi (size));

{Set global variable to indicate playing sound}
Playing := true;
end;

(continued...)
[/CODE]

Comments

  • [CODE]

    (...continued from previous post)

    {This procedure is called at the end of a DMA transfer. It starts the
    playing of the next portion of the wave-file and reads in another block.}
    procedure ServiceIRQ; interrupt;
    var
    b, t : Byte;

    begin
    {relieve card}
    if Card = SB16 then begin
    Port [base + $4] := $82;
    t := Port [base + $5];
    if t and 1 = 1 then b := Port [base + $E]; { 8bit interrupt}
    if t and 2 = 2 then b := Port [base + $F]; {16bit interrupt}
    end else begin
    {8bit interrupt}
    b := Port [base + $E];
    end;

    {Acknowledge hardware interrupt}
    Port [$20] := $20;

    {Stop playing}
    Playing := false;
    if FreeBuffer then begin
    Dispose (SoundBuffer);
    SoundBuffer := nil;
    end;

    {The following is done when the remaining part of the file
    is less than 16K.}
    if OverHead>0 then begin
    {Play the last part of the sound}
    if Upper then
    PlayBack (SoundBuffer, 0, OverHead)
    else
    PlayBack (SoundBuffer, 16384, OverHead);

    {The file may be closed}
    Close (SoundFile);
    OverHead := 0;

    {The next time this routine is called, the sound buffer must
    be freed so that the memory it occupies is available to the
    calling programme.}
    FreeBuffer := true;
    end;

    {If there is more than 16K to be played and/or read, it will
    be done in chunks of 16K.}
    if data.SoundLength - SoundRead > 0 then begin
    if data.SoundLength - SoundRead > 16384 then begin
    {Load into appropriate part of the buffer}
    if Upper then begin
    PlayBack (SoundBuffer, 0, 16384);
    BlockRead (SoundFile, SoundBuffer^ [16384], 16384);
    end else begin
    PlayBack (SoundBuffer, 16384, 16384);
    BlockRead (SoundFile, SoundBuffer^, 16384);
    end;

    {Update position indicators}
    inc (SoundRead, 16384);
    Upper := Not Upper;
    end else begin
    {Load in the last part of the Wave-file and play it.}
    OverHead := data.SoundLength-SoundRead;
    if Upper then begin
    PlayBack (SoundBuffer, 0, 16384);
    BlockRead (SoundFile, SoundBuffer^ [16384], Overhead);
    end else begin
    PlayBack (SoundBuffer, 16384, 16384);
    BlockRead (SoundFile, SoundBuffer^, Overhead);
    end;
    inc (SoundRead, Overhead);
    Upper := Not Upper;
    end;
    end;
    end;

    procedure PlayWave (FileName : String);
    begin
    {Assume no error}
    WaveError := 0;

    {Return error if no sound card found}
    if Base = 0 then begin
    WaveError := NoCard;
    Exit;
    end;

    {Stop any DMA-transfer that might be in progress}
    DMAStop;

    {Initialize settings}
    FreeBuffer := false;
    OverHead := 0;

    {Allow access to read-only files}
    FileMode := 0;

    {$I-}
    {Check for existence of file}
    Assign (SoundFile, FileName);
    Reset (SoundFile, 1);
    {If it doesn't exist, maybe the extension should be added}
    if IOResult <> 0 then begin
    Assign (SoundFile, FileName + '.WAV');
    Reset (SoundFile, 1);
    end;
    {$I+}

    {If it doesn't resist, return an error}
    if IOResult <> 0 then begin
    WaveError := FileNotFound;
    Exit;
    end;

    {Read the RIFF header}
    BlockRead (SoundFile, Header, 8);
    {Check for 'RIFF', if not found : don't play}
    if Header.RIFF <> rId then begin
    WaveError := InvalidWAVE;
    Close (SoundFile);
    Exit;
    end;

    {Read the WAVE header}
    BlockRead (SoundFile, Wave, 4);
    {Check for 'WAVE', if not found : don't play}
    if Wave.WAVE <> wId then begin
    WaveError := InvalidWAVE;
    Close (SoundFile);
    Exit;
    end;

    {Search for the fmt chunk, that starts with 'fmt '}
    repeat
    BlockRead (SoundFile, fmtH, 8);
    if fmtH.fmt <> fId then Seek (SoundFile, FilePos (SoundFile)-7);
    until fmtH.fmt = fId;

    {Read format specifier}
    BlockRead (SoundFile, fmt, fmtH.fmtDataLength);

    {Check format}
    with fmt do begin
    if (Card = SB8) then begin
    {16bit files can't be played through 8bit card}
    if (BitResolution = 16) then begin
    WaveError := No16BitCard;
    Close (SoundFile);
    Exit;
    end;
    {Stereo files are only played over 16bit card}
    if (Channels = 2) then begin
    WaveError := NoStereoCard;
    Close (SoundFile);
    Exit;
    end;
    end;
    {Can only play uncompressed WAVs}
    if WaveType <> 1 then begin
    WaveError := InvalidWAVE;
    Close (SoundFile);
    Exit;
    end;
    end;

    {Search for data chunk, starting with 'data'}
    data.data := 0;
    repeat
    BlockRead (SoundFile, data, 8);
    if data.data <> dId then Seek (SoundFile, FilePos (SoundFile)-7);
    until data.data = dId;

    {Some wave-files have an incorrect SoundLength. This makes sure
    that the SoundLength is never larger than actually fits in the
    wave file.}
    if data.SoundLength>FileSize (SoundFile)-FilePos (SoundFile)-1 then
    data.SoundLength := FileSize (SoundFile)-FilePos (SoundFile)-1;
    WaveType.Length := data.SoundLength;

    {The WaveLength (not SoundLength) indicates the number of Samples,
    not the number of bytes, so this needs to be adjusted for the
    number of channels (Mono/Stereo) and the bit-resolution (8/16-Bit)}
    if WaveType.Stereo = true then WaveType.Length := WaveType.Length shr 1;
    if WaveType.Resolution = 16 then WaveType.Length := WaveType.Length shr 1;

    {set DMAChannel}
    if fmt.BitResolution = 8 then Channel := DMA8;
    if fmt.BitResolution = 16 then Channel := DMA16;

    {Update global variables so that calling programs can identify
    the wave being played. Pretty useless for games though}
    WaveType.SampleRate := fmt.SampleRate;
    WaveType.Resolution := fmt.BitResolution;
    WaveType.Stereo := fmt.Channels = 2;
    SoundRead := 0;

    {Allocate 32K of memory to the sound buffer}
    New (SoundBuffer);
    {If there was an error allocating memory, don't play.}
    if SoundBuffer = nil then begin
    WaveError := NoMemory;
    Close (SoundFile);
    Exit;
    end;

    {set sample rate}
    case Card of
    {Original SB requires a special 'time-frame' computation}
    SB8 : begin
    WriteDSP ($40);
    WriteDSP (256 - 1000000 div fmt.SampleRate);
    end;
    {SB16 just needs the samplerate. Much easier}
    SB16 : begin
    WriteDSP ($41);
    WriteDSP (hi (fmt.SampleRate));
    WriteDSP (lo (fmt.SampleRate));
    end;
    end;

    {check length of file}
    if data.SoundLength>32768 then begin
    {must be played in parts}
    BlockRead (SoundFile, SoundBuffer^, 32768);
    SoundRead := 32768;
    PlayBack (SoundBuffer, 0, 16384);
    Upper := false;
    end else begin
    {can be played at once}
    BlockRead (SoundFile, SoundBuffer^, data.SoundLength);
    PlayBack (SoundBuffer, 0, data.SoundLength);
    SoundRead := data.SoundLength;
    end;
    end;

    {Stops playing the sound file}
    procedure StopWave;
    begin
    DMAStop;
    end;

    {$F+}
    procedure ExitWavePlayer;
    begin
    {Restores the ExitProc pointer to the original value}
    ExitProc := OldEP;

    {Stops any DMA-transfer that might be in progress}
    DMAStop;

    {Free interrupt vectors used to service IRQs}
    case IRQ of
    2 : SetIntVec($71, OldIRQ);
    10 : SetIntVec($72, OldIRQ);
    11 : SetIntVec($73, OldIRQ);
    else
    SetIntVec (8 + IRQ, OldIRQ);
    end;

    {Mask IRQs}
    case IRQ of
    2 : Port[$A1] := Port[$A1] or 2;
    10 : Port[$A1] := Port[$A1] or 4;
    11 : Port[$A1] := Port[$A1] or 8;
    else
    Port[$21] := Port[$21] or (1 shl IRQ);
    end;
    end;
    {$F-}

    var
    BLASTER : String;
    p : Byte;

    begin
    Playing := false;
    Base := 0;
    {Get BLASTER environment string}
    BLASTER := GetEnv ('BLASTER');
    if (BLASTER = '') then Exit;

    {Extract type of card from BLASTER string}
    Card := SB8;
    p := 0;
    repeat inc (p) until (BLASTER [p] = 'T') or (p > length (BLASTER));
    if BLASTER [p + 1] > '5' then Card := SB16;
    {Extract base address from BLASTER string}
    p := 0;
    repeat inc (p) until (BLASTER [p] = 'A') or (p > length (BLASTER));
    Base := Ord (BLASTER [p + 2]) - Ord ('0');
    Base := (Base shl 4) + $200;
    {Extract IRQ level from BLASTER string}
    p := 0;
    repeat inc (p) until (BLASTER [p] = 'I') or (p > length (BLASTER));
    IRQ := Ord (BLASTER [p + 1]) - Ord ('0');
    {Extract low DMA channel from BLASTER string}
    p := 0;
    repeat inc (p) until (BLASTER [p] = 'D') or (p > length (BLASTER));
    DMA8 := Ord (BLASTER [p + 1]) - Ord ('0');
    {Extract high DMA channel from BLASTER string}
    p := 0;
    repeat inc (p) until (BLASTER [p] = 'H') or (p > length (BLASTER));
    DMA16 := Ord (BLASTER [p + 1]) - Ord ('0');

    {Enable speaker}
    SpeakerOn;

    {Save old IRQ vector}
    case IRQ of
    2 : GetIntVec($71, OldIRQ);
    10 : GetIntVec($72, OldIRQ);
    11 : GetIntVec($73, OldIRQ);
    else
    GetIntVec (8 + IRQ, OldIRQ);
    end;

    {Set new IRQ vector}
    case IRQ of
    2 : SetIntVec($71, Addr (ServiceIRQ));
    10 : SetIntVec($72, Addr (ServiceIRQ));
    11 : SetIntVec($73, Addr (ServiceIRQ));
    else
    SetIntVec (8 + IRQ, Addr (ServiceIRQ));
    end;

    {Enable IRQ}
    case IRQ of
    2 : Port[$A1] := Port[$A1] and not 2;
    10 : Port[$A1] := Port[$A1] and not 4;
    11 : Port[$A1] := Port[$A1] and not 8;
    else
    Port[$21] := Port[$21] and not (1 shl IRQ);
    end;
    if IRQ in [2, 10, 11] then Port[$21] := Port[$21] and not 4;

    {Save ExitProc pointer and set it to our own exit procedure.
    The ExitProc procedure is called after the main (calling)
    programme terminates. The main programme doesn't have to take
    care of resetting the IRQs and so on.}
    OldEP := ExitProc;
    ExitProc := Addr (ExitWavePlayer);
    end.
    [/CODE]

  • : Hi!
    :
    : I'm trying to add sound effects to a game I've programmed in Borland Pascal 7.0. I'v found the below code, which is really easy to use for playing wav files. So far so good. However, whenever I play a wav file, it cuts off the sound currently playing. Is there any way to modify this code, so that I have multiple tracks for playing wav files simultaneously? I tried just making a second unit (WavPlay2) which was just a copy of this unit with all the variables and procedures having added "2" at the end. I hoped that in that way I could call PlayWav() and then while that file was playing I could call PlayWav2() for playing another wave file simultaneously. However, this didn't work -- it just cut off the currently playing wav file just as it did before.
    :
    : [CODE]
    : Unit WavPlay;
    : {***************************************************************************
    : ** Unit to play WAV-format files from Turbo Pascal for DOS. **
    : ** by Steven H Don **
    : ** **
    : ** For questions, feel free to e-mail me. **
    : ** **
    : ** shd@earthling.net **
    : ** http://shd.cjb.net **
    : ** **
    : ***************************************************************************}
    :
    : interface
    :
    : {
    : This is used for transmitting wave-information to the calling programme
    : }
    : type WType = record
    : SampleRate : Word;
    : Resolution : Byte;
    : Stereo : Boolean;
    : Length : LongInt;
    : end;
    :
    : {
    : The only 2 procedures available to the calling programme.
    :
    : ** Playing a Wave-file
    : All the calling programme has to do is :
    : PlayWave ('TEST.WAV');
    : and the appropriate file will be played through any SB-compatible card.
    : Is this easy or what? I don't think it comes any easier!
    : On second thought : read the next bit.
    :
    : ** Stopping the currently playing Wave-file :
    : StopWave;
    : Anyone who has trouble doing that is on the wrong news-group and
    : probably has an IQ below absolute 0.
    :
    : }
    : procedure PlayWave (FileName : String);
    : procedure StopWave;
    :
    : {Variables available to the calling programme : }
    : var Playing : Boolean; {True if currently playing a wave-file}
    : WaveError : Byte; {If an error has occurred, contains the error code}
    : WaveType : WType; {Contains wave-file information}
    :
    : {Different error codes. Note that these are the only things
    : the programme checks for. Additional errors might produce
    : unexpected results}
    : const
    : FileNotFound = $01;
    : InvalidWAVE = $02;
    : NoCard = $03;
    : NoStereoCard = $04;
    : No16BitCard = $05;
    : NoMemory = $06;
    :
    : implementation
    :
    : {Needed for I/O}
    : uses Dos, Crt;
    :
    : {Definition of chunk-formats}
    : type
    : HeaderChunk = record
    : RIFF : LongInt;
    : NextChunkSize : LongInt;
    : end;
    :
    : WaveChunk = record
    : WAVE : LongInt;
    : end;
    :
    : fmtHeader = record
    : fmt : LongInt;
    : fmtDataLength : LongInt;
    : end;
    :
    : fmtChunk = record
    : WaveType : Word;
    : Channels : Word;
    : SampleRate : LongInt;
    : BytesPerSecond : LongInt;
    : BlockAlignment : Word;
    : BitResolution : Word;
    : end;
    :
    : DataChunk = record
    : data : LongInt;
    : SoundLength : LongInt;
    : end;
    :
    : ThirtyTwoK = array [0..32767] of Byte;
    :
    : {Local variables}
    : var
    : {Pointer to old IRQ handler}
    : OldIRQ,
    : {Pointer to old exit procedure}
    : OldEP : pointer;
    : {The SB base address}
    : Base : Word;
    : {What kind of card is installed}
    : Card,
    : {The IRQ level}
    : IRQ,
    : {The DMA channel currently used}
    : Channel : Byte;
    : {One DMA channel for 8bit, the other for 16bit}
    : DMA8, DMA16 : Byte;
    :
    : {The sound buffer itself}
    : SoundBuffer : ^ThirtyTwoK;
    :
    : {The amount of bytes already read}
    : SoundRead,
    : {If the amount of bytes to be played is not a multiple of 16384 (most
    : likely, it isn't), this is used to store the difference}
    : OverHead : LongInt;
    : {Which buffer is being played}
    : Upper,
    : {Should the sound buffer be release?}
    : FreeBuffer : Boolean;
    : {A handle to the sound file}
    : SoundFile : File;
    : {The chunks that should be read from the file}
    : Header : HeaderChunk;
    : Wave : WaveChunk;
    : fmtH : fmtHeader;
    : fmt : fmtChunk;
    : data : DataChunk;
    :
    : const
    : SB8 = 8; SB16 = 16;
    : {Constants used for programming of the DMA-controller}
    : DmaChannel : Array [0..7, 1..3] of Byte =
    : ( ($87, $0, $1), ($83, $2, $3), ($81, $4, $5), ($82, $6, $7),
    : ($8F, $C0, $C2), ($8B, $C4, $C6), ($89, $C8, $CA), ($8A, $CC, $CE));
    : DmaPort : Array [0..7, 1..3] of Byte =
    : ( ($A, $B, $C), ($A, $B, $C), ($A, $B, $C), ($A, $B, $C),
    : ($D4, $D6, $D8), ($D4, $D6, $D8), ($D4, $D6, $D8), ($D4, $D6, $D8));
    :
    : {Chunk-identification values}
    : rId = $46464952; {RIFF}
    : wId = $45564157; {WAVE}
    : fId = $20746D66; {fmt }
    : dId = $61746164; {data}
    :
    : {Writes a value to the DSP-chip on the SB}
    : procedure WriteDSP (value : byte);
    : begin
    : while Port [base + $C] And $80 <> 0 do;
    : Port [base + $C] := value;
    : end;
    :
    : {Establishes the DSP<->Speaker connection, necessary for older cards.}
    : function SpeakerOn : byte;
    : begin
    : WriteDSP ($D1);
    : end;
    :
    : {Discontinues the DSP<->Speaker connection, necessary for older cards.}
    : function SpeakerOff : byte;
    : begin
    : WriteDSP ($D3);
    : end;
    :
    : {Stops playing the wave-file.}
    : procedure DMAStop;
    : begin
    : {Set general variable to indicate no sound}
    : Playing := false;
    :
    : {Function : D0 Stop 8 bit DMA transfer}
    : WriteDSP ($D0);
    : {Function : D5 Stop 16 bit DMA transfer}
    : WriteDSP ($D5);
    :
    : {$I-}
    : Close (SoundFile); {Close the soundfile}
    : if IOResult <> 0 then; {Clear Error flag}
    : {$I+}
    :
    : {Free the sound buffer}
    : if SoundBuffer <> nil then begin
    : Dispose (SoundBuffer);
    : SoundBuffer := nil;
    : end;
    : end;
    :
    : {This procedure sets up the DMA controller for DMA transfer.
    : Then it programs the DSP chip to receive the transfer.
    : Finally it initiates the transfer.}
    : {procedure Playback (SoundSeg, SoundOfs, size : longint);}
    : procedure Playback (Location : Pointer; Start, Size : Word);
    : var
    : SoundSeg, SoundOfs : Word;
    : page, offset : longint;
    :
    : begin
    : {Calculate offset and segment part of the buffer}
    : SoundSeg := Seg (Location^);
    : SoundOfs := Ofs (Location^) + Start;
    :
    : {Calculate Offset and Page address of Wave-data}
    : if fmt.BitResolution = 8 then begin
    : offset := SoundSeg Shl 4 + SoundOfs;
    : page := (SoundSeg + SoundOfs shr 4) shr 12;
    : end else begin
    : size := size shr 1;
    : page := (SoundSeg + SoundOfs shr 4) shr 12;
    : offset := (SoundSeg Shl 3 + SoundOfs shr 1) mod 65536;
    : end;
    :
    : {Decrease size by one. This is necessary because the
    : DMA controller sends one byte/word more than it is told to}
    : {Setup DMA Controller for transfer}
    : Port [DMAPort [Channel, 1]] := 4 or (Channel and 3);
    : if fmt.BitResolution = 16 then Port [$D8] := 0;
    : Port [DMAPort [Channel, 3]] := 0;
    : Port [DMAPort [Channel, 2]] := $48 or (Channel and 3);
    : Port [DMAChannel [Channel, 2]] := Lo (offset);
    : Port [DMAChannel [Channel, 2]] := Hi (offset);
    : Port [DMAChannel [Channel, 1]] := page;
    : Port [DMAChannel [Channel, 3]] := Lo (size);
    : Port [DMAChannel [Channel, 3]] := Hi (size);
    : Port [DMAPort [Channel, 1]] := (Channel and 3);
    :
    : {Set DSP}
    : if Card = SB8 then begin
    : {Set up 8-bit card, sorry no stereo SBPRO support}
    : WriteDSP ($14);
    : end else begin
    : {Set up 16-bit card}
    : if fmt.BitResolution = 8 then begin
    : {8-Bit file}
    : WriteDSP ($C0);
    : if fmt.Channels = 1 then WriteDSP ($00); {Mono}
    : if fmt.Channels = 2 then WriteDSP ($20); {Stereo}
    : end else begin
    : {16-Bit file
    : Perhaps this also needs to be changed}
    : WriteDSP ($B0);
    : if fmt.Channels = 1 then WriteDSP ($10); {Mono}
    : if fmt.Channels = 2 then WriteDSP ($30); {Stereo}
    : end;
    : end;
    :
    : {Send the size of the transfer to the SB}
    : WriteDSP (Lo (size));
    : WriteDSP (Hi (size));
    :
    : {Set global variable to indicate playing sound}
    : Playing := true;
    : end;
    :
    : (continued...)
    : [/CODE]
    :
    hi there,
    you forgot that there is only a ubique sound card on board so you cannot do what you are trying to do.
    It is just like trying to print a document on your printer when another one is being printed.
    it makes no sense .But try this : playing part of the first wave the stopping it and paying the other one.
    by the way ,do you even understand how the WAV player works,how wav is being decoded?

  • :
    : : Hi!
    : :
    : : I'm trying to add sound effects to a game I've programmed in Borland Pascal 7.0. I'v found the below code, which is really easy to use for playing wav files. So far so good. However, whenever I play a wav file, it cuts off the sound currently playing. Is there any way to modify this code, so that I have multiple tracks for playing wav files simultaneously? I tried just making a second unit (WavPlay2) which was just a copy of this unit with all the variables and procedures having added "2" at the end. I hoped that in that way I could call PlayWav() and then while that file was playing I could call PlayWav2() for playing another wave file simultaneously. However, this didn't work -- it just cut off the currently playing wav file just as it did before.
    : :
    : : [CODE]
    : : Unit WavPlay;
    : : {***************************************************************************
    : : ** Unit to play WAV-format files from Turbo Pascal for DOS. **
    : : ** by Steven H Don **
    : : ** **
    : : ** For questions, feel free to e-mail me. **
    : : ** **
    : : ** shd@earthling.net **
    : : ** http://shd.cjb.net **
    : : ** **
    : : ***************************************************************************}
    : :
    : : interface
    : :
    : : {
    : : This is used for transmitting wave-information to the calling programme
    : : }
    : : type WType = record
    : : SampleRate : Word;
    : : Resolution : Byte;
    : : Stereo : Boolean;
    : : Length : LongInt;
    : : end;
    : :
    : : {
    : : The only 2 procedures available to the calling programme.
    : :
    : : ** Playing a Wave-file
    : : All the calling programme has to do is :
    : : PlayWave ('TEST.WAV');
    : : and the appropriate file will be played through any SB-compatible card.
    : : Is this easy or what? I don't think it comes any easier!
    : : On second thought : read the next bit.
    : :
    : : ** Stopping the currently playing Wave-file :
    : : StopWave;
    : : Anyone who has trouble doing that is on the wrong news-group and
    : : probably has an IQ below absolute 0.
    : :
    : : }
    : : procedure PlayWave (FileName : String);
    : : procedure StopWave;
    : :
    : : {Variables available to the calling programme : }
    : : var Playing : Boolean; {True if currently playing a wave-file}
    : : WaveError : Byte; {If an error has occurred, contains the error code}
    : : WaveType : WType; {Contains wave-file information}
    : :
    : : {Different error codes. Note that these are the only things
    : : the programme checks for. Additional errors might produce
    : : unexpected results}
    : : const
    : : FileNotFound = $01;
    : : InvalidWAVE = $02;
    : : NoCard = $03;
    : : NoStereoCard = $04;
    : : No16BitCard = $05;
    : : NoMemory = $06;
    : :
    : : implementation
    : :
    : : {Needed for I/O}
    : : uses Dos, Crt;
    : :
    : : {Definition of chunk-formats}
    : : type
    : : HeaderChunk = record
    : : RIFF : LongInt;
    : : NextChunkSize : LongInt;
    : : end;
    : :
    : : WaveChunk = record
    : : WAVE : LongInt;
    : : end;
    : :
    : : fmtHeader = record
    : : fmt : LongInt;
    : : fmtDataLength : LongInt;
    : : end;
    : :
    : : fmtChunk = record
    : : WaveType : Word;
    : : Channels : Word;
    : : SampleRate : LongInt;
    : : BytesPerSecond : LongInt;
    : : BlockAlignment : Word;
    : : BitResolution : Word;
    : : end;
    : :
    : : DataChunk = record
    : : data : LongInt;
    : : SoundLength : LongInt;
    : : end;
    : :
    : : ThirtyTwoK = array [0..32767] of Byte;
    : :
    : : {Local variables}
    : : var
    : : {Pointer to old IRQ handler}
    : : OldIRQ,
    : : {Pointer to old exit procedure}
    : : OldEP : pointer;
    : : {The SB base address}
    : : Base : Word;
    : : {What kind of card is installed}
    : : Card,
    : : {The IRQ level}
    : : IRQ,
    : : {The DMA channel currently used}
    : : Channel : Byte;
    : : {One DMA channel for 8bit, the other for 16bit}
    : : DMA8, DMA16 : Byte;
    : :
    : : {The sound buffer itself}
    : : SoundBuffer : ^ThirtyTwoK;
    : :
    : : {The amount of bytes already read}
    : : SoundRead,
    : : {If the amount of bytes to be played is not a multiple of 16384 (most
    : : likely, it isn't), this is used to store the difference}
    : : OverHead : LongInt;
    : : {Which buffer is being played}
    : : Upper,
    : : {Should the sound buffer be release?}
    : : FreeBuffer : Boolean;
    : : {A handle to the sound file}
    : : SoundFile : File;
    : : {The chunks that should be read from the file}
    : : Header : HeaderChunk;
    : : Wave : WaveChunk;
    : : fmtH : fmtHeader;
    : : fmt : fmtChunk;
    : : data : DataChunk;
    : :
    : : const
    : : SB8 = 8; SB16 = 16;
    : : {Constants used for programming of the DMA-controller}
    : : DmaChannel : Array [0..7, 1..3] of Byte =
    : : ( ($87, $0, $1), ($83, $2, $3), ($81, $4, $5), ($82, $6, $7),
    : : ($8F, $C0, $C2), ($8B, $C4, $C6), ($89, $C8, $CA), ($8A, $CC, $CE));
    : : DmaPort : Array [0..7, 1..3] of Byte =
    : : ( ($A, $B, $C), ($A, $B, $C), ($A, $B, $C), ($A, $B, $C),
    : : ($D4, $D6, $D8), ($D4, $D6, $D8), ($D4, $D6, $D8), ($D4, $D6, $D8));
    : :
    : : {Chunk-identification values}
    : : rId = $46464952; {RIFF}
    : : wId = $45564157; {WAVE}
    : : fId = $20746D66; {fmt }
    : : dId = $61746164; {data}
    : :
    : : {Writes a value to the DSP-chip on the SB}
    : : procedure WriteDSP (value : byte);
    : : begin
    : : while Port [base + $C] And $80 <> 0 do;
    : : Port [base + $C] := value;
    : : end;
    : :
    : : {Establishes the DSP<->Speaker connection, necessary for older cards.}
    : : function SpeakerOn : byte;
    : : begin
    : : WriteDSP ($D1);
    : : end;
    : :
    : : {Discontinues the DSP<->Speaker connection, necessary for older cards.}
    : : function SpeakerOff : byte;
    : : begin
    : : WriteDSP ($D3);
    : : end;
    : :
    : : {Stops playing the wave-file.}
    : : procedure DMAStop;
    : : begin
    : : {Set general variable to indicate no sound}
    : : Playing := false;
    : :
    : : {Function : D0 Stop 8 bit DMA transfer}
    : : WriteDSP ($D0);
    : : {Function : D5 Stop 16 bit DMA transfer}
    : : WriteDSP ($D5);
    : :
    : : {$I-}
    : : Close (SoundFile); {Close the soundfile}
    : : if IOResult <> 0 then; {Clear Error flag}
    : : {$I+}
    : :
    : : {Free the sound buffer}
    : : if SoundBuffer <> nil then begin
    : : Dispose (SoundBuffer);
    : : SoundBuffer := nil;
    : : end;
    : : end;
    : :
    : : {This procedure sets up the DMA controller for DMA transfer.
    : : Then it programs the DSP chip to receive the transfer.
    : : Finally it initiates the transfer.}
    : : {procedure Playback (SoundSeg, SoundOfs, size : longint);}
    : : procedure Playback (Location : Pointer; Start, Size : Word);
    : : var
    : : SoundSeg, SoundOfs : Word;
    : : page, offset : longint;
    : :
    : : begin
    : : {Calculate offset and segment part of the buffer}
    : : SoundSeg := Seg (Location^);
    : : SoundOfs := Ofs (Location^) + Start;
    : :
    : : {Calculate Offset and Page address of Wave-data}
    : : if fmt.BitResolution = 8 then begin
    : : offset := SoundSeg Shl 4 + SoundOfs;
    : : page := (SoundSeg + SoundOfs shr 4) shr 12;
    : : end else begin
    : : size := size shr 1;
    : : page := (SoundSeg + SoundOfs shr 4) shr 12;
    : : offset := (SoundSeg Shl 3 + SoundOfs shr 1) mod 65536;
    : : end;
    : :
    : : {Decrease size by one. This is necessary because the
    : : DMA controller sends one byte/word more than it is told to}
    : : {Setup DMA Controller for transfer}
    : : Port [DMAPort [Channel, 1]] := 4 or (Channel and 3);
    : : if fmt.BitResolution = 16 then Port [$D8] := 0;
    : : Port [DMAPort [Channel, 3]] := 0;
    : : Port [DMAPort [Channel, 2]] := $48 or (Channel and 3);
    : : Port [DMAChannel [Channel, 2]] := Lo (offset);
    : : Port [DMAChannel [Channel, 2]] := Hi (offset);
    : : Port [DMAChannel [Channel, 1]] := page;
    : : Port [DMAChannel [Channel, 3]] := Lo (size);
    : : Port [DMAChannel [Channel, 3]] := Hi (size);
    : : Port [DMAPort [Channel, 1]] := (Channel and 3);
    : :
    : : {Set DSP}
    : : if Card = SB8 then begin
    : : {Set up 8-bit card, sorry no stereo SBPRO support}
    : : WriteDSP ($14);
    : : end else begin
    : : {Set up 16-bit card}
    : : if fmt.BitResolution = 8 then begin
    : : {8-Bit file}
    : : WriteDSP ($C0);
    : : if fmt.Channels = 1 then WriteDSP ($00); {Mono}
    : : if fmt.Channels = 2 then WriteDSP ($20); {Stereo}
    : : end else begin
    : : {16-Bit file
    : : Perhaps this also needs to be changed}
    : : WriteDSP ($B0);
    : : if fmt.Channels = 1 then WriteDSP ($10); {Mono}
    : : if fmt.Channels = 2 then WriteDSP ($30); {Stereo}
    : : end;
    : : end;
    : :
    : : {Send the size of the transfer to the SB}
    : : WriteDSP (Lo (size));
    : : WriteDSP (Hi (size));
    : :
    : : {Set global variable to indicate playing sound}
    : : Playing := true;
    : : end;
    : :
    : : (continued...)
    : : [/CODE]
    : :
    : hi there,
    : you forgot that there is only a ubique sound card on board so you cannot do what you are trying to do.
    : It is just like trying to print a document on your printer when another one is being printed.
    : it makes no sense .But try this : playing part of the first wave the stopping it and paying the other one.
    : by the way ,do you even understand how the WAV player works,how wav is being decoded?
    :
    :
    Hi !

    You should program this with API's and multithreading. ;)
  • : :
    : : : Hi!
    : : :
    : : : I'm trying to add sound effects to a game I've programmed in Borland Pascal 7.0. I'v found the below code, which is really easy to use for playing wav files. So far so good. However, whenever I play a wav file, it cuts off the sound currently playing. Is there any way to modify this code, so that I have multiple tracks for playing wav files simultaneously? I tried just making a second unit (WavPlay2) which was just a copy of this unit with all the variables and procedures having added "2" at the end. I hoped that in that way I could call PlayWav() and then while that file was playing I could call PlayWav2() for playing another wave file simultaneously. However, this didn't work -- it just cut off the currently playing wav file just as it did before.
    : : :
    : : : [CODE]
    : : : Unit WavPlay;
    : : : {***************************************************************************
    : : : ** Unit to play WAV-format files from Turbo Pascal for DOS. **
    : : : ** by Steven H Don **
    : : : ** **
    : : : ** For questions, feel free to e-mail me. **
    : : : ** **
    : : : ** shd@earthling.net **
    : : : ** http://shd.cjb.net **
    : : : ** **
    : : : ***************************************************************************}
    : : :
    : : : interface
    : : :
    : : : {
    : : : This is used for transmitting wave-information to the calling programme
    : : : }
    : : : type WType = record
    : : : SampleRate : Word;
    : : : Resolution : Byte;
    : : : Stereo : Boolean;
    : : : Length : LongInt;
    : : : end;
    : : :
    : : : {
    : : : The only 2 procedures available to the calling programme.
    : : :
    : : : ** Playing a Wave-file
    : : : All the calling programme has to do is :
    : : : PlayWave ('TEST.WAV');
    : : : and the appropriate file will be played through any SB-compatible card.
    : : : Is this easy or what? I don't think it comes any easier!
    : : : On second thought : read the next bit.
    : : :
    : : : ** Stopping the currently playing Wave-file :
    : : : StopWave;
    : : : Anyone who has trouble doing that is on the wrong news-group and
    : : : probably has an IQ below absolute 0.
    : : :
    : : : }
    : : : procedure PlayWave (FileName : String);
    : : : procedure StopWave;
    : : :
    : : : {Variables available to the calling programme : }
    : : : var Playing : Boolean; {True if currently playing a wave-file}
    : : : WaveError : Byte; {If an error has occurred, contains the error code}
    : : : WaveType : WType; {Contains wave-file information}
    : : :
    : : : {Different error codes. Note that these are the only things
    : : : the programme checks for. Additional errors might produce
    : : : unexpected results}
    : : : const
    : : : FileNotFound = $01;
    : : : InvalidWAVE = $02;
    : : : NoCard = $03;
    : : : NoStereoCard = $04;
    : : : No16BitCard = $05;
    : : : NoMemory = $06;
    : : :
    : : : implementation
    : : :
    : : : {Needed for I/O}
    : : : uses Dos, Crt;
    : : :
    : : : {Definition of chunk-formats}
    : : : type
    : : : HeaderChunk = record
    : : : RIFF : LongInt;
    : : : NextChunkSize : LongInt;
    : : : end;
    : : :
    : : : WaveChunk = record
    : : : WAVE : LongInt;
    : : : end;
    : : :
    : : : fmtHeader = record
    : : : fmt : LongInt;
    : : : fmtDataLength : LongInt;
    : : : end;
    : : :
    : : : fmtChunk = record
    : : : WaveType : Word;
    : : : Channels : Word;
    : : : SampleRate : LongInt;
    : : : BytesPerSecond : LongInt;
    : : : BlockAlignment : Word;
    : : : BitResolution : Word;
    : : : end;
    : : :
    : : : DataChunk = record
    : : : data : LongInt;
    : : : SoundLength : LongInt;
    : : : end;
    : : :
    : : : ThirtyTwoK = array [0..32767] of Byte;
    : : :
    : : : {Local variables}
    : : : var
    : : : {Pointer to old IRQ handler}
    : : : OldIRQ,
    : : : {Pointer to old exit procedure}
    : : : OldEP : pointer;
    : : : {The SB base address}
    : : : Base : Word;
    : : : {What kind of card is installed}
    : : : Card,
    : : : {The IRQ level}
    : : : IRQ,
    : : : {The DMA channel currently used}
    : : : Channel : Byte;
    : : : {One DMA channel for 8bit, the other for 16bit}
    : : : DMA8, DMA16 : Byte;
    : : :
    : : : {The sound buffer itself}
    : : : SoundBuffer : ^ThirtyTwoK;
    : : :
    : : : {The amount of bytes already read}
    : : : SoundRead,
    : : : {If the amount of bytes to be played is not a multiple of 16384 (most
    : : : likely, it isn't), this is used to store the difference}
    : : : OverHead : LongInt;
    : : : {Which buffer is being played}
    : : : Upper,
    : : : {Should the sound buffer be release?}
    : : : FreeBuffer : Boolean;
    : : : {A handle to the sound file}
    : : : SoundFile : File;
    : : : {The chunks that should be read from the file}
    : : : Header : HeaderChunk;
    : : : Wave : WaveChunk;
    : : : fmtH : fmtHeader;
    : : : fmt : fmtChunk;
    : : : data : DataChunk;
    : : :
    : : : const
    : : : SB8 = 8; SB16 = 16;
    : : : {Constants used for programming of the DMA-controller}
    : : : DmaChannel : Array [0..7, 1..3] of Byte =
    : : : ( ($87, $0, $1), ($83, $2, $3), ($81, $4, $5), ($82, $6, $7),
    : : : ($8F, $C0, $C2), ($8B, $C4, $C6), ($89, $C8, $CA), ($8A, $CC, $CE));
    : : : DmaPort : Array [0..7, 1..3] of Byte =
    : : : ( ($A, $B, $C), ($A, $B, $C), ($A, $B, $C), ($A, $B, $C),
    : : : ($D4, $D6, $D8), ($D4, $D6, $D8), ($D4, $D6, $D8), ($D4, $D6, $D8));
    : : :
    : : : {Chunk-identification values}
    : : : rId = $46464952; {RIFF}
    : : : wId = $45564157; {WAVE}
    : : : fId = $20746D66; {fmt }
    : : : dId = $61746164; {data}
    : : :
    : : : {Writes a value to the DSP-chip on the SB}
    : : : procedure WriteDSP (value : byte);
    : : : begin
    : : : while Port [base + $C] And $80 <> 0 do;
    : : : Port [base + $C] := value;
    : : : end;
    : : :
    : : : {Establishes the DSP<->Speaker connection, necessary for older cards.}
    : : : function SpeakerOn : byte;
    : : : begin
    : : : WriteDSP ($D1);
    : : : end;
    : : :
    : : : {Discontinues the DSP<->Speaker connection, necessary for older cards.}
    : : : function SpeakerOff : byte;
    : : : begin
    : : : WriteDSP ($D3);
    : : : end;
    : : :
    : : : {Stops playing the wave-file.}
    : : : procedure DMAStop;
    : : : begin
    : : : {Set general variable to indicate no sound}
    : : : Playing := false;
    : : :
    : : : {Function : D0 Stop 8 bit DMA transfer}
    : : : WriteDSP ($D0);
    : : : {Function : D5 Stop 16 bit DMA transfer}
    : : : WriteDSP ($D5);
    : : :
    : : : {$I-}
    : : : Close (SoundFile); {Close the soundfile}
    : : : if IOResult <> 0 then; {Clear Error flag}
    : : : {$I+}
    : : :
    : : : {Free the sound buffer}
    : : : if SoundBuffer <> nil then begin
    : : : Dispose (SoundBuffer);
    : : : SoundBuffer := nil;
    : : : end;
    : : : end;
    : : :
    : : : {This procedure sets up the DMA controller for DMA transfer.
    : : : Then it programs the DSP chip to receive the transfer.
    : : : Finally it initiates the transfer.}
    : : : {procedure Playback (SoundSeg, SoundOfs, size : longint);}
    : : : procedure Playback (Location : Pointer; Start, Size : Word);
    : : : var
    : : : SoundSeg, SoundOfs : Word;
    : : : page, offset : longint;
    : : :
    : : : begin
    : : : {Calculate offset and segment part of the buffer}
    : : : SoundSeg := Seg (Location^);
    : : : SoundOfs := Ofs (Location^) + Start;
    : : :
    : : : {Calculate Offset and Page address of Wave-data}
    : : : if fmt.BitResolution = 8 then begin
    : : : offset := SoundSeg Shl 4 + SoundOfs;
    : : : page := (SoundSeg + SoundOfs shr 4) shr 12;
    : : : end else begin
    : : : size := size shr 1;
    : : : page := (SoundSeg + SoundOfs shr 4) shr 12;
    : : : offset := (SoundSeg Shl 3 + SoundOfs shr 1) mod 65536;
    : : : end;
    : : :
    : : : {Decrease size by one. This is necessary because the
    : : : DMA controller sends one byte/word more than it is told to}
    : : : {Setup DMA Controller for transfer}
    : : : Port [DMAPort [Channel, 1]] := 4 or (Channel and 3);
    : : : if fmt.BitResolution = 16 then Port [$D8] := 0;
    : : : Port [DMAPort [Channel, 3]] := 0;
    : : : Port [DMAPort [Channel, 2]] := $48 or (Channel and 3);
    : : : Port [DMAChannel [Channel, 2]] := Lo (offset);
    : : : Port [DMAChannel [Channel, 2]] := Hi (offset);
    : : : Port [DMAChannel [Channel, 1]] := page;
    : : : Port [DMAChannel [Channel, 3]] := Lo (size);
    : : : Port [DMAChannel [Channel, 3]] := Hi (size);
    : : : Port [DMAPort [Channel, 1]] := (Channel and 3);
    : : :
    : : : {Set DSP}
    : : : if Card = SB8 then begin
    : : : {Set up 8-bit card, sorry no stereo SBPRO support}
    : : : WriteDSP ($14);
    : : : end else begin
    : : : {Set up 16-bit card}
    : : : if fmt.BitResolution = 8 then begin
    : : : {8-Bit file}
    : : : WriteDSP ($C0);
    : : : if fmt.Channels = 1 then WriteDSP ($00); {Mono}
    : : : if fmt.Channels = 2 then WriteDSP ($20); {Stereo}
    : : : end else begin
    : : : {16-Bit file
    : : : Perhaps this also needs to be changed}
    : : : WriteDSP ($B0);
    : : : if fmt.Channels = 1 then WriteDSP ($10); {Mono}
    : : : if fmt.Channels = 2 then WriteDSP ($30); {Stereo}
    : : : end;
    : : : end;
    : : :
    : : : {Send the size of the transfer to the SB}
    : : : WriteDSP (Lo (size));
    : : : WriteDSP (Hi (size));
    : : :
    : : : {Set global variable to indicate playing sound}
    : : : Playing := true;
    : : : end;
    : : :
    : : : (continued...)
    : : : [/CODE]
    : : :
    : : hi there,
    : : you forgot that there is only a ubique sound card on board so you cannot do what you are trying to do.
    : : It is just like trying to print a document on your printer when another one is being printed.
    : : it makes no sense .But try this : playing part of the first wave the stopping it and paying the other one.
    : : by the way ,do you even understand how the WAV player works,how wav is being decoded?
    : :
    : :
    : Hi !
    :
    : You should program this with API's and multithreading. ;)
    :
    BP 7 is for DOS, so the multithreading support is very limited. As for the API's, DOS doesn't provide any multimedia API's, only file API's.
  • I understand that you can't ACTUALLY play two wave files simultaneously -- what I was thinking was allowing the code to switch back and forth between multiple files, playing part of each file, thus effectively playing the files simultaneously. However, I've since come up with a new way to fix my problem of new wave files cutting off the currently playing one. I've just divided the sound effects into a hierarchy, so that a currently playing wave file can only be cut off by a sound effect that is above it in the hierarchy.

    Thanks for all the replies anyway! :-)
  • [b][red]This message was edited by Alcatiz at 2006-10-17 11:16:43[/red][/b][hr]
    : : Hi !
    : :
    : : You should program this with API's and multithreading. ;)
    : :
    : BP 7 is for DOS, so the multithreading support is very limited. As for the API's, DOS doesn't provide any multimedia API's, only file API's.
    :
    Sorry, in PP2005's last threads I saw he used Virtual Pascal.
    I'm confused.


  • : : : Hi !
    : : :
    : : : You should program this with API's and multithreading. ;)
    : : :
    : : BP 7 is for DOS, so the multithreading support is very limited. As for the API's, DOS doesn't provide any multimedia API's, only file API's.
    : :
    : Sorry, in PP2005's last threads I saw he used Virtual Pascal.
    :
    Quote from his first post in this thread: "I'm trying to add sound effects to a game I've programmed in Borland Pascal 7.0"
  • : Hi!
    :
    : I'm trying to add sound effects to a game I've programmed in Borland Pascal 7.0. I'v found the below code, which is really easy to use for playing wav files. So far so good. However, whenever I play a wav file, it cuts off the sound currently playing. Is there any way to modify this code, so that I have multiple tracks for playing wav files simultaneously? I tried just making a second unit (WavPlay2) which was just a copy of this unit with all the variables and procedures having added "2" at the end. I hoped that in that way I could call PlayWav() and then while that file was playing I could call PlayWav2() for playing another wave file simultaneously. However, this didn't work -- it just cut off the currently playing wav file just as it did before.
    :

    Yeah. I've done this. let me look here...

    Here we go:
    http://www.programmersheaven.com/download/1157/download.aspx

    This unit will allow you to play multiple samples at once. I believe it just mixes the samples before it outputs the samples to the speakers. Anyways, it's worked for me. Enjoy ;)

    Phat Nat
  • : Yeah. I've done this. let me look here...
    :
    : Here we go:
    : http://www.programmersheaven.com/download/1157/download.aspx
    :
    : This unit will allow you to play multiple samples at once. I believe it just mixes the samples before it outputs the samples to the speakers. Anyways, it's worked for me. Enjoy ;)
    :
    : Phat Nat


    This seems pretty close to what I'm looking for. However, as far as I can tell, when you use this unit you have to load the 8 samples you want to use when initializing. My game uses a lot more than 8 different samples during play. I've tried fiddling around with the unit a bit, but I couldn't get it to load different samples as I needed them while running my game. Do you know if this is possible with this unit?

    What I is was trying to accomplish with this unit was being able to have 8 'tracks' that I could load sounds to and play from. I basically created a procedure called PlaySound(TrackNumber : Byte; SoundFile : String) that called some procedures and functions in the SMIX unit:

    [CODE]
    PROCEDURE PlaySound(Const TrackNumber : Byte; Const SoundFile : String);
    BEGIN
    IF SoundPlaying(TrackNumber) THEN StopSound(TrackNumber);
    FreeSound(Sound[TrackNumber]);
    LoadSound(Sound[TrackNumber], 'SOUNDS/' + SoundFile + '.WAV');
    StartSound(Sound[TrackNumber], TrackNumber, False);
    END;
    [/CODE]

    I got my game to compile and run, but as soon as I do something that should play a sound it crashes, saying that the program has made an 'illegal action' (translated from danish)...
  • [b][red]This message was edited by PP2005 at 2006-10-17 4:14:57[/red][/b][hr]
    [b][red]This message was edited by PP2005 at 2006-10-17 2:49:50[/red][/b][hr]
    : : Yeah. I've done this. let me look here...
    : :
    : : Here we go:
    : : http://www.programmersheaven.com/download/1157/download.aspx
    : :
    : : This unit will allow you to play multiple samples at once. I believe it just mixes the samples before it outputs the samples to the speakers. Anyways, it's worked for me. Enjoy ;)
    : :
    : : Phat Nat
    :
    :
    : This seems pretty close to what I'm looking for. However, as far as I can tell, when you use this unit you have to load the 8 samples you want to use when initializing. My game uses a lot more than 8 different samples during play. I've tried fiddling around with the unit a bit, but I couldn't get it to load different samples as I needed them while running my game. Do you know if this is possible with this unit?
    :
    : What I is was trying to accomplish with this unit was being able to have 8 'tracks' that I could load sounds to and play from. I basically created a procedure called PlaySound(TrackNumber : Byte; SoundFile : String) that called some procedures and functions in the SMIX unit:
    :
    : [CODE]
    : PROCEDURE PlaySound(Const TrackNumber : Byte; Const SoundFile : String);
    : BEGIN
    : IF SoundPlaying(TrackNumber) THEN StopSound(TrackNumber);
    : FreeSound(Sound[TrackNumber]);
    : LoadSound(Sound[TrackNumber], 'SOUNDS/' + SoundFile + '.WAV');
    : StartSound(Sound[TrackNumber], TrackNumber, False);
    : END;
    : [/CODE]
    :
    : I got my game to compile and run, but as soon as I do something that should play a sound it crashes, saying that the program has made an 'illegal action' (translated from danish)...
    :



    Nevermind. I got it working! :-)

    But the sound quality is very bad. I'll try to get it better...

    EDIT: I converted my WAVs to RAWs and now it all plays beautifully. Man, this unit is great! Thanks a lot for pointing me to it! :-)

    Do you by any chance know of a good unit for playing MIDIs? The best one I've been able to find is a german unit, which plays the MIDIs so that they sound reasonably close to what they sound like when played in Windows. However, the volume control of the unit has not effect (the MIDIs are played too loud for use as background music) and when I run my program in a pure DOS environment, the MIDIs don't play at all.
  • :
    : Nevermind. I got it working! :-)
    :
    : But the sound quality is very bad. I'll try to get it better...
    :
    : EDIT: I converted my WAVs to RAWs and now it all plays beautifully. Man, this unit is great! Thanks a lot for pointing me to it! :-)
    :
    : Do you by any chance know of a good unit for playing MIDIs? The best one I've been able to find is a german unit, which plays the MIDIs so that they sound reasonably close to what they sound like when played in Windows. However, the volume control of the unit has not effect (the MIDIs are played too loud for use as background music) and when I run my program in a pure DOS environment, the MIDIs don't play at all.
    :

    Sorry, never used midis. Check the board filelist though... ther may be something there.

    Phat Nat

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories