home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 7 Games / 07-Games.zip / billy164.zip / src / dart / dart.cc next >
C/C++ Source or Header  |  1997-09-21  |  15KB  |  627 lines

  1.  
  2. #define  INCL_OS2MM                 /* required for MCI and MMIO headers   */
  3. #define  INCL_DOS
  4. #define INCL_DOSFILEMGR /* _read_key til getch */
  5.  
  6. #include <os2.h>
  7. #include <os2me.h>
  8. #include <string.h>
  9. #include <malloc.h>
  10. #include <stdio.h>
  11. #include <iostream.h>
  12. #include <fstream.h>
  13.  
  14. #include <assert.h>
  15. #include "inttype.h"
  16. #include "dart.h"
  17.  
  18. #ifdef DEMO
  19. #include "aflus.h"
  20. #else
  21. #define aflus cerr
  22. #endif
  23.  
  24. #define MIX_BUFFER_EOS 0
  25. #define  STRING_LENGTH  128
  26. #define  MAX_BUFFERS    256
  27.  
  28. #include "utils.h"
  29. #define UD(a) { for (int i=0; i<sizeof(a)/sizeof(int); i++) cerr<<" "<<((int*)&a)[i]; cerr<<endl; }
  30.  
  31. int dError=0;
  32. char *dErrorMsg[]={"ingen lyd"};
  33.  
  34.  
  35. static USHORT               usDeviceID;                /* Amp Mixer device id     */
  36. static ULONG                bufteller;             /* Current file buffer     */
  37. static ULONG                antbuffere;              /* Number of file buffers  */
  38. static MCI_MIX_BUFFER       MixBuffers[MAX_BUFFERS];   /* Device buffers          */
  39. static MCI_MIXSETUP_PARMS   MixSetupParms;             /* Mixer parameters        */
  40. static MCI_BUFFER_PARMS     BufferParms;               /* Device buffer parms     */
  41.  
  42. static ULONG    rc;
  43. static dword sidstemmtime;
  44. static dword mmtimeperbuf;
  45. static dword bufferlgd;
  46.  
  47. struct MixTid {int buf,ofs;};
  48.  
  49.  
  50.  
  51. struct intkanalT {
  52.     int        vol;
  53.     Sample  *samp;
  54.     int finito;
  55.     int lgd;
  56.     MixTid start;
  57. };
  58.  
  59.  
  60. #define ANTKANALER 8
  61. struct intkanalT intkanaler[ANTKANALER];
  62. static int mastervol = 100;
  63. int *mixbuf32;
  64. int mixenbuffer=0;
  65.  
  66.  
  67. int operator -(const MixTid &t1, const MixTid &t2) 
  68. {return (t1.buf-t2.buf)*bufferlgd+(t1.ofs-t2.ofs);}
  69.  
  70.  
  71.  
  72.  
  73.  
  74. void mix(byte *dmabuf8, int mixlgd, int *tmpbuf32, MixTid mixfra)
  75. {
  76.  
  77. // max for een kanal er: 6+8+8+6=28 bit
  78. // 64 (kanalvol)*256 (mastervol)*256 (8 bit sample)*64 (samplevol)
  79. // 28-8=20 er så det der skal skiftes med, hvis man kun har en kanal
  80. // Vi har 8, så en bedre værdi er nok 21.
  81.  
  82. #define MIXSKIFTBIT 21
  83.  
  84.     struct intkanalT *k;
  85.     int *tmp;
  86.     byte *fra;
  87.     byte *til;
  88.     int lgd, vol, i,ofs;
  89.     
  90.  
  91.     memset(tmpbuf32, 0, mixlgd*sizeof(dword));
  92.     k = &intkanaler[0];
  93.  
  94.     for (int ki=0; ki<ANTKANALER; ki++,k++) {
  95. //                cerr<<ki<<k->samp<<endl;
  96.     if (!k->finito) {
  97.         assert(k->samp != NULL);
  98.         vol = k->vol * mastervol * k->samp->Volume;
  99. //        cout<<"VOL="<<vol<<"{"<<k->vol<<"*"<<mastervol<<"*"<<(int)k->samp->Volume<<"}";
  100.         ofs=mixfra-k->start;
  101. //        cerr<<"mix(): ofs="<<ofs;
  102.         
  103.         fra = (byte *)k->samp->DataPtr;
  104.         tmp = (int *) tmpbuf32;
  105.         if (ofs<0) {
  106.         lgd=min(k->samp->Length,mixlgd+ofs);
  107.         tmp-=ofs;
  108.         } else {
  109.         lgd=min(k->samp->Length-ofs,mixlgd);
  110.         fra+=ofs;
  111.         }
  112.  
  113.  
  114.         assert(lgd>=0);
  115.         assert(lgd<=mixlgd);
  116.         assert(lgd<=k->samp->Length);
  117.  
  118.         
  119.         for (i=lgd; i>0; i--) {
  120. //        *tmp += *fra * vol;
  121.         *tmp += ((int) *fra - 128) * vol;
  122.         tmp++;
  123.         fra++;
  124.         }
  125.         if (k->samp->Length <= ofs+mixlgd) k->finito=1;
  126.     }
  127.     }
  128.  
  129. //        cerr<<"mix dmabuf8"<<dmabuf8<<endl;
  130.     til = dmabuf8;
  131.     tmp = (int *) tmpbuf32;
  132. //        cerr<<"mix til"<<(void*) til<<endl;
  133.     for (i=mixlgd; i>0; i--) {
  134.     *til = (*tmp >> MIXSKIFTBIT)+128;
  135. /*
  136.     vol= ((*tmp)>>MIXSKIFTBIT)+128;
  137. //    vol= (*tmp+(128>>MIXSKIFTBIT))>>MIXSKIFTBIT;
  138.     *til =vol;
  139.     if (vol>255 || vol<0) {
  140.         overstyring=vol;
  141.         ostmpverdi=*tmp;
  142.     }
  143.     if (minv > vol) minv = vol;
  144.     if (maxv < vol) maxv = vol;
  145. */
  146.     tmp++;
  147.     til++;
  148.     }
  149. //    cout<<"["<<minv<<" "<<maxv<<"]";
  150. //    for (i=1; i<10; i++) cerr<<" "<<(int) dmabuf8[i];
  151. //    cerr<<endl;    
  152. }
  153.  
  154.  
  155. static    MCI_STATUS_PARMS statpos;
  156.  
  157. MixTid gettid(void)
  158. {
  159.     MixTid t;
  160.  
  161.     t.buf=bufteller+1;/* mellem disse to linier må der helst ikke ske noget */
  162.     t.ofs=0;
  163.     return t;
  164. }
  165.  
  166.  
  167. void DARTopdater(void)
  168. {
  169. /*
  170.     int ki;
  171.     struct intkanalT *k;
  172.     if (overstyring) {
  173.     
  174.         cerr<<"Mix(): overstyring: "<<overstyring<<endl;
  175.         for (ki=0,k = &intkanaler[0]; ki<ANTKANALER; ki++,k++)
  176.         if (k->samp) cerr<<"kanal "<<ki<<" vol="<<k->vol<<" samp->vol="<<(int) k->samp->Volume<<endl;
  177.         cerr<<"mastervol="<<mastervol<<endl<<"*tmp="<<ostmpverdi<<endl;
  178. //        exit(-1);
  179.         overstyring=0;
  180.         
  181.     }
  182. */  
  183. }
  184.  
  185.  
  186. int bufforsinkelse=-1;
  187.  
  188.  
  189. long APIENTRY MixerEvent ( ULONG ulStatus, PMCI_MIX_BUFFER  pBuffer, ULONG  ulFlags  )
  190. {
  191.     if (ulFlags & MIX_STREAM_ERROR) {
  192.     cerr<<"MixerEvent(): MIX_STREAM_ERROR"<<endl;
  193.     exit(-1);
  194.     } else if (ulFlags == MIX_WRITE_COMPLETE) {
  195.     bufteller++;
  196.     MixTid t;
  197.     t.buf=bufteller;
  198.     t.ofs=0;
  199.     mix((byte *)MixBuffers[(bufteller+antbuffere-bufforsinkelse)%antbuffere].pBuffer,bufferlgd,mixbuf32,t);
  200.  
  201.     MixSetupParms.pmixWrite( MixSetupParms.ulMixHandle, &MixBuffers[bufteller%antbuffere], 1 );
  202.  
  203.     mmtimeperbuf=pBuffer->ulTime-sidstemmtime;
  204.     sidstemmtime=pBuffer->ulTime;
  205. //    cerr<<"ulTime="<<pBuffer->ulTime<<" mmtimeperbuf="<<mmtimeperbuf<<endl;    
  206. //        cerr<<"bc="<<bufteller<<endl;
  207.     } else {
  208.     cerr<<"MixerEvent(): ulFlags="<<ulFlags<<endl;
  209.     exit(-1);
  210.     }
  211.  
  212.     return( TRUE );
  213. }
  214.  
  215.  
  216. const char *MciError( ULONG ulError )
  217. {
  218.    static SZ       szBuffer[ STRING_LENGTH ];
  219.    if (ulError==0) return "";
  220.    
  221.    rc = mciGetErrorString( ulError, szBuffer, STRING_LENGTH );
  222.    dErrorMsg[0] = szBuffer;
  223.    cerr<<"MCI error "<<ulError<<": "<<szBuffer<<endl;
  224.    return szBuffer;
  225. }
  226.  
  227.  
  228.  
  229. #define BROK_BIT 12
  230. #define BROK_MASKE 0x00000fff
  231. #define MAX_SAMPLE_LGD 1024*100
  232.  
  233. Sample *resample(Sample *sam, int frek) 
  234. {
  235.     int i,ink,ofs,v1,v2;
  236.     Sample *ret;
  237.     ret=new Sample;
  238.     *ret=*sam;
  239.     int lgd=sam->Length*frek/sam->Rate;
  240.     ret->DataPtr= new byte[lgd];
  241.     ret->Length=lgd;
  242.     ret->Rate=frek;
  243.  
  244.     ink=(sam->Rate<<BROK_BIT)/frek;
  245.     byte *s=(byte *) sam->DataPtr;
  246.     byte *d=(byte *) ret->DataPtr;
  247.     ofs=0;
  248.     for (i=lgd;i>0;i--) {
  249.     v1=s[ofs>>BROK_BIT];
  250.     v2=s[(ofs>>BROK_BIT)+1];
  251.     *d=v1+(((v2-v1)*(ofs&BROK_MASKE))>>BROK_BIT);
  252.     d++;
  253.     ofs+=ink;    
  254.     }
  255. /*
  256.     cout<<endl<<"RESAMPLE:";
  257.     for (i=0;i<10;i++) cout<<(int) (((byte *)ret->DataPtr)[lgd/2+i])<<" ";
  258.     cout<<endl;
  259. */  
  260.     
  261.     return ret;
  262. }
  263.  
  264. static Sample indlessamplebuf;
  265.  
  266.  
  267.  
  268. Sample *dImportSample(char *Filename, int Form)
  269. {
  270.     MMIOINFO             mmioInfo;
  271.     MMAUDIOHEADER        mmAudioHeader;
  272.     HMMIO                hmmio;
  273.     LONG                 lBytesRead;
  274.     Sample *ind;
  275.  
  276.     if (Form != FORM_WAV) {
  277.     dErrorMsg[0]="Only WAV files supported";
  278.     return NULL;
  279.     }
  280.     
  281.  
  282.     /* Open the audio file.
  283.      */
  284.     memset( &mmioInfo, '\0', sizeof( MMIOINFO ));
  285.     mmioInfo.fccIOProc = mmioFOURCC( 'W', 'A', 'V', 'E' );
  286.     hmmio = mmioOpen( Filename, &mmioInfo, MMIO_READ | MMIO_DENYNONE );
  287.     if (!hmmio) {
  288.     dErrorMsg[0]="Could not open a WAV file";
  289.     return NULL;
  290.     }
  291.  
  292.     /* Get the audio file header.
  293.      */
  294.     mmioGetHeader( hmmio,
  295.            &mmAudioHeader,
  296.            sizeof( MMAUDIOHEADER ),
  297.            &lBytesRead,
  298.            0,
  299.            0);
  300.  
  301.     ind = &indlessamplebuf;
  302.     ind->Length = mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes;
  303.     ind->Rate = mmAudioHeader.mmXWAVHeader.WAVEHeader.ulSamplesPerSec;
  304. //   ind->DataPtr = new byte[ind->Length];
  305.     if (ind->Length>MAX_SAMPLE_LGD) {
  306.     cerr<<"dImportSample(): sample "<<Filename<<" too big"<<endl;
  307.     dErrorMsg[0]="sample too big";
  308.     return NULL;
  309.     }
  310.     ind->Volume=64;
  311.  
  312.     rc = mmioRead ( hmmio,(byte *) ind->DataPtr, ind->Length );
  313.     mmioClose( hmmio, 0 );
  314.  
  315. //mix ind i ret->DataPtr !
  316.  
  317.     ind->LoopStart = ind->Length;
  318. //   strncpy(ind->FileName, Filename+20, 13);
  319.    strncpy(ind->FileName, Filename+max(0,(int) strlen(Filename)-13), 13);
  320. //   cerr<<"MixSetupParms.ulSamplesPerSec="<<MixSetupParms.ulSamplesPerSec<<endl;
  321.  
  322. //   cerr<<"Indlæst "<<Filename<<endl;
  323. //   for (int i=0; i<ind->Length; i++) fprintf(stderr,"%3i ",((byte*) ind->DataPtr)[i]);
  324.  
  325.     return resample(ind,MixSetupParms.ulSamplesPerSec);    
  326. }
  327.  
  328.  
  329.  
  330.  
  331. void initDART(void)
  332. {
  333.    MCI_AMP_OPEN_PARMS   AmpOpenParms;
  334.    ULONG                ulIndex;
  335.  
  336.    indlessamplebuf.DataPtr=new char[MAX_SAMPLE_LGD];
  337.    
  338.  
  339.    /* open the mixer device
  340.     */
  341.    memset ( &AmpOpenParms, '\0', sizeof ( MCI_AMP_OPEN_PARMS ) );
  342.    AmpOpenParms.usDeviceID = ( USHORT ) 0;
  343.    AmpOpenParms.pszDeviceType = ( PSZ ) MCI_DEVTYPE_AUDIO_AMPMIX;
  344.  
  345.    rc = mciSendCommand( 0,
  346.                        MCI_OPEN,
  347.                        MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
  348.                        ( PVOID ) &AmpOpenParms,
  349.                        0 );
  350.  
  351.    MciError( rc );
  352.  
  353.    usDeviceID = AmpOpenParms.usDeviceID;
  354.  
  355.  
  356.    /* Set the MixSetupParms data structure to match the loaded file.
  357.     * This is a global that is used to setup the mixer.
  358.     */
  359.    memset( &MixSetupParms, '\0', sizeof( MCI_MIXSETUP_PARMS ) );
  360.  
  361.    MixSetupParms.ulBitsPerSample = BPS_8; // eller evt BPS_16 ?
  362. //         mmAudioHeader.mmXWAVHeader.WAVEHeader.usBitsPerSample;
  363.  
  364.    MixSetupParms.ulFormatTag = DATATYPE_WAVEFORM;
  365. //         mmAudioHeader.mmXWAVHeader.WAVEHeader.usFormatTag;
  366.  
  367. //   MixSetupParms.ulSamplesPerSec = HZ_11025;
  368. //   MixSetupParms.ulSamplesPerSec = HZ_22050;
  369.    MixSetupParms.ulSamplesPerSec = HZ_44100;  // = 44.100
  370. //         mmAudioHeader.mmXWAVHeader.WAVEHeader.ulSamplesPerSec;
  371.  
  372.    MixSetupParms.ulChannels = CH_1; // stereo: CH_2
  373. //         mmAudioHeader.mmXWAVHeader.WAVEHeader.usChannels;
  374.  
  375.    /* Setup the mixer for playback of wave data
  376.     */
  377.    MixSetupParms.ulFormatMode = MCI_PLAY;
  378.    MixSetupParms.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
  379.    MixSetupParms.pmixEvent    = MixerEvent;
  380.  
  381.  
  382.    rc = mciSendCommand( usDeviceID,
  383.                         MCI_MIXSETUP,
  384.                         MCI_WAIT | MCI_MIXSETUP_INIT,
  385.                         ( PVOID ) &MixSetupParms,
  386.                         0 );
  387.  
  388.    MciError( rc );
  389.  
  390.    /* Use the suggested buffer size provide by the mixer device
  391.     * and the size of the audio file to calculate the required
  392.     * number of Amp-Mixer buffers.
  393.     * Note: The result is rounded up 1 to make sure we get the
  394.     *       tail end of the file.
  395.     */
  396.    aflus<<"foreslået MixSetupParms.ulBufferSize="<<MixSetupParms.ulBufferSize<<endl;
  397.    aflus<<"foreslået MixSetupParms.ulNumBuffers="<<MixSetupParms.ulNumBuffers<<endl;
  398.  
  399.  
  400.    antbuffere=MixSetupParms.ulNumBuffers=10;
  401.    bufferlgd =MixSetupParms.ulBufferSize=1024;
  402.  
  403.    aflus<<"anvendt MixSetupParms.ulBufferSize="<<MixSetupParms.ulBufferSize<<endl;
  404.    aflus<<"anvendt MixSetupParms.ulNumBuffers="<<MixSetupParms.ulNumBuffers<<endl;
  405.   
  406.    mixbuf32 = new int[bufferlgd];
  407.  
  408.    /* Set up the BufferParms data structure and allocate
  409.     * device buffers from the Amp-Mixer
  410.     */
  411.    BufferParms.ulNumBuffers = antbuffere;
  412.    BufferParms.ulBufferSize = bufferlgd;
  413.    BufferParms.pBufList = MixBuffers;
  414.  
  415.    rc = mciSendCommand( usDeviceID,
  416.                         MCI_BUFFER,
  417.                         MCI_WAIT | MCI_ALLOCATE_MEMORY,
  418.                         ( PVOID ) &BufferParms,
  419.                         0 );
  420.  
  421.    MciError( rc );
  422.  
  423.  
  424.    for( ulIndex = 0; ulIndex < antbuffere; ulIndex++)
  425.    {
  426.       memset( MixBuffers[ ulIndex ].pBuffer, '\0', BufferParms.ulBufferSize );
  427.       MixBuffers[ ulIndex ].ulBufferLength = BufferParms.ulBufferSize;
  428.    }
  429.  
  430.    bufteller = 0;
  431.  
  432.    for (int i=0; i<ANTKANALER; i++) {
  433.        intkanaler[i].samp=NULL;
  434.        intkanaler[i].vol=0;
  435.        intkanaler[i].finito=1;
  436.        intkanaler[i].lgd=0;
  437.    }
  438.  
  439.       /* Write two buffers to kick off the amp mixer.
  440.        */
  441.    rc = MixSetupParms.pmixWrite( MixSetupParms.ulMixHandle,
  442.                                MixBuffers,
  443.                                antbuffere);
  444. //   MciError(rc);
  445.  
  446.    statpos.ulItem = MCI_STATUS_POSITION;  // bruges i getpos
  447.  
  448. //   cerr<<"initDART() slut"<<endl;
  449.    
  450. }
  451.  
  452.  
  453.  
  454. void exitDART( void )
  455. {
  456. MCI_GENERIC_PARMS    GenericParms;
  457.  
  458. //   cerr<<"mastervol = "<<mastervol<<endl;
  459.  
  460.    rc = mciSendCommand( usDeviceID,
  461.                         MCI_BUFFER,
  462.                         MCI_WAIT | MCI_DEALLOCATE_MEMORY,
  463.                         ( PVOID )&BufferParms,
  464.                         0 );
  465.    MciError( rc );
  466.    rc = mciSendCommand( usDeviceID,
  467.                         MCI_CLOSE,
  468.                         MCI_WAIT ,
  469.                         ( PVOID )&GenericParms,
  470.                         0 );
  471.    MciError( rc );
  472.    delete mixbuf32;
  473.  
  474. //   for (int i=0;i<ANTKANALER;i++) cerr<<"kanal "<<i<<" vol="<<intkanaler[i].vol<<endl;
  475.    
  476. }
  477.  
  478.  
  479.  
  480. void    dPlayVoice(int kanal, Sample *SampPtr)
  481. {
  482.    MixTid t=gettid();
  483.  
  484.    intkanaler[kanal].samp = SampPtr;
  485.    intkanaler[kanal].start = t;
  486.    intkanaler[kanal].vol = 64;
  487.    intkanaler[kanal].lgd = SampPtr->Length;
  488.    intkanaler[kanal].finito = 0;
  489.    
  490.  
  491. //   mix((byte *)MixBuffers[t.buf%antbuffere].pBuffer+t.ofs,bufferlgd-t.ofs,mixbuf32,t);
  492. //   t.buf++;
  493. //   t.ofs=0;
  494.    
  495. //   mix((byte *)MixBuffers[t.buf%antbuffere].pBuffer,bufferlgd,mixbuf32,t);
  496.  
  497. //   cout<<endl<<"dPlayVoice "<<kanal<<" spiller "<<SampPtr->FileName<<" vol="<<intkanaler[kanal].vol<<endl;
  498. }
  499.  
  500.  
  501. void    dSetVoiceVolume(int kanal, int Volume) {  // vol <= 64
  502.    intkanaler[kanal].vol = Volume;
  503. //   cout<<"dSetVoiceVolume "<<kanal<<" vol="<<Volume<<endl;
  504. }
  505.  
  506.  
  507. void    dStopVoice(int kanal) {
  508.    intkanaler[kanal].finito = 1;
  509. }
  510.  
  511.  
  512. void    dSetSoundVolume(int Volume) {   // vol <= 255
  513.   mastervol = Volume;
  514. //  cout<<"dSetSoundVolume "<<Volume<<endl;
  515. }
  516.  
  517.  
  518. long    dGetVoicePos(int Voice) 
  519. {
  520.     int dif = gettid() - intkanaler[Voice].start;
  521.     if (dif > intkanaler[Voice].lgd) return intkanaler[Voice].lgd;
  522.     assert(dif>=0);
  523.     return dif;
  524. }
  525.  
  526.  
  527. void    dFreeSample(Sample *SampPtr){
  528.     for (int i=0; i<ANTKANALER; i++) {  
  529. /* for at være sikker på at den ikke bliver afspillet af en kanal */
  530.     intkanaler[i].samp=NULL;
  531.     intkanaler[i].vol=0;
  532.     intkanaler[i].finito=1;
  533.     intkanaler[i].lgd=0;
  534.     }
  535.  
  536.     if (SampPtr == NULL) return;
  537.     delete SampPtr->DataPtr;
  538.     delete SampPtr;
  539. }
  540.  
  541.  
  542.  
  543. #ifndef DEMO
  544.  
  545. #include <stdio.h>
  546.  
  547.  
  548.  
  549.  
  550.  
  551. char getch(void)
  552. {
  553.     return _read_kbd(0, 1, 0);
  554. }
  555.  
  556. int kbdhit(void)
  557. {
  558.     return (_read_kbd(0, 0, 0) != -1);
  559. }
  560.  
  561.  
  562.  
  563.  
  564. void main ( void )
  565. {
  566.   Sample *s1, *s2;
  567.   initDART();
  568.   dSetSoundVolume(255);
  569. //  dSetVoiceVolume(0,64);
  570. //  dSetVoiceVolume(1,64);
  571. //  s1 = dImportSample("forsk\\bye.wav", FORM_WAV);
  572.   s1 = dImportSample("d:\\spil\\billy\\samples\\bmove16\\fodtap.wav", FORM_WAV);
  573.   s2 = dImportSample("forsk\\hurry3.wav", FORM_WAV);
  574.   char ch;
  575. //  ch=getchar();
  576.   
  577.   dPlayVoice(0,s2);
  578.  
  579.  
  580.   int spillet=0;
  581.   
  582. /*
  583.   while (1) {
  584.       if (mixenbuffer) {
  585.     mixenbuffer=0;
  586.     mix((byte *)MixBuffers[bufteller%antbuffere].pBuffer,bufferlgd,mixbuf32,gettid());
  587.       }
  588.       if (sidstemmtime/3000 > spillet) {
  589.       dPlayVoice(1,s1);
  590.       spillet++;      
  591.       }
  592.       
  593.   }
  594.   */
  595.   
  596.   while ((ch=getch()) != 'x') {
  597.       DARTopdater();
  598.       switch (ch) {
  599.   case '1':
  600.       dPlayVoice(1,s1);
  601.       break;
  602.   case '2':
  603.       dPlayVoice(2,s2);
  604.       break;
  605.   case '3':
  606.       dPlayVoice(3,s1);
  607.       break;
  608.   case '4':
  609.       dPlayVoice(4,s2);
  610.       break;
  611.   case '+':
  612.       bufforsinkelse++;
  613.       break;
  614.   case '-':
  615.       bufforsinkelse--;
  616.       break;
  617.   case '?':
  618.       cerr<<"forsink: "<<bufforsinkelse<<endl;
  619.       break;
  620.       }
  621.   
  622.       
  623.   }
  624. }
  625.  
  626. #endif
  627.