Impostare il volume dei singoli due canali del mixer di ALSA

Da Gambas-it.org - Wikipedia.

Utilizzando alcune risorse dell'interfaccia Mixer di ALSA, è possibile - fra l'altro - impostare e modificare il volume audio di ciascuno dei due canali del mixer.

Sarà ovviamente necessario richiamare in Gambas la libreria condivisa di ALSA: "libasound.so.2.0.0 ".

Mostriamo di seguito due semplici esempi, uno riferito ad un'applicazione a riga di comando e l'altro riferito ad un'applicazione grafica.

Esempio con un'applicazione a riga di comando

In questo esempio bisognerà scrivere nell'apposito spazio al di sotto della console (oppure nel Terminale) del progetto Gambas un valore compreso tra 0 e 100 per impostare il volume audio di ciascun canale del mixer di ALSA per volta.

Library "libasound:2.0.0"

Private Enum SND_MIXER_SCHN_MONO = 0, SND_MIXER_SCHN_FRONT_LEFT = 0, SND_MIXER_SCHN_FRONT_RIGHT

' int snd_mixer_open (snd_mixer_t **mixer, int mode)
' Opens an empty mixer.
Private Extern snd_mixer_open(mixer As Pointer, mode As Integer) As Integer

' int snd_mixer_attach (snd_mixer_t *mixer, const char *name)
' Attach an HCTL specified with the CTL device name to an opened mixer.
Private Extern snd_mixer_attach(mixer As Pointer, name As String) As Integer

' int snd_mixer_selem_register (snd_mixer_t *mixer, struct snd_mixer_selem_regopt *options, snd_mixer_class_t **classp)
' Register mixer simple element class.
Private Extern snd_mixer_selem_register(mixer As Pointer, options As Pointer, classp As Pointer) As Integer

' int snd_mixer_load (snd_mixer_t *mixer)
' Load a mixer elements.
Private Extern snd_mixer_load(mixer As Pointer) As Integer

' int snd_mixer_selem_id_malloc (snd_mixer_selem_id_t **ptr)
' Allocate an invalid snd_mixer_selem_id_t using standard malloc.
Private Extern snd_mixer_selem_id_malloc(ptr As Pointer) As Integer

' void snd_mixer_selem_id_set_index (snd_mixer_selem_id_t *obj, unsigned int val)
' Set index part of a mixer simple element identifier.
Private Extern snd_mixer_selem_id_set_index(obj As Pointer, ival As Integer)

' void snd_mixer_selem_id_set_name (snd_mixer_selem_id_t *obj, const char *val)
' Set name part of a mixer simple element identifier.
Private Extern snd_mixer_selem_id_set_name(obj As Pointer, sval As String)

' snd_mixer_elem_t * snd_mixer_find_selem (snd_mixer_t *mixer, const snd_mixer_selem_id_t *id)
' Find a mixer simple element.
Private Extern snd_mixer_find_selem(mixer As Pointer, id As Pointer) As Pointer

' int snd_mixer_selem_get_playback_volume_range (snd_mixer_elem_t *elem, long *min, long *max)
' Get range for playback volume of a mixer simple element.
Private Extern snd_mixer_selem_get_playback_volume_range(elem As Pointer, lmin As Long, lmax As Long) As Integer
 
' int snd_mixer_selem_set_playback_volume (snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value)
' Set value of playback volume control of a mixer simple element.
Private Extern snd_mixer_selem_set_playback_volume(elem As Pointer, channel As Integer, value As Integer) As Integer
 
' int snd_mixer_close (snd_mixer_t *mixer)
' Close a mixer and free all related resources.
Private Extern snd_mixer_close(mixer As Pointer) As Integer


Public Sub Main()
 
 Dim handle, sid, el As Pointer
 Dim err, i As Integer
 Dim can, vol As String
 Dim volume, mini, maxi As Long

 err = snd_mixer_open(VarPtr(handle), 0)
 If err < 0 Then Error.Raise("Impossibile inizializzare il sub-sistema 'Mixer' di ALSA !")

 snd_mixer_attach(handle, "default")
 snd_mixer_selem_register(handle, 0, 0)
 snd_mixer_load(handle)
 
 snd_mixer_selem_id_malloc(VarPtr(sid))
 snd_mixer_selem_id_set_index(sid, 0)
 snd_mixer_selem_id_set_name(sid, "Master")
 el = snd_mixer_find_selem(handle, sid)
 
 can = "sinistro."
 snd_mixer_selem_get_playback_volume_range(el, VarPtr(mini), VarPtr(maxi))
 
 For i = 0 to SND_MIXER_SCHN_FRONT_RIGHT
   if i = SND_MIXER_SCHN_FRONT_RIGHT Then can = "destro."
   Print "Immettere un valore (0 - 100) per impostare il volume del canale "; can
   Input vol
   volume = CLong(Val(vol))
   snd_mixer_selem_set_playback_volume(el, i, volume * maxi / 100)
 Next
  
' Va in chiusura:
 snd_mixer_close(handle)
 
End


Esempio con un'applicazione in ambiente grafico

In questo esempio in ambiente grafico la modifica del volume (tra 0 e 100) dei due canali avverrà mediante due distinti Slider, mentre la visualizzazione del valore del volume di ciascun canale avverrà mediante due ValueBox.

Private handle As Pointer
Private el As Pointer
Private maxi As Long


Library "libasound:2.0.0"

Private Enum SND_MIXER_SCHN_MONO = 0, SND_MIXER_SCHN_FRONT_LEFT = 0, SND_MIXER_SCHN_FRONT_RIGHT

' int snd_mixer_open (snd_mixer_t **mixer, int mode)
' Opens an empty mixer.
Private Extern snd_mixer_open(mixer As Pointer, mode As Integer) As Integer

' int snd_mixer_attach (snd_mixer_t *mixer, const char *name)
' Attach an HCTL specified with the CTL device name to an opened mixer.
Private Extern snd_mixer_attach(mixer As Pointer, name As String) As Integer

' int snd_mixer_selem_register (snd_mixer_t *mixer, struct snd_mixer_selem_regopt *options, snd_mixer_class_t **classp)
' Register mixer simple element class.
Private Extern snd_mixer_selem_register(mixer As Pointer, options As Pointer, classp As Pointer) As Integer

' int snd_mixer_load (snd_mixer_t *mixer)
' Load a mixer elements.
Private Extern snd_mixer_load(mixer As Pointer) As Integer

' int snd_mixer_selem_id_malloc (snd_mixer_selem_id_t **ptr)
' Allocate an invalid snd_mixer_selem_id_t using standard malloc.
Private Extern snd_mixer_selem_id_malloc(ptr As Pointer) As Integer

' void snd_mixer_selem_id_set_index (snd_mixer_selem_id_t *obj, unsigned int val)
' Set index part of a mixer simple element identifier.
Private Extern snd_mixer_selem_id_set_index(obj As Pointer, ival As Integer)

' void snd_mixer_selem_id_set_name (snd_mixer_selem_id_t *obj, const char *val)
' Set name part of a mixer simple element identifier.
Private Extern snd_mixer_selem_id_set_name(obj As Pointer, sval As String)

' snd_mixer_elem_t * snd_mixer_find_selem (snd_mixer_t *mixer, const snd_mixer_selem_id_t *id)
' Find a mixer simple element.
Private Extern snd_mixer_find_selem(mixer As Pointer, id As Pointer) As Pointer

' int snd_mixer_selem_get_playback_volume (snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value)
' Return value of playback volume control of a mixer simple element.
Private Extern snd_mixer_selem_get_playback_volume(elem As Pointer, channel As Integer, value As Pointer) As Integer

' int snd_mixer_selem_get_playback_volume_range (snd_mixer_elem_t *elem, long *min, long *max)
' Get range for playback volume of a mixer simple element.
Private Extern snd_mixer_selem_get_playback_volume_range(elem As Pointer, lmin As Long, lmax As Long) As Integer

' int snd_mixer_selem_set_playback_volume (snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value)
' Set value of playback volume control of a mixer simple element.
Private Extern snd_mixer_selem_set_playback_volume(elem As Pointer, channel As Integer, value As Integer) As Integer

' int snd_mixer_close (snd_mixer_t *mixer)
' Close a mixer and free all related resources.
Private Extern snd_mixer_close(mixer As Pointer) As Integer


Public Sub Form_Open()
 
 Dim sid As Pointer
 Dim err As Integer
 Dim vld, vls, mini As Long

 err = snd_mixer_open(VarPtr(handle), 0)
 If err < 0 Then Error.Raise("Impossibile inizializzare il sub-sistema 'Mixer' di ALSA !")

 snd_mixer_attach(handle, "default")
 snd_mixer_selem_register(handle, 0, 0)
 snd_mixer_load(handle)
 
 snd_mixer_selem_id_malloc(VarPtr(sid))
 snd_mixer_selem_id_set_index(sid, 0)
 snd_mixer_selem_id_set_name(sid, "Master")
 el = snd_mixer_find_selem(handle, sid)
 
' Ottiene l'attuale volume di ciascuno dei due canali del Mixer di ALSA:
 snd_mixer_selem_get_playback_volume(el, SND_MIXER_SCHN_FRONT_RIGHT, VarPtr(vld))
 snd_mixer_selem_get_playback_volume(el, SND_MIXER_SCHN_FRONT_LEFT, VarPtr(vls))

 snd_mixer_selem_get_playback_volume_range(el, VarPtr(mini), VarPtr(maxi))
 
 With Slider1
   .MinValue = 0
   .MaxValue = 100
   .Value = Round((vls * 100) / maxi)
 End With
 
 With Slider2
   .MinValue = 0
   .MaxValue = 100
   .Value = Round((vld * 100) / maxi)
 End With
   
End


Public Sub Slider1_Change()
 
 Dim volume As Long

 volume = CLong(Slider1.Value)
 
 snd_mixer_selem_set_playback_volume(el, SND_MIXER_SCHN_FRONT_LEFT, volume * maxi / 100)
 ValueBox1.Value = volume
  
End


Public Sub Slider2_Change()

 Dim volume As Long

 volume = CLong(Slider2.Value)
 
 snd_mixer_selem_set_playback_volume(el, SND_MIXER_SCHN_FRONT_RIGHT, volume * maxi / 100)
 ValueBox2.Value = volume
  
End


Public Sub Form_Close()

 snd_mixer_close(handle)
 
End


Riferimenti