2 // Radegast Metaverse Client
\r
3 // Copyright (c) 2009, Radegast Development Team
\r
4 // All rights reserved.
\r
6 // Redistribution and use in source and binary forms, with or without
\r
7 // modification, are permitted provided that the following conditions are met:
\r
9 // * Redistributions of source code must retain the above copyright notice,
\r
10 // this list of conditions and the following disclaimer.
\r
11 // * Redistributions in binary form must reproduce the above copyright
\r
12 // notice, this list of conditions and the following disclaimer in the
\r
13 // documentation and/or other materials provided with the distribution.
\r
14 // * Neither the name of the application "Radegast", nor the names of its
\r
15 // contributors may be used to endorse or promote products derived from
\r
16 // this software without specific prior written permission.
\r
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
\r
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
\r
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
\r
21 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
\r
22 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
\r
23 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
\r
24 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
\r
25 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
\r
26 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
\r
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
32 using System.Collections.Generic;
\r
35 using OpenMetaverse;
\r
37 namespace Radegast.Media
\r
39 public class MediaManager : MediaObject
\r
42 /// Indicated wheather spund sytem is ready for use
\r
44 public bool SoundSystemAvailable { get { return soundSystemAvailable; } }
\r
45 private bool soundSystemAvailable = false;
\r
47 private List<MediaObject> sounds = new List<MediaObject>();
\r
50 /// Parcel music stream player
\r
52 public Sound ParcelMusic { get { return parcelMusic; } set { parcelMusic = value; } }
\r
53 private Sound parcelMusic;
\r
55 public MediaManager(RadegastInstance instance)
\r
60 FMODExec(FMOD.Factory.System_Create(ref system));
\r
62 FMODExec(system.getVersion(ref version));
\r
64 if (version < FMOD.VERSION.number)
\r
65 throw new MediaException("You are using an old version of FMOD " + version.ToString("X") + ". This program requires " + FMOD.VERSION.number.ToString("X") + ".");
\r
67 // Assume no special hardware capabilities except 5.1 surround sound.
\r
68 FMOD.CAPS caps = FMOD.CAPS.NONE;
\r
69 FMOD.SPEAKERMODE speakermode = FMOD.SPEAKERMODE._5POINT1;
\r
71 // Get the capabilities of the driver.
\r
72 int minfrequency = 0, maxfrequency = 0;
\r
73 StringBuilder name = new StringBuilder(128);
\r
74 FMODExec(system.getDriverCaps(0, ref caps,
\r
75 ref minfrequency, ref maxfrequency,
\r
79 // Set FMOD speaker mode to what the driver supports.
\r
80 FMODExec(system.setSpeakerMode(speakermode));
\r
82 // Forcing the ESD sound system on Linux seems to avoid a CPU loop
\r
83 if (System.Environment.OSVersion.Platform == PlatformID.Unix)
\r
84 FMODExec(system.setOutput(FMOD.OUTPUTTYPE.ESD));
\r
86 // The user has the 'Acceleration' slider set to off, which
\r
87 // is really bad for latency. At 48khz, the latency between
\r
88 // issuing an fmod command and hearing it will now be about 213ms.
\r
89 if ((caps & FMOD.CAPS.HARDWARE_EMULATED) == FMOD.CAPS.HARDWARE_EMULATED)
\r
91 FMODExec(system.setDSPBufferSize(1024, 10));
\r
94 // Get driver information so we can check for a wierd one.
\r
95 FMOD.GUID guid = new FMOD.GUID();
\r
96 FMODExec(system.getDriverInfo(0, name, 128, ref guid));
\r
98 // Sigmatel sound devices crackle for some reason if the format is pcm 16bit.
\r
99 // pcm floating point output seems to solve it.
\r
100 if (name.ToString().IndexOf("SigmaTel") != -1)
\r
102 FMODExec(system.setSoftwareFormat(
\r
104 FMOD.SOUND_FORMAT.PCMFLOAT,
\r
106 FMOD.DSP_RESAMPLER.LINEAR)
\r
110 // Try to initialize with all those settings, and Max 32 channels.
\r
111 FMOD.RESULT result = system.init(32, FMOD.INITFLAG.NORMAL, (IntPtr)null);
\r
112 if (result == FMOD.RESULT.ERR_OUTPUT_CREATEBUFFER)
\r
114 // Can not handle surround sound - back to Stereo.
\r
115 FMODExec(system.setSpeakerMode(FMOD.SPEAKERMODE.STEREO));
\r
118 FMODExec(system.init(
\r
120 FMOD.INITFLAG.NORMAL,
\r
125 // Set real-world effect scales.
\r
126 FMODExec(system.set3DSettings(
\r
127 1.0f, // Doppler scale
\r
128 1.0f, // Distance scale is meters
\r
129 1.0f) // Rolloff factor
\r
132 soundSystemAvailable = true;
\r
133 Logger.Log("Initialized FMOD Ex", Helpers.LogLevel.Debug);
\r
135 catch (Exception ex)
\r
137 Logger.Log("Failed to initialize the sound system: ", Helpers.LogLevel.Warning, ex);
\r
141 public override void Dispose()
\r
143 if (parcelMusic != null)
\r
145 if (!parcelMusic.Disposed)
\r
146 parcelMusic.Dispose();
\r
147 parcelMusic = null;
\r
152 for (int i=0; i<sounds.Count; i++)
\r
154 if (!sounds[i].Disposed)
\r
155 sounds[i].Dispose();
\r
162 if (system != null)
\r
171 public static void FMODExec(FMOD.RESULT result)
\r
173 if (result != FMOD.RESULT.OK)
\r
175 throw new MediaException("FMOD error! " + result + " - " + FMOD.Error.String(result));
\r
180 public class MediaException : Exception
\r
182 public MediaException(string msg)
\r