Commit d89e5e4d authored by Viktor Lidholt's avatar Viktor Lidholt

Merge pull request #607 from vlidholt/master

Updates to game sound API
parents bcf18623 e17f6b7b
...@@ -30,7 +30,7 @@ class GameDemoWorld extends NodeWithSize { ...@@ -30,7 +30,7 @@ class GameDemoWorld extends NodeWithSize {
SpriteSheet _spriteSheetUI; SpriteSheet _spriteSheetUI;
Map<String,SoundEffect> _sounds; Map<String,SoundEffect> _sounds;
SoundPool _soundPool = SoundPool.sharedInstance(); SoundEffectPlayer _soundPool = SoundEffectPlayer.sharedInstance();
Navigator _navigator; Navigator _navigator;
......
...@@ -54,6 +54,10 @@ main() async { ...@@ -54,6 +54,10 @@ main() async {
await _sounds["explosion"].load(); await _sounds["explosion"].load();
await _sounds["laser"].load(); await _sounds["laser"].load();
SoundTrackPlayer stPlayer = SoundTrackPlayer.sharedInstance();
SoundTrack music = await stPlayer.load('https://github.com/slembcke/GalacticGuardian.spritebuilder/raw/GDC/Source/Resources/TempMusic.aac');
stPlayer.play(music);
runApp(_app); runApp(_app);
} }
......
...@@ -3,7 +3,7 @@ part of sprites; ...@@ -3,7 +3,7 @@ part of sprites;
// TODO: The sound effects should probably use Android's SoundPool instead of // TODO: The sound effects should probably use Android's SoundPool instead of
// MediaPlayer as it is more efficient and flexible for playing back sound effects // MediaPlayer as it is more efficient and flexible for playing back sound effects
typedef void SoundCompleteCallback(); typedef void SoundEffectStreamCallback(SoundEffectStream);
class SoundEffect { class SoundEffect {
SoundEffect(this._url); SoundEffect(this._url);
...@@ -18,58 +18,54 @@ class SoundEffect { ...@@ -18,58 +18,54 @@ class SoundEffect {
Object _data; Object _data;
} }
class SoundStream { class SoundEffectStream {
SoundStream( SoundEffectStream(
this.sound, this.sound,
this.tag,
this.loop, this.loop,
this.time,
this.volume, this.volume,
this.pitch, this.pitch,
this.pan, this.pan,
this.callback this.onSoundComplete
); );
// TODO: Make these properties work // TODO: Make these properties work
SoundEffect sound; SoundEffect sound;
bool playing = false; bool playing = false;
bool loop = false; bool loop = false;
double time = 0.0;
double volume = 1.0; double volume = 1.0;
double pitch = 1.0; double pitch = 1.0;
double pan = 0.0; double pan = 0.0;
Object tag;
// TODO: Implement completion callback. On completion, sounds should // TODO: Implement completion callback. On completion, sounds should
// also be removed from the list of playing sounds. // also be removed from the list of playing sounds.
SoundCompleteCallback callback; SoundEffectStreamCallback onSoundComplete;
MediaPlayerProxy _player; MediaPlayerProxy _player;
} }
SoundPool _sharedSoundPool; SoundEffectPlayer _sharedSoundEffectPlayer;
class SoundPool { class SoundEffectPlayer {
static SoundPool sharedInstance() { static SoundEffectPlayer sharedInstance() {
if (_sharedSoundPool == null) { if (_sharedSoundEffectPlayer == null) {
_sharedSoundPool = new SoundPool(); _sharedSoundEffectPlayer = new SoundEffectPlayer();
} }
return _sharedSoundPool; return _sharedSoundEffectPlayer;
} }
SoundPool() { SoundEffectPlayer() {
_mediaService = new MediaServiceProxy.unbound(); _mediaService = new MediaServiceProxy.unbound();
shell.requestService(null, _mediaService); shell.requestService(null, _mediaService);
} }
MediaServiceProxy _mediaService; MediaServiceProxy _mediaService;
List<SoundStream> _playingSounds = []; List<SoundEffectStream> _soundEffectStreams = [];
// TODO: This should no longer be needed when moving to SoundPool backing // TODO: This should no longer be needed when moving to SoundPool backing
Map<SoundEffect,MediaPlayerProxy> _mediaPlayers = {}; Map<SoundEffect,MediaPlayerProxy> _mediaPlayers = {};
Future _prepare(SoundStream playingSound) async { Future _prepare(SoundEffectStream playingSound) async {
await playingSound._player.ptr.prepare(playingSound.sound._data); await playingSound._player.ptr.prepare(playingSound.sound._data);
} }
...@@ -87,22 +83,18 @@ class SoundPool { ...@@ -87,22 +83,18 @@ class SoundPool {
// TODO: Add paused property (should pause playback of all sounds) // TODO: Add paused property (should pause playback of all sounds)
bool paused; bool paused;
SoundStream play( SoundEffectStream play(
SoundEffect sound, SoundEffect sound,
[Object tag, [bool loop = false,
bool loop = false,
double volume = 1.0, double volume = 1.0,
double pitch = 1.0, double pitch = 1.0,
double pan = 0.0, double pan = 0.0,
double startTime = 0.0, SoundEffectStreamCallback callback = null]) {
SoundCompleteCallback callback = null]) {
// Create new PlayingSound object // Create new PlayingSound object
SoundStream playingSound = new SoundStream( SoundEffectStream playingSound = new SoundEffectStream(
sound, sound,
tag,
loop, loop,
startTime,
volume, volume,
pitch, pitch,
pan, pan,
...@@ -117,46 +109,104 @@ class SoundPool { ...@@ -117,46 +109,104 @@ class SoundPool {
// Prepare sound, then play it // Prepare sound, then play it
_prepare(playingSound).then((_) { _prepare(playingSound).then((_) {
playingSound._player.ptr.seekTo((startTime * 1000.0).toInt()); playingSound._player.ptr.seekTo(0);
playingSound._player.ptr.start(); playingSound._player.ptr.start();
}); });
_playingSounds.add(playingSound); _soundEffectStreams.add(playingSound);
_mediaPlayers[sound] = playingSound._player; _mediaPlayers[sound] = playingSound._player;
} else { } else {
// Reuse player // Reuse player
playingSound._player = _mediaPlayers[sound]; playingSound._player = _mediaPlayers[sound];
playingSound._player.ptr.seekTo((startTime * 1000.0).toInt()); playingSound._player.ptr.seekTo(0);
playingSound._player.ptr.start(); playingSound._player.ptr.start();
} }
return playingSound; return playingSound;
} }
void stop(Object tag) { void stop(SoundEffectStream stream) {
for (int i = _playingSounds.length; i >= 0; i--) { stream._player.ptr.pause();
SoundStream playingSound = _playingSounds[i]; _soundEffectStreams.remove(stream);
if (playingSound.tag == tag) { }
playingSound._player.ptr.pause();
_playingSounds.removeAt(i); void stopAll() {
} for (SoundEffectStream playingSound in _soundEffectStreams) {
playingSound._player.ptr.pause();
} }
_soundEffectStreams = [];
} }
}
typedef void SoundTrackCallback(SoundTrack);
typedef void SoundTrackBufferingCallback(SoundTrack, int);
class SoundTrack {
MediaPlayerProxy _player;
List<SoundStream> playingSoundsForTag(Object tag) { SoundTrackCallback onSoundComplete;
List<SoundStream> list = []; SoundTrackCallback onSeekComplete;
for (SoundStream playingSound in _playingSounds) { SoundTrackBufferingCallback onBufferingUpdate;
if (playingSound.tag == tag) { bool loop;
list.add(playingSound); double time;
} }
SoundTrackPlayer _sharedSoundTrackPlayer;
class SoundTrackPlayer {
List<SoundTrack> _soundTracks = [];
static sharedInstance() {
if (_sharedSoundTrackPlayer == null) {
_sharedSoundTrackPlayer = new SoundTrackPlayer();
} }
return list; return _sharedSoundTrackPlayer;
}
SoundTrackPlayer() {
_mediaService = new MediaServiceProxy.unbound();
shell.requestService(null, _mediaService);
}
MediaServiceProxy _mediaService;
Future<SoundTrack> load(String url) async {
// Create media player
SoundTrack soundTrack = new SoundTrack();
soundTrack._player = new MediaPlayerProxy.unbound();
_mediaService.ptr.createPlayer(soundTrack._player);
// Load and prepare
UrlResponse response = await fetchUrl(url);
await soundTrack._player.ptr.prepare(response.body);
return soundTrack;
}
void unload(SoundTrack soundTrack) {
stop(soundTrack);
_soundTracks.remove(soundTrack);
}
void play(
SoundTrack soundTrack,
[bool loop = false,
double volume,
double startTime = 0.0]) {
// TODO: Implement looping & volume
// soundTrack._player.ptr.setLooping(loop);
// soundTrack._player.ptr.setVolume(volume);
soundTrack._player.ptr.seekTo((startTime * 1000.0).toInt());
soundTrack._player.ptr.start();
}
void stop(SoundTrack track) {
track._player.ptr.pause();
} }
void stopAll() { void stopAll() {
for (SoundStream playingSound in _playingSounds) { for (SoundTrack soundTrack in _soundTracks) {
playingSound._player.ptr.pause(); soundTrack._player.ptr.pause();
} }
_playingSounds = [];
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment