Anyone Need Basic Waveform Samples?

Hi,
I’ve created a little matlab script that generates samples with given
waveforms, frequencies and amplitudes. It can easily be extended
with some batch processing to spit out hundreds of basic waveforms
with different frequencies, lengths, waveshapes, and more.
Are anyone interested in this? If so, any ideas for extensions are
welcome. Also, how many samples are needed? One for each note
is just as simple to do as one for each octave, but will increase
the size of the sample package a lot…

Current parameters:

  • samplerate
  • length in seconds
    These can be varied in time:
  • frequency
  • amplitude
    And I’ve also added some definable functions for:
  • waveshaping (mapping of one sample value to another)
  • phase distortion (mapping of one phase value to another)

More can be added, if there’s interest and good ideas.
I’ve found that matlab is very easy to program for this kind of task.

To keep the package small, but versatile, I suggest picking a set of
different combinations of waveforms and waveshaping functions,
and keeping the frequency and amplitudes constant. This will give a
package of basic waveforms that can be looped and modified at will.
Then more can follow in other packages, whenever I feel like experimenting.

Personally, I’ve done such things with CSound some time ago.

I’ve also done a chiptune XM with those CSound microsamples.

You can download it here (5kb) (played correctly by FT2 and XmPlay, I don’t know about the other players)

Had to be the soundtrack of a really acid 64kb intro which has never been released (lazy coders!! :angry:)

About the number of samples to generate, I think that one per octave is far enough: after all, at the moment you can’t put more than 16 samples in an instrument, so you should use more than one instrument per… instrument, and this would be a considerable waste of lifetime to manage for a chiptune in my opinion

Maybe I should just learn CSound instead :)

I do this mostly to experiment with generating sounds from the
bottom up. And then I mean from the pure mathematics, so I know
exactly what happens and can reproduce it later in other contexts.
We’ll see how far I push this little script, I don’t have any huge plans.

I’ve currently started reading a bit on physical modelling, hope to get
to some experimenting done there as well before the year is over.
(Maybe that’ll even lead to something useful…)

Maybe a doppler effect on the generated sounds would be cool?

Hi!

At lower frequencies (notes) you could stick with 1 sample per octave. But when you move up to a higher octave(ex. C-4) you need to have at least 2 samples/octave. At C-5/C-6 maybe 4-5 samples/octave. Else you will get unwanted noises (alias-free waveforms). It’s hard to get good chip samples
at C-6 or higher.

A bit off topic but a multi layered instrument editor would be nice. Extend the number of samples to 64 or even 128. Build your own synth with chip samples, Lfo’s, Envelopes etc. and use the built in effects… B)
I’m not a serious coder and I guess it would be a lot of work … so I probably should keep my mouth shut … :rolleyes:

Edit: Was a bit tired yesterday … Didn’t mean oscillator’s … changed to Envelopes :)

Anders Kallander

There are many VSTis capable of making chip sounds. But considering that Renoise has LFOs, filter envelopes and stuff, a small generator feeding the sampler of Renoise would be a great thing. Something like OSCx3 in FL.

I’d like to get my hands on that script :). Or just to know the basic way of creating sound with matlab? Could be very useful…

Ok, I’m posting the script here. Comments in the file should explain how it
works. Some basic math, matlab and sound knowledge doesn’t hurt.
I don’t have time to do much with this now the next month or two, have
to focus on Renoise development and studies. I planned to add some outer
loops with batch processing, to generate many waveforms in one run.
This is a simple extension, for example using cell arrays with “funcs” structures.
Two files follow.

  
% -------------------------------------------------------------------------  
% waveGenerator.m  
%  
% Author: Martin Alnæs  
%  
% Licence: Do whatever you want with this. I don't care. I take no  
% responsibility whatsoever for anything that might happen.  
% Take care of your ears :)  
%   
% -------------------------------------------------------------------------  
  
  
% -------------------------------------------------------------------------  
% What to do with the generated data, for convenience only since of course,  
% this can be handled manually afterwards by using the "wave" vector.  
% -------------------------------------------------------------------------  
  
doPlot = true;  
doPlay = true;  
doSave = false;  
filename = 'test.wav';  
  
  
% -------------------------------------------------------------------------  
% Time parameters  
% -------------------------------------------------------------------------  
  
% samplerate  
samplerate = 44100;  
% seconds of wave to be generated  
seconds = 1;  
  
  
% -------------------------------------------------------------------------  
% Various functions defining the wave generation.  
% All functions must be vectorized. See generateWave for descriptions.  
% -------------------------------------------------------------------------  
  
% ------ frequency function  
frequencyFunc = inline('440'); % constant  
%frequencyFunc = inline('4');  
%frequencyFunc = inline('119.5');  
%frequencyFunc = inline('exp(t)'); % exponentially growing  
  
  
% ------ amplitude function  
amplitudeFunc = inline('1'); % constant  
%amplitudeFunc = inline(['(exp(t)-1) / (exp(max(t))-1)']); % exponentially growing  
%amplitudeFunc = inline(['(exp(max(t)-t)-1) / (exp(max(t))-1)']); % exponentially sinking  
  
  
% ------ shape function  
shapeFunc = inline('sin(2*pi*x)'); % sine  
%shapeFunc = inline('mod(x,1) < 0.5'); % square  
%shapeFunc = inline('mod(x+0.5,1)'); % rising saw  
%shapeFunc = inline('-mod(x+0.5,1)'); % falling saw  
  
  
% ------ phase distortion function  
phaseDistortFunc = inline('x'); % no distortion  
%phaseDistortFunc = inline('abs(sin(2*pi*x))');  
%phaseDistortFunc = inline('exp(20*x)./exp(20)');  
  
  
% ------ waveshape function  
waveshapeFunc = inline('x');  
%waveshapeFunc = inline('exp(3*t) * 2 ./ exp(3) - 1');  
%waveshapeFunc = inline('exp( sin(2*pi*t) .* t ) * 2 ./ exp(1) - 1');  
  
  
% -------------------------------------------------------------------------  
% parameters are collected here in a struct. fields can be omitted, the  
% generate function has defaults for all of them.  
% -------------------------------------------------------------------------  
  
funcs = struct('frequency', frequencyFunc, ...  
 'shape', shapeFunc, ...  
 'amplitude', amplitudeFunc, ...  
 'phasedistort', phaseDistortFunc, ...  
 'waveshape', waveshapeFunc );  
  
  
% -------------------------------------------------------------------------  
% generate wave from given functions  
% -------------------------------------------------------------------------  
[wave,time] = generateWave(funcs, samplerate, seconds);  
  
  
% -------------------------------------------------------------------------  
% "reports"  
% -------------------------------------------------------------------------  
  
if doPlot  
 plot(time, wave);  
end  
if doPlay  
 sound(wave, samplerate);  
end  
if doSave  
 wavwrite(wave, samplerate, 16, filename)  
end  
  
  
% -------------------------------------------------------------------------  
% generateWave.m  
%  
% Author: Martin Alnæs  
%  
% Licence: Do whatever you want with this. I don't care. I take no  
% responsibility whatsoever for anything that might happen.  
% Take care of your ears :)  
%   
% -------------------------------------------------------------------------  
%  
% function [wave,time] = generateWave(funcs, samplerate, seconds)  
%  
% - wave will contain a vector with the sample data, range [-1, +1]  
% - time will contain a vector with the time in seconds corresponding to each  
% sample in wave, convenient for plotting for example.  
% - funcs is a struct containing functions defining the wave.  
% Fields can be omitted, default functions are defined.  
% Description of the functions follow.  
%  
% ------ frequency function  
% - takes a vector of time values in seconds  
% - returns wave frequency in Hz for each time step  
%  
% ------ amplitude function  
% - takes a vector of time values in seconds  
% - returns wave amplitude for each time step  
%  
% ------ shape function  
% - takes a vector of phases x in [0, 1]  
% - returns the shape amplitudes in [-1,1] for each phase value  
%  
% ------ phasedistortion function  
% - takes a vector of phases x in [0, 1]  
% - returns distorted phases in [0, 1]  
% - should result in the same wavelength  
%  
% ------ waveshape function  
% - takes a vector of sample amplitude values  
% - returns new amplitudes for each sample  
function [wave,time] = generateWave(funcs, samplerate, seconds)  
  
% basic default functions  
if ~isfield(funcs, 'frequency')  
 setfield(funcs, 'frequency', inline('440')); % constant 440Hz  
end  
if ~isfield(funcs, 'amplitude')  
 setfield(funcs, 'amplitude', inline('1')); % constant full amplitude  
end  
if ~isfield(funcs, 'shape')  
 setfield(funcs, 'shape', inline('sin(2*pi*x)')); % sine wave  
end  
if ~isfield(funcs, 'phasedistort')  
 setfield(funcs, 'phasedistort', inline('x')); % no distortion  
end  
if ~isfield(funcs, 'waveshape')  
 setfield(funcs, 'waveshape', inline('x')); % no waveshaping  
end  
  
% generate discrete time values (in seconds)  
time = linspace(0, seconds, seconds*samplerate);  
wave = funcs.waveshape( ...  
 funcs.amplitude(time) .* ...  
 funcs.shape( ...  
 funcs.phasedistort( ...  
 mod(time .* funcs.frequency(time), 1) ...  
 ) ...  
 ) ...  
 );  
  
% remove DC offset  
offset = sum(wave) / length(wave);  
wave = wave - offset;  
  
% normalize  
m = max(abs(max(wave)), abs(min(wave)));  
wave = wave ./ m;  
  
% done