- /
-
Oscillator
on 9 Oct 2024
- 11
- 127
- 0
- 0
- 1224
Cite your audio source here (if applicable):
This audio track was generated by this minihack.
function drawframe(f)
samplerate = 12000;
persistent osc p
if f==1
osc = oscillator();
% Axes to draw into
p = plot(1:10,'linewidth',2);
title('Oscillator Signal');
ylabel('Signal Strength');
ylim([-32767 32767]);
xlim tight
end
% Basic time changes for frequency, volume, & vibratto freq & depth
F=cospi(f/48)+1;
V=sinpi(f/48)/3+.65;
VF=sinpi(f/24)+1;
VD=cospi(f/24)+1;
if f==96
% Avoid a pop when this repeats.
V=0;
end
% Adjust simple number into ranges for those values
sample = osc.frame(V,F*100+10,VF*10+5,VD*100+50);
% Plot it
set(p,'xdata',1:size(sample,1),'ydata',sample);
%% Audio Playback
% For testing in desktop MATLAB. You'll need DSP toolbox.
%persistent player
%if f==1
% player = audioDeviceWriter('SampleRate',samplerate);
%end
%player(sample);
%if f==96
% delete(player)
%end
%% Saving the audio
% For building the MP3 during testing
%persistent audiotrack
%if f==1
% audiotrack = int16([]);
%end
%audiotrack = [ audiotrack
% sample ];
%if f==96
% audiowrite('oscillator_tmp.mp3', audiotrack, samplerate);
%end
function osc = oscillator()
% Create a mini stateful oscillator object.
last_freq=0;
last_vol=0;
last_space_value=0;
% Vibratto Freq & Volume
last_vib_freq=0;
last_vib_depth=0;
last_vib_space_value=0;
osc.frame = @frame;
function sample = frame(vol,freq,vib_freq,vib_depth)
% Do one frame computing an oscillating audio signal
% Based on FPS and SampleRate, returns a sample that will
% fill one "frame" at that FPS.
%
% freq - frequency of signal
% vol - volume
% vib_freq - vibratto frequency
% vib_depth - vibratto depth (how much frequency shift)
% I cobbled this together without being familiar with
% signal synthisis when I started. If there is a better
% way, remix or leave a comment.
% compute length of our sample
Tlen = samplerate/24; % samplerate/fps;
% Compute the vibratto pattern.
if vib_freq > 0 && vib_depth > 0
vramp = linspace(last_vib_freq, vib_freq, Tlen)';
venvelope = linspace(last_vib_depth, vib_depth, Tlen)';
% Just the adjusted wave to be added to ramp
vib_space = cumsum(vramp/samplerate*2)+last_vib_space_value;
vib_wave = sinpi(vib_space*2) .* venvelope;
last_vib_space_value = mod(vib_space(end),2);
last_vib_freq = vib_freq;
last_vib_depth = vib_depth;
else
vib_wave = 0;
end
% Compute a frequency ramp which is flat if last and current
% are the same.
ramp = linspace(last_freq, freq, Tlen)';
% based on sample rate, create the repeating pattern.
space = cumsum((ramp+vib_wave)/samplerate*2)+last_space_value;
% Remember last value so our next sample fits in nicely.
last_space_value = mod(space(end),2);
% Remember last frequency we used so we can ramp toward any new value.
last_freq = freq;
% Generate the wave form.
%switch wave
% case 'sin'
Wave = sinpi(space*2);
% case 'saw'
% Wave = -(mod(space,2)-1);
% case 'square'
% Wave = floor(mod(space,2))*2-1;
%end
% Compute the volume envelope to smoothly transition
% from old to new volume, and then apply.
vol_envelope = linspace(last_vol,vol,Tlen)';
doublesample = vol_envelope.*Wave;
last_vol = vol;
% Convert to int16.
int16vol = 32767;
sample = int16(doublesample*int16vol);
end
end
end