|
|
using Apewer.Models; using System; using System.Collections.Generic; using System.Text; // using System.Threading.Tasks;
using System.IO; using Apewer.Internals.Interop;
#if NET40_OR_GREATER
using System.Speech.Synthesis; #endif
namespace Apewer {
/// <summary>音频实用工具。</summary>
public sealed class AudioUtility {
private AudioUtility() { }
#region WAVE 校验。
private static int mmioFOURCC(char ch0, char ch1, char ch2, char ch3) { int num = 0; num |= ch0; num |= (int)((uint)ch1 << 8); num |= (int)((uint)ch2 << 16); return num | (int)((uint)ch3 << 24); }
private static int BytesToInt(byte ch0, byte ch1, byte ch2, byte ch3) { return mmioFOURCC((char)ch3, (char)ch2, (char)ch1, (char)ch0); }
private static short BytesToInt16(byte ch0, byte ch1) { int num = ch1 | ch0 << 8; return (short)num; }
/// <summary>检查字节数组是 WAVE。</summary>
public static bool IsWave(params byte[] data) { if (data == null || data.LongLength < 1L) return false;
int num = 0; short num2 = -1; bool flag = false; if (data.Length < 12) return false; // throw new InvalidOperationException(SR.GetString("SoundAPIInvalidWaveHeader"));
if (data[0] == 82 && data[1] == 73 && data[2] == 70 && data[3] == 70) { if (data[8] == 87 && data[9] == 65 && data[10] == 86 && data[11] == 69) { num = 12; int num3 = data.Length; while (!flag && num < num3 - 8) { if (data[num] == 102 && data[num + 1] == 109 && data[num + 2] == 116 && data[num + 3] == 32) { flag = true; int num4 = BytesToInt(data[num + 7], data[num + 6], data[num + 5], data[num + 4]); int num5 = 16; if (num4 != num5) { int num6 = 18; if (num3 < num + 8 + num6 - 1) return false; // throw new InvalidOperationException(SR.GetString("SoundAPIInvalidWaveHeader"));
short num7 = BytesToInt16(data[num + 8 + num6 - 1], data[num + 8 + num6 - 2]); if (num7 + num6 != num4) return false; // throw new InvalidOperationException(SR.GetString("SoundAPIInvalidWaveHeader"));
} if (num3 < num + 9) return false; // throw new InvalidOperationException(SR.GetString("SoundAPIInvalidWaveHeader"));
num2 = BytesToInt16(data[num + 9], data[num + 8]); num += num4 + 8; } else { num += 8 + BytesToInt(data[num + 7], data[num + 6], data[num + 5], data[num + 4]); } } if (!flag) return false; // throw new InvalidOperationException(SR.GetString("SoundAPIInvalidWaveHeader"));
if (num2 == 1) return true; if (num2 == 2) return true; if (num2 == 3) return true; return false; // throw new InvalidOperationException(SR.GetString("SoundAPIFormatNotSupported"));
} return false; // throw new InvalidOperationException(SR.GetString("SoundAPIInvalidWaveHeader"));
} return false; // throw new InvalidOperationException(SR.GetString("SoundAPIInvalidWaveHeader"));
}
#endregion
#region WinMM 控制。
/// <summary>WinMM:播放音频。</summary>
/// <param name="wave">波形数据。</param>
/// <param name="loop">循环播放。</param>
public static void Play(byte[] wave, bool loop = false) { if (wave == null || wave.LongLength == 0) return;
int flag = loop ? 9 : 1; try { WinMM.PlaySound(wave, IntPtr.Zero, 6 | flag); } catch { } }
/// <summary>WinMM:停止播放。</summary>
public static void Stop() { try { WinMM.PlaySound(null as string, IntPtr.Zero, 64); } catch { } }
private static void MessageBeep(int type) { try { User32.MessageBeep(type); } catch { } }
/// <summary>播放系统声音。</summary>
public static void Asterisk() => MessageBeep(64);
/// <summary>播放系统声音。</summary>
public static void Beep() => MessageBeep(0);
/// <summary>播放系统声音。</summary>
public static void Exclamation() => MessageBeep(48);
/// <summary>播放系统声音。</summary>
public static void Hand() => MessageBeep(16);
/// <summary>播放系统声音。</summary>
public static void Question() => MessageBeep(32);
#endregion
#if NET40_OR_GREATER
/// <summary>列举所有 Speech Voices 的 Name。 </summary>
public static List<string> ListVoices() { var list = new List<string>(); using (var synthesizer = new SpeechSynthesizer()) { var installed = synthesizer.GetInstalledVoices(); foreach (var voice in installed) { list.Add(voice.VoiceInfo.Name); } } return list; }
/// <summary>获取 Voice 信息。</summary>
public static VoiceInfo GetVoice(string name) { if (string.IsNullOrEmpty(name)) return null; using (var synthesizer = new SpeechSynthesizer()) { var installed = synthesizer.GetInstalledVoices(); foreach (var voice in installed) { if (voice.VoiceInfo.Name == name) return voice.VoiceInfo; } } return null; }
/// <summary>讲述文本,默认为异步执行。</summary>
public static void Speak(string text, string voice = null, bool async = true) { if (string.IsNullOrEmpty(text)) return;
if (async) { var wave = Render(text, voice); Play(wave); } else { using (var synthesizer = new SpeechSynthesizer()) { try { if (!string.IsNullOrEmpty(voice)) synthesizer.SelectVoice(voice); synthesizer.Speak(text); } catch { } } } }
/// <summary>渲染为音频数据。</summary>
public static byte[] Render(string text, string voice = null) { if (string.IsNullOrEmpty(text)) return null; using (var memory = new MemoryStream()) { using (var synthesizer = new SpeechSynthesizer()) { try { if (!string.IsNullOrEmpty(voice)) synthesizer.SelectVoice(voice); synthesizer.SetOutputToWaveStream(memory); synthesizer.Speak(text); } catch { } } var bytes = memory.ToArray(); return bytes; } }
#endif
}
}
|