Skip to content

Instantly share code, notes, and snippets.

@michaelbartnett
Created October 15, 2011 01:29
Show Gist options
  • Select an option

  • Save michaelbartnett/1288847 to your computer and use it in GitHub Desktop.

Select an option

Save michaelbartnett/1288847 to your computer and use it in GitHub Desktop.
Generates a signal of the specified type and writes it to a wav file.
% Michael Bartnett
% mrb402
% Friday October 14, 2011
% siggen.m
%
% Function siggen
%
% Generates a signal of the specified type and writes it to a wav file.
%
% Usage: siggen(sampleRate, duration, frequency, numberOfOvertones, signalType, outputFilename)
%
% sampleRate - The sample rate of the output signal.
%
% duration - How long the signal should be in seconds.
%
% frequency - The frequency of the signal
%
% numberOfOvertones - For bandlimited signals, set the number of overtones to add
%
%
% Signal types:
%
% 1 sine
% 2 cosine
% 3 square (bandlimited)
% 4 triangle (bandlimited)
% 5 sawtooth (bandlimited)
% 6 impulse train (bandlimited)
% 7 white noise (zero-mean)
function siggen(sampleRate, duration, frequency, numOvertones, signalType, outFilename)
% Error checking
if nargin < 6
error('siggen requires 6 arguments: sampleRate, duration, frequency, numOvertones, signalType, outFilename')
end
% Calculate values needed to generate sinusoids
timeStep = 1 / sampleRate;
radianFrequency = 2 * pi * frequency;
% Calculate band limitations based on sample rate
nyquist = sampleRate / 2;
maxOvertoneMultiple = floor(nyquist / frequency - 1);
if frequency > nyquist
e = sprintf('Frequency (%f) was higher than nyquist limit (%f)', frequency, nyquist)
error(e)
end
% For loops encapsulated in case statements since signalType is an integral type.
% Avoids the overhead of a function call.
switch signalType
case 1 % sine
samples = sin(radianFrequency * [0:timeStep:duration])';
case 2 % cosine
samples = cos(radianFrequency * [0:timeStep:duration])';
case 3 % square
t = [0:timeStep:duration]';
samples = sin(radianFrequency * t);
% Limit the number of overtones to find under the nyquist limit
if (numOvertones * 2 + 1) * frequency > nyquist
numOvertones = floor(maxOvertoneMultiple / 2);
end
% Generate square wave signal (sum 1/k*sin(wt) where k is odd overtones)
for i = 1:numOvertones
j = i * 2 + 1;
samples = samples + (sin(radianFrequency * j * t) / j);
end
case 4 % triangle
t = [0:timeStep:duration]';
samples = sin(radianFrequency * t);
% Limit the number of overtones to find under the nyquist limit
if (numOvertones * 2 + 1) * frequency > nyquist
numOvertones = floor(maxOvertoneMultiple / 2);
end
% Generate triangle wave signal (sum 1/k^2*sin(wt) where k is odd overtones)
for i = 1:numOvertones
j = i * 2 + 1;
samples = samples + (cos(radianFrequency * j * t) / j^2);
end
case 5 % sawtooth
t = [0:timeStep:duration]';
samples = sin(radianFrequency * t);
% Limit the number of overtones to find under the nyquist limit
if numOvertones * frequency > nyquist
numOvertones = maxOvertoneMultiple;
end
% Generate sawtooth wave signal (sum 1/k*sin(wt) where k is even and odd overtones)
for i = 2:(numOvertones + 1)
samples = samples + (sin(radianFrequency * i * t) / i);
end
case 6 % impulse
t = [0:timeStep:duration]';
samples = cos(radianFrequency * t);
% Limit the number of overtones to find under the nyquist limit
if numOvertones * frequency > nyquist
numOvertones = maxOvertoneMultiple;
end
% Generate impulse train signal (sum k*cos(wt) where k is even and odd overtones)
for i = 1:numOvertones
samples = samples + (cos(radianFrequency * j * t) * i);
end
case 7 % white noise
% Generate random samples for white noise
samples = (rand(floor(duration / timeStep), 1) * 2 - 1)';
end
% Normalize samples
samples = samples / max(max(samples), min(samples));
% Write out the wav file
wavwrite(samples, sampleRate, outFilename);
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment