Skip to content

Instantly share code, notes, and snippets.

@Starpelly
Created May 7, 2022 08:06
Show Gist options
  • Save Starpelly/7f14e9ed31f773991b529fb28fe42610 to your computer and use it in GitHub Desktop.
Save Starpelly/7f14e9ed31f773991b529fb28fe42610 to your computer and use it in GitHub Desktop.
Oscillioscope in Unity using the Shapes plugin. (Can also be used with the default Line Renderer)
// Created by Starpelly, based on the FL STUDIO oscillator
using UnityEngine;
using Shapes;
public class Oscillator : MonoBehaviour
{
public int lengthOfLineRenderer = 16384;
public float thickness;
public float strength;
private Polyline polyline;
public AudioSource source;
[Header("Testing")]
public bool testing;
public double frequency = 400.0;
private double increment;
private double phase;
private readonly double sampleRate = 48000.0;
[Range(0, 32)]
public double gain = 0.5;
[Range(0, 32)]
public double c = 32;
[Range(-32, 32)]
public double ind = 1;
public double z = 5;
[Range(0, 8)]
public byte choice = 0;
void Start()
{
polyline = transform.GetChild(0).GetComponent<Polyline>();
polyline.Closed = false;
for (int i = 0; i < lengthOfLineRenderer; i++)
{
PolylinePoint polylinePoint = new PolylinePoint();
polylinePoint.color = Color.white;
polylinePoint.thickness = thickness;
polyline.points.Add(polylinePoint);
}
}
void LateUpdate()
{
float[] samples = new float[lengthOfLineRenderer];
source.GetOutputData(samples, 0);
for (int i = 0; i < lengthOfLineRenderer; i++)
{
polyline.SetPointPosition(i, new Vector3(i * 0.5f, samples[i] * strength, 0.0f));
}
}
private void OnAudioFilterRead(float[] data, int channels)
{
if (!testing) return;
increment = frequency * 2.0 * Mathf.PI / sampleRate;
for (int i = 0; i < data.Length - 1; i += channels)
{
switch (choice)
{
case 0: //sawtooth
for (float j = Mathf.Floor((float)ind); j < c; j++)
{
data[i] += (float)(gain * (Mathf.Sin((float)(phase * j)) / j));
}
break;
case 1: //square
for (float j = Mathf.Floor((float)ind); j < c; j++)
{
data[i] += (float)(gain * (Mathf.Sin((float)(phase * (2 * j - 1))) / (2 * j - 1)));
}
break;
case 2: //triangle
for (float j = Mathf.Floor((float)ind); j < c; j++)
{
data[i] += (float)(gain * (Mathf.Sin((float)(phase * (2 * j - 1) + Mathf.PI * ((j + 1) % 2)))) / Mathf.Pow((2 * j - 1), 2));
}
break;
case 3: //harmonics
for (int j = (int)Mathf.Floor((float)ind); j < c; j++)
{
data[i] += (float)(gain * (Mathf.Cos((float)(j * phase + z))));
}
break;
default: //sine
data[i] = (float)(gain * Mathf.Sin((float)phase));
break;
}
phase += increment;
if (channels == 2)
{
data[i + 1] = data[i];
// ring mod: Mathf.Sin((float)((Mathf.Pow((float)(phase * j), 3)) * frequency / sampleRate)); data[i] += (float)(gain * (Mathf.Sin((float)((Mathf.Pow((float)(phase * j), 3))))));
// sawtooth: data[i] += (float)(gain * (Mathf.Sin((float)(phase * j)) / j));
// square: data[i] += (float)(gain * (Mathf.Sin((float)(phase * (2 * j - 1))) / (2* j - 1)));
// triangle: data[i] += (float)(gain * (Mathf.Sin((float)(phase * (2 * j - 1) + Mathf.PI * ((j + 1) % 2)))) / Mathf.Pow((2 * j - 1), 2));
// accidental bitcrushed sine: data[i] += (float)(gain * (Mathf.Cos((float)(2 * Mathf.PI * frequency * phase + Mathf.Pow((float)1.618034, j - 1)))));
// harsh squares depending on frequency: data[i] += (float)(gain * (Mathf.Cos((float)(2 * Mathf.PI * frequency * phase + z))));
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment