2017-04-18 5 views
2

Je cherche un moyen de transférer des données audio à partir d'un fichier dans le microphone, donc lorsque des applications tierces (telles que arecord ou la fonction de recherche vocale de Chromium) utilisent le microphone pour l'entrée audio, ils reçoivent les données audio du fichier à la place.Fichier audio de canal Linux vers l'entrée microphone

Voici mon scénario: Une application que j'ai écrite enregistre des données audio du microphone (en utilisant ALSA) et les enregistre dans un fichier (audioFile0.raw). À un moment indéterminé dans le futur, une application tierce inconnue (comme dans, quelque chose que je n'ai pas développé et que je n'ai pas le contrôle du développement, comme la fonctionnalité "search by voice" du navigateur web Chromium) obtenir des données audio. Je voudrais que les données audio que l'application tierce rassemble proviennent d'audioFile.raw plutôt que le microphone lui-même. Je pensais s'il était possible de changer le périphérique d'entrée audio par défaut en un fichier audio, ou peut-être un tuyau nommé et faire quelque chose comme cat audioFile0.raw > mypipe (puisque je ne sais pas quand une autre application va essayer de lire à partir du microphone). Peut-être y a-t-il une façon plus simple de le faire?

J'espère avoir fourni assez de détails et de clarté. S'il vous plaît laissez-moi savoir si quelque chose n'est pas clair.


EDIT: Je compris comment faire un microphone virtuel en créant le fichier .asoundrc suivant dans mon répertoire:

pcm.!virtmic { 
    type file 
    slave.pcm "hw:0,0" 
    file /dev/null 
    infile "/home/charles/audioFiles/audioFile0.raw" 
} 

pcm.!default { 
    type hw 
    card 0 
} 

ctl.!default { 
    type hw 
    card 0 
} 

je puis appeler arecord test.raw -c 1 -f S16_LE -r 16000 -t raw -D virtmic de la ligne de commande et Je suis en mesure d'enregistrer les données audio qui est en audioFile0.raw à test.raw. Mon objectif est maintenant de remplacer le périphérique par défaut par mon microphone virtuel de sorte que toute application accédant au microphone lira les données audio au audioFile0.raw au lieu du microphone lui-même. Donc, j'ai édité mon fichier .asoundrc à apparaître comme suit:

pcm.!virtmic { 
    type file 
    slave.pcm "hw:0,0" 
    file /dev/null 
    infile "/home/charles/audioFiles/audioFile0.raw" 
} 

pcm.!default { 
    type asym 
    playback.pcm { 
     type hw 
     card 0 
    } 
    capture.pcm { 
     type plug 
     slave.pcm "virtmic" 
    } 
} 

ctl.!default { 
    type hw 
    card 0 
} 

Alors j'ai appelé arecord test.raw -c 1 -f S16_LE -r 16000 -t raw de la ligne de commande. Je ai ensuite joué test.raw mais il semblait enregistrer à partir du microphone lui-même et non audioFile0.raw.

Qu'est-ce que je fais mal? Comment exactement changer le périphérique de capture par défaut afin qu'il lise les données de audioFile0.raw plutôt que l'entrée du microphone?


EDIT 2: Ok, donc j'étais sur la bonne voie. J'utilise le même fichier .asoundrc dans mon répertoire personnel que j'ai montré plus tôt où j'ai changé le périphérique par défaut pour être le virtmic. Je avais besoin de modifier le fichier /usr/share/alsa/alsa.conf.d/pulse.conf il ressemble à ceci:

# PulseAudio alsa plugin configuration file to set the pulseaudio plugin as 
# default output for applications using alsa when pulseaudio is running. 
hook_func.pulse_load_if_running { 
    lib "libasound_module_conf_pulse.so" 
    func "conf_pulse_hook_load_if_running" 
} 

@hooks [ 
    { 
     func pulse_load_if_running 
     files [ 
#   "/usr/share/alsa/pulse-alsa.conf" 
      "/home/charles/.asoundrc" 
     ] 
     errors false 
    } 
] 

La seule chose que j'ai été commenter la ligne "/usr/share/alsa/pulse-alsa.conf" et remplacée par "/home/charles/.asoundrc" de sorte que le plug-in PulseAudio n'est pas la valeur par défaut pour les applications utilisant ALSA, mais utilisez plutôt mon micro virtuel par défaut. Ce n'est peut-être pas la meilleure solution, mais cela fonctionne.

Cela a fonctionné quand j'ai fait arecord test.raw -t raw -c 1 -f S16_LE -r 16000.Il a obtenu les données de audiofile0.raw au lieu du microphone! J'ai utilisé la commande lsof /dev/snd/* pour voir ce qui était exactement l'accès au périphérique audio pendant que la commande arecord était en cours d'exécution. La sortie est la suivante:

COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME 
pulseaudi 2044 charles 22u CHR 116,6  0t0 8977 /dev/snd/controlC0 
pulseaudi 2044 charles 29u CHR 116,6  0t0 8977 /dev/snd/controlC0 
arecord 4051 charles mem CHR 116,5   8976 /dev/snd/pcmC0D0c 
arecord 4051 charles 4u CHR 116,5  0t0 8976 /dev/snd/pcmC0D0c 

J'ai ensuite essayé en utilisant la fonction « recherche vocale » du navigateur Chrome et vu que je ne pouvais pas le faire enregistrer à partir audioFile0.raw. J'ai ensuite utilisé lsof /dev/snd/* pour voir ce qui était exactement l'accès au périphérique audio.

COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME 
pulseaudi 2044 charles mem CHR 116,5   8976 /dev/snd/pcmC0D0c 
pulseaudi 2044 charles 22u CHR 116,6  0t0 8977 /dev/snd/controlC0 
pulseaudi 2044 charles 29u CHR 116,6  0t0 8977 /dev/snd/controlC0 
pulseaudi 2044 charles 30r CHR 116,33  0t0 7992 /dev/snd/timer 
pulseaudi 2044 charles 31u CHR 116,5  0t0 8976 /dev/snd/pcmC0D0c 

Je vois qu'ils ont tous le même PID 2044. Ils utilisent tous le démon PulseAudio, ne passe pas par ALSA. Comment est-ce que pulseaudio peut utiliser mon microphone virtuel par défaut de sorte que toutes les applications qui passent par pulseaudio pour l'entrée audio obtiennent à la place les données audio de mon fichier plutôt que le microphone?

+2

Possible duplication de [Sortie de tuyauterie d'aplay pour enregistrement en centos] (http://stackoverflow.com/questions/42843128/piping-output-from-aplay-to-arecord-in-centos) –

+0

@CL. Corrigez-moi si je me trompe, mais dans ce cas, il semble que l'application d'enregistrement soit connue (_arecord test.raw -r 8000 -t raw_). Dans mon cas, je n'ai aucun contrôle sur l'application qui va accéder au microphone. Je veux que toute application qui lit à partir du microphone pour lire à partir de mon fichier à la place. – cheerupcharlie

+1

Veuillez noter que cet appel 'arecord' ne spécifie pas de nom de périphérique et utilise le périphérique par défaut. (Et il est toujours possible pour un programme d'utiliser explicitement un nom de périphérique différent.) –

Répondre

5

Après de nombreuses heures laborieuses, j'ai finalement obtenu quelque chose d'acceptable. Je défais tout ce que j'ai fait avec ALSA (puisque la valeur par défaut est ALSA pour utiliser PulseAudio à la place, que j'ai initialement ignoré). J'ai créé un script bash simple install_virtmic.sh pour créer un "microphone virtuel" pour PulseAudio à utiliser, ainsi que les clients PulseAudio:

#!/bin/bash 

# This script will create a virtual microphone for PulseAudio to use and set it as the default device. 

# Load the "module-pipe-source" module to read audio data from a FIFO special file. 
echo "Creating virtual microphone." 
pactl load-module module-pipe-source source_name=virtmic file=/home/charles/audioFiles/virtmic format=s16le rate=16000 channels=1 

# Set the virtmic as the default source device. 
echo "Set the virtual microphone as the default device." 
pactl set-default-source virtmic 

# Create a file that will set the default source device to virtmic for all 
PulseAudio client applications. 
echo "default-source = virtmic" > /home/charles/.config/pulse/client.conf 

# Write the audio file to the named pipe virtmic. This will block until the named pipe is read. 
echo "Writing audio file to virtual microphone." 
while true; do 
    cat audioFile0.raw > /home/charles/audioFiles/virtmic 
done 

Un script rapide uninstall_virtmic.sh pour annuler tout ce que fait le script d'installation:

#!/bin/bash 

# Uninstall the virtual microphone. 

pactl unload-module module-pipe-source 
rm /home/charles/.config/pulse/client.conf 

J'ai ensuite allumé Chrome et cliqué sur le microphone pour utiliser sa fonction de recherche vocale et cela a fonctionné! J'ai également essayé avec arecord test.raw -t raw -f S16_LE -c 1 -r 16000 et cela a fonctionné aussi! Ce n'est pas parfait, parce que je continue à écrire dans le tube nommé virtmic dans une boucle infinie dans le script (ce qui a rapidement rendu mon fichier test.raw incroyablement grand), mais ça ira pour l'instant.

S'il vous plaît n'hésitez pas à me faire savoir si quelqu'un là-bas trouve une meilleure solution!