NScumm.Scumm.Audio.IMuse.IMuseInternal.StartSoundInternal C# (CSharp) Method

StartSoundInternal() protected method

protected StartSoundInternal ( int sound, int offset ) : bool
sound int
offset int
return bool
        protected bool StartSoundInternal(int sound, int offset = 0)
        {
            // Do not start a sound if it is already set to start on an ImTrigger
            // event. This fixes carnival music problems where a sound has been set
            // to trigger at the right time, but then is started up immediately
            // anyway, only to be restarted later when the trigger occurs.
            //
            // However, we have to make sure the sound with the trigger is actually
            // playing, otherwise the music may stop when Sam and Max are thrown
            // out of Bumpusville, because entering the mansion sets up a trigger
            // for a sound that isn't necessarily playing. This is somewhat related
            // to bug #780918.

            foreach (var trigger in _snm_triggers)
            {
                if (trigger.Sound != 0 && trigger.Id != 0 && trigger.Command[0] == 8 && trigger.Command[1] == sound && GetSoundStatusInternal(trigger.Sound, true) != 0)
                    return false;
            }

            var ptr = FindStartOfSound(sound);
            if (ptr == null)
            {
                Debug.WriteLine("IMuseInternal::startSound(): Couldn't find sound {0}", sound);
                return false;
            }

            // Check which MIDI driver this track should use.
            // If it's NULL, it ain't something we can play.
            var driver = GetBestMidiDriver(sound);
            if (driver == null)
                return false;

            // If the requested sound is already playing, start it over
            // from scratch. This was originally a hack to prevent Sam & Max
            // iMuse messiness while upgrading the iMuse engine, but it
            // is apparently necessary to deal with fade-and-restart
            // race conditions that were observed in MI2. Reference
            // Bug #590511 and Patch #607175 (which was reversed to fix
            // an FOA regression: Bug #622606).
            var player = FindActivePlayer(sound);
            if (player == null)
            {
                ptr = FindStartOfSound(sound, ChunkType.MDhd);
                int size = 128;
                if (ptr != null)
                {
                    using (var br = new BinaryReader(new MemoryStream(ptr)))
                    {
                        br.BaseStream.Seek(4, SeekOrigin.Begin);
                        var tmp = br.ReadUInt32BigEndian();
                        size = tmp != 0 && ptr[10] != 0 ? ptr[10] : 128;
                    }
                }
                player = AllocatePlayer((byte)size);
            }

            if (player == null)
                return false;

            // WORKAROUND: This is to work around a problem at the Dino Bungie
            // Memorial.
            //
            // There are three pieces of music involved here:
            //
            // 80 - Main theme (looping)
            // 81 - Music when entering Rex's and Wally's room (not looping)
            // 82 - Music when listening to Rex or Wally
            //
            // When entering, tune 81 starts, tune 80 is faded down (not out) and
            // a trigger is set in tune 81 to fade tune 80 back up.
            //
            // When listening to Rex or Wally, tune 82 is started, tune 81 is faded
            // out and tune 80 is faded down even further.
            //
            // However, when tune 81 is faded out its trigger will cause tune 80 to
            // fade back up, resulting in two tunes being played simultaneously at
            // full blast. It's no use trying to keep tune 81 playing at volume 0.
            // It doesn't loop, so eventually it will terminate on its own.
            //
            // I don't know how the original interpreter handled this - or even if
            // it handled it at all - but it looks like sloppy scripting to me. Our
            // workaround is to clear the trigger if the player listens to Rex or
            // Wally before tune 81 has finished on its own.

            if (_game_id == GameId.SamNMax && sound == 82 && GetSoundStatusInternal(81, false) != 0)
                ImClearTrigger(81, 1);

            player.Clear();
            player.SetOffsetNote(offset);
            return player.StartSound(sound, driver);
        }