http://worldwide.bose.com/productsupport/en_us/web/soundlink_wireless_mobile/page.html#article_type=top_article+track_article&article_href=../article_596_replacing_the_battery/page.html%23article_body
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System;
[RequireComponent(typeof(AudioSource))]
public class MicrophoneInput : MonoBehaviour
{
AudioSource audioSource;
public float estimatedLatency { get; protected set; }
//public Texture2D textureSamps;
//public int width;
//public int height;
public int globalSampleRate;
[Range(0.002f, 0.005f)]
public float dTime = 0.005f;
[Range(0, 5)]
public double gain = 1;
[Range(0, 1)]
public double gain1 = 1;
[Range(0, 1)]
public double gain2 = 1;
[Range(0, 1)]
public double gain3 = 1;
[Range(0.00f, 20f)]
public double multInterval1 = 1;
[Range(0.00f, 20f)]
public double multInterval2 = 1;
[Range(0.00f, 20f)]
public double multInterval3 = 1;
[Range(0.01f, 0.02f)]
public double phase1base = 0.01;
[Range(0.01f, 0.02f)]
public double phase2base = 0.01;
[Range(0.01f, 0.02f)]
public double phase3base = 0.01;
[Range(0.0f, 1f)]
public double attack1 = 0.01;
[Range(0.0f, 1f)]
public double decay1 = 0.01;
[Range(0.0f, 1f)]
public double attack2 = 0.01;
[Range(0.0f, 1f)]
public double decay2 = 0.01;
[Range(0.0f, 1f)]
public double attack3 = 0.01;
[Range(0.0f, 1f)]
public double decay3 = 0.01f;
public bool bVoiceHigh = true;
public bool bVoiceMid = true;
public bool bVoiceLow = true;
public bool bMicOn = false;
double phase1;
double phase2;
double phase3;
double amp1;
double amp2;
double amp3;
private double nextTick = 0.0F;
private double amp = 0.0F;
private double phase = 0.0F;
private int accent;
private bool running = false;
private float[] _freqs = { 249.66f, 264.505f, 280.235f, 296.9f, 314.55f, 333.255f, 353.075f, 374.07f, 396.31f, 419.875f, 444.845f, 471.295f, 499.32f };
private float[] _dtime = { 0.004124562f, 0.00389302f, 0.003674579f, 0.003468248f, 0.003273644f, 0.003089948f, 0.002916472f,
0.002752773f, 0.00259828f, 0.002452483f, 0.002314815f, 0.002184885f, 0.002062281f};
[Range(0.0f, 1.0f)]
public float echoGain;
[Range(0.001f, 3.0f)]
public float echoTime;
[Range(-1.5f, 0f)]
public float delayTime = 0f;
[Range(0f, 1f)]
public float echoAttenuation;
private float[] echoBuffer = new float[(int)(48000 * 2 * 6.0f)];
public float[] EchoBuffer
{
get { return echoBuffer; }
}
private int _record_Head = 0;
private int _play_head = 0;
private int _delay_head = 0;
public int Record_Head
{
get { return _record_Head; }
}
public int Play_Head
{
get { return _play_head; }
}
public int Delay_Head
{
get { return _delay_head; }
}
void Awake()
{
// Create an audio source.
audioSource = gameObject.GetComponent<AudioSource>();
audioSource.playOnAwake = false;
audioSource.loop = true;
//width = textureSamps.width;
//height = textureSamps.height;
//684,2048
//Color col = new Color(1, 1, 1, 1);
//for (int i = 20; i < height - 20; i++)
//{
// for (int j = -15; j < 15; j++)
// {
// textureSamps.SetPixel(j + width / 2, i, col);
// }
//}
//textureSamps.Apply();
//for(int i = 0; i)
//textureSamps
//StartInput();
}
void OnApplicationPause(bool paused)
{
if (paused)
{
audioSource.Stop();
Microphone.End(null);
audioSource.clip = null;
}
else
StartInput();
}
public void OnMicOn(bool micOn)
{
bMicOn = micOn;
if (!bMicOn)
{
audioSource.Stop();
Microphone.End(null);
audioSource.clip = null;
//clear echo buff
for (int i = 0; i < echoBuffer.Length; i++)
{
echoBuffer[i] = 0f;
}
}
else
StartInput();
}
//void WriteEchoBuff()
//{
// Color col1 = new Color(1, 1, 1, 1);
// Color col2 = new Color(.3f, .3f, 1, 1);
// Color colBlack = new Color(0, 0, 0, 0);
// int displZoneX = width - 40;
// int displZoneY = height - 40;
// int peak = displZoneX / 2;
// float levSum;
// float avgLev;
// int bucketLen = echoBuffer.Length / displZoneY;
// int n = 0;
// int walker = 0;
// for (int i = 20; i < displZoneY; i++)
// {
// levSum = 0;
// for(int k = 0; k<bucketLen;k++)
// {
// levSum += echoBuffer[k + walker];
// }
// walker += bucketLen;
// avgLev = levSum / bucketLen;
// n = 0;
// for (int j = 20; j < displZoneX/2; j++)
// {
// if ((float)(peak - n)/peak > avgLev)
// textureSamps.SetPixel(j, i, colBlack);
// else
// textureSamps.SetPixel(j, i, col2);
// n++;
// }
// }
// for (int i = 20; i < height - 20; i++)
// {
// for (int j = -4; j < 4; j++)
// {
// textureSamps.SetPixel(j + width / 2, i, col1);
// }
// }
// textureSamps.Apply();
//}
void Update()
{
//WriteEchoBuff();
}
void StartInput()
{
globalSampleRate = AudioSettings.outputSampleRate;
// Create a clip which is assigned to the default microphone.
audioSource.clip = Microphone.Start(null, true, 1, globalSampleRate);
if (audioSource.clip != null)
{
// Wait until the microphone gets initialized.
int delay = 0;
while (delay <= 0) delay = Microphone.GetPosition(null);
// Start playing.
audioSource.Play();
// Estimate the latency.
estimatedLatency = (float)delay / globalSampleRate;
}
else
Debug.LogWarning("GenericAudioInput: Initialization failed.");
}
int count1 = 0;
int count2 = 0;
int count3 = 0;
double phasemult1 = 3.0f;
double phasemult2 = 2.0f;
double phasemult3 = 1.0f;
bool switch1 = true;
bool switch2 = true;
bool switch3 = true;
double time1;
double time2;
double time3;
double accumTime;
bool aOn = true;
double ampSamp(int voice, double sampTime)
{
amp = 0;
if (voice == 1)
{
if (sampTime - time1 < attack1)
{
amp = CubicEaseIn(sampTime - time1, 0, 1, attack1);
}
else if (accumTime - time1 < attack1 + decay1)
{
amp = CubicEaseOut((sampTime - time1 - attack1), 1, -1, decay1);
}
else
{
amp = 0;
}
}
if (voice == 2)
{
if (sampTime - time2 < attack2)
{
amp = CubicEaseIn(sampTime - time2, 0, 1, attack2);
}
else if (accumTime - time2 < attack2 + decay2)
{
amp = CubicEaseOut((sampTime - time2 - attack2), 1, -1, decay2);
}
else
{
amp = 0;
}
}
if (voice == 3)
{
if (sampTime - time3 < attack3)
{
amp = CubicEaseIn(sampTime - time3, 0, 1, attack3);
}
else if (accumTime - time3 < attack3 + decay3)
{
amp = CubicEaseOut((sampTime - time3 - attack3), 1, -1, decay3);
}
else
{
amp = 0;
}
}
return amp;
}
float dTIME = 0f;
double dt;
void OnAudioFilterRead(float[] data, int channels)
{
accumTime = (double)AudioSettings.dspTime;
//private float[] _freqs = { 249.66f, 264.505f, 280.235f, 296.9f, 314.55f, 333.255f, 353.075f, 374.07f, 396.31f, 419.875f, 444.845f, 471.295f,499.32f };
// private float[] _dtime = { 0.004124562f, 0.00389302f, 0.003674579f, 0.003468248f, 0.003273644f, 0.003089948f, 0.002916472f,
// 0.002752773f, 0.00259828f, 0.002452483f, 0.002314815f, 0.002184885f, 0.002062281f};
//float dTIME = dTime;
//for (int i = 0; i<12; i++)
//{
// if(freq > 2*_freqs[i] && freq < 2*_freqs[i+1])
// {
// dTIME = _dtime[i + 1];
// }
//}
// phase1 = dTime * 2f * Mathf.PI / globalSampleRate;
if (count1++ > 10 * multInterval1)
{
time1 = accumTime;//Attack
if (switch1)
{
if (++phasemult1 > 11)
{
switch1 = false;
}
}
else
{
if (--phasemult1 < 2)
{
switch1 = true;
}
}
count1 = 0;
dTIME = _dtime[(int)phasemult1];
}
//if (count2++ > 10* multInterval2)
//{
// time2 = accumTime;//Attack
// if (switch2)
// {
// if (++phasemult2 > 4)
// {
// switch2= false;
// }
// }
// else
// {
// if (--phasemult2 < 4)
// {
// switch2 = true;
// }
// }
// count2 = 0;
//}
//if (count3++ > 10*multInterval3)
//{
// time3 = accumTime;//Attack
// if (switch3)
// {
// if (++phasemult3 > 2)
// {
// switch3 = false;
// }
// }
// else
// {
// if (--phasemult3 < 2)
// {
// switch3 = true;
// }
// }
// count3 = 0;
//}
double samples = AudioSettings.dspTime * globalSampleRate;
int dataLen = data.Length / channels;
double deltTime = (AudioSettings.dspTime / samples);
int n = 0;
double a, b, c;
double sampTime = accumTime;
dt = deltTime / dTIME * 2f * Mathf.PI;
while (n < dataLen)
{
sampTime += deltTime;
if (bVoiceHigh) a = gain * ampSamp(1, sampTime)* Math.Sin(phase1); else a = 0;//ampSamp(1,sampTime)
if (bVoiceMid) b = gain * ampSamp(2, sampTime) * Math.Sin(phase2); else b = 0;
if (bVoiceLow) c = gain * ampSamp(3, sampTime) * Math.Sin(phase3); else c = 0;
float x = (float)(gain1 * a + gain2 * b + gain3 * c);
int i = 0;
while (i < channels)
{
if (bMicOn)
{
record(data[n * channels + i] + playback(delayTime) + x);
//data[n * channels + i] = (float)a;
data[n * channels + i] = echoGain * playback();
}
else
{
data[n * channels + i] = 0f;
}
i++;
}
phase1 += dt;
if (phase1 > Math.PI * 2f) phase1 = 0f;
phase2 += phase2base * phasemult2;
if (phase2 > Math.PI * 2f) phase2 = 0f;
phase3 += phase3base * phasemult3;
if (phase3 > Math.PI * 2f) phase3 = 0f;
n++;
}
}
/// </summary>
/// <param name= t "current">how long into the ease are we</param>
/// <param name= b "initialValue">starting value if current were 0</param>
/// <param name= c "totalChange">total change in the value (not the end value, but the end - start)</param>
/// <param name= d "duration">the total amount of time (when current == duration, the returned value will == initial + totalChange)</param>
/// <returns></returns>
private void record(float samp)
{
if (++_record_Head > echoBuffer.Length - 1) _record_Head = 0;
echoBuffer[_record_Head] = samp;
}
private float playback()
{
_play_head = (int)(_record_Head - (echoTime * globalSampleRate * 2f));
if (_play_head < 0) _play_head = (int)(6.0f * globalSampleRate * 2f) + _play_head;
return echoBuffer[_play_head] * echoAttenuation;
}
private float playback(float delay)
{
_delay_head = (int)(_record_Head + (delayTime * globalSampleRate * 2f));
if (_delay_head < 0) _delay_head = (int)(6.0f * globalSampleRate * 2f) + _delay_head;
if (_delay_head > echoBuffer.Length - 1) _delay_head = _delay_head - (echoBuffer.Length - 1);
_delay_head = (int)(_delay_head - (echoTime * globalSampleRate * 2f));
if (_delay_head < 0) _delay_head = (int)(6.0f * globalSampleRate * 2f) + _delay_head;
return echoBuffer[_delay_head] * echoAttenuation;
}
public static double CubicEaseOut(double t, double b, double c, double d)
{
if (t < d)
{
return c * ((t = t / d - 1) * t * t + 1) + b;
}
else
{
return b + c;
}
}
public static double CubicEaseIn(double t, double b, double c, double d)
{
if (t < d)
{
return c * (t /= d) * t * t + b;
}
else
{
return b + c;
}
}
}