Limiting sounds playing at once

Questions about Wine on Linux
Post Reply
CharlieB
Level 1
Level 1
Posts: 8
Joined: Sun Jan 23, 2011 9:14 am

Limiting sounds playing at once

Post by CharlieB » Sat Jan 04, 2020 2:05 pm

Hi all,

I am running Battlezone Redux from GOG and noticed a severe slowdown (slide show) when there was a lots of sounds playing. 31 at once. Since there was no setting in the game to fix this I went into the Wine code for mixer.c. I added a function that would stop sounds based on the most likely not needed. I put the max sounds at 20 which my computer handles fine. Here is the hack I added that is called at the end of function DSOUND_MixToPrimary()

Code: Select all

void stop_excess_dsound_channels (const DirectSoundDevice *device)
{
  int i, n, c, max, mv;
  IDirectSoundBufferImpl *dsb;
  
  mv = rint (DSBVOLUME_MIN * 0.3);      /* calc lower volume */
  n = 0; max = 20;
  for (i = 0; i < device->nrofbuffers; i++) 
  {
    dsb = device->buffers[i];
    if (dsb->state == STATE_PLAYING) n++;
  }
  if (n <= max) return;
  
  for (i = 0; i < device->nrofbuffers; i++) /* remove lower volume sounds */
  {
    dsb = device->buffers[i];
    if (dsb->state != STATE_PLAYING) continue;
    /* printf ("buffer volume = %d, mv = %d\n", dsb->volpan.lVolume, mv); */
    if ((dsb->playflags & DSBPLAY_LOOPING) != 0) continue;  /* skip looping */
    if (dsb->volpan.lVolume > mv) continue;
    dsb->state = STATE_STOPPING;
    n--;
    if (n <= max) return;
  }
  
  for (i = 0; i < device->nrofbuffers; i++) /* remove sounds already played 1/2 way thru */
  {
    dsb = device->buffers[i];
    if (dsb->state != STATE_PLAYING) continue;
    if ((dsb->playflags & DSBPLAY_LOOPING) != 0) continue;  /* skip looping */
    
    if (dsb->sec_mixpos >= (dsb->buflen >> 1))
    {
      dsb->state = STATE_STOPPING;
      n--;
      if (n <= max) return;
    }
  }

  for (i = 0; i < device->nrofbuffers; i++) 
  {
    dsb = device->buffers[i];
    if (dsb->state != STATE_PLAYING) continue;
    dsb->state = STATE_STOPPING;
    n--;
    if (n <= max) return;
  }
}
Incidentally when I used the Microsoft's dsound it seemed to do the same thing but would cull the next sound making the important ones not heard. Plus adding a lag when the sounds played.

What is even more strange is it appears that DSOUND_MixToPrimary() isn't called until there starts to be many sounds playing. DSOUND_MixToPrimary() seems to be called when they "get out of hand" so to speak.

Would it be possible to add an environment variable to specify how many sounds can play at once? Such as WINEMIXMAX.

Thanks

User avatar
DarkShadow44
Level 8
Level 8
Posts: 1108
Joined: Tue Nov 22, 2016 5:39 pm

Re: Limiting sounds playing at once

Post by DarkShadow44 » Sun Jan 19, 2020 5:15 pm

Possible? Sure.
Will it happen? IMHO not.
But devs don't always visit the forums, you could try posting to wine-devel.

Post Reply