From ca6debde66c14a3bec982226798b8b438046f1df Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Wed, 11 Aug 2010 22:56:32 +1200 Subject: [PATCH] buffer up all the audio upfront --- OpenRA.FileFormats/Graphics/VqaReader.cs | 71 +++++++++++++++++------- OpenRA.Game/Sound.cs | 5 +- OpenRA.Game/Widgets/VqaPlayerWidget.cs | 29 +++++----- mods/ra/chrome/mainmenu.yaml | 2 +- 4 files changed, 69 insertions(+), 38 deletions(-) diff --git a/OpenRA.FileFormats/Graphics/VqaReader.cs b/OpenRA.FileFormats/Graphics/VqaReader.cs index 91694e6dc8..84658e94b8 100644 --- a/OpenRA.FileFormats/Graphics/VqaReader.cs +++ b/OpenRA.FileFormats/Graphics/VqaReader.cs @@ -6,15 +6,12 @@ * as published by the Free Software Foundation. For more information, * see LICENSE. */ -#endregion - -using System.Collections; -using System.Collections.Generic; -using System.Drawing; -using System.IO; -using System; -using System.Drawing.Imaging; - +#endregion + +using System; +using System.Drawing; +using System.IO; + namespace OpenRA.FileFormats { public class VqaReader @@ -48,7 +45,8 @@ namespace OpenRA.FileFormats int[,] frameData; byte[] audioData; // audio for this frame: 22050Hz 16bit mono pcm, uncompressed. - public byte[] AudioData { get { return audioData; } } + public byte[] AudioData { get { return audioData; } } + public int CurrentFrame { get { return currentFrame; } } public VqaReader( Stream stream ) { @@ -107,13 +105,49 @@ namespace OpenRA.FileFormats offsets[i] = reader.ReadUInt32(); if (offsets[i] > 0x40000000) offsets[i] -= 0x40000000; offsets[i] <<= 1; - } + } + + CollectAudioData(); // Load the first frame currentFrame = 0; AdvanceFrame(); - } - + } + + void CollectAudioData() + { + var ms = new MemoryStream(); + var adpcmIndex = 0; + + for (var i = 0; i < Frames; i++) + { + stream.Seek(offsets[i], SeekOrigin.Begin); + BinaryReader reader = new BinaryReader(stream); + var end = (i < Frames - 1) ? offsets[i + 1] : stream.Length; + + while (reader.BaseStream.Position < end) + { + var type = new String(reader.ReadChars(4)); + var length = Swap(reader.ReadUInt32()); + + switch (type) + { + case "SND2": + var rawAudio = reader.ReadBytes((int)length); + ms.Write(rawAudio); + break; + default: + reader.ReadBytes((int)length); + break; + } + + if (reader.PeekChar() == 0) reader.ReadByte(); + } + } + + audioData = AudLoader.LoadSound(ms.ToArray(), ref adpcmIndex); + } + public void AdvanceFrame() { // Seek to the start of the frame @@ -129,11 +163,8 @@ namespace OpenRA.FileFormats switch(type) { case "SND2": - // Don't parse sound (yet); skip data - { - var rawAudio = reader.ReadBytes((int)length); - audioData = AudLoader.LoadSound(rawAudio, ref adpcmIndex); - } + // Don't parse sound here. + reader.ReadBytes((int)length); break; case "VQFR": DecodeVQFR(reader); @@ -147,9 +178,7 @@ namespace OpenRA.FileFormats } if (++currentFrame == Frames) currentFrame = cbOffset = cbChunk = 0; - } - - int adpcmIndex = 0; + } // VQA Frame public void DecodeVQFR(BinaryReader reader) diff --git a/OpenRA.Game/Sound.cs b/OpenRA.Game/Sound.cs index d113c17bb8..a6f85a3d77 100644 --- a/OpenRA.Game/Sound.cs +++ b/OpenRA.Game/Sound.cs @@ -48,10 +48,11 @@ namespace OpenRA public static void SetListenerPosition(float2 position) { soundEngine.SetListenerPosition(position); } + static ISoundSource rawSource; public static void PlayRaw(byte[] raw) { - var sound = LoadSoundRaw(raw); - soundEngine.Play2D(sound, false, true, float2.Zero, SoundVolume); + rawSource = LoadSoundRaw(raw); + soundEngine.Play2D(rawSource, false, true, float2.Zero, SoundVolume); } public static void Play(string name) diff --git a/OpenRA.Game/Widgets/VqaPlayerWidget.cs b/OpenRA.Game/Widgets/VqaPlayerWidget.cs index 932e307625..056111c184 100644 --- a/OpenRA.Game/Widgets/VqaPlayerWidget.cs +++ b/OpenRA.Game/Widgets/VqaPlayerWidget.cs @@ -6,14 +6,12 @@ * as published by the Free Software Foundation. For more information, * see LICENSE. */ -#endregion -using System; -using System.Drawing; -using System.Linq; +#endregion + +using System; +using System.Drawing; +using OpenRA.FileFormats; using OpenRA.Graphics; -using OpenRA.Traits; -using OpenRA.Widgets; -using OpenRA.FileFormats; namespace OpenRA.Widgets { @@ -37,19 +35,22 @@ namespace OpenRA.Widgets int lastTime; bool advanceNext = false; public override void DrawInner(World world) - { - if (video == null) - LoadVideo(Video); + { + if (video == null) + { + LoadVideo(Video); + Sound.PlayRaw(video.AudioData); + } int t = Environment.TickCount; int dt = t - lastTime; if (advanceNext) - { + { + if (video.CurrentFrame == 0) + Sound.PlayRaw(video.AudioData); advanceNext = false; - video.AdvanceFrame(); - - Sound.PlayRaw(video.AudioData); + video.AdvanceFrame(); } if (dt > timestep) diff --git a/mods/ra/chrome/mainmenu.yaml b/mods/ra/chrome/mainmenu.yaml index ed6ebb71ca..4c534c399b 100644 --- a/mods/ra/chrome/mainmenu.yaml +++ b/mods/ra/chrome/mainmenu.yaml @@ -3,7 +3,7 @@ VqaPlayer: Y:WINDOW_BOTTOM - 200 Width:200 Height:200 - Video:aagun.vqa + Video:ally10.vqa Background@MAINMENU_BG: Id:MAINMENU_BG X:(WINDOW_RIGHT - WIDTH)/2