SWAGOLX.EXE (c) 1993 GDSOFT ALL RIGHTS RESERVED 00016 SOUNDBLASTER/ADLIB ROUTINES 1 05-28-9313:57ALL SWAG SUPPORT TEAM ALLNOTES.PAS IMPORT 25 {π> Anyone out there ever bothered to fing out what numbers make which note,π> eg. does any know if Sound(3000) makes an A, a C, D#, or what? I'd likeπ> to know as many as possible, hopefully With the middle C on a piano asπ> one of them.π}ππConstπ Notes : Array[1..96] Of Word =π { C C#,D- D D#,E- E F F#,G- G G#,A- A A#,B- B }π (0033, 0035, 0037, 0039, 0041, 0044, 0046, 0049, 0052, 0055, 0058, 0062,π 0065, 0069, 0073, 0078, 0082, 0087, 0093, 0098, 0104, 0110, 0117, 0123,π 0131, 0139, 0147, 0156, 0165, 0175, 0185, 0196, 0208, 0220, 0233, 0247,π 0262, 0277, 0294, 0311, 0330, 0349, 0370, 0392, 0415, 0440, 0466, 0494,π 0523, 0554, 0587, 0622, 0659, 0698, 0740, 0784, 0831, 0880, 0932, 0987,π 1047, 1109, 1175, 1245, 1329, 1397, 1480, 1568, 1661, 1760, 1865, 1976,π 2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951,π 4186, 4435, 4699, 4978, 5274, 5588, 5920, 6272, 6645, 7040, 7459, 7902);ππ{πEach line represents one octave, starting With octave 0. Middle C is 523Hz andπMiddle A is 440 (middle A is what all other note calculations are besed on;πeach note it the 12th root of 2 times the previous one.) You should be able toπarrange the Array into two dimensions if you want to access it using an octaveπand note #.π}ππ{πHere are the notes..ππ C0 16.35 C2 65.41 C4 261.63 C6 1046.50π C#0 17.32 C#2 69.30 C#4 277.18 C#6 1108.73π D0 18.35 D2 73.42 D4 293.66 D6 1174.66π D#0 19.45 D#2 77.78 D#4 311.13 D#6 1244.51π E0 20.60 E2 82.41 E4 329.63 E6 1328.51π F0 21.83 F2 87.31 F4 349.23 F6 1396.91π F#0 23.12 F#2 92.50 F#4 369.99 F#6 1479.98π G0 24.50 G2 98.00 G4 392.00 G6 1567.98π G#0 25.96 G#2 103.83 G#4 415.30 G#6 1661.22π A0 27.50 A2 110.00 A4 440.00 A6 1760.00π A#0 29.14 A#2 116.54 A#4 466.16 A#6 1864.66π B0 30.87 B2 123.47 B4 493.88 B6 1975.53π C1 32.70 C3 130.81 C5 523.25 C7 2093.00π C#1 34.65 C#3 138.59 C#5 554.37 C#7 2217.46π D1 36.71 D3 146.83 D5 587.33 D7 2349.32π D#1 38.89 D#3 155.56 D#5 622.25 D#7 2489.02π E1 41.20 E3 164.81 E5 659.26 E7 2637.02π F1 43.65 F3 174.61 F5 698.46 F7 2793.83π F#1 46.25 F#3 185.00 F#5 739.99 F#7 2959.96π G1 49.00 G3 196.00 G5 783.99 G7 3135.96π G#1 51.91 G#3 207.65 G#5 830.61 G#7 3322.44π A1 55.00 A3 220.00 A5 880.00 A7 3520.00π A#1 58.27 A#3 233.08 A#5 932.33 A#7 3729.31π B1 61.74 B3 246.94 B5 987.77 B7 3951.07π} C8 4186.01πππ 2 05-28-9313:57ALL SWAG SUPPORT TEAM DETCADLB.PAS IMPORT 13 Usesπ Crt; (* Crt Needed For Delay Routine *)ππFunction AdlibCard : Boolean;π (* Routine to determine if a Adlib compatible card is installed *)πVarπ Val1,Val2 : Byte;πbeginπ Port[$388] := 4; (* Write 60h to register 4 *)π Delay(3); (* Which resets timer 1 and 2 *)π Port[$389] := $60;π Delay(23);π Port[$388] := 4; (* Write 80h to register 4 *)π Delay(3); (* Which enables interrupts *)π Port[$389] := $80;π Delay(23);π Val1 := Port[$388]; (* Read status Byte *)π Port[$388] := 2; (* Write ffh to register 2 *)π Delay(3); (* Which is also Timer 1 *)π Port[$389] := $FF;π Delay(23);π Port[$388] := 4; (* Write 21h to register 4 *)π Delay(3); (* Which will Start Timer 1 *)π Port[$389] := $21;π Delay(85); (* wait 85 microseconds *)π Val2 := Port[$388]; (* read status Byte *)π Port[$388] := 4; (* Repeat the first to steps *)π Delay(3); (* Which will reset both Timers *)π Port[$389] := $60;π Delay(23);π Port[$388] := 4;π Delay(3);π Port[$389] := $80; (* Now test the status Bytes saved *)π If ((Val1 And $e0) = 0) And ((Val2 And $e0) = $c0) Thenπ AdlibCard := True (* Card was found *)π Elseπ AdlibCard := False; (* No Card Installed *)πend;ππbeginπ ClrScr; (* Clear the Screen *)π Write(' Adlib Card '); (* Prepare Response *)π If AdlibCard Thenπ Writeln( 'Found!') (* There is one *)π Elseπ Writeln('Not Found!'); (* Not! *)πend.π 3 05-28-9313:57ALL SWAG SUPPORT TEAM MODMUSIC.PAS IMPORT 30 MOD File DEMOπππ ST> I do, however, have the MOD File structures in a Text File.π ST> NetMail if you want them.ππ EW> Hey.. Could you post them here if their not too long?π EW> All I have For MOD Files is a Program (so so) that plays themπ EW> through the PCSpeaker, and it's *ALL* in Asm, and I'd loveπ EW> to be able to convert at least the File reading to pascal,ππ The MOD File Format is not overly Complicated in itself, but the musicπ encoded therein is very intricate, since the notes use non-standardπ notations For the frequency, and the effects For each note are veryπ involved. I can, however, post a good skeleton For the File structure,π but if you want the effects commands, we'll have to go to NetMail,π since it would not be in Pascal.ππType SongNameT = String[20]; {This is the first structure in the File, theπ full name of the song in the File}π SampleT = Record {This structure is Repeated 31 times, andπ describes each instrument}π Name : String[22];π Len : Word; {Length of the sample wave pattern, which isπ Near the end of the File. This number isπ the number of Words, use MUL 2 For Bytes}π FineTune : Byte; {0-7 = 0 to +7, 8-F = -8 to -1 offset fromπ normal played notes. Useful For off-keyπ instruments}π Volume : Byte; {0-64 Normal volume of instrument}π RepeatAt : Word; {offset in Words of the start of the patternπ Repeat For long notes.}π RepeatLn : Word; {Length in Words of the Repeated part of theπ sample pattern}π end;ππ VoiceT = Record {This structure is not in the MOD File itself, butπ should help in organizing all of the voice'sπ Charicteristics}π Sample : Byte; {0-31 Which instrument sample to play}π note : Word; {12 bits Which note. Non-standard strange numbers}π Effect : Byte; {0-F Effect to use on note}π EffectC : Byte; {00-FF Control Variable to effect}π end;ππ SongDataT = Record {This Record, at offset 950, contains inFormationπ about the song music itself}π SongLength : Byte; {1-128 Number of patterns (not wave) ofπ sets of musical notes}π Fill1 : Byte; {Set to 127}π Patterns : Array[0..127] of Byte; {0-63 Outline of song}π {Tells which score to play where. Number ofπ patterns is the highest number here}π Initials : String[4]; {"M.K.","FLT4", or "FLT8"}π end;ππ PatternDataT = Array[1..4] of Byte; {This structure is Repeatedπ four times For each note in the score (4 voices,π 4 Bytes each}ππ {After this the wave patterns For the samples are placed}ππVar Voice : Array[1.. 4] of VoiceT; {Four voices}π Sample : Array[1..31] of SampleT; {31 samples}ππProcedure ParseData (Patt : PatternDataT, VoiceNum : Byte);π{Stuffs voice With pattern data beFore playing}πbeginπ Voice[VoiceNum].Sample := (Patt[1] mod 16) shl 4 + (Patt[3] mod 16);π Voice[VoiceNum].note := (Patt[2] shl 4) + (Patt[2] div 16);π Voice[VoiceNum].Effect := (Patt[3] div 16;π Voice[VoiceNum].EffectC := Patt[4];π end;ππAnyway, this should help explain how to do something With the File.πif you need inFormation on what the numbers For the notes are or howπto interprit the effects, send NetMail.π 4 05-28-9313:57ALL SWAG SUPPORT TEAM MUSCNOTE.PAS IMPORT 21 {π> Does anyone have a "musical scale" of all the values With the Soundπ> Function? A friend is writing a "happy birthday" Program and wants toπ> get a list of all the notes without actually testing them (G)ππ{ Here's a handy Unit that takes a lot of work out of playing music. }π{ I think it originally came from this echo. }ππUnit Music;πInterfaceπUses Crt;πConstπ e_note = 15; { Eighth Note }π q_note = 30; { Quarter Note }π h_note = 60; { Half Note }π dh_note = 90; { Dotted Half Note }π w_note = 120; { Whole Note }π R = 0; { Rest }π C = 1; { C }π Cs = 2; { C Sharp }π Db = 2; { D Flat }π D = 3; { D }π Ds = 4; { D Sharp }π Eb = 4; { E Flat }π E = 5; { Etc... }π F = 6;π Fs = 7;π Gb = 7;π G = 8;π Gs = 9;π Ab = 9;π A = 10;π As = 11;π Bb = 11;π B = 12;ππProcedure PlayTone(Octave : Byte; Note : Byte; Duration : Word);πProcedure ToneOn(Octave : Byte; Note : Byte);ππImplementationππVarπ Oct_Val : Array [0..8] Of Real;π Freq_Val : Array [C..B] Of Real;ππProcedure Set_Frequencies;πVar N : Byte;πbeginπ Freq_Val[1] := 1;π For N := 2 To 12 Doπ Freq_Val[N] := Freq_Val[N-1] * 1.0594630944;π Oct_Val[0] := 32.70319566;π For N := 1 To 8 Doπ Oct_Val[N] := Oct_Val[N-1] * 2;πend;ππProcedure PlayTone(Octave : Byte;π Note : Byte;π Duration : Word);πbeginπ If Note = R Thenπ NoSoundπ Elseπ Sound(Round(Oct_Val[Octave] * Freq_Val[Note]));π Delay(Duration*8);π NoSound;πend;ππProcedure ToneOn(Octave : Byte;π Note : Byte);πbeginπ If Note = R Then NoSoundπ Else Sound(Round(Oct_Val[Octave] * Freq_Val[Note]));ππend;ππbeginπSet_Frequencies;πNoSound;πend.πππ{πSomeone else: Here they are:ππConstπ C = 2093;π C# = 2217;π D = 2349;π D# = 2489;π E = 2637;π F = 2794;π F# = 2960;π G = 3136;π G# = 3322;π A = 3520;π A# = 3729;π H = 3951;ππThe next C is 2*2093, the C below is 2093 div 2 etc. pp.π}ππ{ππHere's an octive:π C = 262;π CSHARP = 277;π D = 294;π DSHARP = 311;π E = 330;π F = 349;π FSHARP = 370;π G = 392;π GSHARP = 415;π A = 440;π ASHARP = 466;π B = 494;π CC = 523;π} 5 05-28-9313:57ALL SWAG SUPPORT TEAM PIANO.PAS IMPORT 33 {πBILL BUCHANANππ> I'm just learning Pascal, and I was 1dering if it's possible 2 playπ> music in Pascal? if so... how?ππHere's a little Program that allows you to play the "PIANO" on your keyboard.πNo Soundcard needed or anything like that. This may give you a small ideaπon how to create your own Sounds ...ππ}ππProgram Music; {by Judy Birmingham, 9/18/92}πUsesπ Crt;ππConstπ {-------------------------------------------------------------------}π {These values will Vary by the song you choose}π {I wish I could have made these Variables instead of Constants,π but I seemed to be locked into using Const, because they defineπ Array sizes in the Types declared below.}ππ TotalLinesInSong = 4; {Number of lines in song}π MaxNotesInPhrase = 9; {Max number of notes in any line}π BeatNote = 4; {Bottom number in Time Signature}π {Handles cut time (2/2), 6/8 etc.}π Tempo = 160; {Number of beats per minute}π {-------------------------------------------------------------------}π {Note frequencies}π R = 0; {Rest = frequency of 0 : silence}π C = 260; {Frequency of middle c }π CC = 277; {Double letter indicates a sharp}π D = 294;π DD = 311;π E = 330;π F = 349;π FF = 370;π G = 392;π GG = 415;π A = 440;π AA = 466;π B = 494;ππ {Note durations}π Q = 1 * (BeatNote/4); {Quarter note}π I = 0.5 * (BeatNote/4); {Eighth note}π H = 2 * (BeatNote/4); {Half note}π W = 4 * (BeatNote/4); {Whole note}π S = 0.25 * (BeatNote/4); {Sixteenth note}π DQ = 1.5 * (BeatNote/4); {Dotted quarter}π DI = 0.75 * (BeatNote/4); {Dotted eighth}π DH = 3 * (BeatNote/4); {Dotted half}π DS = 0.375 * (BeatNote/4); {Dotted sixteenth}ππ Beat = 60000/Tempo; {Duration of 1 beat in millisecs}ππTypeπ IValues = Array [1..MaxNotesInPhrase] of Integer;π RValues = Array [1..MaxNotesInPhrase] of Real;π Phrase = Recordπ Lyric : String;π Notes : IValues; {Array of note frequencies}π Octave : IValues; {Array of note octaves}π Rhythm : RValues; {Array of note durations}π end;π Song = Array [1..TotalLinesInSong] of Phrase;ππ {Sample song}πConstπ RowRow : Song = (π (Lyric : 'Row Row Row Your Boat';π NOTES : (C,C,C,D,E,R,0,0,0);π OCTAVE : (1,1,1,1,1,1,0,0,0);π RHYTHM : (DQ,DQ,Q,I,Q,I,R,0,0)π ),ππ (Lyric : 'Gently down the stream';π NOTES : (E,D,E,F,G,R,0,0,0);π OCTAVE : (1,1,1,1,1,1,0,0,0);π RHYTHM : (Q,I,Q,I,DQ,DQ,0,0,0)π ),ππ (Lyric : 'Merrily merrily merrily merrily';π NOTES : (C,C,G,G,E,E,C,C,0 );π OCTAVE : (2,2,1,1,1,1,1,1,0 );π RHYTHM : (Q,I,Q,I,Q,I,Q,I,0 )π ),ππ (Lyric : 'Life is but a dream.';π NOTES : (G,F,E,D,C,R,0,0,0 );π OCTAVE : (1,1,1,1,1,1,0,0,0 );π RHYTHM : (Q,I,Q,I,H,Q,0,0,0 )π ));ππProcedure LYRICS(THE_WORDS : String);πbeginπ Writeln(THE_WORDS);πend;ππProcedure PLAYNOTE (NOTE, OCT: Integer; DURATION : Real);πbeginπ Sound (NOTE * OCT);π Delay (Round(BEAT * DURATION));π NoSound;πend;ππProcedure PLAYPHRASE(N : Integer; NOTES, OCTAVE : IValues; RHYTHM : RValues);πVarπ INDEX : Integer;πbeginπ For INDEX := 1 to N doπ PLAYNOTE (NOTES[INDEX], OCTAVE[INDEX], RHYTHM[INDEX]);πend;ππProcedure PLAYSONG (Title : String; Tune : Song);πVarπ Counter : Integer;πbeginπ ClrScr;π GotoXY(11,3);π Writeln (Title);π Window (10,5,70,19);π ClrScr;π For counter := 1 to TotalLinesInSong doπ beginπ LYRICS(Tune[counter].Lyric);π PLAYPHRASE(MaxNotesInPhrase, Tune[counter].Notes,π Tune[counter].Octave, Tune[counter].Rhythm);π end;πend;ππbeginπ ClrScr;π PlaySong('"Row Row Row Your Boat "', RowRow);πend.π 6 05-28-9313:57ALL SWAG SUPPORT TEAM PLAYMUSC.PAS IMPORT 16 { Here is a Unit that plays music. It came out of this echo recently. }πππUnit Music;ππInterfaceππUsesπ Crt;πConstπ e_note = 15; { Eighth Note }π q_note = 30; { Quarter Note }π h_note = 60; { Half Note }π dh_note = 90; { Dotted Half Note }π w_note = 120; { Whole Note }π R = 0; { Rest }π C = 1; { C }π Cs = 2; { C Sharp }π Db = 2; { D Flat }π D = 3; { D }π Ds = 4; { D Sharp }π Eb = 4; { E Flat }π E = 5; { Etc... }π F = 6;π Fs = 7;π Gb = 7;π G = 8;π Gs = 9;π Ab = 9;π A = 10;π As = 11;π Bb = 11;π B = 12;ππProcedure PlayTone(Octave : Byte; Note : Byte; Duration : Word);πProcedure ToneOn(Octave : Byte; Note : Byte);ππImplementationππVarπ Oct_Val : Array [0..8] Of Real;π Freq_Val : Array [C..B] Of Real;ππProcedure Set_Frequencies;πVarπ N : Byte;πbeginπ Freq_Val[1] := 1;π For N := 2 To 12 Doπ Freq_Val[N] := Freq_Val[N-1] * 1.0594630944;π Oct_Val[0] := 32.70319566;π For N := 1 To 8 Doπ Oct_Val[N] := Oct_Val[N-1] * 2;πend;ππProcedure PlayTone(Octave : Byte; Note : Byte; Duration : Word);πbeginπ If Note = R Thenπ NoSoundπ Elseπ Sound(Round(Oct_Val[Octave] * Freq_Val[Note]));π Delay(Duration*8);π NoSound;πend;ππProcedure ToneOn(Octave : Byte; Note : Byte);πbeginπ If Note = R Thenπ NoSoundπ Elseπ Sound(Round(Oct_Val[Octave] * Freq_Val[Note]));πend;ππbeginπ Set_Frequencies;π NoSound;πend.ππ{π This does not include the actual values of the tones, but it is stillπvery helpful (more so than if you had the actual freqencies). If you stillπwant the tones, just substitute the value For the tone into the Proceduresπthat play the tone.π} 7 05-28-9313:57ALL SWAG SUPPORT TEAM SB-VOC.PAS IMPORT 28 { JR> Well, Can you post the sorce code on how to play to the Sound blasterπ JR> Byte by Byte? I could probley find out after that!π JR> JamesππSure thing... this Program will load a File into memory then play it a Byteπat a time... It should be pretty self-explanatory.π}ππProgram rawdemo;ππUses Crt;ππ{$I-}ππConstπ fname = 'NELLAF.VOC'; { Can be any raw data File }π resetport = $226;π readport = $22A;π Writeport = $22C;π statusport = $22E;π dac_Write = $10;π adc_read = $20;π midi_read = $30;π midi_Write = $38;π speakeron = $D1;π speakeroff = $D3;ππFunction reset_dsp : Boolean;πVarπ count, bdum : Byte;πbeginπ reset_dsp := False;π port[resetport] := 1;π For count := 1 to 6 doπ bdum := port[statusport];π port[resetport] := 0;π For count := 1 to 6 doπ bdum := port[statusport];π Repeat Until port[statusport] > $80;π if port[readport] = $AA thenπ reset_dsp := True;πend;ππProcedure spk_on;πbeginπ Repeat Until port[Writeport] < $80;π port[Writeport] := $D1;πend;ππProcedure spk_off;πbeginπ Repeat Until port[Writeport] < $80;π port[Writeport] := $D3;πend;ππProcedure generic(reg,cmd:Integer; data:Byte);πbeginπ Repeat Until port[Writeport] < $80;π port[reg] := cmd;π Repeat Until port[Writeport] < $80;π port[reg] := data;πend;ππProcedure Write_dsp(data:Byte); Assembler;πAsmπ mov dx,$22Cπ mov cx,6 { Change either value of CX For }π@1:π in al,dxπ loop @1ππ mov al,10hπ out dx,alπ mov cx,36 { faster or slower playing. }π@2:π in al,dxπ loop @2ππ mov al,dataπ out dx,alπend;ππFunction read_dsp : Byte;πbeginπ Repeat Until port[Writeport] < $80;π port[Writeport] := $20;π Repeat Until port[statusport] > $80;π read_dsp := port[readport];πend;ππProcedure Write_midi(data:Byte);πbeginπ Repeat Until port[Writeport] < $80;π port[Writeport] := $38;π Repeat Until port[Writeport] < $80;π port[Writeport] := data;πend;ππFunction read_midi : Byte;πbeginπ Repeat Until port[Writeport] < $80;π port[Writeport] := $30;π Repeat Until port[statusport] > $80;π read_midi := port[readport];πend;ππFunction loadFile(Var buffer:Pointer; Filename:String) : Word;πVarπ fromf : File;π size : LongInt;π errcode : Integer;πbeginπ assign(fromf,Filename);π reset(fromf,1);π errcode := ioresult;π if errcode = 0 thenπ beginπ size := Filesize(fromf);π Writeln(size);π getmem(buffer,size);π blockread(fromf,buffer^,size);π endπ else size := 0;π loadFile := size;π close(fromf);πend;ππProcedure unload(buffer:Pointer; size:Word);πbeginπ freemem(buffer,size);πend;ππVarπ ch : Char;π buf : Pointer;π index, fsize : Word;ππbeginπ ClrScr;π Writeln;π Writeln;π if not reset_dsp thenπ beginπ Writeln('Unable to initialize SoundBlaster.');π halt(1);π end;π fsize := loadFile(buf,fname);π if (fsize <= 0) thenπ beginπ Writeln(fname, ' not found.');π halt(2);π end;π{ For index := 1 to fsize doπ dec(mem[seg(buf^):ofs(buf^)+index-1],80);} { For MOD samples }π spk_on;π Writeln('Playing...');π For index := 1 to fsize doπ Write_dsp(mem[seg(buf^):ofs(buf^)+index-1]);π spk_off;π unload(buf,fsize);π Writeln('Done.');π ch := ReadKey;πend.ππ 8 05-28-9313:57ALL SWAG SUPPORT TEAM SBDEMO.PAS IMPORT 5 {$M 16384,0,0}ππProgram Demo; { to demonstrate the SBVoice Unit }π { Copyright 1991 Amit K. Mathur, Windsor, Ontario }ππUses SBVoice;ππbeginπif SBFound then beginπ if paramcount=1 then beginπ LoadVoice(ParamStr(1),0,0);π sb_Output(seg(SoundFile),ofs(SoundFile)+26);π Repeatπ Write('Ha');π Until StatusWord=0;π end elseπ Writeln('Usage: DEMO [d:\path\]Filename.voc');π end elseπ Writeln('SoundBlaster Init Error. SoundBlaster v1.00 not Found.');πend.ππ 9 05-28-9313:57ALL SWAG SUPPORT TEAM SBVOICE.PAS IMPORT 78 {---------------------------------------------------------------------------π Unit SBVoice (v1.10) For Turbo Pascal 6.0π For interfacing With the SoundBlaster's digitized voice channel.π Copyright (c) 1991, Amit K. Mathur, Windsor, Ontario.ππ By: Amit K. Mathurπ 3215 St. Patrick's Driveπ Windsor, Ontarioπ N9E 3H2 CANADAπ Ph: (519) 966-6924ππ Networks: RIME(tm) R/O ->WinDSor, ILink (Shareware), NA-Net (Gaming),π WWIVNet (#198@5950), or direct on NorthSTAR (519)735-1504.ππ These routines are released to the public domain. However I will gladlyπ accept contributions towards further development of this and other products.π Please send any changes or improvements my way. and I'm interested inπ other SoundBlaster utilities and Programming tools. Thanks in advance.π --------------------------------------------------------------------------}ππ{$O+,F+}π{ Allow this Unit to Be Overlayed (doesn't affect Compilation if you decideπ not to overlay it), and Force Far calls. }ππUnit SBVoice;ππInterfaceππUses MemAlloc; { Memory Allocation Proc }ππVarπ{$ifNDEF NoSBVoiceArray} { to use your own }π SoundFile: Array[1..64000] of Byte; { whatever size you want }π{$endif}π sgSBDriver, ofSBDriver: Word; { seg and ofs of Driver }π SBDriver: Pointer; { Pointer to the driver }π StatusWord: Word; { stores SB status }π SBFound: Boolean; { whether Init worked }ππProcedure loaddriver(fi:String);π{ Loads CT-VOICE.DRV into memory. 'fi' is the path to the driver. }ππProcedure closedriver;π{ Clean up routine. not Really necessary if your Program is over. }ππProcedure loadvoice(f:String;start,size:Word);π{ Load 'f' into memory. Start is the start of the area withinπ 'f' to load and size is the amount to laod. if you set size to 0π then it will load the entire File. }ππFunction sb_getversion:Integer;π{ Get the version number of the CT-VOICE.DRVπ Returns the Version number }ππFunction sb_init:Integer;π{ Initialize the SoundBlaster. Call this right after load driver, unlessπ you have to change the BaseIOAddress or Interrupt number and haven'tπ changed the CT-VOICE.DRV File itself.π Returns: 0 - no problemπ 1 - Sound card failiureπ 2 - I/O failiureπ 3 - DMA interrupt failiure }ππProcedure sb_output(sg,os:Word);π{ Output the digitized Sound. You must load the Sound first!π sg and os are the segment and offset of either SoundFile or whateverπ Array you use to store the Sound. if you use a .VOC File then callπ With 26 added to the offset. }ππProcedure sb_setstatusWord(sg,os:Word);π{ Sets the location of the status Word. This is the third thing you shouldπ do, after loading the driver and initializing it.π The StatusWord will contain $0FFFF if input/output is in output, andπ 0 when it's done. It will also hold the values of the markers in voiceπ Files if any are encounterred, allowing you to coordinate output withπ your Programs. }ππProcedure sb_speaker(mode:Word);π{ Set the speaker on/off. off is mode 0, and On is anything else. Thisπ is the fourth thing you should do in your initialization. }ππProcedure sb_uninstall;π{ Uninstall the driver from memory. Used by CloseDriver. }ππProcedure sb_setIOaddress(add:Word);π{ Override the IOaddress found inside the CT-VOICE.DRV File. Add is theπ new IO address. }ππProcedure sb_setinterruptnumber(intno:Word);π{ Allows you to override the Interrupt number in the driver. IntNo is yourπ new interrupt number (3, 5, 7 or 9). }ππProcedure sb_stopoutput;π{ Stops the output in progress }ππFunction sb_pauseoutput: Integer;π{ PaUses the output in progress.π Returns: 0 - successπ 1 - fail }ππFunction sb_continueoutput: Integer;π{ Continues a paused output.π Returns: 0 - successπ 1 - fail (nothing to continue) }ππFunction sb_breakloop(mode:Word): Integer;π{ Breaks out of the currect output loop.π Modes: 0 - continue round, stop when doneπ 1 - stop immediatelyπ Returns: 0 - successπ 1 - not in loop }ππProcedure sb_input(highlength,lowlength,seginputbuff,ofsinputbuff:Word);π{ Input digitized Sound.π HighLength: The high Byte of the length of the input buffer.π LowLength: The low Byte of the length of the input buffer.π SegInputBuff: The Segment of the start of the input buffer.π ofsInputBuff: The offset of the start of the input buffer. }ππProcedure sb_setuserFunction(segaddress,ofsaddress:Word);π{ Sets up a user Function that the SB calls when it encounters a new dataπ block. It must perForm a Far ret, preserve DS,DI,SI and flag register.π Clear Carry flag if you want the driver to process the block, or set itπ if your routine will. It must be clear if the block Type is 0, thatπ is the terminate block.π SegAddress is the segment of your user Function in memory.π ofsAddress is the ofset of your user Function in memory. }ππImplementationππUses Dos;ππProcedure Abort(s:String);πbeginπ Writeln('The Following Error Has Occurred: ',s);π Writeln('Remedy and try again. We apologize For any inconvenience.');π halt(1);πend;ππProcedure loaddriver(fi:String);πVar f: File;π k: Integer;π t: String[8];πbeginπ assign(f,fi+'CT-VOICE.DRV');π {$I-} Reset(f,1); {$I+}π if Ioresult <> 0 thenπ Abort('Cannot Open '+fi+'CT-VOICE.DRV');π blockread(f,Mem[sgSBDriver:ofSBDriver],Filesize(f));π close(f);π t:='';π For k:=0 to 7 doπ t:=t+chr(Mem[sgSBDriver:ofSBDriver+k+3]);π if t<>'CT-VOICE' thenπ abort('Invalid CT-VOICE Driver!');πend;ππProcedure closedriver;πbeginπ sb_uninstall;π if dalloc(sbdriver)=0 thenπ abort('Uninstall Error!');πend;ππProcedure loadvoice(f:String;start,size:Word);πVar fi: File;π k: Word;πbeginπ assign(fi,f);π {$I-} Reset(fi,1); {$I+}π if Ioresult <> 0 thenπ abort('Cannot Open '+f+'!');π k:=0;π seek(fi,start);π if size=0 then size:=Filesize(fi);π blockread(fi,Mem[seg(SoundFile):ofs(SoundFile)],size);π close(fi);πend;ππFunction sb_getversion: Integer; Assembler;πAsmπ push bpπ mov bx,0π call SBDriverπ pop bpπend;ππProcedure sb_setIOaddress(add:Word); Assembler;πAsmπ push bpπ mov bx,1π mov ax,addπ call SBDriverπ pop bpπend;ππProcedure sb_setinterruptnumber(intno:Word); Assembler;πAsmπ push bpπ mov bx,2π mov ax,intnoπ call SBDriverπ pop bpπend;ππProcedure sb_stopoutput; Assembler;πAsmπ push bpπ mov bx,8π call SBDriverπ pop bpπend;ππFunction sb_init: Integer; Assembler;πAsmπ push bpπ mov bx, 3π call SBDriverπ pop bpπend;ππFunction sb_pauseoutput: Integer; Assembler;πAsmπ push bpπ mov bx,10π call SBDriverπ pop bpπend;ππFunction sb_continueoutput: Integer; Assembler;πAsmπ push bpπ mov bx,11π call SBDriverπ pop bpπend;ππFunction sb_breakloop(mode:Word): Integer; Assembler;πAsmπ push bpπ mov bx,12π mov ax,modeπ call SBDriverπ pop bpπend;ππProcedure sb_output(sg,os:Word); Assembler;πAsmπ push bpπ push diπ mov bx,6π mov di,os { offset of voice }π mov es,sg { segment of voice }π call SBDriverπ pop diπ pop bpπend;ππProcedure sb_input(highlength,lowlength,seginputbuff,ofsinputbuff:Word);πAssembler;πAsmπ push bpπ push diπ mov bx,7π mov dx,highlengthπ mov cx,lowlengthπ mov es,seginputbuffπ mov di,ofsinputbuffπ call SBDriverπ pop diπ pop bpπend;ππProcedure sb_setstatusWord(sg,os:Word); Assembler;πAsmπ push bpπ push diπ mov bx,5π mov di,osπ mov es,sgπ call SBDriverπ pop diπ pop bpπend;ππProcedure sb_speaker(mode:Word); Assembler;πAsmπ push bpπ mov bx,4π mov ax,modeπ call SBDriverπ pop bpπend;ππProcedure sb_uninstall; Assembler;πAsmπ push bpπ mov bx,9π call SBDriverπ pop bpπend;ππProcedure sb_setuserFunction(segaddress,ofsaddress:Word); Assembler;πAsmπ push bpπ mov dx,segaddressπ mov ax,ofsaddressπ mov bx,13π call SBDriverπ pop bpπend;πππbegin {set up SB}ππ if DosMemAvail < 5000 then { lower the heap }π abort('not Enough Memory'); { With $M to fix }π StatusWord:=MAlloc(SBDriver,5000);π if StatusWord<>0 thenπ abort('Memory Allocation Error');ππ sgSBDriver:=MemW[seg(SBDriver):ofs(SBDriver)+2];π ofSBDriver:=MemW[seg(SBDriver):ofs(SBDriver)];ππ Loaddriver(''); { change at will }π if sb_init<>0 then { or stick in your }π SBFound:=False { own Program init }π elseπ SBFound:=True;ππ if SBFound then beginπ sb_setstatusWord(seg(statusWord),ofs(statusWord));π sb_speaker(1); { turn SB on }π end;πend.πππ{There's the Unit For .VOC playing.}π 10 05-28-9313:57ALL SWAG SUPPORT TEAM SOUNDINF.PAS IMPORT 96 {πJOE DICKSONππ> Hello there.. I was just wondering if anyone had any ideaπ> on how to play a wav/voc File over the pc speaker. I have aπ> Program called PC-VOICE, written by Shin K.H. (Is he here?)π> that will play voc's and wav's (whats the difference?) overπ> the speaker.. I don't know assembly, just pascal, but I'veπ> got a friend that can show me how to link the assembly stuffπ> in With the Pascal, so that shouldn't be a problem..π> Also, I've tried and failed to find the format of a voc/wavπ> File, so if anyone has that, it would be much appriciated.π}ππHeader-- CT-VOICE Header Blockπ-=-πThe header is a data block that identifies the File as a CT-format File. Thisπmeans that you can use the header to check whether the File is an actualπCT-format File.ππBytes $00 - $13 (0-19)ππThe first 19 Bytes of a VOC File contain the Text "Creative Voice File", asπwell as a Byte With the value $1A. This identifies the File as a VOC File.ππBytes $14 - $15 (20-21)ππThese Bytes contain the offset address of the sample data as aπlow-Byte/high-Byte value. At this point, this value is $001A because theπheader is exactly $1A Bytes long.ππHowever, if the length of the header changes later, the Programs that accessπthe VOC data in this File will be able to use the values stored in these twoπBytes to determine the location at which the sample data begins.ππBytes $16 - $17 (22-23)ππThese two Bytes contain the CT-Voice format version number as aπlow-Byte/high-Byte value. The current version number is still 1.10 (NOTE--Thisπmay have changed, this was published in 92) so Byte $17 contains the mainπversion number ($01) and Byte $16 contains the version subnumber ($0A). Theπversion number is very important because later CT-Voice format versions may useπan entirely different method For storing the sample data than the currentπversion.ππTo ensure that the data contained in the File will be processed correctly, youπshould always check the File's version number. if a different version numberπappears, an appropriate warning should be displayed.ππBytes $18 - $19 (24-25)ππThe importance of the version number is obvious in Bytes $18 and $19. TheseπBytes contain the complement of the version number, added to $1234, as aπlow-Byte/high-Byte value.ππTherefore, With the current version number $010A, Byte $18 contains the valueπ$29, While Byte $19 contains $11. This results in the Word value $1129. Ifπyou check this value and succesfully compare it to the version number stored inπthe previos two Bytes, you can be almost certain that you're using a VOC File.ππThis completes the desciprtion of Bytes contained in the header. Everythingπthat follows these Bytes in the File belongs to the File's data blocks.ππThe Data Blocks-- The eight data blocks of the CT-Voice format have the sameπstructure, except For block 0. Each block begins With a block identifier,πwhich is a Byte containing a block-Type number between 0 and 7. This number isπfollowed by three Bytes specifying the length of the block, and then theπspecified number of additional data.ππThe three length Bytes contain increasing values (i.e., the first Byteπrepresents the lowest value and the third Byte represents the highest). SO theπblock's length can be calculated by using the formula:ππByte1 + Byte2*256 + Byte3*65536ππIn all other cases, the CT-Voice format stores values requiring more than oneπByte in a low Byte followed by a high-Byte, which corresponds to the Word dataπType.ππBlock 0 - end BlockππThe end block has the lowest block number. It indicates that there aren't anyπadditional data blocks. When such a block is reached, the output of VOC dataπduring the playback of digitized Sounds stops. Therefore, this block should beπlocated only at the end of a VOC File. The end block is the only block thatπdoesn't have Bytes indicating its block length.ππ+----------------------------+π| STRUCTURE of THE end BLOCK |π| |π| Block Type: 1 Byte = 0 |π| Block Length: None |π| Data Bytes: None |π+----------------------------+ππBlock 1 - New Voice BlockππThe block Type number 1 is the most frequently used block Type. It containsπplayable sample data. The three block length Bytes are followed by a Byteπspecifying the sampling rate (SR) that was used to Record the Sounds.ππCalculatin The Sampling Rate-- Since only 256 different values can be stored inπa singly Byte, the actual sampling rate must be calculated from the value ofπthis Byte.ππUse the following formula to do this:ππ Actual_sampling_rate = -1000000 div (SR - 256)ππTo convert a sampling rate into the corresponding Byte value, reverse theπequation:ππ SR = 256 - 1000000 div actual_sampling_rateππThe pack Byte follows the SR Byte. This value indicates whether and how theπsample data have been packed.ππThe value 0 indicates that the data hasn't been packed; so 8 bits form one dataπvalue. This is the standard Recording format. However, your Sound Blasterπcard is also capable of packing data on a hardware level. (good luck trying toπrecreate that)ππA value of 1 in the pack Byte indicates that the original 8 bit values haveπbeen packed to 4 bits. This results in a pack rate of 2:1. Although the dataπrequires only half as much memory, this method also reduces the Sound quality.ππThe value 2 indicates a pack rate of 3:1, so the data requires only a third ofπthe memory. Sound quality reduces significantly.ππA pack Byte value of 3 indicates a pack rate of 4:1, so 8 original bits haveπbeen packed down to 2. This pack rate results in A LOT of reduction in Soundπquality.ππThe pack Byte is followed by the actual sample data. The values contained inπthe block length Bytes also indicate the length of the sample data. Toπdetermine the length of the actual sample data in Bytes, simply subtract the SRπand pack Bytes from the block length.ππ+---------------------------------+π| STRUCTRE of THE NEW VOICE BLOCK |π| |π| Block Type: 1 Byte = 1 |π| Block Length: 3 Bytes |π| SR Byte: 1 Byte |π| Pack Byte: 1 Byte = 0,1,2,3 |π| Data Bytes: X Bytes. |π+---------------------------------+ππBlock 2 - Subsequent Voice BlockππBlock Type 2 is used to divide sample data into smaller individual blocks. Thisπmethod is used by the Creative Labs Voice Editor when you want to work With aπsample block that's too large to fit into memory in one piece. This block isπthen simply divided into several smaller blocks.ππSince these blocks contain only three length Bytes and the actual sample data,πblocks of Type 2 must always be preceded by a block of Type 1. So, theπsampling rate and the pack rate are determined by the preceeding block Type 1.ππ+-----------------------------------------+π| STRUCTURE of THE SUBSEQUENT VOICE BLOCK |π| |π| Block Type: 1 Byte = 2 |π| Block Length: 3 Bytes |π| Data Bytes: X Bytes |π+-----------------------------------------+ππBlock 3 - Silence BlockππBlock Type 3 Uses a small number of Bytes to represent a mass of zeros. Firstπthere are the three familiar block length Bytes. The length of a silence blockπis always 3, so the lowest Byte contains a three, and then the other two Bytesπcontain zeros.ππThe length Bytes are followed by two other Bytes, which indicate how many zeroπBytes should be replaced by the silence block.ππThis is followed by a Byte that indicates the sampling rate For the silenceπblock. The SR Byte is encoded in the same way as indicated in block Type 1.ππSilence blocks can be used to insert longer paUses or silences in a sample,πwhich reduces the required data to a few Bytes. The Voice Editor will insertπthese silence blocks through the Silence Packing Function.ππ+--------------------------------+π| STRUCTURE of THE SILENCE BLOCK |π| |π| Block Type: 1 Byte = 3 |π| Block Length: 3 Bytes = 3 |π| Duration: 2 Bytes |π| Sample Rate: 1 Byte |π+--------------------------------+ππBlock 4 - Marker BlockππThe marker block is an important element of the CT-Voice format. It also hasπthree block length Bytes followed by two marker Bytes. The block length Bytesπalways contain the value 2 in the lowest Byte.ππWhen the playback routine of "CT-VOICE.DRV" encounters a marker block, theπvalue of the marker Byte is copied to a memory location that was specified toπthe driver. The marker block is often used to determine where exactly inπplayback you are. This is useful For synchronizing the action of your Programπwith the playback, For a Graphical intro For example.ππUsing the Voice Editor, you can divide large sample data blocks into smallerπones, inserting marker blocks at important locations. This doesnt affect theπplayback of the sample. However, you'll be able to determine, from yourπProgram, which point of the sample the playback routine is currently reading.ππ+-------------------------------+π| STRUCTURE of THE MARKER BLOCK |π| |π| Block Type : 1 Byte = 4 |π| Block Length: 3 Bytes = 2 |π| Marker: 2 Bytes |π+-------------------------------+ππBlock 5 - Message BlockππIt's also possible to insert ASCII Texts Within a VOC File. Use the messageπblock to do this. if you want to identify a specific seciont of a sample Fileπby adding a title, simply add a block of Type 5, in which you can then storeπthe desired Text.ππThis block also has three block length Bytes. These Bytes are followed by theπText in ASCII format. The Text must contain a 0 in the last Byte to indicateπthe end of the Text. This corresponds to the String convention of the CπProgramming language. This allows you to pring the Texts in a VOC Fileπdirectly from memory using the printf() Function in ANSI C.ππ+--------------------------------+π| STRUCTURE of THE MESSAGE BLOCK |π| |π| Block Type: 1 Byte = 5 |π| Block Length: 3 Bytes |π| ASCII Data: X Bytes |π| end Character: 1 Byte = 0 |π+--------------------------------+ππBlock 6 - Repeat BlockππAnother special Characteristic of the CT-Format is that it's possible toπspecify, Within a VOC File, whether specific sample sequences should beπRepeated. Blocks 6 and 7 are used to do this.ππBlock 6 has three block length Bytes, followed by two Bytes indicating howπoften the following data block should be Repeated. if the value specified hereπis 4, the next block is played a total of five times (one "normal" playback andπfour Repeats).ππ+-------------------------------+π| STRUCTURE of THE Repeat BLOCK |π| |π| Block Type: 1 Byte = 6 |π| Block Length: 3 Bytes = 2 |π| Counter: 2 Bytes |π+-------------------------------+ππBlock 7 - Repeat end BlockππBlock 7 indicates that all blocks between block 6 and block 7 should beπRepeated. With this block, several data blocks can be included in a Repeatπloop. However, nested loops aren't allowed. The driver is capable of handlingπonly one loop level.ππBlock Type 7 also has three block length Bytes, which actually aren't necessaryπbecause this block doesnt contain any additional data. Therefore, the blockπlength is always 0.ππ+-------------------------------+π| STRUCUTRE of Repeat end BLOCK |π| |π| Block Type: 1 Byte = 7 |π| Block Length: 3 Bytes = 0 |π+-------------------------------+ππWe've now described all the different block Types used in VOC Files. TheseπFunctions are fully supported by the CT-VOICE.DRV driver software.ππif you'll be writing your own Sound Programs, you should follow this formatπbecause it's easy to use and flexible. When needed, new block Types are easilyπadded. Programs that dont recognize block Types should be written so theyπcontinue operating after an unrecognized block. This is easy to do becauseπeach Function specifies its own block length.ππBiblioGraphy: Stolz, Axel "The Sound Blaster Book", Abacus Copyright (c)1992,πA Data Decker Book Copyright (c) 1992ππ 11 05-28-9313:57ALL SWAG SUPPORT TEAM SOUNDOFF.PAS IMPORT 10 {πSTEVEN TALLENTππ> I am look For a piece of code [...] that will turn off the speaker.ππThis is tested code, and should do the trick. It does its work byπturning off the PC speaker 18.2 times per second. This should reduceπany Sound to maybe a click or two. Unfortunately, some games andπmusic software will bypass it (ModPlay, Wolfenstein), but most beepsπand whistles will be gone. This is a TSR Program, and takes about 3kπmemory (yuk), but you can load it high if you want. I've found itπespecially useful during late-night BBSing (no alarms at connect/Fileπxfer finish). Hope this does the trick! Considering its size andπrelative isolation from normal Programs, I didn't see fit to use CLI/STI.π}ππ{$M 1024,0,0} {BTW, is there any way to make this smaller?!?}π{$N-,S-,G+} { Use g- For 8088 systems, g+ For V20 and above }πProgram NoSpeak;πUsesπ Dos;ππProcedure ShutOff; INTERRUPT;πbeginπ Port [97] := Port[97] and 253; {Turn off speaker and disconnect timer}πend;ππbeginπ SetIntVec( $1C, @ShutOff);π Keep(0);πend.ππ 12 05-28-9313:57ALL SWAG SUPPORT TEAM VOC2LPT1.PAS IMPORT 14 {π This is a Program to export a VOC or other Raw Sound File to a Parallelπport DAC.. (only For LPT1 now, but i think you can make it work on LPT2 byπchanging the 'PORT[$0378]' to 'PORT[$0388]'...ππ I know, This is a Real mess For figuring it out... I originally had noπintention of posting it, but I believe in free access to info, so here it is!πIf you have any questions about it, just ask... and if you figure out whereπthat bug is (you'll know what I mean, it only plays PART of the VOC) I'dπappreciate input.π}ππ{This Program Assumes you have a DAC on LPT1}π{$M 65520,0,300000} {only use memory that is needed}πProgram Voc_Play;πUsesπ Crt;ππProcedure Wait(N : Word); {Very Crude wait routine}πVarπ counter : Word;πbeginπ For Counter:= 1 to N do;πend;ππType Ra = Array[0..0] of Byte;ππVarπ I2 : ^Ra;π spd : Integer;π res : Word;π siz : LongInt;π B : Word;π s : String;π f1 : File of Byte;π F : File;ππbeginπ Write('Enter Voc Filename: ');π readln(S);π {Get Size of File}π Assign(f1,s);π Reset(f1);π spd:=30; {this is the play speed}π siz := FileSize(f1);π close(f1);π {Load up Voc File}π Assign(f,s);π Reset(f);π getmem(I2,siz); {Allocate Memory For VOC File}π BlockRead(f,I2^,siz,res); {Load VOC into Memory)π Writeln('FileSize = ',siz); {Testing Point, not needed}ππ Repeat {This is the actual Play routine} beginπ For b:=0 to siz doπ beginπ Wait(spd); {Wait a bit}π Port[$0378]:=I2^[b]; {Put Byte to DAC}π end;π end Until KeyPressed;ππend.ππ 13 05-28-9313:57ALL SWAG SUPPORT TEAM VOCINFO.PAS IMPORT 19 {π I posted beFore about sample converting... the .VOC to the sampleπ Format used by MODS. You gave me some example code, but the prob is,π VOC Files have a header, how would I do it so that the header wasn'tπ converted?ππHere is the VOC File Format that was posted here a While back. It worksπwell For me.πππA .VOC File consists of a 26-Byte header Record plus sample data.πThe header Record has the following layout:π}πVoiceHeader : Recordπ signature : Array[1..20] of Char; { Vendor's name }π DataStart : Word; { Start of data in File }π Version : Integer; { BCD value: min. driver version required }π ID : Integer; { 1-Complement of Version field+$1234 }π end; { used to indentify a .VOC File }ππThe data is divided into 'blocks'. There are 8 Types of blocks:ππ- 0 : Terminatorπ 1 Byte Record, value 00ππ- 1 : Voice Dataπ 1 Byte, value 01: identifierπ 3 Bytes: length of voice data (len data + 2)π 1 Byte: SR= 256-(1,000,000 / sampling rate)π 1 Byte: pack field, value:π 0 : unpacked, 1 : 4-bit, 2 : 2.6 bit, 3 : 2 bit packedπ <follows voice data>ππ- 2 : Voice Continuationπ 1 Byte, value 02: identifierπ 3 Bytes: length of voice dataπ <follows voice data>ππ- 3 : Silenceπ 1 Byte, value 03: identifierπ 3 Bytes: length of silence period (value 3?)π 2 Bytes: silence period in Units of sampling cyclesπ 1 Byte: SR (see above)ππ- 4 : Markerπ 1 Byte, value 04: identifierπ 3 Bytes: length of marker, value 2π 2 Bytes: user defined markerππ- 5 : ASCII Textπ 1 Byte, value 05: identifierπ 3 Bytes, length of String (not counting null Byte)π <String>π 1 Byte, value 0: String terminatorππ- 6 : Repeat Loopπ 1 Byte, value 06: identifierπ 3 Bytes: length of block, value 2π 2 Bytes: count value+1ππ- 7 : end Repeat Loopπ 1 Byte, value 07: identifierπ 3 Bytes: length of block, value 0ππ{πto my knowledge, the .VOC File Format is proprietary and the dataπherein is only of value For the specific SoundBlaster hardware. I thinkπyou'll have a hard time converting samples to another synthesizer.π}π 14 05-28-9313:57ALL SWAG SUPPORT TEAM VOCPLAY.PAS IMPORT 37 {π> Does anybody know where to get some good source that plays Vocs?π}ππ{$A+,B-,D+,E-,F+,G-,I-,L-,N-,O+,R-,S-,V-,X-}π{$M 1024,0,0 }πUnit VOCPlay;ππInterfaceππUsesπ Dos;ππVarπ VoiceStatusWord : Word;π VocPaused,VOCDrvInstalled : Boolean;ππProcedure AllocateMem(Var P : Pointer;Size : LongInt);πFunction AllocateMemFunc(Var P : Pointer;Size : LongInt) : Boolean;πFunction ReAllocateMem(Var P : Pointer;NewSize : LongInt) : Boolean;πProcedure DisAllocateMem(Var P : Pointer);ππProcedure VocOutPut(AdrtoPlay : Pointer);πProcedure VocStop;πProcedure VocPause;πProcedure VocContinue;πProcedure VocSetSpeaker(Onoff : Boolean);πFunction VocInitDriver : Byte;πFunction LoadVoctoMem(DateiName : String;Var VocMem : Pointer) : Boolean;ππImplementationπConstπ VocDriverHeader = 12;π VocFileHeaderLen = $1A;πVarπ PtrtoDriver,OldExitProc : Pointer;π Regs : Registers;π SizeIntern : Word;ππProcedure AllocateMem;πbeginπ Inc(Size,15);π SizeIntern := (Size SHR 4);π Regs.AH := $48;π Regs.BX := SizeIntern;π MsDos(Regs);π if Regs.Flags and FCarry <> 0 thenπ P := NILπ elseπ P := Ptr(Regs.AX,0);πend;ππFunction AllocateMemFunc;πbeginπ AllocateMem(P,Size);π AllocateMemFunc := P <> NIL;πend;ππFunction ReAllocateMem;πbeginπ Inc(NewSize,15);π SizeIntern := (NewSize SHR 4);π Regs.AH := $4A;π Regs.BX := SizeIntern;π Regs.ES := Seg(P^);π MsDos(Regs);π ReAllocateMem := (Regs.BX=SizeIntern);πend;ππProcedure DisAllocateMem;πbeginπ Regs.AH := $49;π Regs.ES := Seg(P^);π MsDos(Regs);πend;ππFunction Exists(FileName : String) : Boolean;πVarπ S : SearchRec;πbeginπ FindFirst(FileName,AnyFile,S);π Exists := (DosError=0);πend;ππFunction VocInitDriver;πConstπ DriverName = 'CT-VOICE.DRV';πTypeπ DriverType = Array [0..VocDriverHeader] of Char;πVarπ Out,S,O : Word;π F : File;πbeginπ Out := 0;π if not Exists(DriverName) thenπ beginπ VocInitDriver := 4;π Exit;π end;π Assign(F,DriverName);π Reset(F,1);π if not AllocateMemFunc(PtrtoDriver,FileSize(F)) then Out := 5;π if Out=0 then BlockRead(F,PtrtoDriver^,FileSize(F));π Close(F);π if Out<>0 thenπ beginπ VocInitDriver := Out;π Exit;π end;π if (DriverType(PtrtoDriver^)[3]<>'C') orπ (DriverType(PtrtoDriver^)[4]<>'T') thenπ beginπ VocInitDriver := 4;π Exit;π end;π S := Seg(VoiceStatusWord);π O := ofs(VoiceStatusWord);π Asmπ mov bx,3π call PtrtoDriverπ mov Out,axπ mov bx,5π mov es,Sπ mov di,Oπ call PtrtoDriverπ end;π VocInitDriver := Out;πend;ππProcedure VocUninstallDriver;πbeginπ if VocDrvInstalled thenπ Asmπ mov bx,9π call PtrtoDriverπ end;πend;ππProcedure VocOutPut;πVarπ S,O : Word;πbeginπ VocSetSpeaker(True);π S := Seg(AdrtoPlay^);π O := ofs(AdrtoPlay^)+VocFileHeaderLen;π Asmπ mov bx,6π mov es,Sπ mov di,Oπ call PtrtoDriverπ end;πend;ππProcedure VocStop;πbeginπ Asmπ mov bx,8π call PtrtoDriverπ end;πend;ππProcedure VocPause;πbeginπ Asmπ mov bx,10π call PtrtoDriverπ end;πend;ππProcedure VocContinue;πbeginπ Asmπ mov bx,11π call PtrtoDriverπ end;πend;ππProcedure VocSetSpeaker;πVar B : Byte;πbeginπ B := ord(Onoff) and $01;π Asmπ mov bx,4π mov al,Bπ call PtrtoDriverπ end;πend;ππFunction LoadVoctoMem;πVar F : File;π Out : Boolean;π Gelesen,Segs : Word;πbeginπ Out := Exists(DateiName);π if Out thenπ beginπ Assign(F,DateiName);Reset(F,1);π if not AllocateMemFunc(VocMem,FileSize(F)) thenπ beginπ Close(F);π LoadVoctoMem := False;π Exit;π end;π Segs := 0;π Repeatπ BlockRead(F,Ptr(Seg(VocMem^)+4096*Segs,ofs(VocMem^))^,$FFFF,Gelesen);π Inc(Segs);π Until Gelesen=0;π Close(F);π end;π LoadVoctoMem := Out;πend;ππ{$F+}πProcedure VocPlayExitProc;πbeginπ VocUninstallDriver;π ExitProc := OldExitProc;πend;π{$F-}ππbeginπ OldExitProc := ExitProc;π ExitProc := @VocPlayExitProc;π VoiceStatusWord := 0;π VocPaused := False;π VocDrvInstalled := (VocInitDriver=0);πend.πππ{$A+,B-,D+,E-,F-,G-,I-,L-,N-,O-,R-,S-,V-,X-}π{$M 1024,0,0 }πUses Crt,VOCPlay;πVar VocMem : Pointer;π FileName : String;π Ok : Boolean;πbeginπ FileName := ParamStr(1);π Ok := False;π if VocDrvInstalled then Ok := LoadVoctoMem(DateiName,VocMem);π if Ok thenπ beginπ Write('Playing VOC-File ...');π VocOutPut(VocMem);π Repeatπ Until (VoiceStatusWord=0) or KeyPressed;π Writeln;π DisAllocateMem(VocMem);π endπ else Writeln('Hey, there was something wrong.');πend.π 15 05-28-9313:57ALL SWAG SUPPORT TEAM WHISTLE.PAS IMPORT 5 { BILL BUCHANAN }ππUsesπ Crt;ππProcedure OpenWhistle;πVarπ Frequency : Integer;πbeginπ For Frequency := 500 to 1000 doπ beginπ Delay(1);π Sound(Frequency)π end;π NoSoundπend;ππProcedure CloseWhistle;πVarπ Frequency: Integer;πbeginπ For Frequency := 1000 downto 500 doπ beginπ Delay(1);π Sound(Frequency)π end;π NoSoundπend;ππbeginπ OpenWhistle;π Readln;π CloseWhistle;πend. 16 05-28-9313:57ALL SWAG SUPPORT TEAM WINSOUND.PAS IMPORT 9 {πFellow Windows voyeurs,ππA While ago people were asking how to obtain Sound throughπthe PC speaker without using the multimedia DLL (or aπspeaker driver For that matter.) Below is a basic exampleπof how to do this.π}π Procedure SoundStart;π Varπ Pitch : Integer;π beginπ OpenSound;π For Pitch:= 80 to 84 doπ beginπ SetVoicenote (1, Pitch, 100, 1);π SetVoiceAccent (1, 15, 255, s_Legato, Pitch);π end;π StartSound;π WaitSoundState (S_QueueEmpty);π StopSound;π CloseSoundπ end;ππ{πPlease reference your Windows API reference manual Forπthe SetVoicenote() and SetVoiceAccent() synopsys.ππMicrosoft supports the calls in Windows 3.0, howeverπdocumentation in 3.1 suggests that it will no longerπsupport them. My interpretation is that For theπfuture these calls will be supported, however will notπbe enhanced or Extended. Their reasoning is probablyπbased on there drive to sell their multimedia kits.π}π