windows mobile 播放声音C#(转)
http://hi.baidu.com/wgscd/blog/item/401bcf08fbc035810a7b8292.html
Recently I created a Smart Device application called SightReader. There is a virtual piano keyboard in it and I need to play sound when the user clicks a key on keyboard. I was trying to use the WavPlayer I created before. It is easy to use, but it only support WAV file. I generated the sound MIDI file for each key and then converted them to WAV file. However I couldn’t get the wav file to be reasonable size. So the compiled executable was huge and impossible to use on a Smart Device. Finally I created another SoundPlayer which can play MIDI, MP3 and WAV file. It works fine except it has slower response time.
New update(3/3/2009): I really don't like the sound of the MIDI in my SightReader. So I searched and searched. Finally somebody mentioned that you can use "Sound Recorder" in Windows to reduce the size of a WAV file. But when I looked the Sound Recorder in Vista, I don't see any choice other than recording sound. So I went to a Windows 2000. Aha! Here we go. Now I was able to use audio format "11.025 khz, 16 Bit, Mono" to convert my once 200 KB WAV file to 22 KB. Other good things about the Sound Record is you can do some editing to the WAV file, such as increase the volume or deletion. It is a shame that Microsoft doesn't provide the same features in Vista.
How to play WAV file?
public class WavPlayer
{
private byte[] m_soundBytes;
private string m_fileName;
private enum Flags
{
SND_SYNC = 0x0000, /* play synchronously (default) */
SND_ASYNC = 0x0001, /* play asynchronously */
SND_NODEFAULT = 0x0002, /* silence (!default) if sound not found */
SND_MEMORY = 0x0004, /* pszSound points to a memory file */
SND_LOOP = 0x0008, /* loop the sound until next sndPlaySound */
SND_NOSTOP = 0x0010, /* don't stop any currently playing sound */
SND_NOWAIT = 0x00002000, /* don't wait if the driver is busy */
SND_ALIAS = 0x00010000, /* name is a registry alias */
SND_ALIAS_ID = 0x00110000, /* alias is a predefined ID */
SND_FILENAME = 0x00020000, /* name is file name */
SND_RESOURCE = 0x00040004 /* name is resource name or atom */
}
[DllImport("CoreDll.DLL", EntryPoint = "PlaySound", SetLastError = true)]
private extern static int WCE_PlaySound(string szSound, IntPtr hMod, int flags);
[DllImport("CoreDll.DLL", EntryPoint = "PlaySound", SetLastError = true)]
private extern static int WCE_PlaySoundBytes(byte[] szSound, IntPtr hMod, int flags);
/// <summary>
/// Construct the Sound object to play sound data from the specified file.
/// </summary>
public WavPlayer(string fileName)
{
m_fileName = fileName;
}
/// <summary>
/// Construct the Sound object to play sound data from the specified stream.
/// </summary>
public WavPlayer(Stream stream)
{
// read the data from the stream
m_soundBytes = new byte[stream.Length];
stream.Read(m_soundBytes, 0, (int)stream.Length);
}
public WavPlayer(byte[] soundBytes)
{
m_soundBytes = soundBytes;
}
/// <summary>
/// Play the sound
/// </summary>
public void Play()
{
// if a file name has been registered, call WCE_PlaySound,
// otherwise call WCE_PlaySoundBytes
if (m_fileName != null)
WCE_PlaySound(m_fileName, IntPtr.Zero, (int)(Flags.SND_SYNC | Flags.SND_FILENAME));
else
WCE_PlaySoundBytes(m_soundBytes, IntPtr.Zero, (int)(Flags.SND_SYNC | Flags.SND_MEMORY));
}
}
How to play MIDI, MP3 and other sound?
This method will only work in Windows Mobile 6 and later.
public enum SoundFileType { WAV, MP3, MIDI, WMA }
public class SoundPlayer : IDisposable
{
[DllImport("aygshell.dll")]
static extern uint SndOpen(string pszSoundFile, ref IntPtr phSound);
[DllImport("aygshell.dll")]
static extern uint SndPlayAsync(IntPtr hSound, uint dwFlags);
[DllImport("aygshell.dll")]
static extern uint SndClose(IntPtr hSound);
[DllImport("aygshell.dll")]
static extern uint SndStop(int SoundScope, IntPtr hSound);
[DllImport("aygshell.dll")]
static extern uint SndPlaySync(string pszSoundFile, uint dwFlags);
const int SND_SCOPE_PROCESS = 0x1;
IntPtr sound = IntPtr.Zero;
Thread soundThread = null;
string _filePath = string.Empty;
public string FilePath
{
get { return _filePath; }
set { _filePath = value; }
}
public SoundPlayer(string filePath)
{
_filePath = filePath;
}
public SoundPlayer(byte[] soundBytes, SoundFileType fileType)
{
string fileExtension = ".wav";
switch (fileType)
{
case SoundFileType.WAV:
fileExtension = ".wav";
break;
case SoundFileType.MP3:
fileExtension = ".mp3";
break;
case SoundFileType.MIDI:
fileExtension = ".mid";
break;
default:
throw new Exception("Audio format is not supported.");
break;
}
_filePath = Path.GetTempPath() + "tempSound" + fileExtension;
FileStream fs = new FileStream(_filePath, FileMode.Create, FileAccess.ReadWrite);
fs.Write(soundBytes, 0, soundBytes.Length);
fs.Close();
}
public void Play()
{
SndPlaySync(_filePath, 0);
}
public void PlayLooping()
{
soundThread = new Thread(Playing);
soundThread.Start();
}
private void Playing()
{
while (true)
{
SndPlaySync(_filePath, 0);
}
}
public void PlayAsync()
{
SndOpen(_filePath, ref sound);
SndPlayAsync(sound, 0);
}
public void Stop()
{
if (soundThread != null)
{
SndStop(SND_SCOPE_PROCESS, IntPtr.Zero);
soundThread.Abort();
soundThread = null;
}
if (sound != IntPtr.Zero)
{
SndStop(SND_SCOPE_PROCESS, IntPtr.Zero);
SndClose(sound);
sound = IntPtr.Zero;
}
}
#region IDisposable Members
public void Dispose()
{
Stop();
}
#endregion
}
--------------------- 例子代码----------------------------------------------------
我现在用的是CoreDll.DLL,但是只能播放wav格式的,我想实现的功能是读取到短信铃声,并播放出来.下面的代码完全可以直接使用
public class Sound
{
private byte[] m_soundBytes;
private string m_fileName;
private enum Flags
{
SND_SYNC = 0x0000, /* play synchronously (default) */
SND_ASYNC = 0x0001, /* play asynchronously */
SND_NODEFAULT = 0x0002, /* silence (!default) if sound not found */
SND_MEMORY = 0x0004, /* pszSound points to a memory file */
SND_LOOP = 0x0008, /* loop the sound until next sndPlaySound */
SND_NOSTOP = 0x0010, /* don't stop any currently playing sound */
SND_NOWAIT = 0x00002000, /* don't wait if the driver is busy */
SND_ALIAS = 0x00010000, /* name is a registry alias */
SND_ALIAS_ID = 0x00110000, /* alias is a predefined ID */
SND_FILENAME = 0x00020000, /* name is file name */
SND_RESOURCE = 0x00040004 /* name is resource name or atom */
}
[DllImport("CoreDll.DLL", EntryPoint = "PlaySound", SetLastError = true)]
private extern static int WCE_PlaySound(string szSound, IntPtr hMod, int flags);
[DllImport("CoreDll.DLL", EntryPoint = "PlaySound", SetLastError = true)]
private extern static int WCE_PlaySoundBytes(byte[] szSound, IntPtr hMod, int flags);
/// <summary>
/// Construct the Sound object to play sound data from the specified file.
/// </summary>
public Sound(string fileName)
{
m_fileName = fileName;
}
public Sound()
{ }
/// <summary>
/// Construct the Sound object to play sound data from the specified stream.
/// </summary>
public Sound(Stream stream)
{
// read the data from the stream
m_soundBytes = new byte[stream.Length];
stream.Read(m_soundBytes, 0, (int)stream.Length);
}
/// <summary>
/// Play the sound
/// </summary>
public void Play()
{
// if a file name has been registered, call WCE_PlaySound,
// otherwise call WCE_PlaySoundBytes
if (m_fileName != null)
WCE_PlaySound(m_fileName, IntPtr.Zero, (int)(Flags.SND_ASYNC | Flags.SND_FILENAME));
else
WCE_PlaySoundBytes(m_soundBytes, IntPtr.Zero, (int)(Flags.SND_ASYNC | Flags.SND_MEMORY));
}
public void Stop()
{
if (m_fileName != null)
WCE_PlaySound(null, IntPtr.Zero, (int)(Flags.SND_ASYNC | Flags.SND_FILENAME));
else
WCE_PlaySoundBytes(null, IntPtr.Zero, (int)(Flags.SND_ASYNC | Flags.SND_MEMORY));
}
}