Skip to content

Instantly share code, notes, and snippets.

@cubed2d
Created May 18, 2016 19:42
Show Gist options
  • Save cubed2d/cf1f37fc02cea7fc48bc7306b43ee87b to your computer and use it in GitHub Desktop.
Save cubed2d/cf1f37fc02cea7fc48bc7306b43ee87b to your computer and use it in GitHub Desktop.
using UnityEngine;
using System;
using System.Collections;
public class SineSynth : MonoBehaviour
{
[Range(100,1000)]
public double Frequency = 440;
[Range(0.05f, 0.3f)]
public double Gain = 0.05; // Amplitude?
public int sampleCount, channelCount;
private double increment, incrementLinear;
private double phase, phaseLinear;
private double samplingFrequency = 48000;
public AnimationCurve curve;
public WaveType WaveType;
[Range(2,50)]
public int WaveRefinement = 20;
int[] harmonics;
void Start()
{
int bpm = 120;
float beat = 60 / bpm;
harmonics = new int[50];
harmonics[0] = 3;
for (int i = 1; i < 50; i++)
{
harmonics[i] = harmonics[i - 1] + 2;
}
curve = new AnimationCurve();
FllCurve();
}
void FllCurve()
{
while (curve.length > 0)
{
curve.RemoveKey(0);
}
float t = 0;
for (int i = 0; i < 1024; i++)
{
curve.AddKey(t, 0);
t += 2f;
}
}
int count;
void OnAudioFilterRead(float[] data, int channels)
{
count = 0;
// update increment in case frequency has changed
channelCount = channels;
sampleCount = data.Length / channels;
increment = Frequency * 2 * Math.PI / samplingFrequency;
incrementLinear = increment / (Math.PI * 2);
for (var i = 0; i < data.Length; i = i + channels)
{
phase = phase + increment;
phaseLinear = phaseLinear + incrementLinear;
// this is where we copy audio data to make them “available” to Unity
//float sample = SineSyth();
float sample = PerfectSyth();
data[i] = sample;
try
{
var key = curve[count];
key.value = sample;
curve.MoveKey(count, key);
}
catch
{
Debug.Log("fff");
}
// if we have stereo, we copy the mono data to each channel
if (channels == 2) data[i + 1] = sample;
if (phase > 2 * Math.PI) phase = 0;
if (phaseLinear > 1) phaseLinear = 0;
count++;
}
}
private float SineSyth()
{
float sample = (float)(Gain * Math.Sin(phase));
if (WaveType != WaveType.Sine)
{
for (int j = 2; j < WaveRefinement; j++)
{
switch (WaveType)
{
case WaveType.Square:
sample += (float)(Gain * (Math.Sin((j * 2 - 1) * phase) / (j * 2 - 1)));
break;
case WaveType.Triangle:
sample += (float)(Gain * (Math.Sin((j * 2 - 1) * phase) / Math.Pow(2, (j * 2 - 1))));
break;
case WaveType.Saw:
sample += (float)(Gain * (Math.Sin((j * 2) * phase) / (j)));
break;
case WaveType.Noise:
break;
}
}
}
return sample;
}
private float PerfectSyth()
{
float sample = 0;
switch (WaveType)
{
case WaveType.Sine:
sample = (float)Math.Sin(Math.PI * 2.0 * phaseLinear);
break;
case WaveType.Square:
sample = phaseLinear < 0.5 ? 1 : -1;
break;
case WaveType.Triangle:
sample = (float)(phaseLinear < 0.25 ? phaseLinear * 4.0 : phaseLinear < 0.75 ? 2.0 - phaseLinear * 4.0 : phaseLinear * 4.0 - 4.0);
break;
case WaveType.Saw:
sample = (float)(phaseLinear < 0.5 ? phaseLinear * 2.0 : phaseLinear * 2.0 - 2.0);
break;
case WaveType.Noise:
sample = 0.5f;
break;
default:
break;
}
return (float)Gain * sample;
}
}
public enum WaveType
{
Sine,
Square,
Triangle,
Saw,
Noise
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment