Skip to content

Instantly share code, notes, and snippets.

@troy-lamerton
Last active August 20, 2019 06:50
Show Gist options
  • Save troy-lamerton/bb456504cc5c9271ecbbe22bf8f9300e to your computer and use it in GitHub Desktop.
Save troy-lamerton/bb456504cc5c9271ecbbe22bf8f9300e to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Dissonance.Audio.Capture;
using NAudio.Wave;
using UnityEngine;
/// <summary>
/// Microphone that connects to discord bot. It plays the audio it receives from the bot.
/// </summary>
public class UdpMicrophone : MonoBehaviour, IMicrophoneCapture {
private readonly WaveFormat formatFromDiscord = new WaveFormat(48000, 2);
private readonly List<IMicrophoneSubscriber> Listeners;
private readonly Queue<ArraySegment<float>> CapturedAudio;
private UdpUser client;
public UdpMicrophone() {
Listeners = new List<IMicrophoneSubscriber>();
CapturedAudio = new Queue<ArraySegment<float>>();
}
public bool IsRecording { get; private set; }
public TimeSpan Latency => TimeSpan.FromMilliseconds(10);
public WaveFormat StartCapture(string name) {
// todo: connect to discordbot's udp server
IsRecording = true;
ConnectToDiscordBot();
return formatFromDiscord;
}
public void ConnectToDiscordBot() {
// open udp connection to the discord bot
// todo (possibly): use named pipe to communicate with bot process when a udp connection cant be made
Debug.Log("Connecting to discord bot's udp server...");
client = UdpUser.ConnectTo("127.0.0.1", 9050);
Task.Factory.StartNew(async () => {
// connect to server wait for reply messages from server and send
Debug.Log("Sending hello to udp server");
client.SendString("I am unity");
try {
while (true) {
// wait for data from discord
var received = await client.Receive();
byte[] data = received.Data;
if (data.Length < 10) {
Debug.Log($"Server says: {Encoding.ASCII.GetString(data)}");
continue;
}
Debug.Log($"Got {data.Length} bytes");
// create a float array and copy the bytes into it
var voiceData = new float[data.Length / 4];
Buffer.BlockCopy(data, 0, voiceData, 0, data.Length);
// voiceData is ready for dissonance
CapturedAudio.Enqueue(new ArraySegment<float>(voiceData));
}
} catch (Exception ex) {
Debug.LogException(ex);
}
});
}
public void StopCapture() {
IsRecording = false;
}
public void Subscribe(IMicrophoneSubscriber listener) {
Listeners.Add(listener);
}
public bool Unsubscribe(IMicrophoneSubscriber listener) {
return Listeners.Remove(listener);
}
public bool UpdateSubscribers() {
if (CapturedAudio.Count == 0) return false;
var audioSample = CapturedAudio.Dequeue();
foreach (var subscriber in Listeners) {
subscriber.ReceiveMicrophoneData(audioSample, formatFromDiscord);
}
return false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment