マイクで取った音をUDPで送って別のマシンのスピーカから再生させる
ManagedDirectXのDirectSoundでマイクを拾ってUDPに詰め込んでネットワークに流し、受け取った側で再生させる例。
ハウリングの防止とか、認証とか何もしてない。圧縮もせず44.1KHzのwaveをだだ流ししてるだけ。
送信側
using Org.Shokai.Net; VoiceChat chat = new VoiceChat(this); // 使用するFormなどのcontrolを渡す chat.StartSend("192.168.0.3", 6656); // IPアドレス、Port番号
音声入力デバイスの選択はまだ作ってない
受信側
chat.StartReceive(6656); // Port番号
再生デバイスの選択まだ作ってない
VoiceChat.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.DirectX.DirectSound; using System.IO; using System.Threading; using System.Net.Sockets; using System.Net; using System.Windows.Forms; namespace Org.Shokai.Net { public partial class VoiceChat { public string userName; private Control owner; private Device device; private Capture capture; private WaveFormat format; private CaptureBuffer captureBuffer; private CaptureBufferDescription captureBufferDescription; private Thread threadSend, threadReceive; private UdpClient sendClient, receiveClient; private bool sending; /// <summary> /// 送信中かどうか /// </summary> public bool Sending { get { return sending; } } private bool receiving; /// <summary> /// 受信中かどうか /// </summary> public bool Receiving { get { return receiving; } } public VoiceChat(Control owner) { this.owner = owner; sending = false; receiving = false; format = new WaveFormat(); format.Channels = 1; format.FormatTag = WaveFormatTag.Pcm; format.BitsPerSample = 16; format.SamplesPerSecond = 44100; // 44.1KHz format.BlockAlign = (short)(format.Channels * (format.BitsPerSample / (short)8)); format.AverageBytesPerSecond = format.BlockAlign * format.SamplesPerSecond; device = new Device(); device.SetCooperativeLevel(owner, CooperativeLevel.Normal); CaptureDevicesCollection captureDevices = new CaptureDevicesCollection(); DeviceInformation deviceInfo = captureDevices[0]; capture = new Capture(deviceInfo.DriverGuid); } /// <summary> /// 集音/送信開始 /// </summary> /// <param name="ipaddr">送信先IPアドレス or ホスト名</param> /// <param name="port">送信先Port番号</param> public void StartSend(string ipaddr, int port) { sending = true; try { captureBufferDescription = new CaptureBufferDescription(); captureBufferDescription.BufferBytes = format.AverageBytesPerSecond / 5; // 200ms分確保 captureBufferDescription.Format = format; sendClient = new UdpClient(); threadSend = new Thread(delegate() { captureBuffer = new CaptureBuffer(captureBufferDescription, capture); captureBuffer.Start(true); bool readFirstBufferPart = true; int offset = 0; MemoryStream ms = new MemoryStream(captureBufferDescription.BufferBytes / 2); while (true) { ms.Seek(0, SeekOrigin.Begin); captureBuffer.Read(offset, ms, captureBufferDescription.BufferBytes / 2, LockFlag.None); readFirstBufferPart = !readFirstBufferPart; offset = readFirstBufferPart ? 0 : captureBufferDescription.BufferBytes / 2; byte[] bytes = ms.GetBuffer(); sendClient.Send(bytes, bytes.Length, ipaddr, port); Thread.Sleep(10); } }); threadSend.Start(); } catch (Exception ex) { throw ex; } } /// <summary> /// 受信/再生開始 /// </summary> /// <param name="port">受信Port番号</param> public void StartReceive(int port) { BufferDescription playbackBufferDescription = new BufferDescription(); playbackBufferDescription.BufferBytes = format.AverageBytesPerSecond / 5; playbackBufferDescription.Format = format; receiving = true; try { receiveClient = new UdpClient(port); IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, port); threadReceive = new Thread(delegate() { while (true) { byte[] bytes = receiveClient.Receive(ref remoteEP); byte[] decoded = new byte[bytes.Length * 2]; SecondaryBuffer playbackBuffer = new SecondaryBuffer(playbackBufferDescription, device); playbackBuffer.Write(0, bytes, LockFlag.None); playbackBuffer.Play(0, BufferPlayFlags.Default); Thread.Sleep(10); } }); threadReceive.Start(); } catch (Exception ex) { throw ex; } } public void StopSend() { if (captureBuffer != null && captureBuffer.Looping) { captureBuffer.Stop(); captureBuffer = null; } if (sendClient != null) { sendClient.Close(); sendClient = null; } if (threadSend != null) { threadSend.Abort(); threadSend = null; } sending = false; } public void StopReceive() { if (receiveClient != null) { receiveClient.Close(); receiveClient = null; } if (threadReceive != null) { threadReceive.Abort(); threadReceive = null; } receiving = false; } public void Close() { StopSend(); StopReceive(); if (device != null) { device.Dispose(); device = null; } } } }