In this tuturial we lay the basis for an softsynth application using OpenAL.
Once again we start by using the files from lesson#1.
For a softsynth application we do not want to load the sound data from wave or ogg files, but we want to generate them while running our application. Therefore we do not need the following lines anymore:
AlutLoadWavFile('ding.wav', format, data, size, freq, loop);
AlutUnloadWav(format, data, size, freq);
Remove those lines.
Sine Wave
Basicly all sounds that you hear can be seen as waves (like the ones in the ocean). A basic waveform is a sine wave. This means that all the waves are equaly in shape. For calculation a sine wave you need to add the following lines into the var section of your application:
SR: integer; //sample rate
L: integer; //lenth of sample
F: single; //frequency of sample
Hz: integer; //frequency in hertz of sample (cycles per second)
A: integer; //amplitude
O: Array[0..1000] OF SmallInt; //output sample (1000=L) signed 16-bit
T: integer; //time
You need to calculate the sine wave in the initialisation part of your form. So it is best to place it just in front where you generate the buffer. The code looks like this:
//calculate the sine waveform
Hz := 440; //440
L := 1000; //be carefull when changing this value as we use a static array O
A := 32760; //maximum amplitude value for 16bit
SR := 22000;
F :=(2*pi*Hz)/SR;
For T:=0 to L do
begin
O[T]:=Round(A*sin(F*T));
end;
This will generate a 440hz sine wave with an sample rate of 2200hz and a depth of 16bit.
To hear this sound you need to ajust the albufferdata call to:
alBufferData(buffer, AL_FORMAT_MONO16, @O, L, SR);
Try changing the Hz variable value to hear different versions of the sine wave.
Additive Synthesis
To make things sound more interesting it is possible to layer sine waves on top of each other by just adding them and divide by the number of layers you added together.
Add the folowing lines to the var section:
O1: Array[0..1000] OF SmallInt; //output sample (1000=L) signed 16-bit
O2: Array[0..1000] OF SmallInt; //output sample (1000=L) signed 16-bit
Also add the folowing code just before the albufferdata call:
//sample O1
Hz:=800;
F :=(2*pi*Hz)/SR;
For T:=0 to L do
begin
O1[T]:=round(A*sin(F*T));
end;
//sample O2
Hz:=1200;
F :=(2*pi*Hz)/SR;
For T:=0 to L do
begin
O2[T]:=round(A*sin(F*T));
end;
//combine sample O1 & O2 into O
For T:=0 to L do
begin
O[T]:=(O1[T]+O2[T]) div 2;
end;
This will layer a 1200hz sine on top of an 800hz sine wave to generate a third new wave sound.
Feedback Sine Wave
For some further effects you can use a previous generated sine to distort a newly calculated wave like this:
//sample O feedback
Hz:=440;
F :=(2*pi*Hz)/SR;
FB := 10 / ( A*25); //keep the value 10 between 0 and 100
For T:=0 to L do
begin
O[T]:=round(A*(sin(F*T)+(FB*O[T])));
end;
Do not forget to add:
FB: single;
to the var section.
In the line FB := 10 / (A*25) the 10 is the amount influence of the previous calculated sind on the new one. Try lowering or increasing it.
To be continued
For now try to experiment with changing the sine hz values and layering them in different combinations. In the next softsynth lesson you will learn how to do FM synthesis.
- Example
The sourcecode for this lesson.