2011-05-29 99 views
8

我意识到您可以使用SoundPlayer在C#中播放声音;但是,我希望能够使用此方法从以字节数组表示的声音中播放OS默认声音播放器的声音。这可能吗?在C#中播放声音字节[]#

+1

尝试什么是你的byte []的来源是什么?它是wav还是什么? – abatishchev 2011-05-29 16:53:50

+0

这是一个WAV文件。 – Mani5556 2011-05-29 16:55:52

回答

7

用应用程序打开任何文件,例如媒体播放器,需要一个文件。

因此,您需要以某种格式将字节数组保存到文件中,例如, WAV,并打开它:

byte[] bytes = ... 
string name = Path.ChangeExtension(Path.GetRandomFileName(), ".wav"); 
string path = Path.Combine(Path.GetTempPath(), name); 
File.WriteAllBytes(path, bytes); 
Process.Start(path); 

此代码将打开用户默认媒体播放器,就像您在Windows资源管理器中单击它一样。

+0

好的,我很怀疑!谢谢。 – Mani5556 2011-05-29 16:59:14

+0

@ user624071:很高兴帮助:) – abatishchev 2011-05-29 17:01:02

7

SoundPlayer构造函数接受要播放的流。你可以通过创建一个MemoryStream从一个byte []获得一个Stream。

4

abatishchev有一个很好的答案,但您不需要将字节保存到文件,然后播放该文件。你可以写这些字节到一个MemoryStream,然后播放MemoryStream的,因为这方法做:

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Windows.Forms; 

public static void PlayBeep(UInt16 frequency, int msDuration, UInt16 volume = 16383) 
{ 
    var mStrm = new MemoryStream(); 
    BinaryWriter writer = new BinaryWriter(mStrm); 

    const double TAU = 2 * Math.PI; 
    int formatChunkSize = 16; 
    int headerSize = 8; 
    short formatType = 1; 
    short tracks = 1; 
    int samplesPerSecond = 44100; 
    short bitsPerSample = 16; 
    short frameSize = (short)(tracks * ((bitsPerSample + 7)/8)); 
    int bytesPerSecond = samplesPerSecond * frameSize; 
    int waveSize = 4; 
    int samples = (int)((decimal)samplesPerSecond * msDuration/1000); 
    int dataChunkSize = samples * frameSize; 
    int fileSize = waveSize + headerSize + formatChunkSize + headerSize + dataChunkSize; 
    // var encoding = new System.Text.UTF8Encoding(); 
    writer.Write(0x46464952); // = encoding.GetBytes("RIFF") 
    writer.Write(fileSize); 
    writer.Write(0x45564157); // = encoding.GetBytes("WAVE") 
    writer.Write(0x20746D66); // = encoding.GetBytes("fmt ") 
    writer.Write(formatChunkSize); 
    writer.Write(formatType); 
    writer.Write(tracks); 
    writer.Write(samplesPerSecond); 
    writer.Write(bytesPerSecond); 
    writer.Write(frameSize); 
    writer.Write(bitsPerSample); 
    writer.Write(0x61746164); // = encoding.GetBytes("data") 
    writer.Write(dataChunkSize); 
    { 
     double theta = frequency * TAU/(double)samplesPerSecond; 
     // 'volume' is UInt16 with range 0 thru Uint16.MaxValue (= 65 535) 
     // we need 'amp' to have the range of 0 thru Int16.MaxValue (= 32 767) 
     double amp = volume >> 2; // so we simply set amp = volume/2 
     for (int step = 0; step < samples; step++) 
     { 
      short s = (short)(amp * Math.Sin(theta * (double)step)); 
      writer.Write(s); 
     } 
    } 

    mStrm.Seek(0, SeekOrigin.Begin); 
    new System.Media.SoundPlayer(mStrm).Play(); 
    writer.Close(); 
    mStrm.Close(); 
} // public static void PlayBeep(UInt16 frequency, int msDuration, UInt16 volume = 16383) 

对于你的问题,你不需要在大多数这种方法创建WAV格式的字节流的代码,但您可以在该方法的最后使用该技巧以避免将字节保存到文件中。

1

How to play from an array

PlayerEx pl = new PlayerEx(); 

private static void PlayArray(PlayerEx pl) 
{ 
    double fs = 8000; // sample freq 
    double freq = 1000; // desired tone 
    short[] mySound = new short[4000]; 
    for (int i = 0; i < 4000; i++) 
    { 
     double t = (double)i/fs; // current time 
     mySound[i] = (short)(Math.Cos(t * freq) * (short.MaxValue)); 
    } 
    IntPtr format = AudioCompressionManager.GetPcmFormat(1, 16, (int)fs); 
    pl.OpenPlayer(format); 
    byte[] mySoundByte = new byte[mySound.Length * 2]; 
    Buffer.BlockCopy(mySound, 0, mySoundByte, 0, mySoundByte.Length); 
    pl.AddData(mySoundByte); 
    pl.StartPlay(); 
}