How to get the volume from audio input on Linux?

Linux specific forum
User avatar
Kukulkan
Addict
Addict
Posts: 1352
Joined: Mon Jun 06, 2005 2:35 pm
Location: germany
Contact:

How to get the volume from audio input on Linux?

Post by Kukulkan »

Hi,

I like to display a volume meter in my PB app on Linux and therefore I need the volume (stereo, separated channels) from a given input (eg line or microphone). I do not need to record the audio. Just the volume levels.

I assume it also depends on what audio engine the system is using? ALSA? JACK? Mainly it should work out of the box on current Debian systems like Xubuntu, Linux Mint etc.

Any idea what API I need to call for such? I currently have no clue and therefore, any guidance to the right direction is useful.

Best,

Kukulkan
DarkDragon
Addict
Addict
Posts: 2228
Joined: Mon Jun 02, 2003 9:16 am
Location: Germany
Contact:

Re: How to get the volume from audio input on Linux?

Post by DarkDragon »

Gnome mainly uses pulseaudio, but it is often just used as a software mixer extension for alsa. Therefore I would suggest using the ALSA API. Jack is not mainstream, yet. You can try it yourself in these ways to determine which would be most useful:
http://unix.stackexchange.com/questions ... m-terminal
bye,
Daniel
User avatar
Kukulkan
Addict
Addict
Posts: 1352
Joined: Mon Jun 06, 2005 2:35 pm
Location: germany
Contact:

Re: How to get the volume from audio input on Linux?

Post by Kukulkan »

Hi Daniel,

thanks, but I do no want to set, I need to get the current volume level of both channels (left and right) a few times per second. Not the level that is set by the user. The level of the current input on the soundcard. I like to do some VU-meter style software.

Sadly I can not find any ALSO API call example for PureBasic... I will see if I can use BASS library or such for this purpose...
DarkDragon
Addict
Addict
Posts: 2228
Joined: Mon Jun 02, 2003 9:16 am
Location: Germany
Contact:

Re: How to get the volume from audio input on Linux?

Post by DarkDragon »

Hello,

Oh sorry I've read set. But still it should be the same somehow.

Here is another example how to set it from C-code with libalsa:
http://stackoverflow.com/questions/6787 ... rom-c-code

I'm sure you only need to replace snd_mixer_selem_set_playback_volume_all with snd_mixer_selem_get_playback_volume (without all). The documentation can be found here:
http://www.alsa-project.org/alsa-doc/al ... mixer.html

If you want it way simpler, there is also 'amixer get Master'.

[EDIT]
corrected first link
bye,
Daniel
User avatar
Kukulkan
Addict
Addict
Posts: 1352
Joined: Mon Jun 06, 2005 2:35 pm
Location: germany
Contact:

Re: How to get the volume from audio input on Linux?

Post by Kukulkan »

Hi,

thanks, but I do not want to know the position of the faders. I need the current input level for a VU meter style application. So, the volume of the signals on the input!

Image

To do something similar, I need the signal level (better word) from a selectable audio input (eg line in or mic).
DarkDragon
Addict
Addict
Posts: 2228
Joined: Mon Jun 02, 2003 9:16 am
Location: Germany
Contact:

Re: How to get the volume from audio input on Linux?

Post by DarkDragon »

Hello,

I think it was too hot for me in the last few days. At least here is an example how you can record stuff with pulseaudio:

https://freedesktop.org/software/pulsea ... ample.html

This would give you a stream of audio data and you could process this and find the VU values with it maybe.

[EDIT]

If you like python, here is another short example which also converts the stream into VU values I think:

http://freshfoo.com/posts/pulseaudio_monitoring/
bye,
Daniel
User avatar
Kukulkan
Addict
Addict
Posts: 1352
Joined: Mon Jun 06, 2005 2:35 pm
Location: germany
Contact:

Re: How to get the volume from audio input on Linux?

Post by Kukulkan »

Hi DarkDragon,

thanks, that is helping me. I started a quick and dirty test code. This is how I convert the functions and things needed for me to PB so far, but I'm stuck here:

Code: Select all

; PulseAudio test

Enumeration pa_sample_format
  #PA_SAMPLE_U8
  #PA_SAMPLE_ALAW
  #PA_SAMPLE_ULAW
  #PA_SAMPLE_S16LE
  #PA_SAMPLE_S16BE
  #PA_SAMPLE_FLOAT32LE
  #PA_SAMPLE_FLOAT32BE
  #PA_SAMPLE_S32LE
  #PA_SAMPLE_S32BE
  #PA_SAMPLE_S24LE
  #PA_SAMPLE_S24BE
  #PA_SAMPLE_S24_32LE
  #PA_SAMPLE_S24_32BE
  #PA_SAMPLE_MAX
  #PA_SAMPLE_INVALID = -1
EndEnumeration

Enumeration pa_stream_direction
  #PA_STREAM_NODIRECTION 	
  #PA_STREAM_PLAYBACK 	
  #PA_STREAM_RECORD 	
  #PA_STREAM_UPLOAD 	
EndEnumeration

Enumeration pa_channel_position
  #PA_CHANNEL_POSITION_INVALID = -1
  #PA_CHANNEL_POSITION_MONO = 0
  #PA_CHANNEL_POSITION_FRONT_LEFT
  #PA_CHANNEL_POSITION_FRONT_RIGHT
  #PA_CHANNEL_POSITION_FRONT_CENTER
  #PA_CHANNEL_POSITION_LEFT = #PA_CHANNEL_POSITION_FRONT_LEFT
  #PA_CHANNEL_POSITION_RIGHT = #PA_CHANNEL_POSITION_FRONT_RIGHT
  #PA_CHANNEL_POSITION_CENTER = #PA_CHANNEL_POSITION_FRONT_CENTER
  #PA_CHANNEL_POSITION_REAR_CENTER
  #PA_CHANNEL_POSITION_REAR_LEFT
  #PA_CHANNEL_POSITION_REAR_RIGHT
  #PA_CHANNEL_POSITION_LFE
  #PA_CHANNEL_POSITION_SUBWOOFER = #PA_CHANNEL_POSITION_LFE
  #PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
  #PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
  #PA_CHANNEL_POSITION_SIDE_LEFT
  #PA_CHANNEL_POSITION_SIDE_RIGHT
  #PA_CHANNEL_POSITION_AUX0
  #PA_CHANNEL_POSITION_AUX1
  #PA_CHANNEL_POSITION_AUX2
  #PA_CHANNEL_POSITION_AUX3
  #PA_CHANNEL_POSITION_AUX4
  #PA_CHANNEL_POSITION_AUX5
  #PA_CHANNEL_POSITION_AUX6
  #PA_CHANNEL_POSITION_AUX7
  #PA_CHANNEL_POSITION_AUX8
  #PA_CHANNEL_POSITION_AUX9
  #PA_CHANNEL_POSITION_AUX10
  #PA_CHANNEL_POSITION_AUX11
  #PA_CHANNEL_POSITION_AUX12
  #PA_CHANNEL_POSITION_AUX13
  #PA_CHANNEL_POSITION_AUX14
  #PA_CHANNEL_POSITION_AUX15
  #PA_CHANNEL_POSITION_AUX16
  #PA_CHANNEL_POSITION_AUX17
  #PA_CHANNEL_POSITION_AUX18
  #PA_CHANNEL_POSITION_AUX19
  #PA_CHANNEL_POSITION_AUX20
  #PA_CHANNEL_POSITION_AUX21
  #PA_CHANNEL_POSITION_AUX22
  #PA_CHANNEL_POSITION_AUX23
  #PA_CHANNEL_POSITION_AUX24
  #PA_CHANNEL_POSITION_AUX25
  #PA_CHANNEL_POSITION_AUX26
  #PA_CHANNEL_POSITION_AUX27
  #PA_CHANNEL_POSITION_AUX28
  #PA_CHANNEL_POSITION_AUX29
  #PA_CHANNEL_POSITION_AUX30
  #PA_CHANNEL_POSITION_AUX31
  #PA_CHANNEL_POSITION_TOP_CENTER
  #PA_CHANNEL_POSITION_TOP_FRONT_LEFT
  #PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
  #PA_CHANNEL_POSITION_TOP_FRONT_CENTER
  #PA_CHANNEL_POSITION_TOP_REAR_LEFT
  #PA_CHANNEL_POSITION_TOP_REAR_RIGHT
  #PA_CHANNEL_POSITION_TOP_REAR_CENTER
  #PA_CHANNEL_POSITION_MA
EndEnumeration

Structure pa_buffer_attr
  maxlength.l
  tlength.l
  prebuf.l
  minreq.l
  fragsize.l
EndStructure
  
Structure pa_sample_spec
  pa_sample_format.l
  rate.l
  channels.a
EndStructure

Structure pa_channel_map
  channels.a
  pa_channel_position.l
EndStructure

; prototypes for pulseAudio
Prototype.i pa_simple_new(server.p-ascii, name.p-ascii, dir.l, dev.p-ascii, stream_name.p-ascii, ss.l, mp.l, attr.l, error.l)
Prototype.i pa_get_library_version()
Prototype.i pa_strerror(error.i)

; Open libPulse library for "simple" interface
pulseLib.i = OpenLibrary(#PB_Any, "libpulse-simple.so")
If pulseLib.i = 0
  Debug "No pulse lib loaded"
  End
EndIf

; assign prototype functions
pa_get_library_version.pa_get_library_version = GetFunction(pulseLib, "pa_get_library_version")
pa_simple_new.pa_simple_new = GetFunction(pulseLib, "pa_simple_new")
pa_strerror.pa_strerror = GetFunction(pulseLib, "pa_strerror")

; get version
p.i = pa_get_library_version()
Debug "libpulse version: V" + PeekS(p.i, -1, #PB_Ascii)

; open record stream
*ss.pa_sample_spec = AllocateMemory(SizeOf(pa_sample_spec))
*ss\channels = 2
*ss\rate = 44100
*ss\pa_sample_format = #PA_SAMPLE_S16LE

error.i = 0
*s = pa_simple_new("", "PulseTest", #PA_STREAM_RECORD, "", "record", *ss, 0, 0, @error.i)
If error.i <> 0
  p.i = pa_strerror(error.i)
  Debug "Error " + Str(error) + ": " + PeekS(p.i, -1, #PB_Ascii)
Else
  Debug "Stream open"
EndIf

FreeMemory(*ss)

CloseLibrary(pulseLib)
Result:
libpulse version: V4.0.0
Error 3: Invalid argument

I try to follow the linked example, but not sure about the datatypes for pa_sample_format_t and some others. Is this so far correct? I translated uint32_t with long (.l) and uint8_t with byte/ascii (.a). But what type is pa_sample_format_t and pa_stream_direction_t? I translated with long (.l) for the moment, but not sure. Also for pa_channel_position_t. This is really confusing...

Kukulkan
DarkDragon
Addict
Addict
Posts: 2228
Joined: Mon Jun 02, 2003 9:16 am
Location: Germany
Contact:

Re: How to get the volume from audio input on Linux?

Post by DarkDragon »

NULL is not empty string:

Code: Select all

; PulseAudio test

Enumeration pa_sample_format
  #PA_SAMPLE_U8
  #PA_SAMPLE_ALAW
  #PA_SAMPLE_ULAW
  #PA_SAMPLE_S16LE
  #PA_SAMPLE_S16BE
  #PA_SAMPLE_FLOAT32LE
  #PA_SAMPLE_FLOAT32BE
  #PA_SAMPLE_S32LE
  #PA_SAMPLE_S32BE
  #PA_SAMPLE_S24LE
  #PA_SAMPLE_S24BE
  #PA_SAMPLE_S24_32LE
  #PA_SAMPLE_S24_32BE
  #PA_SAMPLE_MAX
  #PA_SAMPLE_INVALID = -1
EndEnumeration

Enumeration pa_stream_direction
  #PA_STREAM_NODIRECTION    
  #PA_STREAM_PLAYBACK    
  #PA_STREAM_RECORD    
  #PA_STREAM_UPLOAD    
EndEnumeration

Enumeration pa_channel_position
  #PA_CHANNEL_POSITION_INVALID = -1
  #PA_CHANNEL_POSITION_MONO = 0
  #PA_CHANNEL_POSITION_FRONT_LEFT
  #PA_CHANNEL_POSITION_FRONT_RIGHT
  #PA_CHANNEL_POSITION_FRONT_CENTER
  #PA_CHANNEL_POSITION_LEFT = #PA_CHANNEL_POSITION_FRONT_LEFT
  #PA_CHANNEL_POSITION_RIGHT = #PA_CHANNEL_POSITION_FRONT_RIGHT
  #PA_CHANNEL_POSITION_CENTER = #PA_CHANNEL_POSITION_FRONT_CENTER
  #PA_CHANNEL_POSITION_REAR_CENTER
  #PA_CHANNEL_POSITION_REAR_LEFT
  #PA_CHANNEL_POSITION_REAR_RIGHT
  #PA_CHANNEL_POSITION_LFE
  #PA_CHANNEL_POSITION_SUBWOOFER = #PA_CHANNEL_POSITION_LFE
  #PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
  #PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
  #PA_CHANNEL_POSITION_SIDE_LEFT
  #PA_CHANNEL_POSITION_SIDE_RIGHT
  #PA_CHANNEL_POSITION_AUX0
  #PA_CHANNEL_POSITION_AUX1
  #PA_CHANNEL_POSITION_AUX2
  #PA_CHANNEL_POSITION_AUX3
  #PA_CHANNEL_POSITION_AUX4
  #PA_CHANNEL_POSITION_AUX5
  #PA_CHANNEL_POSITION_AUX6
  #PA_CHANNEL_POSITION_AUX7
  #PA_CHANNEL_POSITION_AUX8
  #PA_CHANNEL_POSITION_AUX9
  #PA_CHANNEL_POSITION_AUX10
  #PA_CHANNEL_POSITION_AUX11
  #PA_CHANNEL_POSITION_AUX12
  #PA_CHANNEL_POSITION_AUX13
  #PA_CHANNEL_POSITION_AUX14
  #PA_CHANNEL_POSITION_AUX15
  #PA_CHANNEL_POSITION_AUX16
  #PA_CHANNEL_POSITION_AUX17
  #PA_CHANNEL_POSITION_AUX18
  #PA_CHANNEL_POSITION_AUX19
  #PA_CHANNEL_POSITION_AUX20
  #PA_CHANNEL_POSITION_AUX21
  #PA_CHANNEL_POSITION_AUX22
  #PA_CHANNEL_POSITION_AUX23
  #PA_CHANNEL_POSITION_AUX24
  #PA_CHANNEL_POSITION_AUX25
  #PA_CHANNEL_POSITION_AUX26
  #PA_CHANNEL_POSITION_AUX27
  #PA_CHANNEL_POSITION_AUX28
  #PA_CHANNEL_POSITION_AUX29
  #PA_CHANNEL_POSITION_AUX30
  #PA_CHANNEL_POSITION_AUX31
  #PA_CHANNEL_POSITION_TOP_CENTER
  #PA_CHANNEL_POSITION_TOP_FRONT_LEFT
  #PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
  #PA_CHANNEL_POSITION_TOP_FRONT_CENTER
  #PA_CHANNEL_POSITION_TOP_REAR_LEFT
  #PA_CHANNEL_POSITION_TOP_REAR_RIGHT
  #PA_CHANNEL_POSITION_TOP_REAR_CENTER
  #PA_CHANNEL_POSITION_MA
EndEnumeration

Structure pa_buffer_attr
  maxlength.l
  tlength.l
  prebuf.l
  minreq.l
  fragsize.l
EndStructure
  
Structure pa_sample_spec
  pa_sample_format.l
  rate.l
  channels.a
EndStructure

Structure pa_channel_map
  channels.a
  pa_channel_position.l
EndStructure

; prototypes for pulseAudio
Prototype.i pa_simple_new(*server, name.p-ascii, dir.l, *dev, stream_name.p-ascii, ss.l, mp.l, attr.l, error.l)
Prototype.i pa_get_library_version()
Prototype.i pa_strerror(error.i)

; Open libPulse library for "simple" interface
pulseLib.i = OpenLibrary(#PB_Any, "libpulse-simple.so")
If pulseLib.i = 0
  Debug "No pulse lib loaded"
  End
EndIf

; assign prototype functions
pa_get_library_version.pa_get_library_version = GetFunction(pulseLib, "pa_get_library_version")
pa_simple_new.pa_simple_new = GetFunction(pulseLib, "pa_simple_new")
pa_strerror.pa_strerror = GetFunction(pulseLib, "pa_strerror")

; get version
p.i = pa_get_library_version()
Debug "libpulse version: V" + PeekS(p.i, -1, #PB_Ascii)

; open record stream
*ss.pa_sample_spec = AllocateMemory(SizeOf(pa_sample_spec))
*ss\channels = 2
*ss\rate = 44100
*ss\pa_sample_format = #PA_SAMPLE_S16LE

error.i = 0
*s = pa_simple_new(0, "PulseTest", #PA_STREAM_RECORD, 0, "record", *ss, 0, 0, @error.i)
If error.i <> 0
  p.i = pa_strerror(error.i)
  Debug "Error " + Str(error) + ": " + PeekS(p.i, -1, #PB_Ascii)
Else
  Debug "Stream open"
EndIf

FreeMemory(*ss)

CloseLibrary(pulseLib)
Output:
libpulse version: V9.0.0
Stream open
bye,
Daniel
User avatar
Kukulkan
Addict
Addict
Posts: 1352
Joined: Mon Jun 06, 2005 2:35 pm
Location: germany
Contact:

Re: How to get the volume from audio input on Linux?

Post by Kukulkan »

Hi Daniel,

thanks! So I can continue now :) If I finally get a working module (this is the goal), I will post it to the forum.

Kukulkan
Post Reply