Recent

Author Topic: alsa beep - linux only  (Read 16839 times)

Fred vS

  • Hero Member
  • *****
  • Posts: 3158
    • StrumPract is the musicians best friend
Re: alsa beep - linux only
« Reply #45 on: October 27, 2020, 12:57:15 pm »
https://github.com/fredvs/alsa_sound

Fre;D

Totally off-topic and, please, excuse me for that but in your repo, what's dummy.txt for?

Huh, because I did not find a other way with GitHub to not remove empty directories after a git push.
I prefer to give the sub-directory /units in source so people dont have to create it when using this command line:

Code: Bash  [Select][+][-]
  1. $ fpc -FUunits alsa_sound_test.pas
« Last Edit: October 27, 2020, 01:16:31 pm by Fred vS »
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

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

PascalDragon

  • Hero Member
  • *****
  • Posts: 5444
  • Compiler Developer
Re: alsa beep - linux only
« Reply #46 on: October 27, 2020, 03:13:38 pm »
Huh, because I did not find a other way with GitHub to not remove empty directories after a git push.

That is because Git tracks files not paths (like SVN does). If there is no file in a directory then it does not exist from Git's point of view.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6646
Re: alsa beep - linux only
« Reply #47 on: October 27, 2020, 04:47:54 pm »
I've sent the .zip I uploaded yesterday to Mantis as https://bugs.freepascal.org/view.php?id=37997

If FPC accepts it as a package then possibly Lazarus/LCL would incorporate a function calling it. I see non-GUI programs as less of an issue since it is reasonable for a shell to process a bell character.

I'll try to raise related issues on the XDG mailing list when I have time.

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

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: alsa beep - linux only
« Reply #48 on: October 29, 2020, 01:51:33 am »

I added ALSAbeeperStereo(), a stereo beeper with custom frequency for each channel.

https://github.com/fredvs/alsa_sound

Fre;D

Hi Fred!

I am still fiddeling with  the alsa_beep unit.

One small problem is:
When you play two differet tones anfter another, then every time the lib is loaded and unloaded.
That is nonsense. Anf results in a small gap between the two sounds.
This solves it:

Code: Pascal  [Select][+][-]
  1. initialization
  2. ab_Load;
  3. finalization
  4. ab_Unload;
  5. end.
  6.  

Second: sinus sound is not very interesting.
This can be easy changed by some lines of code inside the beep.

Here  are sinus as used before,  sqare waves and saw tooth waves:

Code: Pascal  [Select][+][-]
  1. for I := 0 to 359 do SA[I] := round(sin(pi * I / 180.0) * volume);           // create sine wave pattern
  2.  
Code: Pascal  [Select][+][-]
  1. for I := 0 to 359 do if I < 180 then SA[i] := +1*volume else  SA[i] := -1* volume;//  sqare wave

Code: Pascal  [Select][+][-]
  1. for I := 0 to 359 do SA[i] := (round((360 - i)/180) -1)*volume;   //   saw tooth wave  
   

The square wave posseses only the odd overtones.
It sounds like wooden wind instruments or like  a wooden pipe of an organ - top closed.

The saw tooth wave contains all overtones.
It sounds like a Bach trumpet or an metal organ pipe - top open.

No further knowledge of Fourier needed .....

And third I created a police horn - american style:

Code: Pascal  [Select][+][-]
  1. function ALSAPolice(BaseFreq,duration, volume: integer; speed: single): Boolean;
  2. var
  3.   buffer: array[0..9600 - 1] of byte;
  4.   frames: snd_pcm_sframes_t;    
  5.   pcm: PPsnd_pcm_t;
  6.   I, FC: integer;
  7.   SA: array[0..359] of shortint;
  8. const
  9.   device = 'default' + #0;                      // name of sound device
  10. var
  11.   count1, count2, N, X: integer;
  12.   DeltaStep: single;   //winni
  13.   delta : Integer;     //  "
  14.   PeakFreq: Integer;   // "
  15.   upDown  : Integer;   // "
  16. begin
  17.   Result := False;
  18.  
  19.   //ab_Load;
  20.  
  21.   if snd_pcm_open(@pcm, @device[1], SND_PCM_STREAM_PLAYBACK, 0) = 0 then
  22.     if snd_pcm_set_params(pcm, SND_PCM_FORMAT_U8,
  23.       SND_PCM_ACCESS_RW_INTERLEAVED,
  24.       1,                        // number of channels
  25.       48000,                    // sample rate (Hz)
  26.       1,                        // resampling on/off
  27.       500000) = 0 then          // latency (us)
  28.     begin
  29.       Result := True;
  30.       PeakFreq := round (BaseFreq * 4/3); //fourth - most used in signal horns
  31.       speed := EnsureRange (abs(speed),0.1,1.0); // avoid div by zero
  32.       speed := 1/speed *2400;
  33.       duration := EnsureRange(abs(duration),50,maxint);// 24.85 days
  34.       volume   := EnsureRange(abs(Volume),0,100);
  35.       // 48 samples per ms -->
  36.       // 360 / 48 = 7.5
  37.       upDown := 400; // ms interval
  38.       DeltaStep := 7.5*(PeakFreq - BaseFreq) /upDown;
  39.  
  40.       for I := 0 to 359 do
  41.         SA[I] := round(sin(pi * I / 180.0) * volume);           // create sine wave pattern
  42.       X       := 0;
  43.       N       := 0;                                                              // up/down counter used by unequal interval division
  44.  
  45.       count1 := 0;                                                         // count1 counts up, count2 counts down
  46.       count2 := duration * 48;                                               // (at 48000Hz there are 48 samples per ms)
  47.  
  48.       while count2 > 0 do                                                  // start making sound!
  49.       begin
  50.         FC    := 0;
  51.         for I := 0 to sizeof(buffer) - 1 do                                  // fill buffer with samples
  52.         begin
  53.           if count2 > 0 then
  54.           begin
  55.             if count1 < 480 then
  56.               buffer[I] := 128 + ((count1 * SA[X]) div 480)
  57.             else   // 10ms feather in
  58.             if count2 < 480 then
  59.               buffer[I] := 128 + ((count2 * SA[X]) div 480)
  60.             else   // 10ms feather out
  61.               buffer[I] := 128 + SA[X];
  62.             Inc(FC);
  63.           end
  64.           else
  65.           begin
  66.             buffer[I] := 128;                             // no signal on trailing end of buffer, just in case
  67.             if (FC mod 2400) <> 0 then
  68.               Inc(FC);            // keep increasing FC until is a multiple of 2400
  69.           end;
  70.  
  71.          delta := round (sin(Count1/speed)*DeltaStep*upDown*48/2);   // winni
  72.          Inc(N,BaseFreq*360+Delta);          // winni
  73.           while (N > 0) do
  74.           begin                                           // (a variation on Bresenham's Algorithm)
  75.             Dec(N, 48000);
  76.             Inc(X);
  77.           end;
  78.           X := X mod 360;
  79.  
  80.           Inc(count1);
  81.           Dec(count2);
  82.         end;
  83.  
  84.         frames   := snd_pcm_writei(pcm, @buffer, max(2400, FC));             // write AT LEAST one full period
  85.         if frames < 0 then
  86.           frames := snd_pcm_recover(pcm, frames, 0);        // try to recover from any error
  87.         if frames < 0 then
  88.           break;                                            // give up if failed to recover
  89.       end;
  90.       snd_pcm_drain(pcm);                                   // drain any remaining samples
  91.       snd_pcm_close(pcm);
  92.     end;
  93.   //ab_unload;
  94. end; //AlsaPolice
  95.  
  96.  

The top frequency is - like in most horns - the (musical) fourth of the BaseFreq -
relation 4 : 3.
BaseFreq should be something between 600 and 800 Hz.
Speed should be between zero and 1.0
Zero is shifted to 0.1 . If you need zero then you can use AlsaBeep ....

Winni

PS.:  The square waves were the first step to the synthesizer because the could easily be made with a flipflop. It was my first "sythesizer" with two BC 107 transistors when I was 14 .



« Last Edit: October 29, 2020, 02:00:01 am by winni »

MarkMLl

  • Hero Member
  • *****
  • Posts: 6646
Re: alsa beep - linux only
« Reply #49 on: October 29, 2020, 09:40:34 am »
PS.:  The square waves were the first step to the synthesizer because the could easily be made with a flipflop. It was my first "sythesizer" with two BC 107 transistors when I was 14 .

I'll forgive you a lot for that :-)

Have you considered a port of http://bulba.untergrund.net/Ay_Emul29b26.src.7z ? It's already based on an older version of the same libraries that Robert tidied up.

MarkMLl
« Last Edit: October 29, 2020, 10:10:17 am by MarkMLl »
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & 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: 3158
    • StrumPract is the musicians best friend
Re: alsa beep - linux only
« Reply #50 on: October 29, 2020, 02:20:16 pm »
https://github.com/fredvs/alsa_sound

One small problem is:
When you play two differet tones anfter another, then every time the lib is loaded and unloaded.
That is nonsense. Anf results in a small gap between the two sounds.
This solves it:

Code: Pascal  [Select][+][-]
  1. initialization
  2. ab_Load;
  3. finalization
  4. ab_Unload;
  5. end.
  6.  

Hum, did you see that there is the "CloseLib" parameter for each method?

Code: Pascal  [Select][+][-]
  1. function ALSAglide(StartFreq, EndFreq, Duration, Volume: integer;  CloseLib : boolean): Boolean;
  2.  
  3. function ALSAbeep(Frequency, Duration, Volume: integer; Warble: Boolean;   CloseLib: boolean): Boolean;
  4.  

The parameter CloseLib decides if the library must be closed after running the method.

In the example "alsa_sound_test.pas" it shows how to use multi-play:

Code: Pascal  [Select][+][-]
  1. program alsa_sound_test;
  2.  
  3. uses
  4. alsa_sound;
  5.  
  6. begin
  7. ALSAglide(20, 880, 500, 75, false);
  8. ALSAglide(880, 20, 500, 75, false);
  9. ALSAbeep(880, 100, 75, false, false);  
  10. ALSAbeep(840, 100, 75, false, false);
  11. ALSAbeepStereo(440, 660, 1000, 75, 50, false, true); // CloseLib = true to close the library
  12. end.

If you do it in initialization the library will be loaded even if no beep or few beeps are called:

Code: Pascal  [Select][+][-]
  1. initialization
  2. as_Load;
  3.  

But for finalization, it is already in code in case of people forgot to unload the library:

Code: Pascal  [Select][+][-]
  1. finalization
  2. as_Unload;
  3. end.
  4.  


[EDIT]
as_Load uses a reference counter so there is no problem to use it at beginning of each ALSAxxx() method.

and at end simply use this: 
Code: Pascal  [Select][+][-]
  1. if CloseLib then as_unload;
« Last Edit: October 29, 2020, 04:31:27 pm by Fred vS »
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

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

Fred vS

  • Hero Member
  • *****
  • Posts: 3158
    • StrumPract is the musicians best friend
Re: alsa beep - linux only
« Reply #51 on: October 29, 2020, 06:20:32 pm »
Hello Wini.

Quote
Second: sinus sound is not very interesting.
This can be easy changed by some lines of code

This is very interesting, you give all the keys for total control, many thanks.

Quote
And third I created a police horn - american style:

EXCELLENT and very WOW and easy to use.

Do you agree if I add into alsa_sound.pas + in the demo?
https://github.com/fredvs/alsa_sound

Fre;D
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

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

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: alsa beep - linux only
« Reply #52 on: October 30, 2020, 11:15:28 pm »

Quote
And third I created a police horn - american style:

EXCELLENT and very WOW and easy to use.

Do you agree if I add into alsa_sound.pas + in the demo?
https://github.com/fredvs/alsa_sound

Fre;D

Yes, put it in the Alsa_beep unit and the demo!

Winni

Fred vS

  • Hero Member
  • *****
  • Posts: 3158
    • StrumPract is the musicians best friend
Re: alsa beep - linux only
« Reply #53 on: October 30, 2020, 11:35:56 pm »

Quote
And third I created a police horn - american style:

EXCELLENT and very WOW and easy to use.

Do you agree if I add into alsa_sound.pas + in the demo?
https://github.com/fredvs/alsa_sound

Fre;D

Yes, put it in the Alsa_beep unit and the demo!

Winni

Done, many thanks.
https://github.com/fredvs/alsa_sound/commit/e6beb42

About
Quote
Here  are sinus as used before,  sqare waves and saw tooth waves:

Do you agree if I use your code for the 'sinetype' parameter for some ALSAxxx methods?

Fre;D
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

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

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: alsa beep - linux only
« Reply #54 on: October 31, 2020, 01:34:28 am »
Hi Fred!

Yes use the wave type stuff in the unit. But call it "WaveType" - that is more correct than "SineType".

And i have some more fun for the demo:

German alarm horns go always with the musical fourth , in this case
a1 and d2.

Code: Pascal  [Select][+][-]
  1. // Germany: ambulace, fire brigade, police
  2. // 440 Hz und 585 Hz: a1 - d2
  3. for i := 1 to 3 do
  4. begin
  5. ALSAbeep(440,400,20,false);
  6. AlsaBeep(585,400,20,false);
  7. end;                    

And the children sing with it: Too late, too late, .... ("Zu spät, zu spät, ...")

And Switzerland is always a little bit different.
Nice music by the horn of their mountain buses:

Code: Pascal  [Select][+][-]
  1. // swiss mountain bus
  2. // cis'–e–a :   277.183  164.814  220.000
  3. for i := 1 to 3 do
  4. begin
  5. ALSAbeep(277,400,20,false);
  6. AlsaBeep(165, 400,20,false);
  7. AlsaBeep(220, 400,20,false);
  8. sleep(200);
  9. end;        
  10.  

And Switzerland has a lot of mountains!

Put it in the demo if you like it.

Winni

PS.: Volume at 75%????
        Then my neighbors would be angry!
« Last Edit: October 31, 2020, 01:47:48 am by winni »

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: alsa beep - linux only
« Reply #55 on: October 31, 2020, 02:16:02 am »

Have you considered a port of http://bulba.untergrund.net/Ay_Emul29b26.src.7z ? It's already based on an older version of the same libraries that Robert tidied up.

MarkMLl

Thanx for the the link.

What is that a strange kind of source?
A sound chip emu, a Motorola 680x0 sound emu, some hooks for the BASS.dll and in the last corner some code for Alsa.

Need some time to find out.

Winni

« Last Edit: October 31, 2020, 02:18:06 am by winni »

MarkMLl

  • Hero Member
  • *****
  • Posts: 6646
Re: alsa beep - linux only
« Reply #56 on: October 31, 2020, 08:59:33 am »
Have you considered a port of http://bulba.untergrund.net/Ay_Emul29b26.src.7z ? It's already based on an older version of the same libraries that Robert tidied up.
What is that a strange kind of source?

It was a very popular sound chip back in the day, my recollection is that it's got 3x tones plus noise with overall ASDR. I've seen a homebrew with I think three of them, and the results were extremely impressive. For anybody into murdering Mozart, see https://www.instructables.com/Arduino-MIDI-Chiptune-Synthesizer/

That project appears to have quite a lot of other stuff in there, possibly including Z80 and 68k emulators. The sound stuff is based on an earlier version of fpalsa, which is the library whence Robert and Fred cleaned up the PCM unit.

I'd mistakenly confused fpalsa and alsapas. It's now obvious that fpalsa is "lean and mean" while alsapas is anything but... why anybody should want to muddle a Lisp implementation in with the low-level libraries like this defies speculation.

Later: I notice that alsalisp (a derivative of slisp) is embedded in the C libraries themselves, so I am perhaps being a little uncharitable blaming alsapas for interfacing to it. Alsapas is creditably complete, but it's still a PITA to use since there's a runtime check that the expected version of libasound.so is on the system... forget about having a single development system targetting e.g. both Debian "stable" and "oldstable".

MarkMLl
« Last Edit: December 18, 2020, 11:46:41 pm by MarkMLl »
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & 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: 3158
    • StrumPract is the musicians best friend
Re: alsa beep - linux only
« Reply #57 on: October 31, 2020, 12:03:48 pm »
@Winni:

Your code was added in ALSA_Sound:
https://github.com/fredvs/alsa_sound/commit/c723f909

Many thanks!

Fre;D
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

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

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: alsa beep - linux only
« Reply #58 on: November 02, 2020, 11:33:30 pm »
Hi Fred!

I did some " cleaning" at theunit alsa_sound:

* Moved a lot of stuff from the interface to the implementation

* Made a procedure SetWaveType to reduce code. The filling of the array[0..359] of shortint appears nearly in every beep-procedur so we need the code only once.

* I have added AlsaBeepFlanger and AlsaMexicanTruck - last is "La Cucaraca"  which they use as horn.

And finally I made a little App where the user kann play around with the sound:

3 trackbars for frequency, volume and duration. A Radiogroup for wavetype sinus/square/saw tooth. And so on.

Screenshot + source in attachment.

Winni

Fred vS

  • Hero Member
  • *****
  • Posts: 3158
    • StrumPract is the musicians best friend
Re: alsa beep - linux only
« Reply #59 on: November 03, 2020, 02:43:47 am »
Hello Winni.

Superb.

I did merge your cleaned code.
https://github.com/fredvs/alsa_sound/commit/68492aab

There is a little change in ALSAmexicantruck to turn it into a function and adapt the result for it.
Same for all others call to functions.

Lot of sounds now, we can do a international symphony!

Your demo is great too (but your license is GPL, alsa_sound is LGPL).

Many thanks.

Fre;D
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

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

 

TinyPortal © 2005-2018