Présentation
Je suis musicien et informaticien depuis une 20aine d'année maintenant. Musicien amateur,je joue du saxophone ténor, des flûtes à bec ténor, alto et soprano et je pratique la mao pour le plaisir. Anciennement informaticien professionnel, je programme en python, php et j'ai quelques notions de C++, VB, javascript. J'ai, dans mon passé, fait de l'installation de serveurs Linux, du réseau (restructuration, topologie, sécurité, etc...), de l'administration et un peu de développement pour des outils sans prétention. Actuellement instituteur, je pratique mes deux passions pour le plaisir.
Pc:
- I7 2600K, 16Go ram, HD ssd 90Go, 2 HD sata2 500Go, ATI 7870 sapphire, Tripple écrans.
- OS: ubuntu studio 13.10, gnome 3 + cairo-dock. Pulseaudio dégagé, jack only!!
Matériel musical:
Logiciels régulièrement utilisés:
- LAditray
- Qjackctl
- Ardour
- Rosegarden
- Hydrogen
- linuxsampler
- Qsynth
- Audacity
- Musescore
- Rakarrak
- avec wine: A band in box 2009
- En virtualbox xp (je sais c'est mal): Cubase vst32,Prodipe Virtual Expendeur(livré avec la carte)
Instruments:
- Sax ténor Selmer SA II 80 jubilé
- Flûte ténor Mallenhaur Dener poirier
- Flûte soprano Moeck hérable.
- Synthétiseur Général Music S3
Problème de son flash, wine, skype etc... sans pulseaudio
En enlevant pulseaudio, je me suis trouvé face à un problème bête, les applications comme flash, wine, skype et autres qui n'utilisent que pulseaudio n'avaient plus de son. en fouillant les forums, j'ai trouvé cette solution qui fonctionne très bien chez moi: en utilisant les paquets snd_aloop et alsa_in/alsa_out (en version pré-compilés) et un script python fait par falkTX (
la source de tout ça). Je joins mon asoundrc et le script:
Explications:
ATTENTION, si ce script python est lancé avec zita ou pulseaudio actifs, ceux-ci seront tués, je n'ai pas fait de tests mais je pense qu'il n'est pas compatible avec les modules jack pour pulseaudio. De plus, toutes les entrées/sorties alsa_in/out déjà présentes sont fermées.
- Les applications comme flash, wine, skype, etc... devront être réglées sur l'interface alsa virtuelle aloop pour fonctionner et non pas directement sur la carte son de alsa.
- Un petite explication du fonctionnement (si j'ai tout bien compris): Les applications qui normalement utilisent pulseaudio pour le son, lorsque celui-ci n'est plus là, se connectent directement à alsa (via gstreamer). Et, lorsque jack est lancé, il occupe pleinement la carte son. Les flux audio des applications arrivent donc vers une carte qui n'est plus disponible. Le principe est donc de créer une interface virtuelle qui récupère ces flux (grâce à snd_aloop) et les redirigent vers des entrées/sorties disponibles dans jack (alsa_in/out). L’intérêt du script python réside dans la multitude de vérifications qu'il effectue avant d'activer les interfaces. Si jack n'est pas lancé, le script le lance. En cas de perte de jack, le script ferme toutes ses entrées/sorties proprement.
- Mon Jack est réglé avec une période de 64, en 48Khz, un période/tampon de 2. Ardour m'indique une latence de 1,3ms et je n'ai aucun Xrun. Il faut utiliser les même réglages dans le asoundrc que jack pour que ça fonctionne.
- J'utilise aussi alsa_in pour réinjecter l'entrée line de ma carte son intégrée (HDA intel 7.1) dans jack. Je lance cette connexion au besoin et après l’exécution du script. Pour l'instant, je n'ai eu aucun problème de désynchro à l'enregistrement. Je m'en sers uniquement pour éviter de jouer avec les câbles quand je veux enregistrer mon synthé externe qui est piloté en midi par rosegarden.
alsa_in
alsa_in -dhw:1 -j "gemS3"
asoundrc
[+]
asoundrc
# ------------------------------------------------------
# Custom asoundrc file for use with snd-aloop and JACK
# ------------------------------------------------------
# playback device
pcm.aloopPlayback {
type dmix
ipc_key 1
ipc_key_add_uid true
slave {
pcm "hw:Loopback,0,0"
format S32_LE
rate {
@func igetenv
vars [ JACK_SAMPLE_RATE ]
default 48000
}
period_size {
@func igetenv
vars [ JACK_PERIOD_SIZE ]
default 64
}
buffer_size 4096
}
}
# capture device
pcm.aloopCapture {
type dsnoop
ipc_key 2
ipc_key_add_uid true
slave {
pcm "hw:Loopback,0,1"
format S32_LE
rate {
@func igetenv
vars [ JACK_SAMPLE_RATE ]
default 48000
}
period_size {
@func igetenv
vars [ JACK_PERIOD_SIZE ]
default 64
}
buffer_size 4096
}
}
# duplex device
pcm.aloopDuplex {
type asym
playback.pcm "aloopPlayback"
capture.pcm "aloopCapture"
}
# ------------------------------------------------------
# default device
pcm.!default {
type plug
slave.pcm "aloopDuplex"
}
# ------------------------------------------------------
# alsa_in -j alsa_in -dcloop -q 1
pcm.cloop {
type dsnoop
ipc_key 3
ipc_key_add_uid true
slave {
pcm "hw:Loopback,1,0"
format S32_LE
rate {
@func igetenv
vars [ JACK_SAMPLE_RATE ]
default 48000
}
period_size {
@func igetenv
vars [ JACK_PERIOD_SIZE ]
default 64
}
buffer_size 4096
}
}
# ------------------------------------------------------
# alsa_out -j alsa_out -dploop -q 1
pcm.ploop {
type plug
slave {
pcm "hw:Loopback,1,1"
}
}
Le script pyhton
[+]
script python aloop vers jack
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Imports (Global)
from ctypes import *
from os import system
from sys import version_info
from signal import signal, SIGINT, SIGTERM
from time import sleep
# --------------------------------------------------
# Test for python 3.x
if (version_info >= (3,0)):
PYTHON3 = True
else:
PYTHON3 = False
# --------------------------------------------------
# Global loop check
global doLoop, doRunNow
doLoop = True
doRunNow = True
# --------------------------------------------------
# Global JACK variables
global sample_rate, buffer_size
sample_rate = 48000
buffer_size = 4096
# --------------------------------------------------
# JACK ctypes implementation
jacklib = cdll.LoadLibrary("libjack.so.0")
class jack_client_t(Structure):
_fields_ = []
jack_nframes_t = c_uint32
JackBufferSizeCallback = CFUNCTYPE(c_int, jack_nframes_t, c_void_p)
JackShutdownCallback = CFUNCTYPE(None, c_void_p)
jacklib.jack_client_open.argtypes = [c_char_p, c_int, POINTER(c_int)]
jacklib.jack_client_open.restype = POINTER(jack_client_t)
jacklib.jack_client_close.argtypes = [POINTER(jack_client_t)]
jacklib.jack_client_close.restype = c_int
jacklib.jack_activate.argtypes = [POINTER(jack_client_t)]
jacklib.jack_activate.restype = c_int
jacklib.jack_deactivate.argtypes = [POINTER(jack_client_t)]
jacklib.jack_deactivate.restype = c_int
jacklib.jack_connect.argtypes = [POINTER(jack_client_t), c_char_p, c_char_p]
jacklib.jack_connect.restype = c_int
jacklib.jack_get_sample_rate.argtypes = [POINTER(jack_client_t)]
jacklib.jack_get_sample_rate.restype = jack_nframes_t
jacklib.jack_get_buffer_size.argtypes = [POINTER(jack_client_t)]
jacklib.jack_get_buffer_size.restype = jack_nframes_t
jacklib.jack_on_shutdown.argtypes = [POINTER(jack_client_t), JackShutdownCallback, c_void_p]
jacklib.jack_on_shutdown.restype = None
jacklib.jack_set_buffer_size_callback.argtypes = [POINTER(jack_client_t), JackBufferSizeCallback, c_void_p]
jacklib.jack_set_buffer_size_callback.restype = c_int
def jack_client_open(client_name, options, status):
if (PYTHON3): client_name = client_name.encode("ascii")
return jacklib.jack_client_open(client_name, options, status)
def jack_client_close(client):
return jacklib.jack_client_close(client)
def jack_activate(client):
return jacklib.jack_activate(client)
def jack_deactivate(client):
return jacklib.jack_deactivate(client)
def jack_connect(client, source_port, destination_port):
if (PYTHON3): source_port = source_port.encode("ascii")
if (PYTHON3): destination_port = destination_port.encode("ascii")
return jacklib.jack_connect(client, source_port, destination_port)
def jack_get_sample_rate(client):
return jacklib.jack_get_sample_rate(client)
def jack_get_buffer_size(client):
return jacklib.jack_get_buffer_size(client)
def jack_on_shutdown(client, shutdown_callback, arg):
global _shutdown_callback
_shutdown_callback = JackShutdownCallback(shutdown_callback)
jacklib.jack_on_shutdown(client, _shutdown_callback, arg)
def jack_set_buffer_size_callback(client, bufsize_callback, arg):
global _bufsize_callback
_bufsize_callback = JackBufferSizeCallback(bufsize_callback)
return jacklib.jack_set_buffer_size_callback(client, _bufsize_callback, arg)
# --------------------------------------------------
# quit on SIGINT or SIGTERM
def signal_handler(sig, frame=0):
global doLoop
doLoop = False
# --------------------------------------------------
# listen to jack buffer size changes
def buffer_size_callback(new_buffer_size, arg):
global doRunNow, buffer_size
buffer_size = new_buffer_size
doRunNow = True
return 0
# --------------------------------------------------
# listen to jack shutdown
def shutdown_callback(arg):
global doLoop
doLoop = False
# --------------------------------------------------
# run alsa_in and alsa_out
def run_alsa_bridge():
global sample_rate, buffer_size
system("killall alsa_in alsa_out zita-a2j zita-j2a pulseaudio")
#if (False):
system("env JACK_SAMPLE_RATE=%i JACK_PERIOD_SIZE=%i alsa_in -j alsa2jack -d cloop -q 1 2>&1 1> /dev/null &" % (sample_rate, buffer_size))
system("env JACK_SAMPLE_RATE=%i JACK_PERIOD_SIZE=%i alsa_out -j jack2alsa -d ploop -q 1 2>&1 1> /dev/null &" % (sample_rate, buffer_size))
#else:
#system("env JACK_SAMPLE_RATE=%i JACK_PERIOD_SIZE=%i zita-a2j -j alsa2jack -d hw:Loopback,1,0 -r 44100 &" % (sample_rate, buffer_size))
#system("env JACK_SAMPLE_RATE=%i JACK_PERIOD_SIZE=%i zita-j2a -j jack2alsa -d hw:Loopback,1,1 -r 44100 &" % (sample_rate, buffer_size))
# Pause it for a bit, and connect to the system ports
sleep(1)
jack_connect(client, "alsa2jack:capture_1", "system:playback_1")
jack_connect(client, "alsa2jack:capture_2", "system:playback_2")
jack_connect(client, "system:capture_1", "jack2alsa:playback_1")
jack_connect(client, "system:capture_2", "jack2alsa:playback_2")
#--------------- main ------------------
if __name__ == '__main__':
# Init JACK client
client = jack_client_open("jack-aloop-daemon", 0, None)
if (not client):
quit()
jack_set_buffer_size_callback(client, buffer_size_callback, None)
jack_on_shutdown(client, shutdown_callback, None)
jack_activate(client)
# Quit when requested
signal(SIGINT, signal_handler)
signal(SIGTERM, signal_handler)
# Get initial values
sample_rate = jack_get_sample_rate(client)
buffer_size = jack_get_buffer_size(client)
# Keep running until told otherwise
while (doLoop):
if (doRunNow):
doRunNow = False
run_alsa_bridge()
sleep(1)
# Close JACK client
jack_deactivate(client)
jack_client_close(client)