Bernhard K. hat geschrieben: ↑25.10.2021 21:45:29
tritt bei euch auch das Problem auf, dass manche Fahrpläne (z.B. Grenzlandbahnen oder Lehrte-Harburg 2018) den Simulator aufhängen?
Ja, das liegt bei mir an dsound. Es sind sehr viele Soundbuffer gleichzeitig im Zustand "Abspielen", einige (?) davon müssen wohl auch noch resampled werden, damit sie zur Ausgabe passen. Die Zahl der Soundbuffer geht mit der Zahl der in der Nähe befindlichen Schienenfahrzeuge stark nach oben, wahrscheinlich sind es Rollgeräusche. Der Trick ist jetzt, dass fast alle dieser Soundbuffer zwar im "Abspielen"-Zustand sind, aber auf Lautstärke 0, weil das Fahrzeug steht. Wine macht sich trotzdem den Stress mit resampling, mixing usw. obwohl am Ende natürlich alles mit 0 multipliziert wird (in DSOUND_MixerVol()).
Ich hatte auch schon eine Serie von Patches dafür erstellt, aber die waren dann am Ende viel zu groß und umständlich und hätten wohl kaum den Segen der Wine-Maintainer gefunden.
Jetzt habe ich mal eine relativ "minimalinvasive" Version erstellt. Ich bin mir nur nicht ganz sicher, ob das vielleicht unerwünschte Nebenwirkungen hat. Diesen FIR-Filter für das Resampling kapiere ich nicht. Möglicherweise muss man den Zustand davon irgendwie resetten, wenn man aufgrund von Lautstärke 0 den Resampling-Schritt überspringt, damit es beim Hochfahren der Lautstärke dann nicht falsch klingt? Entweder ich kapiere es irgendwann noch, oder ich wage es, das Ding mal an die Mailingliste zu schicken und zu schauen, was dort dazu gesagt wird… So sieht es momentan aus, wobei die Festlegung von is_muted glaube ich noch etwas zu einfach ist und so Dinge wie das Flag "dsb->dsbd.dwFlags & DSBCAPS_CTRLPAN" berücksichtigen müsste, so wie es auch in DSOUND_MixerVol() getan wird.
Code: Alles auswählen
diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c
index e9d8a6e3cdd..c0fd437096a 100644
--- a/dlls/dsound/mixer.c
+++ b/dlls/dsound/mixer.c
@@ -283,13 +283,18 @@ static inline float get_current_sample(const IDirectSoundBufferImpl *dsb,
return dsb->get(dsb, buffer + (mixpos % buflen), channel);
}
-static UINT cp_fields_noresample(IDirectSoundBufferImpl *dsb, UINT count)
+static UINT cp_fields_noresample(IDirectSoundBufferImpl *dsb, UINT count,
+ BOOL is_muted)
{
UINT istride = dsb->pwfx->nBlockAlign;
UINT ostride = dsb->device->pwfx->nChannels * sizeof(float);
UINT committed_samples = 0;
DWORD channel, i;
+ /* If the buffer is muted, we won't hear anything anyway, so skip this. */
+ if (is_muted)
+ return count;
+
if(dsb->use_committed) {
committed_samples = (dsb->writelead - dsb->committed_mixpos) / istride;
committed_samples = committed_samples <= count ? committed_samples : count;
@@ -308,7 +313,8 @@ static UINT cp_fields_noresample(IDirectSoundBufferImpl *dsb, UINT count)
return count;
}
-static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count, LONG64 *freqAccNum)
+static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count,
+ LONG64 *freqAccNum, BOOL is_muted)
{
UINT i, channel;
UINT istride = dsb->pwfx->nBlockAlign;
@@ -329,6 +335,12 @@ static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count, LONG64 *
len += fir_cachesize;
len *= sizeof(float);
+ *freqAccNum = freqAcc_end % dsb->freqAdjustDen;
+
+ /* If the buffer is muted, we won't hear anything anyway, so skip this. */
+ if (is_muted)
+ return max_ipos;
+
if (!dsb->device->cp_buffer) {
dsb->device->cp_buffer = HeapAlloc(GetProcessHeap(), 0, len);
dsb->device->cp_buffer_len = len;
@@ -386,19 +398,23 @@ static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count, LONG64 *
}
}
- *freqAccNum = freqAcc_end % dsb->freqAdjustDen;
-
return max_ipos;
}
static void cp_fields(IDirectSoundBufferImpl *dsb, UINT count, LONG64 *freqAccNum)
{
DWORD ipos, adv;
+ UINT channel;
+ BOOL is_muted = TRUE;
+
+ for (channel = 0; channel < dsb->device->pwfx->nChannels; channel++)
+ if (dsb->volpan.dwTotalAmpFactor[channel] != 0)
+ is_muted = FALSE;
if (dsb->freqAdjustNum == dsb->freqAdjustDen)
- adv = cp_fields_noresample(dsb, count); /* *freqAccNum is unmodified */
+ adv = cp_fields_noresample(dsb, count, is_muted); /* *freqAccNum is unmodified */
else
- adv = cp_fields_resample(dsb, count, freqAccNum);
+ adv = cp_fields_resample(dsb, count, freqAccNum, is_muted);
ipos = dsb->sec_mixpos + adv * dsb->pwfx->nBlockAlign;
if (ipos >= dsb->buflen) {
Eine andere Baustelle bzgl. Performance ist auch die gdi+-Bibliothek. Die integrierten ZusiDisplay-Displays hinken dadurch teilweise hinterher und vor allem die FIS-Bedienung ist fast unmöglich, jedenfalls auf meiner altersschwachen Hardware. Als ich vor längerer Zeit mal geschaut hatte, hat da diese Änderung relativ viel gebracht, aber auch noch nicht genug (wobei die mapping.c jetzt von gdi32 in win32u umgezogen ist):
Code: Alles auswählen
diff --git a/dlls/gdi32/mapping.c b/dlls/gdi32/mapping.c
index 83582846486..7bf7f3e17bb 100644
--- a/dlls/gdi32/mapping.c
+++ b/dlls/gdi32/mapping.c
@@ -156,8 +156,12 @@ INT CDECL nulldrv_SetMapMode( PHYSDEV dev, INT mode )
if (mode == dc->MapMode && (mode == MM_ISOTROPIC || mode == MM_ANISOTROPIC)) return ret;
- virtual_size = get_dc_virtual_size( dc );
- virtual_res = get_dc_virtual_res( dc );
+ if (mode != MM_TEXT)
+ {
+ virtual_size = get_dc_virtual_size( dc );
+ virtual_res = get_dc_virtual_res( dc );
+ }
+
switch (mode)
{
case MM_TEXT:
Weil get_dc_virtual_size() ziemlich teuer war damals, das fragte irgendwie extra den X-Server nach der Auflösung oder so, und das Ergebnis wird für die häufigen Aufrufe mit MM_TEXT gar nicht benötigt. Das Resampling beim Verkleinern von Bitmaps in der gdiplus von wine, was ZusiDisplay auch benötigt, ist auch nicht gerade sehr flott.
Danke auch für das Einfügen der für die neuen Buchfahrpläne nötigen Konvertierung :-)
Edit: Hatte den halben Patch nicht mitkopiert