Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor the ReelMagic audio FIFO class #2090

Merged
merged 6 commits into from Nov 29, 2022
Merged

Refactor the ReelMagic audio FIFO class #2090

merged 6 commits into from Nov 29, 2022

Conversation

kcgen
Copy link
Member

@kcgen kcgen commented Nov 26, 2022

Suggest reviewing commit-by-commit.

The refactored ReelMagic AudioFifo class now loads audio directly into DOSBox Staging's mixer (via pointer from the MPEG stream's decoded interleaved audio buffer) without queuing or math operations performed on the samples.

It now also skips initial gaps in decoded audio.

The ReelMagic's mixer channel is now activated on an as-needed basis.

Playback is working smooth with fewer initial audio hiccups, even at 800 Mhz:

2022-11-26_13-11

Tips for optimal performance

  1. Use your lowest latency [sdl] conf settings. If you're using a Raspberry Pi, be sure to use the recommended baseline configs.

  2. In addition to the baseline settings, further apply these ReelMagic specific settings, which are suitable for all the ReelMagic games:

[mixer]
rate = 44100
prebuffer = 33

[cpu]
core = dynamic
cycles = 3000

[dos]
umb = false
ems = false
xms = true

[reelmagic]
reelmagic = on

Notes:

  • The mixer's rate is run at 44.1 KHz to match the MEPG-1 Layer II audio streams found in all known ReelMagic DOS MPEG games.
  • The mixer's prebuffer is set to 33 ms to match the MPEG decoder's single frame of latency (1 000 ms / 29.97 fps = 33.36 ms). To confirm AV sync, watch scenes with explosions, gunshots, and verbal plosives.

@kcgen kcgen added the refactoring Code refactoring without any functional changes label Nov 26, 2022
@kcgen kcgen self-assigned this Nov 26, 2022
@kcgen kcgen force-pushed the kc/reelmagic-fifo-3 branch 7 times, most recently from 664ee68 to 787b2dd Compare November 27, 2022 19:31
@kcgen kcgen requested a review from kklobe November 27, 2022 19:47
@kcgen kcgen force-pushed the kc/reelmagic-fifo-3 branch 2 times, most recently from b98a5e7 to 79e99f3 Compare November 28, 2022 02:53
Context: the Sound Blaster's internal frequency can be derived from the
Transfer Time constant passed into the 40h call:

Time Constant = 65536 - (256 000 000/(channels * sampling rate)

 - The channels parameter is 1 for mono, 2 for stereo.

 - Only the high byte of the result is sent to the DSP.

Ref:
 Sound Blaster Series Hardware Programming Guide
 Set digitized sound  transfer time constant, 6-14 DSP Commands
 https://pdos.csail.mit.edu/6.828/2018/readings/hardware/SoundBlaster.pdf

---

If we solve for the sampling rate:

                            256 000 000
sampling rate = ----------------------------------------
                <channels> * (65536 - (<high-byte> << 8))

Where <channels> can be 1 or 2 and <high-byte> 0 to 255.

Here's are some sample rates:

  mono (1 channel) with high-byte 0   =>     3 906 Hz
  mono (1 channel) with high-byte 127 =>     7 751 Hz
  mono (1 channel) with high-byte 166 =>    11 111 Hz
  mono (1 channel) with high-byte 234 =>    45 454 Hz
  mono (1 channel) with high-byte 255 => 1 000 000 Hz

  stereo (2 channels) with high-byte 0   =>   1 953 Hz
  stereo (2 channels) with high-byte 127 =>   3 875 Hz
  stereo (2 channels) with high-byte 211 =>  11 111 Hz
  stereo (2 channels) with high-byte 245 =>  45 454 Hz
  stereo (2 channels) with high-byte 255 => 500 000 Hz

The high-byte passed into 40h is valid for setting DMA rates however the
above shows we can't trust it to give us a valid playback rate within the
documented 5-45 Khz range.

So this commit simply keeps the the sound blaster's requested channel rate
between the 5 to 45 KHz range.

This can be seen in The Horde ReelMagic edition, which, on initialization,
feeds the Sound Blaster a 255-value via 40h, which in turn (previously)
asked the mixer channel to run at 1 million Hz :)
The prior code could overflow into a large negative number if the elapsed
PIT ticks exceeded the read latch. This would result in the uint32_t
wrapping to a value of 4+ billion, exceeding `iround`'s signed integer
limit.

This occurs in The Horde, ReelMagic edition.
A double free was encountered when shutting down
The Horde (ReelMagic edition) using Opus CD-DA tracks.
DOSBox's mixer has (for a very long time) allowed adjustment of a
channel's volume through a user control (via MIXER) and by the
application (via the SB Mixer), however the names of these
member variables and their functions to manage them were often not
obvious.

This commit renames names these variables and functions to match
their purpose.

It also adds a third fixed volume scalar to let a channel scale up
or down it's samples to get to 0 dB on the signed 16-bit scale,
which is used by the ReelMagic and GUS chanels.
This uses current decoded MP2 frame as the FIFO
itself without any copying or re-buffering.
@kcgen
Copy link
Member Author

kcgen commented Nov 29, 2022

Completed testing on the Pi 4. See recommended settings in the PR comment above (applicable to all systems).

Even during playback, the Pi only runs its CPU between ~1.1 - 1.4 GHz to keep up. Here's a 3-second running log of the core's frequency (Hz):

frequency =  600169920 // idle
frequency =  600117184 // idle
frequency =  600117184 // idle
frequency = 1000265600 // launch
frequency = 1000212864 // game starting
frequency = 1300324224 // initial decode
frequency = 1100249984 // video streaming
frequency = 1100249984 // video streaming
frequency = 1100249984 // ...
frequency = 1400361344
frequency = 1100249984
frequency = 1200339840
frequency = 1300324224
frequency = 1100302720
frequency = 1400361344
frequency = 1100302720
frequency = 1400361344
frequency = 1100249984
frequency = 1300324224
frequency = 1400308608
frequency = 1100249984
frequency = 1300324224
frequency = 1300271488
frequency = 1100302720
frequency = 1400308608
frequency = 1500398464
frequency = 1100249984
frequency = 1200287104
frequency = 1100249984
frequency = 1300324224
frequency = 1100302720
frequency = 1200287104
frequency = 1200287104
frequency = 1300324224
frequency = 1300324224
frequency = 1100302720
frequency = 1300324224
frequency = 1400308608
frequency = 1400361344 // exit
frequency =  600117184
frequency =  600169920
frequency =  600169920
frequency =  600169920
frequency =  600169920

@kcgen kcgen merged commit 6609229 into main Nov 29, 2022
@pr-triage pr-triage bot added the PR: merged label Nov 29, 2022
@delete-merged-branch delete-merged-branch bot deleted the kc/reelmagic-fifo-3 branch November 29, 2022 19:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
refactoring Code refactoring without any functional changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants