2 // Radegast Metaverse Client
3 // Copyright (c) 2009-2013, Radegast Development Team
4 // All rights reserved.
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
9 // * Redistributions of source code must retain the above copyright notice,
10 // this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above copyright
12 // notice, this list of conditions and the following disclaimer in the
13 // documentation and/or other materials provided with the distribution.
14 // * Neither the name of the application "Radegast", nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 // $Id: Sound.cs 502 2010-03-14 23:13:46Z latifer $
32 using System.Runtime.InteropServices;
36 namespace Radegast.Media
38 public class Speech : MediaObject
41 /// Fired when a stream meta data is received
43 /// <param name="sender">Sender</param>
44 /// <param name="e">Key, value are sent in e</param>
45 public delegate void SpeechDoneCallback(object sender, EventArgs e);
47 /// Fired when a stream meta data is received
49 public event SpeechDoneCallback OnSpeechDone;
50 private String filename;
51 private Vector3 speakerPos;
54 /// If true, decrease distance falloff effect in volume.
56 private static Boolean compress = true;
57 public static Boolean Compress
59 set { compress = value; }
60 get { return compress; }
64 /// Creates a new sound object
66 /// <param name="system">Sound system</param>
70 extraInfo.format = SOUND_FORMAT.PCM16;
75 /// Releases resources of this sound object
77 public override void Dispose()
88 /// Plays audio from a file, as created by an external speech synthesizer.
90 /// <param name="filename">Name of a WAV file</param>
91 /// <param name="global"></param>
92 /// <returns>Length of the sound in ms</returns>
93 public uint Play(string speakfile, bool global, Vector3 pos)
100 // Set flags to determine how it will be played.
101 FMOD.MODE mode = FMOD.MODE.SOFTWARE | FMOD.MODE._3D;
103 // Set coordinate space interpretation.
105 mode |= FMOD.MODE._3D_WORLDRELATIVE;
107 mode |= FMOD.MODE._3D_HEADRELATIVE;
109 System.Threading.AutoResetEvent done = new System.Threading.AutoResetEvent(false);
111 invoke(new SoundDelegate(
117 system.createSound(filename,
122 // Register for callbacks.
123 RegisterSound(sound);
125 // Find out how long the sound should play
126 FMODExec(sound.getLength(ref len, TIMEUNIT.MS));
128 // Allocate a channel, initially paused.
129 FMODExec(system.playSound(CHANNELINDEX.FREE, sound, true, ref channel));
131 // Set general Speech volume.
132 //TODO Set this in the GUI
134 FMODExec(channel.setVolume(volume));
136 // Set attenuation limits so distant people get a little softer,
139 FMODExec(sound.set3DMinMaxDistance(
140 2f, // Any closer than this gets no louder
141 3.5f)); // Further than this gets no softer.
143 FMODExec(sound.set3DMinMaxDistance(
144 2f, // Any closer than this gets no louder
145 10f)); // Further than this gets no softer.
147 // Set speaker position.
148 position = FromOMVSpace(speakerPos);
149 FMODExec(channel.set3DAttributes(
155 "Speech at <{0:0.0},{1:0.0},{2:0.0}>",
159 Helpers.LogLevel.Debug);
161 // SET a handler for when it finishes.
162 FMODExec(channel.setCallback(endCallback));
163 RegisterChannel(channel);
165 // Un-pause the sound.
166 FMODExec(channel.setPaused(false));
170 Logger.Log("Error playing speech: ", Helpers.LogLevel.Error, ex);
178 done.WaitOne(30 * 1000, false);
183 /// Handler for reaching the end of playback of a speech.
185 /// <returns></returns>
186 protected override RESULT EndCallbackHandler()
188 invoke(new SoundDelegate(
194 FMODExec(sound.release());
197 // Tell speech control the file has been played. Note
198 // the event is dispatched on FMOD's thread, to make sure
199 // the event handler does not start a new sound before the
200 // old one is cleaned up.
201 if (OnSpeechDone != null)
204 OnSpeechDone(this, new EventArgs());
206 catch (Exception) { }