Commit Graph

32 Commits

Author SHA1 Message Date
Hubert Maier
abcf7ba960 JANITORIAL: AUDIO: Correct Spelling Mistakes
occured -> occurred
occassionally -> occasionally
rythm -> rhythm
2022-11-15 22:52:43 +02:00
Coen Rampen
32ba866499 AUDIO: Move MIDI parser source handling to superclass
This commit moves the source handling from the SMF and XMIDI parsers to the
MIDI parser superclass. This reduces code duplication.
2022-05-09 17:19:43 +02:00
Coen Rampen
00a907f524 MIDI: Fix parser auto loop skipping first event
The auto loop functionality of the MIDI parser would call jumpToTick to jump
back to the start of the MIDI stream, then call parseNextEvent to read the
first MIDI event. However, jumpToTick already makes sure the first MIDI event
after the jump point is parsed. Calling parseNextEvent again would discard the
first and parse the second MIDI event.
Fixed this by removing the call to parseNextEvent after jumping to the start.
2022-05-09 17:19:43 +02:00
Coen Rampen
1f0e905160 AGOS: Add MIDI parsers for GMF and Windows
This commit adds MIDI parser subclasses for the Simon 1 GMF format and for the
SMF variant used by the Windows versions of Simon 1 and 2.

The GMF format was handled by the SMF parser, which can now be removed from
that class. It also fixes the tempos not matching the DOS interpreter.

The Simon Windows SMF variant was handled in the AGOS midi class. Moving it to
a separate parser allows for some cleaner code in that class. It now also
corrects the tempos to match those of the DOS interpreter.
2022-05-09 17:19:41 +02:00
Eugene Sandulenko
abea37c9bb
ALL: Update ScummVM project license to GPLv3+ 2021-12-26 18:48:43 +01:00
Orgad Shaneh
af529f568b AUDIO: Use nullptr
Using clang-tidy modernize-use-nullptr
2021-11-14 13:41:02 +02:00
sluicebox
93eeffc84d JANITORIAL: Update old bug tracker numbers 2021-03-03 02:15:05 +02:00
NMIError
da64fdc3d1 MIDI: Fix MIDI parser tracker overflow
The MIDI parser tracks the number of ticks and microseconds since the start of
playback of the current track. If a track loops infinitely, the tracker
eventually overflows (after about 71 minutes). The parser would then go haywire,
sending out the MIDI events at full speed and not terminating hanging notes,
resulting in loads of polyphony overrun errors. This does not affect looping
using jumpToTick or autoLoop, because that resets the tracker.

This change fixes this for the XMIDI parser. processEvent implementations can
now set a bool flag on the event, indicating that the event has caused a loop.
The MIDI parser will then reset the ticks and microseconds on the tracker to 0,
maintaining the deltas between the previous event values and current values.
The absolute number of ticks and microseconds since track start do not seem to
be needed anywhere; only the difference with the previous event is relevant.

This should fix bugs #6275 and #4354.
2020-07-25 00:35:47 +02:00
NMIError
3ad8c85af2 MIDI: Prevent duplicate MIDI messages
The MIDI parser would send All Notes Off events on all MIDI channels as a
safety measure when stopping playback in various situations without first
checking if a track was actually playing. Depending on the specifics of the
code driving the MIDI parser, this could generate many duplicate All Notes Off,
Sustain off and/or Pitch Bend center messages. This is a problem for slow MIDI
hardware like the MT-32, which needs some time to process all these messages.
As a result, the timing at the beginning of the next track could be wrong.

I've introduced checks in stopPlaying, setTrack, unloadMusic and the MIDI
parser destructor so that allNotesOff is called once when a track is playing,
and not a second time when playback has already stopped. Similarly, unloadMusic
does not execute when no music is loaded to prevent duplicate Pitch Bend
messages.
2020-07-25 00:35:47 +02:00
NMIError
315bbc7b5b MIDI: Use driver-specific impl. for stopping all notes
When the MIDI parser wanted to stop all notes on a MIDI device, it would send
an All Notes Off message and, optionally, a Sustain off message on all 16 MIDI
channels. This is inefficient for devices like the MT-32, which uses only 9
channels. The MT-32 hardware is also quite slow, so it is more responsive if it
has to process less messages.

I've added a generic stopAllNotes message to the MIDI driver using the old
method, which can be overriden by more specific implementations in subclasses.
The Miles MIDI driver implementation sends All Notes Off only on the channels
used by the MT-32. There are probably also more efficient implementations
possible for f.e. AdLib.
2020-07-25 00:35:47 +02:00
NMIError
b38f1f00ac MIDI/GROOVIE: Fix MT-32 XMIDI timbre init delays
XMIDI data for the MT-32 can contain a timbre chunk which contains the custom
timbre numbers used for a track. Before starting playback of the track, the
timbres must be loaded into the MT-32 using SysEx messages. Each SysEx message
needs a delay before sending the next message to give the MT-32 enough time to
process it.

The delays between the messages were generated using the OSystem::delayMillis
function. This throws off the timing of the MidiParser, which causes MIDI
messages to "pile up", in this case at the start of the track. This change adds
a queue to the Miles MIDI driver, which can store the SysEx messages that must
be executed. The MidiParser suspends playback until the driver has sent all
messages in the queue.

This fixes the start of tracks in The 7th Guest, which had incorrect timing.

Because of the new SysEx queue, MT-32 initialization of The 7th Guest takes a
bit longer than it did before. The game plays an animation of a fixed length
and aborts the initialization if it is not done by the end of the animation.
This problem was already fixed for the GM initialization, so I've applied the
same fix for the MT-32.
2020-07-25 00:35:47 +02:00
NMIError
50772c1fbc MIDI: Fix XMIDI custom timbre loading
XMIDI files have an optional header defining custom timbres used for each
track. Before playback these timbres have to be sent to the MIDI device. The
old implementation of this functionality had two problems:

- The custom timbres were only sent during loading of the XMIDI data, for the
first track. If another track was played, the custom timbres for that track
would not be loaded.
- The custom timbres were sent after starting playback of the track. This
caused the sending of the timbres to sometimes overlap with the start of the
playback of the track, causing wrong instruments and bad timing.

If fixed these issues by moving the loading of the timbres to a new event
handler which is triggered during the setTrack function, before playback is
started.

This fixes problems with some MT-32 tracks in The 7th Guest, f.e. the second
track that plays on the main menu after starting the game.
2020-07-25 00:35:47 +02:00
NMIError
0af83d3faa
KYRA/MIDI: Fix minor MT-32/GM issues (#2333)
* KYRA: Added GM initialization for Lands of Lore

The original interpreter of Lands of Lore uses two executables, which
both do initialization of MIDI devices. The main executable runs a
sysex file for GM devices; the intro executable does not.

ScummVM only does MIDI initialization once and it performs this like
the intro executable. I've added the GM initialization of the main
executable. Note that the initialization file consists mostly of
sysexes which alter the display of the SC-55, so it's not particulary
useful. Not many games did this though, so I thought it would be a
fun feature to include.

I also noticed that the check which distinguishes between the two
demo versions of LoL did not work properly; the useAltShapeHeader
flag was true for both versions. I've changed it to check for the
existence of a PAK file which was only included with one of the two
demos.

* MIDI: Delay parser after handling SysEx events

This changes the way delays between SysEx events in MIDI data are handled from
delaying the backend to delaying the MidiParser.

SysEx events require a delay between events to ensure correct processing by the
MIDI device. This is usually implemented by calling OSystem::delayMillis.
Some games use some form of MIDI sequence filled with SysEx messages to
initialize the MIDI device. This is handled by the MidiParser. Using the
delayMillis method causes the following MIDI events to be "bunched up" and be
executed in a shorter timespan than intended.

I've altered this by making the MidiParser stop parsing when a SysEx event is
encountered and not enough time has passed since the last SysEx. After enough
time has passed, the next SysEx is sent and parsing resumes. To facilitate
this, I've introduced an alternate sysExNoDelay fuction on the MidiDiver. This
does not execute the delay itself, but instead returns the required delay time,
so the parser can handle this instead.

I've currently only implemented this method for the Miles MT-32/GM driver. For
other driver implementations, this will call the regular sysEx method and
return a 0 delay time, so there will be no change in behavior.

This restores a sound effect at the end of the Legend of Kyrandia MT-32 MIDI
initialization. Before, the Note On and Note Off events would be transmitted
instantly after each other, causing the notes not to play.

* MIDI: Add instrument bank fallback

Some games rely on a feature of the Roland SC-55 v1.xx that corrects invalid
instrument banks. This feature was removed in later versions of the device and
not implemented in most other GM devices, causing some MIDI data (sound effects
mostly) to play incorrectly.

Specifically, this applies to Lands of Lore. For example, in the intro, the
sound effect of the ring sparkling uses an incorrect instrument bank. Depending
on how the MIDI device handles this, the sound will play correctly, with the
wrong instrument, or not at all.

This commit emulates the SC-55 functionality that corrects the invalid bank
numbers. I've implemented this (partially) on the MidiDriver, so that it can be
re-used for other games (Xeen 4 and 5 also have this issue with some sound
effects).

* KYRA: Start MIDI playback after selecting track

The MIDI parser would automatically start playback after loading MIDI data, but
KYRA engine games use MIDI files with multiple tracks. Because of this it was
necessary to immediately stop playback after loading MIDI data, and then select
the track that should be played for correct playback. The parser now has a
feature to disable automatically starting playback, so I've implemented this
for KYRA.

* KYRA: Improve stopping MIDI playback

In two places All Notes Off events were sent on all channels to stop MIDI
playback of the background music. However, this will also cut off any MIDI
sound effects which are playing. Where needed I've replaced this with simply
stopping playback of the background music; the parser will turn off any active
notes.
I've also made sure playback is stopped before freeing the music data
memory to prevent any issues.
I've added sending All Notes Off events when the game quits, just in case any
hanging notes are not ended by the parsers (should not really be a problem
though).

* MIDI/KYRA: Add pausing playback to MIDI parser

* KYRA: Fix invalid track selection

If a game would attempt to play an invalid track, the parser would start
playing the previously selected track. Fixed this so the parser will not start
playing.
2020-06-20 23:27:30 +02:00
D G Turner
286c5d6f1e AUDIO: Fix Compiler Warnings in MIDI / XMIDI Parser
The _activeTrack variable is of type byte which is defined in
common/scummsys.h as unsigned char so this variable can never
be negative and thus the checks removed here were causing compiler
warnings.
2020-06-13 18:31:32 +01:00
NMIError
0f297559cd ULTIMA8/MIDI: Rename doNotAutoStartPlayback
Renamed doNotAutoStartPlayback to disableAutoStartPlayback for more consistency
in property naming.
2020-06-12 13:46:27 -05:00
NMIError
f497753b21 MIDI: Add support for XMIDI sequence branch indexes
This adds support for the "sequence branch index" feature of the XMIDI format.
These "branches" (positions in the MIDI bytestream) are defined in the track
header. I've added two generic methods to the MidiParser interface to set the
current parsing position to one of these positions, or to check for the
existence of a position with a certain number (this is needed for Ultima 8).

Additionally, I've added an option to the MIDI parser to prevent the parser
from starting playback immediately after parsing, so that a starting position
(or a track) can be selected first. Playback can then be started with the new
startPlaying method.
2020-06-12 13:46:27 -05:00
NMIError
62387f8d38
MIDI/KYRA: Miles channel locking and GM support (#2273)
* MIDI/KYRA: Add channel locking and GM to XMIDI

This improves support for XMIDI channel locking and moves it from the KYRA
engine to the generic Miles MIDI driver. To support this, a source parameter
is added to the XMIDI parser and Miles driver so the driver can distinguish
several XMIDI parser instances sending MIDI events. I've also added GM support
to the generic Miles MIDI driver.

The previous implementation of channel locking did not always track and restore
controller values properly when unlocking a channel. Specifically, at the start
of Legend of Kyrandia, when Brandon talks to the tree, the tree "creaking"
sound effect uses some channels from the background music. The volume of the
music channels was not correctly restored, resulting in some instruments being
much louder then others.
Another issue was that volume was not always properly set when locking a
channel. In the Legend of Kyrandia intro, when Brandon is lifted up to the
house, some sound effects were missing because MIDI channel volume was 0.
This new implementation fixes these issues.

* MIDI: Suppress Miles controller warnings

Several Miles controller MIDI messages generate warnings in the XMIDI parser,
even though they are handled by the Miles drivers. I've removed these.

* MIDI: Fix Codacy issues
2020-05-29 17:50:14 +02:00
D G Turner
28287d70b6 AUDIO: Fix Missing Default Switch Cases
These are flagged by GCC if -Wswitch-default is enabled.
2019-11-17 08:20:01 +00:00
Johannes Schickel
452cec49d9 AUDIO: Make GPL headers consistent in themselves. 2014-02-18 02:39:32 +01:00
Alyssa Milburn
f92df4c6aa Revert "AUDIO: Simplify MidiTracker::processEvent return value"
MI2 deletes the parser object(!) so we can't access any member
variables here. Thanks to athrxx for finding this.

This reverts commit 86c2fe47e0 and adds
a comment explaining why.
2014-01-27 00:20:50 +01:00
Alyssa Milburn
83ce4cfb5e Revert "AUDIO: fix invalid mem access in midiparser.cpp"
This broke SCI, since it doesn't call processEvent any more.

This reverts commit afa54072a9.
2014-01-27 00:08:57 +01:00
athrxx
afa54072a9 AUDIO: fix invalid mem access in midiparser.cpp
(this caused a crash in MI2)
2014-01-26 22:51:39 +01:00
Willem Jan Palenstijn
3792af8e95 AUDIO: Simplify SCI inFastForward flag by moving it to MidiParser 2013-09-21 09:31:08 +02:00
Willem Jan Palenstijn
86c2fe47e0 AUDIO: Simplify MidiTracker::processEvent return value 2013-09-21 01:08:26 +02:00
Willem Jan Palenstijn
da81c59308 AUDIO: Let jumpToTick use processEvent too 2013-09-21 00:22:58 +02:00
Willem Jan Palenstijn
6c5a5cd8e9 AUDIO: Split event processing from MidiParser::onTimer
This is to prepare for overriding more of this functionality in SCI.
2013-09-21 00:22:56 +02:00
Eugene Sandulenko
7c26b6ee0a AUDIO: Fix unitialized variable. CID 1003162 2013-05-02 14:01:13 +03:00
Alyssa Milburn
f08978a075 JANITORIAL: Remove underscores from MidiParser variable names. 2012-09-07 23:04:34 +02:00
strangerke
69b1485a22 GIT: Clean up: Suppress SVN tags, now useless 2011-05-12 01:16:22 +02:00
Ori Avtalion
9414d7a6e2 JANITORIAL: Reduce header dependencies in shared code
Some backends may break as I only compiled SDL
2011-04-28 15:08:58 +03:00
Max Horn
db3802b021 AUDIO: Whitespace fix 2011-03-25 14:15:52 +01:00
Max Horn
42ab839dd6 AUDIO: Rename sound/ dir to audio/
svn-id: r55850
2011-02-09 01:09:01 +00:00