有关音频的实现
最近在做新加坡政府项目时用到了声音。在此记录一下整个实现过程。
第一阶段实现:
System.Media.SoundPlayer sp = new System.Media.SoundPlayer("./FireCoding.wav");
sp.Load();
sp.PlaySync()
第二阶段的实现:
后来声音要求发送到不同的音频设备上去
于是使用了WinMM5.1
class WaveLib
{
#region properties
//int m_currentDeviceId = 0;
private int CurrentDeviceId
{
get
{
int id = 1;
try
{
id = int.Parse(ConfigurationSettings.AppSettings["SoundDevice"]);
}
catch(Exception ex)
{
Logger.GetLogger(Logger.LOCAL_LOG).Error("Sound Device number invaild in config file", ex);
}
return id - 1;
}
//set { m_currentDeviceId = value; }
}
private WaveFormat m_coutWaveFormat = WaveFormat.Pcm44Khz16BitStereo;
public WaveFormat CoutWaveFormat
{
get { return m_coutWaveFormat; }
set { m_coutWaveFormat = value; }
}
private string m_wavFileName = @"./FireCoding.wav";
public string AudioFileName
{
get { return m_wavFileName; }
set { m_wavFileName = value; }
}
//private string m_requiredProperty = "ProductName";
//public string RequiredProperty
//{
// get { return m_requiredProperty; }
// set { m_requiredProperty = value; }
//}
//private string m_device = "Win32_SoundDevice";
//public string Device
//{
// get { return m_device; }
// set { m_device = value; }
//}
#endregion
#region get the sound device count
//method1
private const string mmdll = "winmm.dll";
[DllImport(mmdll)]
public static extern int waveOutGetNumDevs();
public static int DeviceCount
{
get { return waveOutGetNumDevs(); }
}
//method2
//List<ManagementObject> m_managementObjects = new List<ManagementObject>();
//public void waveOutGetDevices()
//{
// SelectQuery query = new SelectQuery(Device);
// ManagementObjectSearcher objSearcher = new ManagementObjectSearcher(query);
// ManagementObjectCollection objCollection = objSearcher.Get();
// foreach (ManagementObject obj in objCollection)
// {
// foreach (PropertyData property in obj.Properties)
// {
// if (property.Name == RequiredProperty)
// {
// m_managementObjects.Add(obj);
// }
// }
// }
// //return m_managementObjects;
//}
#endregion
public WaveLib()
{
//init devices list
//waveOutGetDevices();
}
#region play the sound
public bool Play()
{
try
{
int deviceId = 0;
//if there is at least one sound device.
//if (m_managementObjects.Count > 1)
if(DeviceCount>1)
{
deviceId = CurrentDeviceId;
}
WaveOut waveOut = new WaveOut(deviceId);
byte[] data = ReadAudioFile();
waveOut.Open(CoutWaveFormat);
waveOut.Write(data);
}
catch (Exception ex)
{
return false;
}
return true;
}
#endregion
#region read the sound file to buffer
private byte[] ReadAudioFile()
{
byte[] buffer;
FileStream fileStream = new FileStream(AudioFileName, FileMode.Open, FileAccess.Read);
try
{
int length = (int)fileStream.Length; // get file length
buffer = new byte[length]; // create buffer
int count; // actual number of bytes read
int sum = 0; // total number of bytes read
// read until Read method returns 0 (end of the stream has been reached)
while ((count = fileStream.Read(buffer, sum, length - sum)) > 0)
{
sum += count; // sum is a buffer offset for next reading
}
}
finally
{
fileStream.Close();
}
return buffer;
}
#endregion
}
调用方法:
if (File.Exists(tape.WavFile))
{
//SoundPlayer sp = new SoundPlayer(tape.WavFile);
//sp.Load();
//sp.PlaySync();
//@yohen 08/12/2010
var waveLib = new WaveLib();
waveLib.AudioFileName = tape.WavFile;
waveLib.CoutWaveFormat = tape.Name == "DefaultVoice" ? WaveFormat.Pcm11Khz8BitMono : WaveFormat.Pcm44Khz16BitStereo;
waveLib.Play();
}
第三阶段的实现:
用户的要求现在不只停留在生简的声音上面了,而且要求根据不同的报警声音,朗读不同的事件文本。
于是我改用了SpeechLib.
郎读文本的代码
public TTSConverter()
{
this.voice = new SpVoice();
}
public bool Play(string text)
{
if (string.IsNullOrEmpty(text))
return false;
//set the speech device if there are more than one device.
//@yohen 08/12/2010
var spObjectTokens = voice.GetAudioOutputs(string.Empty, string.Empty);
if(spObjectTokens.Count>1)
{
voice.AudioOutput = spObjectTokens.Item(CurrentSoundDeviceId);
}
//speak speed @yohen 14/12/2010
voice.Rate = -1;
//voice.Speak("<pron sym=\"h eh 1 l ow & we\">hello</pron>", spFlags);
//voice.Speak("<PRON SYM=\"d eh l f y\">Delphi</PRON>", spFlags);
this.voice.Speak(text, this.flags);
return true;
}
播放声音的代码
SpVoiceClass pp = new SpVoiceClass();
var spObjectTokens = pp.GetAudioOutputs(string.Empty, string.Empty);
if (spObjectTokens.Count > 1)
{
pp.AudioOutput = spObjectTokens.Item(CurrentSoundDeviceId);
}
SpFileStreamClass spFs = new SpFileStreamClass();
spFs.Open(AudioFileName, SpeechStreamFileMode.SSFMOpenForRead, true);
ISpeechBaseStream Istream = spFs as ISpeechBaseStream;
pp.SpeakStream(Istream, SpeechVoiceSpeakFlags.SVSFIsFilename);
spFs.Close();
最终使用SpeechLib,播放声音和朗读文本,并实现用户可选择音频设备。