Add a streaming audio playback interface.

This allows audio to be streamed, rather than needed to be fully loaded into memory.
This commit is contained in:
RoosterDragon
2017-06-16 20:06:45 +01:00
committed by Paul Chote
parent 45606c9528
commit 85c948fd8d
5 changed files with 337 additions and 107 deletions

View File

@@ -37,10 +37,10 @@ namespace OpenRA
public sealed class Sound : IDisposable
{
readonly ISoundEngine soundEngine;
ISoundLoader[] loaders;
IReadOnlyFileSystem fileSystem;
Cache<string, ISoundSource> sounds;
ISoundSource rawSource;
Func<string, ISoundSource> getSoundSource;
ISoundSource musicSource;
ISound music;
ISound video;
MusicInfo currentMusic;
@@ -54,12 +54,12 @@ namespace OpenRA
MuteAudio();
}
ISoundSource LoadSound(ISoundLoader[] loaders, IReadOnlyFileSystem fileSystem, string filename)
T LoadSound<T>(string filename, Func<ISoundFormat, T> loadFormat)
{
if (!fileSystem.Exists(filename))
{
Log.Write("sound", "LoadSound, file does not exist: {0}", filename);
return null;
return default(T);
}
using (var stream = fileSystem.Open(filename))
@@ -70,8 +70,7 @@ namespace OpenRA
stream.Position = 0;
if (loader.TryParseSound(stream, out soundFormat))
{
var source = soundEngine.AddSoundSourceFromMemory(
soundFormat.GetPCMInputStream().ReadAllBytes(), soundFormat.Channels, soundFormat.SampleBits, soundFormat.SampleRate);
var source = loadFormat(soundFormat);
soundFormat.Dispose();
return source;
}
@@ -84,15 +83,18 @@ namespace OpenRA
public void Initialize(ISoundLoader[] loaders, IReadOnlyFileSystem fileSystem)
{
StopMusic();
soundEngine.ReleaseSourcePool();
soundEngine.StopAllSounds();
if (sounds != null)
foreach (var soundSource in sounds.Values)
if (soundSource != null)
soundSource.Dispose();
getSoundSource = s => LoadSound(loaders, fileSystem, s);
sounds = new Cache<string, ISoundSource>(getSoundSource);
this.loaders = loaders;
this.fileSystem = fileSystem;
Func<ISoundFormat, ISoundSource> loadIntoMemory = soundFormat => soundEngine.AddSoundSourceFromMemory(
soundFormat.GetPCMInputStream().ReadAllBytes(), soundFormat.Channels, soundFormat.SampleBits, soundFormat.SampleRate);
sounds = new Cache<string, ISoundSource>(filename => LoadSound(filename, loadIntoMemory));
currentSounds = new Dictionary<uint, ISound>();
video = null;
}
@@ -172,7 +174,7 @@ namespace OpenRA
public void Tick()
{
// Song finished
if (MusicPlaying && !music.Playing)
if (MusicPlaying && music.Complete)
{
StopMusic();
onMusicComplete();
@@ -204,11 +206,17 @@ namespace OpenRA
StopMusic();
musicSource = getSoundSource(m.Filename);
if (musicSource == null)
return;
Func<ISoundFormat, ISound> stream = soundFormat => soundEngine.Play2DStream(
soundFormat.GetPCMInputStream(), soundFormat.Channels, soundFormat.SampleBits, soundFormat.SampleRate,
false, true, WPos.Zero, MusicVolume);
music = LoadSound(m.Filename, stream);
if (music == null)
{
onMusicComplete = null;
return;
}
music = soundEngine.Play2D(musicSource, false, true, WPos.Zero, MusicVolume, false);
currentMusic = m;
MusicPlaying = true;
}
@@ -233,14 +241,9 @@ namespace OpenRA
if (music != null)
{
soundEngine.StopSound(music);
soundEngine.ReleaseSound(music);
music = null;
}
if (musicSource != null)
musicSource.Dispose();
music = null;
musicSource = null;
currentMusic = null;
MusicPlaying = false;
}
@@ -405,6 +408,11 @@ namespace OpenRA
public void Dispose()
{
StopAudio();
if (sounds != null)
foreach (var soundSource in sounds.Values)
if (soundSource != null)
soundSource.Dispose();
soundEngine.Dispose();
}
}