Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
AudioEngine.Android.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 
4 #if SILICONSTUDIO_PLATFORM_ANDROID
5 
6 using System;
7 using System.Diagnostics;
8 using IOException = Java.IO.IOException;
9 using Android.Media;
10 using Java.IO;
11 using Java.Lang;
12 
13 namespace SiliconStudio.Paradox.Audio
14 {
15  partial class AudioEngine
16  {
17  private readonly MediaPlayer mediaPlayer = new MediaPlayer();
18 
19  private void DestroyImpl()
20  {
21  SoundEffectInstance.StaticDestroy();
22 
23  mediaPlayer.Release();
24  }
25 
26  private void AudioEngineImpl(AudioDevice device)
27  {
28  mediaPlayer.Completion += OnMusicCompletion;
29  mediaPlayer.Error += OnMusicError;
30  mediaPlayer.Prepared += OnMusicPrepared;
31 
32  SoundEffectInstance.CreateAudioTracks();
33  }
34 
35  private void StopCurrentMusic()
36  {
37  mediaPlayer.Stop();
38 
39  ResetMusicPlayer();
40  }
41 
42  private void StartCurrentMusic()
43  {
44  if (isMusicPlayerReady)
45  mediaPlayer.Start();
46  else
47  mediaPlayer.PrepareAsync();
48  }
49 
50  private void PauseCurrentMusic()
51  {
52  mediaPlayer.Pause();
53  }
54 
55  private void UpdateMusicVolume()
56  {
57  // volume factor used in order to adjust Sound Music and Sound Effect Maximum volumes
58  const float volumeAdjustFactor = 0.5f;
59 
60  var vol = volumeAdjustFactor * currentMusic.Volume;
61 
62  mediaPlayer.SetVolume(vol, vol);
63  }
64 
65  private void ResetMusicPlayer()
66  {
67  mediaPlayer.Reset();
68 
69  isMusicPlayerReady = false;
70 
71  currentMusic = null;
72  }
73 
74  private Stopwatch loadTime = new Stopwatch();
75  private void LoadNewMusic(SoundMusic soundMusic)
76  {
77  loadTime.Restart();
78  try
79  {
80  using (var javaFileStream = new FileInputStream(soundMusic.FileName))
81  mediaPlayer.SetDataSource(javaFileStream.FD, soundMusic.StartPosition, soundMusic.Length);
82 
83  mediaPlayer.PrepareAsync();
84 
85  currentMusic = soundMusic;
86  }
87  catch (IOException)
88  {
89  // this can happen namely if too many files are already opened (should not throw an exception)
90  Logger.Warning("The audio file '{0}' could not be opened", soundMusic.FileName);
91  }
92  catch (SecurityException)
93  {
94  throw new InvalidOperationException("The sound file is not accessible anymore.");
95  }
96  catch (IllegalArgumentException e)
97  {
98  throw new AudioSystemInternalException("Error during the SetDataSouce: "+e);
99  }
100  }
101 
102  private void OnMusicCompletion(object o, EventArgs args)
103  {
104  musicMediaEvents.Enqueue(new SoundMusicEventNotification(SoundMusicEvent.EndOfTrackReached, args));
105  }
106 
107  private void OnMusicError(object o, MediaPlayer.ErrorEventArgs args)
108  {
109  musicMediaEvents.Enqueue(new SoundMusicEventNotification(SoundMusicEvent.ErrorOccurred, args));
110  }
111 
112  private void OnMusicPrepared(object o, EventArgs args)
113  {
114  musicMediaEvents.Enqueue(new SoundMusicEventNotification(SoundMusicEvent.ReadyToBePlayed, args));
115  }
116 
117  private void RestartCurrentMusic()
118  {
119  mediaPlayer.SeekTo(0);
120  }
121 
122  private void PlatformSpecificProcessMusicReady()
123  {
124  loadTime.Stop();
125 
126  if(currentMusic != null)
127  Logger.Verbose("Time taken for music '{0}' loading = {0}", currentMusic.Name, loadTime.ElapsedMilliseconds);
128  }
129 
130  private void ProcessPlayerClosed()
131  {
132  throw new AudioSystemInternalException("Should never arrive here. (Used only by windows implementation.");
133  }
134 
135  private void ProcessMusicMetaData()
136  {
137  throw new AudioSystemInternalException("Should never arrive here. (Used only by windows implementation.");
138  }
139 
140  private void ProcessMusicError(SoundMusicEventNotification eventNotification)
141  {
142  if (eventNotification.Event != SoundMusicEvent.ErrorOccurred) // no errors
143  return;
144 
145  var soundMusicName = "Unknown";
146 
147  if (currentMusic != null)
148  {
149  currentMusic.SetStateToStopped();
150  soundMusicName = currentMusic.Name;
151  }
152 
153  Logger.Error("Error while playing the sound music '{0}'. Details follows:");
154 
155  var errorEvent = (MediaPlayer.ErrorEventArgs)eventNotification.EventData;
156  if (errorEvent.What == MediaError.Unknown && errorEvent.Extra == 0xfffffc0e) // MEDIA_ERROR_UNSUPPORTED (Hardware dependent?)
157  {
158  Logger.Error("The data format of the music file is not supported.");
159  }
160  else if ((uint)errorEvent.What == 0xffffffed) // underlying audio track returned -12 (no memory) -> try to recreate the player once more
161  {
162  Logger.Error("The OS did not have enough memory to create the audio track.", soundMusicName);
163  }
164  else
165  {
166  Logger.Error(" [Details: ErrorCode={1}, Extra={2}]", soundMusicName, errorEvent.What, errorEvent.Extra);
167  }
168 
169  // reset the music player to a valid state for future plays
170  ResetMusicPlayer();
171  }
172 
173  private void PauseAudioPlatformSpecific()
174  {
175  // nothing to do for windows
176  }
177 
178  private void ResumeAudioPlatformSpecific()
179  {
180  // nothing to do for windows
181  }
182  }
183 }
184 
185 #endif