### Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

### Author Topic: Generate square / sinusoidal waves  (Read 2348 times)

#### MarkMLl

• Hero Member
• Posts: 2345
##### Re: Generate square / sinusoidal waves
« Reply #15 on: January 13, 2021, 04:53:50 pm »
Now i have to produce square wave too, any idea how to do that?

Change the half-wave generation to a simple level rather than a sum of sin() functions. The other half-wave will (obviously) "just work".

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

#### Fred vS

• Hero Member
• Posts: 2188
##### Re: Generate square / sinusoidal waves
« Reply #16 on: January 13, 2021, 05:25:22 pm »
> Now i have to produce square wave too, any idea how to do that?

Hello.

In the link I give you previously:

https://github.com/fredvs/alsa_sound.

In /alsa_sound/src/alsa_sound.pas:

Code: Pascal  [Select][+][-]
1. function ALSAbeep(frequency, duration, volume: cint; warble: Boolean;
2. WaveType: cint; CloseLib : boolean): Boolean; // WaveType: 0=sine, 1=square, 2=tooth

Just take a look at "WaveType" parameter ( 0=sine, 1=square, 2=tooth (or triangle)) and the code about it.

Code: Pascal  [Select][+][-]
1. procedure SetWave (var SA: TAr360; WaveType, Volume: integer); inline;
2. var i : integer;
3. begin
4.     if NOT (waveType in [0..2]) then waveType := 0;
5.
6.          case WaveType of
7.       0: begin
8.           for I := 0 to 359 do
9.           SA[I] := round(sin(pi * I / 180.0) * volume);  // create sine wave pattern
10.          end;
11.
12.       1: begin
13.           for I := 0 to 359 do
14.           if I < 180 then SA[i] := +1*volume else  SA[i] := -1* volume;//  sqare wave
15.          end;
16.
17.       2: begin
18.           for I := 0 to 359 do
19.           SA[i] := (round((360 - i)/180) -1)*volume;   //   saw tooth (triangle) wave
20.          end;
21.       end;
22. end;

Fre;D
« Last Edit: January 13, 2021, 05:51:07 pm by Fred vS »
I use Lazarus 2.0.6 32/64 and FPC 3.2.0 32/64 on Debian 10.2 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs
https://gitlab.com/fredvs

#### Ramses

• New Member
• Posts: 41
##### Re: Generate square / sinusoidal waves
« Reply #17 on: January 15, 2021, 04:47:38 am »

Just take a look at "WaveType" parameter ( 0=sine, 1=square, 2=tooth (or triangle)) and the code about it.

Thanks for that! i have try it today, and it is very easy to use! thats exactly what i needed!

for now it seem to work great, so next week i will test it with an oscilloscope to make sure everything is ok, thats the next step.

So thanks again for your help!

#### Ramses

• New Member
• Posts: 41
##### Re: Generate square / sinusoidal waves
« Reply #18 on: January 15, 2021, 09:50:02 pm »
One more question:

when i use Alsabeep, My program freeze completely while the sound is playing, and i can not do anything or press any button while sound is playing.. is there any way to prevent program from freezing?

here is the code i use

Code: Pascal  [Select][+][-]
1. ALSAbeep(40, 10000, 100, true,0, true);
2.

#### MarkMLl

• Hero Member
• Posts: 2345
##### Re: Generate square / sinusoidal waves
« Reply #19 on: January 15, 2021, 10:05:36 pm »
Well, you don't show what the code /really/ is, only how you're calling it, and since it's obviously not something I wrote I can only make a couple of general suggestions.

The "right" way would probably be to put it in a thread, I don't know whether ALSA provides any equivalent functionality. Alternatively you could insert an Application.ProcessMessages into the loop, but (a) protect it in case you later move the code to a thread, (b) expect it to mess up latency, and (c) if you call it too often it will /really/ mess up latency... you probably don't need it more than 10 times a second.

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

#### Fred vS

• Hero Member
• Posts: 2188
##### Re: Generate square / sinusoidal waves
« Reply #20 on: January 15, 2021, 11:31:22 pm »
One more question:

when i use Alsabeep, My program freeze completely while the sound is playing, and i can not do anything or press any button while sound is playing.. is there any way to prevent program from freezing?

here is the code i use

Code: Pascal  [Select][+][-]
1. ALSAbeep(40, 10000, 100, true,0, true);
2.

Hello.

Like MarkMLI explained, you need to run ALSAbeep() inside a other thread if you want that your main thread still runs while the sound is playing,

Alternatively you may use a other library for that, like uos: https://github.com/fredvs/uos

Each player is a independent thread.

Take a look at example consolesynth.pas:

https://github.com/fredvs/uos/blob/master/examples/consolesynth.pas

I use Lazarus 2.0.6 32/64 and FPC 3.2.0 32/64 on Debian 10.2 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs
https://gitlab.com/fredvs

#### Ramses

• New Member
• Posts: 41
##### Re: Generate square / sinusoidal waves
« Reply #21 on: January 17, 2021, 03:35:11 pm »
Like MarkMLI explained, you need to run ALSAbeep() inside a other thread if you want that your main thread still runs while the sound is playing,

Alternatively you may use a other library for that, like uos: https://github.com/fredvs/uos

Well, i have put a speaker on my raspberry, and i tried the library you told me, and i never figure out how to use it! i never get any sound on my speaker..I dont figure out how to use this library to generate a sound in my button...

So i have try to run ALSAbeep inside a thread, but after all day long of trying, iḿ still not able to do that.. i have read a LOT of documentation but it still not working... I dont figure out how to do that! (i know i'm a beginer in this)

I show you a very basic code that work, maybe you can tell me how to modify my code to make it work in a thread? or how to use the new library to generate sound when pressing my button?

Code: Pascal  [Select][+][-]
1. unit Unit1;
2.
3. {\$mode objfpc}{\$H+}
4.
5. interface
6.
7. uses
8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls,alsa_sound;
9.
10. type
11.
12.   { TForm1 }
13.
14.   TForm1 = class(TForm)
15.     Button1: TButton;
16.     procedure Button1Click(Sender: TObject);
17.   private
18.
19.   public
20.
21.   end;
22.
23. var
24.   Form1: TForm1;
25.
26. implementation
27.
28. {\$R *.lfm}
29.
30. { TForm1 }
31.
32. procedure TForm1.Button1Click(Sender: TObject);
33. begin
34.   ALSAbeep(40, 10000, 100, true,0, true);
35. end;
36.
37. end.
38.

#### Fred vS

• Hero Member
• Posts: 2188
##### Re: Generate square / sinusoidal waves
« Reply #22 on: January 17, 2021, 03:54:39 pm »
Like MarkMLI explained, you need to run ALSAbeep() inside a other thread if you want that your main thread still runs while the sound is playing,

Alternatively you may use a other library for that, like uos: https://github.com/fredvs/uos

Well, i have put a speaker on my raspberry, and i tried the library you told me, and i never figure out how to use it! i never get any sound on my speaker..I dont figure out how to use this library to generate a sound in my button...

Hello.

Here how to use uos:

1) Go on site: https://github.com/fredvs/uos
2) Click on the green button [ Code ] + Download ZIP.
4) Run Lazarus - Open Project
5) Choose in /uos/examples/ a demo project, for example  /uos/examples/simpleplayer.lpi (or in your case consolesynth.lpi)
6) Compile and run it using Lazarus.
7) Check the code to understand how it works.

Fre;D
« Last Edit: January 17, 2021, 03:56:49 pm by Fred vS »
I use Lazarus 2.0.6 32/64 and FPC 3.2.0 32/64 on Debian 10.2 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs
https://gitlab.com/fredvs

#### MarkMLl

• Hero Member
• Posts: 2345
##### Re: Generate square / sinusoidal waves
« Reply #23 on: January 17, 2021, 05:02:35 pm »
not working... I dont figure out how to do that! (i know i'm a beginer in this)

Not working HOW????? Where's your example code?????

Sorry, asking us to fix a not-quite-right attempt is one thing, but asking us to do it from scratch is something else entirely.

Did you try putting Application.ProcessMessages in your loop which was the fallback suggestion? What happened?

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

#### Ramses

• New Member
• Posts: 41
##### Re: Generate square / sinusoidal waves
« Reply #24 on: January 17, 2021, 06:11:34 pm »
Not working HOW????? Where's your example code?????

Did you try putting Application.ProcessMessages in your loop which was the fallback suggestion? What happened?

i have not posted any exemple code, because i tried to follow like 5 or 6 tutorial about "multithreading" that i found on the web, so i decided to not post all those "test" i made.....

For your last question, yes i have try putting Application.ProcessMessages: for example, have try to split the 10 second sound in 10 X 1 second song separate by "application.processmessages", but on the speaker the sound cut 10 time ( i hear a silence each time application.processmessages is called) ... i want to generate a wave with no "silence" in it..

now im looking at the library UOS (from the post of "Fred vS"), when i compile it i hear a sound in my speaker, but there is no graphical user interface, and i want to generate my wave by pressing a button, so iḿ actually trying to copy the code from "consolesynth" inside my graphical program, thats what iḿ working on...

#### Fred vS

• Hero Member
• Posts: 2188
##### Re: Generate square / sinusoidal waves
« Reply #25 on: January 17, 2021, 06:20:36 pm »
now im looking at the library UOS (from the post of "Fred vS"), when i compile it i hear a sound in my speaker, but there is no graphical user interface, and i want to generate my wave by pressing a button, so iḿ actually trying to copy the code from "consolesynth" inside my graphical program, thats what iḿ working on...

Hello.

All the "consoleXXX.lpi" demos are console applications, no GUI applications, all others are GUI demos..

Did you try, like proposed in previous post, SimplePlayer.lpi demo, it is a graphical application using LCL (Lazarus component) ?

I use Lazarus 2.0.6 32/64 and FPC 3.2.0 32/64 on Debian 10.2 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs
https://gitlab.com/fredvs

#### Ramses

• New Member
• Posts: 41
##### Re: Generate square / sinusoidal waves
« Reply #26 on: January 17, 2021, 06:50:43 pm »
Did you try, like proposed in previous post, SimplePlayer.lpi demo, it is a graphical application using LCL (Lazarus component) ?

yes i tried it, but for what i understand, this demo is made to play a song from my computer, and i dont figure out how to generate sin/square wave from it.. so not really what i need.. or maybe i have not understand correctly how to use it?

#### Fred vS

• Hero Member
• Posts: 2188
##### Re: Generate square / sinusoidal waves
« Reply #27 on: January 17, 2021, 07:05:24 pm »
Did you try, like proposed in previous post, SimplePlayer.lpi demo, it is a graphical application using LCL (Lazarus component) ?

yes i tried it, but for what i understand, this demo is made to play a song from my computer, and i dont figure out how to generate sin/square wave from it.. so not really what i need.. or maybe i have not understand correctly how to use it?

Ok, last try.

In the graghic application that you have done, in the procedure Button1Click, insert the code of procedure TuosConsole.ConsolePlay; from uos demo consoleplay.pas

Code: Pascal  [Select][+][-]
1. program consolesynth;
2. ...
3.
4. procedure TuosConsole.ConsolePlay;
5.   begin
6.   ...
7.   // Copy all the code inside
8.   end;

Code: Pascal  [Select][+][-]
1. procedure TForm1.Button1Click(Sender: TObject);
2. begin
3. // Insert the code of procedure TuosConsole.ConsolePlay;
4. end;
« Last Edit: January 17, 2021, 07:10:27 pm by Fred vS »
I use Lazarus 2.0.6 32/64 and FPC 3.2.0 32/64 on Debian 10.2 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs
https://gitlab.com/fredvs

#### MarkMLl

• Hero Member
• Posts: 2345
##### Re: Generate square / sinusoidal waves
« Reply #28 on: January 17, 2021, 07:17:52 pm »
Not working HOW????? Where's your example code?????

Did you try putting Application.ProcessMessages in your loop which was the fallback suggestion? What happened?

i have not posted any exemple code, because i tried to follow like 5 or 6 tutorial about "multithreading" that i found on the web, so i decided to not post all those "test" i made.....

FFS man, I'm trying to /help/ here: you've said you've tried something but it didn't work for you so SHOW US WHAT YOU TRIED! Post the whole project with your attempt at threads and we'll try to sort you out.

Quote
For your last question, yes i have try putting Application.ProcessMessages: for example, have try to split the 10 second sound in 10 X 1 second song separate by "application.processmessages", but on the speaker the sound cut 10 time ( i hear a silence each time application.processmessages is called) ... i want to generate a wave with no "silence" in it..

When I said "you probably don't need it more than 10 times a second" I meant "don't call it every millisecond". I definitely didn't mean "call it every second", since apart from anything else if you do that then your GUI will only come to life once a second. What's more if you look at the example I pointed you at in my Github repository it EXPLICITLY says

Code: Pascal  [Select][+][-]
1. (* Output the buffer, retrying/recovering as necessary. If this is irregular or *)
2. (* results in error messages, try increasing the value in the latency parameter *)
3. (* to snd_pcm_set_params() above.                                               *)
4.

I don't put comments into code purely for the fun of it...

Somewhat later: I've added an APM to the outer loop, which was trivial since it was only running at 20Hz. I've heard no jitter etc. so far.

MarkMLl
« Last Edit: January 18, 2021, 10:40:33 am by MarkMLl »
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

#### Ramses

• New Member
• Posts: 41
##### Re: Generate square / sinusoidal waves
« Reply #29 on: January 17, 2021, 07:51:39 pm »
In the graghic application that you have done, in the procedure Button1Click, insert the code of procedure TuosConsole.ConsolePlay; from uos demo consoleplay.pas

Ok, i have do that, now i got an error when i compile
Quote

and my code now look like that:
Code: Pascal  [Select][+][-]
1. unit Unit1;
2.
3. {\$mode objfpc}{\$H+}
4.
5. interface
6.
7. uses
8.  {\$IFDEF UNIX}
10.  {\$ENDIF}
11.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls,
12.   uos_flat;
13.
14. type
15.
16.   { TForm1 }
17.
18.   TForm1 = class(TForm)
19.     Button1: TButton;
20.     procedure Button1Click(Sender: TObject);
21.   private
22.
23.   public
24.
25.   end;
26.
27. var
28.   Form1: TForm1;
29.          res, x, y, z: integer;
30.   ordir, opath, SoundFilename, PA_FileName, PC_FileName, SF_FileName, MP_FileName: string;
31.   PlayerIndex1, InputIndex1, OutputIndex1: integer;
32.
33. implementation
34.
35. {\$R *.lfm}
36.
37. { TForm1 }
38.
39. procedure TForm1.Button1Click(Sender: TObject);
40. begin
41.             ordir := IncludeTrailingBackslash(ExtractFilePath(ParamStr(0)));
42.
43.  {\$IFDEF Windows}
44.      {\$if defined(cpu64)}
45.     PA_FileName := ordir + 'lib\Windows\64bit\LibPortaudio-64.dll';
46.     SF_FileName := ordir + 'lib\Windows\64bit\LibSndFile-64.dll';
47.      {\$else}
48.     PA_FileName := ordir + 'lib\Windows\32bit\LibPortaudio-32.dll';
49.     SF_FileName := ordir + 'lib\Windows\32bit\LibSndFile-32.dll';
50.      {\$endif}
51.     SoundFilename := ordir + 'sound\test.ogg';
52.  {\$ENDIF}
53.
54.      {\$if defined(CPUAMD64) and defined(linux) }
55.   SF_FileName := ordir + 'lib/Linux/64bit/LibSndFile-64.so';
56.   PA_FileName := ordir + 'lib/Linux/64bit/LibPortaudio-64.so';
57.     SoundFilename := ordir + 'sound/test.ogg';
58.    {\$ENDIF}
59.
60.    {\$if defined(cpu86) and defined(linux)}
61.     PA_FileName := ordir + 'lib/Linux/32bit/LibPortaudio-32.so';
62.     SF_FileName := ordir + 'lib/Linux/32bit/LibSndFile-32.so';
63.    SoundFilename := ordir + 'sound/test.ogg';
64.    {\$ENDIF}
65.
66.   {\$if defined(linux) and defined(cpuaarch64)}
67.   PA_FileName := ordir + 'lib/Linux/aarch64_raspberrypi/libportaudio_aarch64.so';
68.   SF_FileName := ordir + 'lib/Linux/aarch64_raspberrypi/libsndfile_aarch64.so';
69.   SoundFilename := ordir + 'sound/test.ogg';
70.   {\$ENDIF}
71.
72.   {\$if defined(linux) and defined(cpuarm)}
73.     PA_FileName := ordir + 'lib/Linux/arm_raspberrypi/libportaudio-arm.so';
74.     SF_FileName := ordir + ordir + 'lib/Linux/arm_raspberrypi/libsndfile-arm.so';
75.       SoundFilename := ordir + 'sound/test.ogg';
76.    {\$ENDIF}
77.
78.  {\$IFDEF freebsd}
79.     {\$if defined(cpu64)}
80.     PA_FileName := ordir + 'lib/FreeBSD/64bit/libportaudio-64.so';
81.     SF_FileName := ordir + 'lib/FreeBSD/64bit/libsndfile-64.so';
82.     {\$else}
83.     PA_FileName := ordir + 'lib/FreeBSD/32bit/libportaudio-32.so';
84.     SF_FileName := ordir + 'lib/FreeBSD/32bit/libsndfile-32.so';
85.     {\$endif}
86.     SoundFilename := ordir + 'sound/test.ogg';
87.  {\$ENDIF}
88.
89.  {\$IFDEF Darwin}
90.   {\$IFDEF CPU32}
91.     opath := ordir;
92.     opath := copy(opath, 1, Pos('/UOS', opath) - 1);
93.     PA_FileName := opath + '/lib/Mac/32bit/LibPortaudio-32.dylib';
94.     SF_FileName := opath + '/lib/Mac/32bit/LibSndFile-32.dylib';
95.     SoundFilename := ordir + '/sound/test.ogg';
96.     {\$ENDIF}
97.
98.    {\$IFDEF CPU64}
99.     opath := ordir;
100.     opath := copy(opath, 1, Pos('/UOS', opath) - 1);
101.     PA_FileName := opath + '/lib/Mac/64bit/LibPortaudio-64.dylib';
102.     SF_FileName := opath + '/lib/Mac/64bit/LibSndFile-64.dylib';
103.     SoundFilename := ordir + '/sound/test.ogg';
104.     {\$ENDIF}
105.  {\$ENDIF}
106.
108.     // function uos_loadlib(PortAudioFileName, SndFileFileName, Mpg123FileName, Mp4ffFileName, FaadFileName,  opusfilefilename: PChar) : LongInt;
109.
110.     res := uos_LoadLib(PChar(PA_FileName), PChar(SF_FileName), nil, nil, nil, nil);
111.
112.     writeln;
113.     if res = 0 then
115.     else
117.
118.     if res = 0 then
119.     begin
120.       writeln();
121.
122.       //    writeln('Libraries version: '+ uos_GetInfoLibraries());
123.
124.       //// Create the player.
125.       //// PlayerIndex : from 0 to what your computer can do !
126.       //// If PlayerIndex exists already, it will be overwriten...
127.
128.       PlayerIndex1 := 0;
129.
130.       if uos_CreatePlayer(PlayerIndex1) then
131.       begin
132.
133.         //// add a Input from audio-file with default parameters
134.         //////////// PlayerIndex : Index of a existing Player
135.         ////////// FileName : filename of audio file
136.         //  result : -1 nothing created, otherwise Input Index in array
137.
138.         InputIndex1 := uos_AddFromFile(PlayerIndex1, PChar((SoundFilename)), -1, -1, -1);
139.
140.
141.         writeln('InputIndex1 = ' + IntToStr(InputIndex1));
142.
143.         if InputIndex1 > -1 then
144.         begin
145.           //// add a Output into device with default parameters
146.           //////////// PlayerIndex : Index of a existing Player
147.           //  result : -1 nothing created, otherwise Output Index in array
148.
149.        {\$if defined(cpuarm) or defined(cpuaarch64)}  // need a lower latency
150.         OutputIndex1 := uos_AddIntoDevOut(PlayerIndex1, -1, 0.3, -1, -1, -1, -1, -1) ;
151.        {\$else}
153.           OutputIndex1 := uos_AddIntoDevOut(PlayerIndex1, -1, -1, -1, -1, -1, -1, -1);
154.        {\$endif}
155.
156.           writeln('OutputIndex1 = ' + IntToStr(OutputIndex1));
157.
158.         //   uos_AddIntoFile(PlayerIndex1,pchar('/home/fred/mytest.ogg'), -1, -1, -1, -1, 3);
159.
160.           if OutputIndex1 > -1 then
161.           begin
162.
163.             /////// everything is ready, here we are, lets play it...
164.
165.             uos_Play(PlayerIndex1);
166.
167.             sleep(1000);
168.             writeln;
169.             writeln('Title: ' + uos_InputGetTagTitle(PlayerIndex1, InputIndex1));
170.             sleep(1500);
171.             writeln();
172.             writeln('Artist: ' + uos_InputGetTagArtist(PlayerIndex1, InputIndex1));
173.             writeln;
174.
175.             sleep(2000);
176.           end;
177.         end;
178.       end;
179.     end;
180.
181. end;
182.
183. end.
184.

So my "cthreads" is the first in "uses", but it told me "Make cthreads one of the first units in your uses clause." I dont see what iḿ doing wrong..