76 lines
3.0 KiB
Ada
76 lines
3.0 KiB
Ada
with Interfaces.C;
|
|
use Interfaces.C;
|
|
|
|
with Ada.Numerics;
|
|
use Ada.Numerics;
|
|
|
|
with Ada.Numerics.Elementary_Functions;
|
|
use Ada.Numerics.Elementary_Functions;
|
|
|
|
package body Super_Saw is
|
|
function Super_Saw(Time : Interfaces.C.C_Float; Pitch : Interfaces.C.C_Float;
|
|
Detune : Interfaces.C.C_Float; Mix : Interfaces.C.C_Float;
|
|
Sample_Rate : Interfaces.C.C_Float)
|
|
return Interfaces.C.C_Float is
|
|
Offsets : Offset_Array_Type := (0.01952356,0.06288439,0.11002313);
|
|
Sample : Float := 0.0;
|
|
Mix_Level : Mix_Level_Type := Compute_Mix(Float(Mix));
|
|
begin
|
|
-- Main oscillator
|
|
Sample := Sample + Saw(Float(Time),Float(Pitch), Float(Sample_Rate))*Mix_Level.Master;
|
|
|
|
-- 3 oscillators of higher pitch than main
|
|
Higher_Oscillators:for D in 1 .. 3 loop
|
|
Sample := Sample + Saw(Float(Time),Float(Pitch)*(1.0+Offsets(D)*Compute_Detune(Float(Detune))),
|
|
Float(Sample_Rate))*Mix_Level.Slave;
|
|
end loop Higher_Oscillators;
|
|
|
|
-- 3 oscillators of lower pitch than main
|
|
Lower_Oscillators:for D in 1 .. 3 loop
|
|
Sample := Sample + Saw(Float(Time),Float(Pitch)*(1.0+Offsets(D)*Compute_Detune(Float(Detune))),
|
|
Float(Sample_Rate))*Mix_Level.Slave;
|
|
end loop Lower_Oscillators;
|
|
return Interfaces.C.C_FLoat(Sample);
|
|
end Super_Saw;
|
|
|
|
function Saw(Time : Float; Pitch : Float; Sample_Rate : Float) return Float is
|
|
Number_Of_Harmonics : Integer := 0;
|
|
Sample : Float := 0.0;
|
|
begin
|
|
while 2.0*Pi*Pitch*Float(Number_Of_Harmonics) < Sample_Rate/2.0 loop
|
|
Number_Of_Harmonics := Number_Of_Harmonics + 1;
|
|
end loop;
|
|
|
|
for I in 1 .. Number_Of_Harmonics loop
|
|
Sample := Sample + ((((1.0)**Float(I))*Sin(Float(I)*((2.0*Pi*Pitch)/Sample_Rate)*Time)));
|
|
end loop;
|
|
Sample := 0.5 - Sample/Pi;
|
|
|
|
-- Add a few extra sines to simulate aliasing above fundamental frequency of main oscillator
|
|
Simulate_Aliasing:for I in 1 .. Number_Of_Harmonics loop
|
|
if (0.5-2.0*Pi*Float(I)*Pitch/Sample_Rate) >= (2.0*Pi*Pitch)/Sample_Rate then
|
|
Sample := Sample + Sin((0.5-2.0*Pi*Float(I)*Pitch/Sample_Rate)*Time)*0.6;
|
|
end if;
|
|
end loop Simulate_Aliasing;
|
|
|
|
return Sample;
|
|
end Saw;
|
|
function Compute_Detune(Amount : Float) return Float is
|
|
begin
|
|
return (10028.7312891634*Amount**11)-(50818.8652045924*Amount**10)
|
|
+(111363.4808729368*Amount**9)-(138150.6761080548*Amount**8)+
|
|
(106649.6679158292*Amount**7)-(53046.9642751875*Amount**6)+
|
|
(17019.9518580080*Amount**5)-(3425.0836591318*Amount**4)+
|
|
(404.2703938388*Amount**3)-(24.1878824391*Amount**2)+
|
|
(0.6717417634*Amount)+0.0030115596;
|
|
end Compute_Detune;
|
|
function Compute_Mix(Level : Float) return Mix_Level_Type is
|
|
Mix_Level : Mix_Level_Type;
|
|
begin
|
|
Mix_Level.Master := -0.55366*Level + 0.99785;
|
|
Mix_Level.Slave := -0.73764*Level**2 + 1.2841*Level + 0.044372;
|
|
return Mix_Level;
|
|
end Compute_Mix;
|
|
end Super_Saw;
|
|
|