Changeset 5553 for trunk/src


Ignore:
Timestamp:
Apr 20, 2001, 3:22:38 PM (24 years ago)
Author:
phaller
Message:

Fix crashes in PowerDVD 3

Location:
trunk/src/dsound
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/dsound/dart.cpp

    r5285 r5553  
    1 /* $Id: dart.cpp,v 1.4 2001-03-06 20:11:16 mike Exp $ */
     1/* $Id: dart.cpp,v 1.5 2001-04-20 13:22:37 phaller Exp $ */
    22/*
    33 *  Dart Interface..
     
    5151     )
    5252   {
    53       lLastBuff++;
    54       if (lLastBuff == ulNumDartBuffs){
    55          lLastBuff = 0;
    56       }
    57 
    58       if( fIsPlaying == FALSE /*&& lLastBuff == 0*/ ){
    59          mciSendCommand(usDeviceID, MCI_STOP, MCI_WAIT, NULL, 0);
    60          return TRUE;
    61       }
     53     // wrap last buffer index
     54     lLastBuff++;
     55     if (lLastBuff >= ulNumDartBuffs)
     56     {
     57       lLastBuff = 0;
     58     }
     59
     60     if( fIsPlaying == FALSE /*&& lLastBuff == 0*/ )
     61     {
     62       mciSendCommand(usDeviceID, MCI_STOP, MCI_WAIT, NULL, 0);
     63       return TRUE;
     64     }
    6265
    6366      /* Now mix sound from all playing secondary SoundBuffers into the primary buffer */
     
    370373long Dart_Play(USHORT usDeviceID, void *vpMixSetup, void *vpMixBuffer, long playing)
    371374{
    372    ULONG   rc;
    373    MCI_MIXSETUP_PARMS  *MixSetup;
    374    MCI_MIX_BUFFER      *MixBuffer;
    375 
    376    MixSetup  = (MCI_MIXSETUP_PARMS*)vpMixSetup;
    377    MixBuffer = (MCI_MIX_BUFFER*)vpMixBuffer;
    378 
    379    dprintf(("DSOUND-DART: Dart_Play"));
    380 
    381    if (playing == TRUE) {
    382       rc = mciSendCommand(usDeviceID, MCI_RESUME, MCI_WAIT, NULL, 0);
    383       if (rc != MCIERR_SUCCESS) {
    384          dprintf(("DSOUND-DART: MCI_RESUME %d", rc));
    385          return DSERR_GENERIC;
    386       }
    387    } else { //if (playing==FALSE)
    388       dprintf(("DSOUND-DART: Playback started!!!!"));
    389 
    390       /* Mix the first buffer before playing */
     375  ULONG   rc;
     376  MCI_MIXSETUP_PARMS  *MixSetup;
     377  MCI_MIX_BUFFER      *MixBuffer;
     378
     379  MixSetup  = (MCI_MIXSETUP_PARMS*)vpMixSetup;
     380  MixBuffer = (MCI_MIX_BUFFER*)vpMixBuffer;
     381
     382  dprintf(("DSOUND-DART: Dart_Play"));
     383
     384  if (playing == TRUE)
     385  {
     386    rc = mciSendCommand(usDeviceID, MCI_RESUME, MCI_WAIT, NULL, 0);
     387    if (rc != MCIERR_SUCCESS)
     388    {
     389      dprintf(("DSOUND-DART: MCI_RESUME %d", rc));
     390      return DSERR_GENERIC;
     391    }
     392  }
     393  else
     394  { //if (playing==FALSE)
     395    dprintf(("DSOUND-DART: Playback started!!!!"));
     396   
     397    // verify if buffers have actually been allocated
     398    // PH 2001-04-20 Power DVD 3 seens to come in here
     399    // with ulNumDartBuffs == 0 and also pmixWrite==NULL.
     400    // However pmixEvent is != NULL. So I assume (!)
     401    // this might fix the cause.
     402    //
     403    // Does fix the crash actually. I suspect DART cannot
     404    // deliver mixing functions for the requested sound format:
     405    // 16-Bit, 4-channel?, 48kHz.
     406    if( (MixSetup->pmixWrite != NULL) &&
     407        (MixSetup->ulNumBuffers > 0) )
     408    {
     409
     410    /* Mix the first buffer before playing */
    391411      MixCallback(BUFFER_SIZE/ulNumDartBuffs);
    392412      memcpy(MixBuffer[lLastBuff].pBuffer, &pDSoundBuff[lLastBuff*(BUFFER_SIZE/ulNumDartBuffs)], BUFFER_SIZE/ulNumDartBuffs);
     
    398418      SetFS(sel);
    399419      fIsPlaying = TRUE;
    400    }
    401 
    402    return DS_OK;
    403 }
     420    }
     421  }
     422
     423  return DS_OK;
     424}
  • trunk/src/dsound/dsmixer.cpp

    r5285 r5553  
    1 /* $Id: dsmixer.cpp,v 1.4 2001-03-06 20:11:17 mike Exp $ */
     1/* $Id: dsmixer.cpp,v 1.5 2001-04-20 13:22:38 phaller Exp $ */
    22/*
    33 * DirectSound Software Mixer
     
    2828#include <misc.h>
    2929
    30 signed long mixbuf[2300*2]; /* enough for 50 ms at 44100Hz stereo */
    31 
    32 void MixCallback(ULONG cbMix) {
    33    // Check for priority level here; for DSSCL_WRITEPRIMARY just play directly
    34    // from the primary buffer; for all others mix the secondary buffers
    35    if (OS2IDirectSoundBuffer::primary->parentDS->GetCoopLevel() != DSSCL_WRITEPRIMARY)
    36       MixFunc(OS2IDirectSoundBuffer::dsbroot, OS2IDirectSoundBuffer::primary, cbMix);
    37    else {
    38    }
     30//@@@ signed long mixbuf[2300*2]; /* enough for 50 ms at 44100Hz stereo */
     31
     32
     33// The internal mixer buffer for sample calculations
     34// It's allocated on demand by MixFunc.
     35static signed long* mixbuf = NULL;   // pointer to the mixer data buffer
     36static ulMixerBufferSize = 0;        // current size of the mixer buffer
     37
     38
     39void MixCallback(ULONG cbMix)
     40{
     41  // Check for priority level here; for DSSCL_WRITEPRIMARY just play directly
     42  // from the primary buffer; for all others mix the secondary buffers
     43  if (OS2IDirectSoundBuffer::primary->parentDS->GetCoopLevel() != DSSCL_WRITEPRIMARY)
     44    MixFunc(OS2IDirectSoundBuffer::dsbroot, OS2IDirectSoundBuffer::primary, cbMix);
     45  else
     46  {
     47  }
    3948}
     49
    4050
    4151void MixOneBuffer(OS2IDirectSoundBuffer *inBuf, int tomix, int outrate)
    4252{
    43    unsigned char *data8b;
    44    signed short *data16b;
    45    int inpos, spd, i, j, sample, len, bytespersample, vol1, vol2;
    46    int oldpos;
    47 
    48    bytespersample = inBuf->lpfxFormat->wBitsPerSample *
    49       inBuf->lpfxFormat->nChannels / 8;
    50    inpos = inBuf->playpos / bytespersample * 1024 + inBuf->frac;
    51    spd = 1024 * inBuf->frequency / outrate;
    52    if (inBuf->pan <= 0)
    53       vol1 = inBuf->volume;
    54    else
    55       vol1 = inBuf->volume * (256 - inBuf->pan) / 256;
    56    if (inBuf->pan >= 0)
    57       vol2 = inBuf->volume;
    58    else
    59       vol2 = inBuf->volume * (256 + inBuf->pan) / 256;
    60 
    61    len = inBuf->bufferdesc.dwBufferBytes / bytespersample * 1024;
    62    if ((inBuf->lpfxFormat->nChannels == 2) && (inBuf->lpfxFormat->wBitsPerSample == 16)) {
    63       data16b = (signed short *) inBuf->lpBuffer;
    64       for (i = 0; i < tomix; i++) {
    65          j = inpos / 1024 * 2;
    66          mixbuf[i*2] += data16b[j] * vol1 / 256;
    67          mixbuf[i*2+1] += data16b[j+1] * vol2 / 256;
    68          inpos += spd;
    69          if (inpos >= len) {
    70             if (inBuf->fLoop) inpos -= len;
    71             else {
    72                inBuf->fPlaying = FALSE;
    73                if (inBuf->notify != NULL)
    74                   inBuf->notify->CheckStop();
    75                break;
    76             }
    77          }
    78       }
    79    }
    80    if ((inBuf->lpfxFormat->nChannels == 1) && (inBuf->lpfxFormat->wBitsPerSample == 16)) {
    81       data16b = (signed short *) inBuf->lpBuffer;
    82       for (i = 0; i < tomix; i++) {
    83          j = inpos / 1024;
    84          sample = data16b[j];
    85          mixbuf[i*2] += sample * vol1 / 256;
    86          mixbuf[i*2+1] += sample * vol2 / 256;
    87          inpos += spd;
    88          if (inpos >= len) {
    89             if (inBuf->fLoop) inpos -= len;
    90             else {
    91                inBuf->fPlaying = FALSE;
    92                if (inBuf->notify != NULL)
    93                   inBuf->notify->CheckStop();
    94                break;
    95             }
    96          }
    97       }
    98    }
    99    if ((inBuf->lpfxFormat->nChannels == 2) && (inBuf->lpfxFormat->wBitsPerSample == 8)) {
    100       data8b = (unsigned char *) inBuf->lpBuffer;
    101       for (i = 0; i < tomix; i++) {
    102          j = inpos / 1024 * 2;
    103          sample = ((int) data8b[j] - 128) * vol1;
    104          mixbuf[i*2] += sample;
    105          sample = ((int) data8b[j+1] - 128) * vol2;
    106          mixbuf[i*2+1] += sample;
    107          inpos += spd;
    108          if (inpos >= len) {
    109             if (inBuf->fLoop) inpos -= len;
    110             else {
    111                inBuf->fPlaying = FALSE;
    112                if (inBuf->notify != NULL)
    113                   inBuf->notify->CheckStop();
    114                break;
    115             }
    116          }
    117       }
    118    }
    119    if ((inBuf->lpfxFormat->nChannels == 1) && (inBuf->lpfxFormat->wBitsPerSample == 8)) {
    120       data8b = (unsigned char *) inBuf->lpBuffer;
    121       for (i = 0; i < tomix; i++) {
    122          j = inpos / 1024;
    123          sample = (int) data8b[j] - 128;
    124          mixbuf[i*2] += sample * vol1;
    125          mixbuf[i*2+1] += sample * vol2;
    126          inpos += spd;
    127          if (inpos >= len) {
    128             if (inBuf->fLoop) inpos -= len;
    129             else {
    130                inBuf->fPlaying = FALSE;
    131                if (inBuf->notify != NULL)
    132                   inBuf->notify->CheckStop();
    133                break;
    134             }
    135          }
    136       }
    137    }
    138    oldpos         = inBuf->playpos;
    139    inBuf->playpos = inpos / 1024 * bytespersample;
    140    inBuf->frac    = inpos % 1024;
    141 
    142    // Check if any notifications are to be signaled
    143    if (inBuf->notify != NULL)
    144       inBuf->notify->CheckPos(oldpos, inBuf->playpos);
    145 
    146    // keep the write cursor about 15ms ahead of the play cursor
    147    inBuf->writepos  = inBuf->playpos + inBuf->frequency * bytespersample / 67;
    148    inBuf->writepos %= inBuf->bufferdesc.dwBufferBytes;
     53  unsigned char *data8b;
     54  signed short *data16b;
     55  int inpos, spd, i, j, sample, len, bytespersample, vol1, vol2;
     56  int oldpos;
     57
     58  bytespersample = inBuf->lpfxFormat->wBitsPerSample *
     59    inBuf->lpfxFormat->nChannels / 8;
     60  inpos = inBuf->playpos / bytespersample * 1024 + inBuf->frac;
     61  spd = 1024 * inBuf->frequency / outrate;
     62  if (inBuf->pan <= 0)
     63    vol1 = inBuf->volume;
     64  else
     65    vol1 = inBuf->volume * (256 - inBuf->pan) / 256;
     66  if (inBuf->pan >= 0)
     67    vol2 = inBuf->volume;
     68  else
     69    vol2 = inBuf->volume * (256 + inBuf->pan) / 256;
     70
     71  len = inBuf->bufferdesc.dwBufferBytes / bytespersample * 1024;
     72  if ((inBuf->lpfxFormat->nChannels == 2) &&
     73      (inBuf->lpfxFormat->wBitsPerSample == 16))
     74  {
     75    data16b = (signed short *) inBuf->lpBuffer;
     76    for (i = 0; i < tomix; i++)
     77    {
     78      j = inpos / 1024 * 2;
     79      mixbuf[i*2] += data16b[j] * vol1 / 256;
     80      mixbuf[i*2+1] += data16b[j+1] * vol2 / 256;
     81      inpos += spd;
     82      if (inpos >= len)
     83      {
     84        if (inBuf->fLoop) inpos -= len;
     85        else
     86        {
     87          inBuf->fPlaying = FALSE;
     88          if (inBuf->notify != NULL)
     89            inBuf->notify->CheckStop();
     90         
     91          break;
     92        }
     93      }
     94    }
     95  }
     96 
     97  if ((inBuf->lpfxFormat->nChannels == 1) &&
     98      (inBuf->lpfxFormat->wBitsPerSample == 16))
     99  {
     100    data16b = (signed short *) inBuf->lpBuffer;
     101    for (i = 0; i < tomix; i++)
     102    {
     103      j = inpos / 1024;
     104      sample = data16b[j];
     105      mixbuf[i*2] += sample * vol1 / 256;
     106      mixbuf[i*2+1] += sample * vol2 / 256;
     107      inpos += spd;
     108      if (inpos >= len)
     109      {
     110        if (inBuf->fLoop) inpos -= len;
     111        else
     112        {
     113          inBuf->fPlaying = FALSE;
     114          if (inBuf->notify != NULL)
     115            inBuf->notify->CheckStop();
     116         
     117          break;
     118        }
     119      }
     120    }
     121  }
     122 
     123  if ((inBuf->lpfxFormat->nChannels == 2) &&
     124      (inBuf->lpfxFormat->wBitsPerSample == 8))
     125  {
     126    data8b = (unsigned char *) inBuf->lpBuffer;
     127    for (i = 0; i < tomix; i++)
     128    {
     129      j = inpos / 1024 * 2;
     130      sample = ((int) data8b[j] - 128) * vol1;
     131      mixbuf[i*2] += sample;
     132      sample = ((int) data8b[j+1] - 128) * vol2;
     133      mixbuf[i*2+1] += sample;
     134      inpos += spd;
     135      if (inpos >= len)
     136      {
     137        if (inBuf->fLoop) inpos -= len;
     138        else
     139        {
     140          inBuf->fPlaying = FALSE;
     141          if (inBuf->notify != NULL)
     142            inBuf->notify->CheckStop();
     143         
     144          break;
     145        }
     146      }
     147    }
     148  }
     149 
     150  if ((inBuf->lpfxFormat->nChannels == 1) &&
     151      (inBuf->lpfxFormat->wBitsPerSample == 8))
     152  {
     153    data8b = (unsigned char *) inBuf->lpBuffer;
     154    for (i = 0; i < tomix; i++)
     155    {
     156      j = inpos / 1024;
     157      sample = (int) data8b[j] - 128;
     158      mixbuf[i*2] += sample * vol1;
     159      mixbuf[i*2+1] += sample * vol2;
     160      inpos += spd;
     161      if (inpos >= len)
     162      {
     163        if (inBuf->fLoop) inpos -= len;
     164        else
     165        {
     166          inBuf->fPlaying = FALSE;
     167          if (inBuf->notify != NULL)
     168            inBuf->notify->CheckStop();
     169         
     170          break;
     171        }
     172      }
     173    }
     174  }
     175 
     176  oldpos         = inBuf->playpos;
     177  inBuf->playpos = inpos / 1024 * bytespersample;
     178  inBuf->frac    = inpos % 1024;
     179
     180  // Check if any notifications are to be signaled
     181  if (inBuf->notify != NULL)
     182    inBuf->notify->CheckPos(oldpos, inBuf->playpos);
     183
     184  // keep the write cursor about 15ms ahead of the play cursor
     185  inBuf->writepos  = inBuf->playpos + inBuf->frequency * bytespersample / 67;
     186  inBuf->writepos %= inBuf->bufferdesc.dwBufferBytes;
    149187}
    150188
    151 void MixFunc (OS2IDirectSoundBuffer *firstBuf, OS2IDirectSoundBuffer *outBuf,
    152    ULONG cbMix) {
    153    OS2IDirectSoundBuffer *inBuf = firstBuf;
    154    int i, outbits, outrate, outnch, tomix, outpos, outlen;
    155    unsigned char *data8b;
    156    signed short *data16b;
    157 
    158    outbits = outBuf->lpfxFormat->wBitsPerSample;
    159    outrate = outBuf->lpfxFormat->nSamplesPerSec;
    160    outnch = outBuf->lpfxFormat->nChannels;
    161    tomix = cbMix * 8 / outbits / outnch;
    162 
    163    memset(&mixbuf[0], 0, tomix * 2 * sizeof(mixbuf[0]));
    164 
    165    while (inBuf != NULL) {
    166       if (inBuf->fPlaying) {
    167          MixOneBuffer(inBuf, tomix, outrate);
    168       }
    169       inBuf = inBuf->next;
    170    }
    171 
    172    outpos = outBuf->playpos * 8 / outbits;
    173    outlen = outBuf->bufferdesc.dwBufferBytes * 8 / outbits;
    174    if (outbits == 16) {
    175       data16b = (signed short *) outBuf->lpBuffer;
    176       for (i = 0; i < tomix * outnch; i++) {
    177          if (mixbuf[i] <= -32768) data16b[outpos] = -32768;
    178          else if (mixbuf[i] >= 32767) data16b[outpos] = 32767;
    179          else data16b[outpos] = (signed short)mixbuf[i];
    180          outpos++;
    181          if (outpos >= outlen) outpos = 0;
    182       }
    183    } else {
    184       data8b = (unsigned char *) outBuf->lpBuffer;
    185       for (i = 0; i < tomix * outnch; i++) {
    186          if (mixbuf[i] <= -32768) data8b[outpos] = 0;
    187          else if (mixbuf[i] >= 32767) data8b[outpos] = 255;
    188          else data8b[outpos] = (signed short)mixbuf[i] / 256 + 128;
    189          outpos++;
    190          if (outpos >= outlen) outpos = 0;
    191       }
    192    }
    193    outBuf->playpos = outpos * outbits / 8;
     189
     190void MixFunc (OS2IDirectSoundBuffer *firstBuf,
     191              OS2IDirectSoundBuffer *outBuf,
     192              ULONG cbMix)
     193{
     194  OS2IDirectSoundBuffer *inBuf = firstBuf;
     195  int i;
     196  int outbits;
     197  int outrate;
     198  int outnch;
     199  int tomix;
     200  int outpos;
     201  int outlen;
     202  unsigned char *data8b;
     203  signed short *data16b;
     204
     205  outbits = outBuf->lpfxFormat->wBitsPerSample;
     206  outrate = outBuf->lpfxFormat->nSamplesPerSec;
     207  outnch = outBuf->lpfxFormat->nChannels;
     208  tomix = cbMix * 8 / outbits / outnch;
     209 
     210  // calculate required size (elements) of mixer buffer
     211  ULONG ulRequiredSize = tomix * outnch;
     212 
     213  // dynamically allocate the mixerbuffer as required
     214  if (ulMixerBufferSize < ulRequiredSize)
     215  {
     216    // check if buffer has been allocated at all
     217    if (NULL == mixbuf)
     218    {
     219      // allocate new buffer
     220      mixbuf = (signed long*) malloc(ulRequiredSize * sizeof(mixbuf[0]));
     221      ulMixerBufferSize = tomix;
     222    }
     223    else
     224    {
     225      // reallocate existing buffer
     226      mixbuf = (signed long*) realloc(mixbuf, ulRequiredSize * sizeof(mixbuf[0]));
     227      ulMixerBufferSize = tomix;
     228    }
     229  }
     230 
     231 
     232  /* PH 2001-04-20 PowerDVD 3 comes in with tomix==4096
     233   * (ulNumDartBuffers == 1.
     234   * So below memset() crashed as the former static
     235   * mixer buffer was way to small. The dynamic allocation
     236   * is supposed to fix this.
     237   *
     238   * Also the assumption (?) of outnch == 2 is not met here.
     239   * PowerDVD tries with 4 channels, thus requiring an even
     240   * larger buffer.
     241   */
     242  memset(&mixbuf[0], 0, ulRequiredSize * sizeof(mixbuf[0]));
     243
     244 
     245  while (inBuf != NULL)
     246  {
     247    if (inBuf->fPlaying)
     248    {
     249      MixOneBuffer(inBuf, tomix, outrate);
     250    }
     251    inBuf = inBuf->next;
     252  }
     253
     254  outpos = outBuf->playpos * 8 / outbits;
     255  outlen = outBuf->bufferdesc.dwBufferBytes * 8 / outbits;
     256
     257  if (outbits == 16)
     258  {
     259    data16b = (signed short *) outBuf->lpBuffer;
     260    for (i = 0; i < tomix * outnch; i++)
     261    {
     262      if (mixbuf[i] <= -32768)
     263        data16b[outpos] = -32768;
     264      else
     265        if (mixbuf[i] >= 32767)
     266          data16b[outpos] = 32767;
     267        else
     268          data16b[outpos] = (signed short)mixbuf[i];
     269     
     270      outpos++;
     271     
     272      if (outpos >= outlen)
     273        outpos = 0;
     274    }
     275  }
     276  else
     277  {
     278    data8b = (unsigned char *) outBuf->lpBuffer;
     279    for (i = 0; i < tomix * outnch; i++)
     280    {
     281      if (mixbuf[i] <= -32768)
     282        data8b[outpos] = 0;
     283      else
     284        if (mixbuf[i] >= 32767)
     285          data8b[outpos] = 255;
     286        else
     287          data8b[outpos] = (signed short)mixbuf[i] / 256 + 128;
     288     
     289      outpos++;
     290      if (outpos >= outlen)
     291        outpos = 0;
     292    }
     293  }
     294 
     295  outBuf->playpos = outpos * outbits / 8;
    194296}
    195297
Note: See TracChangeset for help on using the changeset viewer.