Recent

Author Topic: Help with Alsa C conversion.  (Read 2981 times)

AL

  • Full Member
  • ***
  • Posts: 181
Re: Help with Alsa C conversion.
« Reply #45 on: August 07, 2020, 02:50:36 am »
Made a test project with a progressbar and it work OK.
Made a project with a timer and it work OK.

If I make the procedure stop with a show message, then the progressbar does work.
Like:
Code: Pascal  [Select][+][-]
  1. Repeat
  2.    ShowMessage (' PorgressBar');
  3.  
  4.   err := snd_pcm_readi (capture_handle, buffer, buffer_frames);
  5.  
  6.   if err <> buffer_frames then
  7.   begin
  8.         PostError ('Read from audio interface failed. Error = '+inttostr(err));
  9.         exit ;
  10.   end
  11.   else
  12.   begin     //we have a full buffer      

So it is really the read that prevent it from working.
Laz 2.1.0, fpc 3.3.1, Win10
Laz 2.1.0, fpc 3.3.1, Mac OS Mojave running on VMWare
Laz 2.1.0  fpc 3.3.1 Ubuntu 20.04

AL

  • Full Member
  • ***
  • Posts: 181
Re: Help with Alsa C conversion.
« Reply #46 on: August 07, 2020, 03:56:52 am »
I finally resorted to split my read in small chunks and call application.processmessages at each read.
The following is now working and the progressbar updating properly.
Code: Pascal  [Select][+][-]
  1. Procedure StartRecording ;
  2. Const Buffer_Frames = NBPoints;  // in Main   = 16384    int 16 bits
  3.  
  4. Var
  5.   // Samplerate       : Int32 = 8192 ; defined in Main
  6.   // Capture_handle   : Psnd_pcm_t ;  // declared as global to unit
  7.   // Channels         : int32 = 1 ; //mono    defined In Main
  8.      buffer           : Pchar ;
  9.      hw_params        : Psnd_pcm_hw_params_t ;
  10.      format           : snd_pcm_format_t = SND_PCM_FORMAT_S16_LE ;  // 16 bits signed little endian
  11.      direction        : integer = 0 ;
  12.      i,err ,readsize  : Integer;
  13. begin
  14.   ReadSize := Buffer_Frames  div 16 ; // 2048 bytes 16 times     1024 read * 2 bytes
  15.   err := snd_pcm_open(@capture_handle,Pchar(deviceTable[MainForm.CBListDevices.itemIndex].iname),SND_PCM_STREAM_CAPTURE,0(*SND_PCM_NONBLOCK*))  ;
  16.   If err < 0 then begin PostError('Error opening PCM') ; Exit ;end;
  17.  
  18.   err := snd_pcm_hw_params_malloc (@hw_params)  ;
  19.   If err < 0 then begin PostError('Error hwparams'); Exit ;end;
  20.  
  21.   err := snd_pcm_hw_params_any (capture_handle, hw_params) ;
  22.   if err< 0 then begin PostError('Cannot initialize hardware parameter structure') ; Exit ; end ;
  23.                                                                   // SND_PCM_ACCESS_MMAP_NONINTERLEAVED
  24.   err := snd_pcm_hw_params_set_access (capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
  25.   if err < 0 then begin PostError('Cannot access PCM type');Exit;end;
  26.  
  27.   err := snd_pcm_hw_params_set_format (capture_handle, hw_params, format) ;
  28.   if err < 0 then begin Posterror('Cannot set format') ; Exit; end;
  29.  
  30.   err := snd_pcm_hw_params_set_rate_near (capture_handle, hw_params, @samplerate, @direction);
  31.   if err < 0 then begin Posterror('Cannot set rate') ; Exit ; end;
  32.   if Direction  <> 0 then begin Posterror('Cannot set exact rate') ; Exit; end;
  33.  
  34.   err := snd_pcm_hw_params_set_channels (capture_handle, hw_params, channels) ;   // 1 channel = mono
  35.   if err < 0 then begin PostError('Cannot set channel count') ; Exit ; end;
  36.  
  37.   err := snd_pcm_hw_params (capture_handle, hw_params) ;
  38.   if err < 0 then Begin PostError('Cannot set parameters') ; Exit ; end ;
  39.  
  40.   snd_pcm_hw_params_free (hw_params);
  41.  
  42.   err := snd_pcm_prepare (capture_handle) ;
  43.   if err < 0 then begin PostError('Cannot prepare audio interface for use'); Exit ; end;
  44.  
  45.   buffer := GetMem ((Buffer_Frames * snd_pcm_format_width(format) DIV 8 * Channels) div 16);
  46.  
  47.  
  48.   FillWord(SavedFrameData,length(SavedFrameData),0);  // remove garbage
  49.  
  50. Repeat
  51.   for i := 0 to 15 do begin
  52.     err := snd_pcm_readi (capture_handle, buffer, ReadSize);
  53.     Move(buffer^,SavedFrameData[i*ReadSize],ReadSize *2)  ;
  54.     // SavedFrameData is int16 array no need to multiply ReadSize in index
  55.     Application.ProcessMessages ;
  56.    end;
  57.  
  58. // we assume we have a full buffer
  59.  
  60.    // Find the max value
  61.    gMax := 0 ;
  62.    gMaxIndex := 0 ;
  63.    For i := 0 to  length(SavedFrameData)-1 do
  64.       begin
  65.          if abs(SavedFrameData[i])> gmax then       // use only positives values
  66.          begin
  67.           gMax := Abs( SavedFrameData[i]);
  68.           gMaxIndex := i ;
  69.          End;
  70.       End;
  71.      If gMax > gSensitivity then        // Check if level is higher than sensitivity set level
  72.        begin
  73.         //  StopVisualBuffer ;
  74.           MainForm.RBdataReady.checked := true ;     // set an event to draw graphs
  75.        end   // gMax > sensivity
  76.        else
  77.        begin   // gMax is lower then sensitivity
  78.          ResetVisualBuffer ;
  79.        end;
  80.  
  81.    until gMax > gSensitivity ;
  82.  
  83.    Processing := False   ;
  84.    FreeMem(Buffer) ;
  85.    //snd_pcm_close (Capture_handle)  is called from main by Stop Recording ;
  86.  
  87. end;
  88.  
  89. Procedure StopRecording ;
  90. begin
  91.     snd_pcm_Close (Capture_Handle) ;
  92. end;                                    

Thank you to all for the great help.
Laz 2.1.0, fpc 3.3.1, Win10
Laz 2.1.0, fpc 3.3.1, Mac OS Mojave running on VMWare
Laz 2.1.0  fpc 3.3.1 Ubuntu 20.04

PascalDragon

  • Hero Member
  • *****
  • Posts: 2090
  • Compiler Developer
Re: Help with Alsa C conversion.
« Reply #47 on: August 07, 2020, 09:28:50 am »
Quote
 
Quote
PulseAudio that was using ALSA at the beginning has developed his own audio drivers and use this now.

Source please

From https://en.wikipedia.org/wiki/PulseAudio

In a typical installation scenario under Linux, the user configures ALSA to use a virtual device provided by PulseAudio. Thus, applications using ALSA will output sound to PulseAudio, which then uses ALSA itself to access the real sound card. PulseAudio also provides its own native interface to applications that want to support PulseAudio directly, as well as a legacy interface for ESD applications, making it suitable as a drop-in replacement for ESD.

Fre;D

Please read this carefully. It only talks about the user facing API: If PulseAudio is active and an (old) application uses the ALSA API directly, it gets redirected to PulseAudio: Application -> Wrapper -> PulseAudio. But (newer) applications can also use the PulseAudio interface directly. However, In both cases PulseAudio uses ALSA to stream the data to the audio hardware.

From https://en.wikipedia.org/wiki/Advanced_Linux_Sound_Architecture:
Advanced Linux Sound Architecture (ALSA) is a software framework and part of the Linux kernel that provides an application programming interface (API) for sound card device drivers.
The sound servers PulseAudio and JACK (low-latency professional-grade audio editing and mixing), the higher-level abstraction APIs OpenAL, SDL audio, etc. work on top of ALSA and implemented sound card device drivers. On Linux systems, ALSA succeeded the older Open Sound System (OSS).

Edit: In case you don't believe Wikipedia:
From the official page: https://www.freedesktop.org/wiki/Software/PulseAudio/Backends/ALSA/
The primary backend used on Linux is ALSA.

Correct. One needs to differentiate between the backend drivers (where PulseAudio mainly uses ALSA on Linux) and the frontend where one can use ALSA as a wrapper towards PulseAudio or PulseAudio directly (among other possibilities).

Fred vS

  • Hero Member
  • *****
  • Posts: 1836
    • StrumPract is the musicians best friend
Re: Help with Alsa C conversion.
« Reply #48 on: August 07, 2020, 02:07:45 pm »
Quote
 
Quote
PulseAudio that was using ALSA at the beginning has developed his own audio drivers and use this now.

Source please

From https://en.wikipedia.org/wiki/PulseAudio

In a typical installation scenario under Linux, the user configures ALSA to use a virtual device provided by PulseAudio. Thus, applications using ALSA will output sound to PulseAudio, which then uses ALSA itself to access the real sound card. PulseAudio also provides its own native interface to applications that want to support PulseAudio directly, as well as a legacy interface for ESD applications, making it suitable as a drop-in replacement for ESD.

Fre;D

Please read this carefully. It only talks about the user facing API: If PulseAudio is active and an (old) application uses the ALSA API directly, it gets redirected to PulseAudio: Application -> Wrapper -> PulseAudio. But (newer) applications can also use the PulseAudio interface directly. However, In both cases PulseAudio uses ALSA to stream the data to the audio hardware.

From https://en.wikipedia.org/wiki/Advanced_Linux_Sound_Architecture:
Advanced Linux Sound Architecture (ALSA) is a software framework and part of the Linux kernel that provides an application programming interface (API) for sound card device drivers.
The sound servers PulseAudio and JACK (low-latency professional-grade audio editing and mixing), the higher-level abstraction APIs OpenAL, SDL audio, etc. work on top of ALSA and implemented sound card device drivers. On Linux systems, ALSA succeeded the older Open Sound System (OSS).

Edit: In case you don't believe Wikipedia:
From the official page: https://www.freedesktop.org/wiki/Software/PulseAudio/Backends/ALSA/
The primary backend used on Linux is ALSA.

Correct. One needs to differentiate between the backend drivers (where PulseAudio mainly uses ALSA on Linux) and the frontend where one can use ALSA as a wrapper towards PulseAudio or PulseAudio directly (among other possibilities).

Hum, did you read the topics of Martin (I give it some topic before and like you I was thinking that PulseAudio still used ALSA):?

Quote
http://mseide-msegui-talk.13964.n8.nabble.com/MSEide-MSEgui-talk-MSE-pcaudio-td610i20.html
 The discussion begin from  Mar 09, 2018; 10:57pm Re: [MSEide-MSEgui-talk] MSE pcaudio

Anyway, it is maybe a problem of naming because PulseAudio has his own audio kernel now.

And yes it seems that the audio kernel used by Linux is called ALSA, and that there is also thecalled ALSA audio server (that you may compare to the PulseAudio or Jack audio server.)

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

Fred vS

  • Hero Member
  • *****
  • Posts: 1836
    • StrumPract is the musicians best friend
Re: Help with Alsa C conversion.
« Reply #49 on: August 07, 2020, 02:16:24 pm »
@  PascalDragon

All that is not clear.
And I agree, it is important to know the truth.

But does the truth still exist in 2020?

Anyway, I will open a issue in the GitLab site of PulseAudio and ask them what is their truth about PusleAudio using ALSA.

Fre;D
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

Fred vS

  • Hero Member
  • *****
  • Posts: 1836
    • StrumPract is the musicians best friend
Re: Help with Alsa C conversion.
« Reply #50 on: August 07, 2020, 02:42:21 pm »
@  PascalDragon

All that is not clear.
And I agree, it is important to know the truth.

But does the truth still exist in 2020?

Anyway, I will open a issue in the GitLab site of PulseAudio and ask them what is their truth about PusleAudio using ALSA.

Fre;D

Done: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/issues/959

I hope it will give some clarification.
(And if you see something else to ask, please say it, I will ask).
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

PascalDragon

  • Hero Member
  • *****
  • Posts: 2090
  • Compiler Developer
Re: Help with Alsa C conversion.
« Reply #51 on: August 07, 2020, 02:52:31 pm »
Done: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/issues/959

I hope it will give some clarification.
(And if you see something else to ask, please say it, I will ask).

I assume this is simply a language barrier, so I will try again:

An application that wants to process audio on Linux needs to use some audio library. This can be libalsa or libpulse or whatever it is that Jack provides (I assume libjack). Now if you're using PulseAudio as audio server then libalsa will route everything to the PulseAudio server and a conversion from the ALSA API to the (internal) PulseAudio API will take place. If you use libpulse then no conversion is needed. This here is indeed where ALSA (the user space part) is no longer needed.

Now the audio server needs to handle audio devices, which can be sound cards, HDMI audio outputs or whatever. Right now there is only one infrastructure for this in the Linux kernel and that is called ALSA as well. But compared to the above this is the kernel interface. This did not change with the advent of PulseAudio, because the kernel interface is working well enough for PulseAudio to use. Thus in this context ALSA is still required by PulseAudio. This doesn't matter for an application however, because that picks its API independently of that (it can use libalsa or libpulse depending on its needs).

Thus saying ALSA as a whole is no longer required for PulseAudio is wrong. What is no longer required is the user space part.

MarkMLl

  • Hero Member
  • *****
  • Posts: 1214
Re: Help with Alsa C conversion.
« Reply #52 on: August 07, 2020, 02:58:45 pm »
I think we all appreciate you doing that, Fred.

I've just been taking a bit of a look at the situation from the POV of Debian: the pulseaudio package depends on libasound2 but it's not explicitly stated that ALSA depends on Pulseaudio. However libasound2 is merely a wrapper around ALSA "glue" provided by the kernel and can be replaced... ALSA itself is a kernel thing and the low-level drivers are also part of the kernel.

The previous stuff that I've come across where ALSA appeared to depend on Pulseaudio was related to MIDI, and it's also confusing that when a MIDI-related program e.g. Rosegarden starts up it can also put things in the device list. Kill Pulseaudio and MIDI didn't work, however I don't know whether this applies to both hardware and emulated MIDI :-(

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.

MarkMLl

  • Hero Member
  • *****
  • Posts: 1214
Re: Help with Alsa C conversion.
« Reply #53 on: August 07, 2020, 03:01:12 pm »
Now if you're using PulseAudio as audio server

What is an "audio server" in this context?

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.

Fred vS

  • Hero Member
  • *****
  • Posts: 1836
    • StrumPract is the musicians best friend
Re: Help with Alsa C conversion.
« Reply #54 on: August 07, 2020, 03:05:23 pm »
Done: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/issues/959

I hope it will give some clarification.
(And if you see something else to ask, please say it, I will ask).

I assume this is simply a language barrier, so I will try again:

...

Now the audio server needs to handle audio devices, which can be sound cards, HDMI audio outputs or whatever. Right now there is only one infrastructure for this in the Linux kernel and that is called ALSA as well. But compared to the above this is the kernel interface. This did not change with the advent of PulseAudio, because the kernel interface is working well enough for PulseAudio to use. Thus in this context ALSA is still required by PulseAudio. This doesn't matter for an application however, because that picks its API independently of that (it can use libalsa or libpulse depending on its needs).

Thus saying ALSA as a whole is no longer required for PulseAudio is wrong. What is no longer required is the user space part.

Be quiet, it is not a barrier of language.

And what you explained is exactly what was in my brain before the discussion with Martin.

What I understood from him is that PulseAudio has now his own audio kernel drivers to deal with the audio cards and they are not the same as ALSA use.

Maybe I am wrong and I would like to be certified by a "official" PulseAudio man.
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: 1214
Re: Help with Alsa C conversion.
« Reply #55 on: August 07, 2020, 03:48:55 pm »
What I understood from him is that PulseAudio has now his own audio kernel drivers to deal with the audio cards and they are not the same as ALSA use.

Maybe I am wrong and I would like to be certified by a "official" PulseAudio man.

Or even better, by somebody who can speak for the kernel developers and maintainers.

I'm currently downloading the sources from kernel.org since at least part of this can be answered by reference to the build process, but my strong suspicion (which I will come back and correct if necessary) is that there are

* Kernel facilities for ALSA "glue" functionality.

* Kernel drivers for low-level devices.

* /Possibly/ kernel facilities for Pulseaudio.

However note that the low-level drivers are part of neither ALSA nor of Pulseaudio, even though they might be aware of one or the other APIs.

Slightly later: there are no files in the Linux kernel tree with a case-insensitive match of "pulseaudio" in their name. There's half a dozen content matches, entirely in documentation or comments, including in Documentation/sound/designs/jack-controls.rst "This means userspace applications like pulseaudio can switch off headphones and switch on speakers when no headphones are pluged in."

At least some of the multimedia devices (soundcards etc.) appear under Device Drivers -> Sound card support -> Advanced Linux Sound Architecture which also has settings for OSS emulation.

So Pulseaudio is NOT part of the kernel, ALSA covers various "glue" APIs, and device drivers are grouped under ALSA because they make use of some of those APIs (before ALSA, they were probably part of OSS).

There's obviously still a possibility that some of Pulseaudio is shipped as out-of-tree kernel modules, but I have no immediate reason to believe that to be the case.

Jack, OTOH, does appear to be part of the kernel to at least some extent.

MarkMLl
« Last Edit: August 07, 2020, 04:12:22 pm 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.

Fred vS

  • Hero Member
  • *****
  • Posts: 1836
    • StrumPract is the musicians best friend
Re: Help with Alsa C conversion.
« Reply #56 on: August 07, 2020, 04:12:40 pm »
What I understood from him is that PulseAudio has now his own audio kernel drivers to deal with the audio cards and they are not the same as ALSA use.

Maybe I am wrong and I would like to be certified by a "official" PulseAudio man.

Or even better, by somebody who can speak for the kernel developers and maintainers.

I'm currently downloading the sources from kernel.org since at least part of this can be answered by reference to the build process, but my strong suspicion (which I will come back and correct if necessary) is that there are

* Kernel facilities for ALSA "glue" functionality.

* Kernel drivers for low-level devices.

* /Possibly/ kernel facilities for Pulseaudio.

However note that the low-level drivers are part of neither ALSA nor of Pulseaudio, even though they might be aware of one or the other APIs.

MarkMLl

Thanks for this Mark, it is highly appreciated and will be very useful to know the "true truth".

Fred
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: 1214
Re: Help with Alsa C conversion.
« Reply #57 on: August 07, 2020, 04:13:57 pm »
You're welcome Fred, and I'm sorry if we appear to be at odds over this.

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.

TRon

  • Hero Member
  • *****
  • Posts: 533
Re: Help with Alsa C conversion.
« Reply #58 on: August 07, 2020, 10:20:34 pm »
I finally resorted to split my read in small chunks and call application.processmessages at each read.
Would be cheap to say told you so...  ;) (actually MarkMLl who did that if not mistaken)

How ALSA is implemented for each and every platform simply differs (and how that impacts for instance gui related updates).

Fact is however that readi is a blocking call by default (as stated in ALSA documentation), therefor it might be that other parts of your program (such as GUI) are not given enough time to be updated.

Your buffer was 2 seconds so in theory that might mean that for 2 seconds your program is completely blocked for whatever other operation during that time.

If you cut down that time, and do multiple reads you are able to 'lift' (some of) that restriction.

This can stil cause issues because updating the GUI (or doing other time-consuming operations) might take too much time so that your 'recording' buffer overruns.

That is why the non-blocking mode exist (internally by ALSA threaded if I understood the ALSA documentation correctly). That will read whatever is currently in the buffer but does not mean that the complete buffer is saturated (after a single read).

It might only be a few samples. This can be detected by the returning value from readi. So if that does not match a saturated buffer, you will receive a EAGAIN value.

Because you then know the buffer is not saturated, but the readi call did return you have time to do other stuff before you do a read again (such as updating the GUI). That usually is enough because ALSA itself is doing that call threaded as well.

If even that is not enough to do other stuff while reading the buffer then it becomes time to start thinking about putting all your ALSA related code inside a (pascal) thread.

Your code seems pretty simple in nature so should not affect your program much but, you could perhaps imagine that you are working with midi or are implementing your own sequencer. In such cases timing is particularly of the essence and requires  more attention with regards to what I wrote above.

Just meant as some additional background information in case you wish to explore other adventures using ALSA.

Quote
The following is now working and the progressbar updating properly.
Thank you for having posted your code. For sure it would be helpful to others.

Note that by using a smaller recording buffer you can also taken out some code of your read loop that consumes time (the normalising of the samples), as you did in your final code.

Using a smaller buffer also allows for toying with such things and allows to see if it does fit (time-wise) inside your read loop, if you so wish to do so.

Happy coding !

 

TinyPortal © 2005-2018