9
votes

Annulation d'écho acoustique en Java

Je suis en train de mettre en œuvre une application VoIP utilisant Pure Java. Il y a un problème d'écho qui se produit lorsque les utilisateurs n'utilisent pas de casques de tête (principalement sur les ordinateurs portables avec des microphones intégrés).

Qu'est-ce qui arrive actuellement

Les écrous et les boulons du L'application VoIP n'est que des données de données simples du cadre multimédia de Java. Essentiellement, j'aimerais effectuer un traitement du signal numérique sur les données audio avant que je l'écrive au haut-parleur pour la sortie. xxx

Comme vous pouvez voir les données audio arrive et est Enquassue dans un tampon. Ceci est nécessaire pour répondre aux connexions dodgy et permettre de différentes tailles de paquets. Cela signifie également que j'ai accès à autant de données audio que nécessaire pour toutes les opérations DSP fantaisie avant de jouer les données audio à la ligne de haut-parleurs.

J'ai géré un cancelleur d'écho qui fonctionne, mais elle Nécessit de nombreuses entrées d'utilisateur interactives et j'aimerais avoir un cancelleur d'écho automatique.

Annuille manuel d'écho manuel xxx

Filtres adaptatifs

J'ai lu que Filtres adaptatifs sont la voie à suivre. Plus précisément, un filtre des carrés moins significatifs. Cependant, je suis coincé. La plupart des échantillons de code pour ce qui précède sont en C et C ++ et ils ne se traduisent pas bien en Java.

Est-ce que quelqu'un a des conseils sur la manière de les implémenter en Java? Toute autre idée serait également grandement appréciée. Merci d'avance.


1 commentaires

J'ai trouvé ce guide d'annulation d'écho acoustique très très utile jusqu'à présent: andreadrian.de/echo_cancel/index. HTML


4 Réponses :


1
votes

Ceci est une zone très complexe et pour obtenir une solution AEC utilisable fonctionner, vous aurez besoin de faire un peu de R & D. Tous les bons AEC sont exclusifs et il y a un lot plus à l'annulation de l'écho que de simplement mettre en œuvre un filtre adaptatif tel que LMS. Je vous suggère de développer votre algorithme d'annulation d'écho initialement à l'aide de Matlab (ou d'octave) - lorsque vous avez quelque chose qui semble fonctionner de manière raisonnable avec des télécommunications «Real World», vous pouvez mettre en œuvre l'algorithme en C et le test / l'évaluer en temps réel. Une fois que cela fonctionne, vous pouvez utiliser JNI pour appeler la mise en œuvre C à partir de Java.


2 commentaires

Merci pour la réponse. J'essaie d'éviter d'utiliser Jni mais d'avoir assez désespéré pour essayer n'importe quoi.


Vous constaterez peut-être que vous devez faire des choses spécifiques à la plate-forme dans votre AEC, par exemple. Les appels d'API d'OS / audio à bas niveau, de sorte que cela pourrait aussi bien être C + JNI.



4
votes

Au cas où n'importe qui est intéressé, j'ai réussi à construire un cancelleur d'écho de travail équitable en convertissant essentiellement le Annulation d'écho acoustique Méthode mentionné par Paul R < / a> qui utilise un algorithme carré des moyens normalisés et quelques filtres de C en Java. La route JNI est probablement toujours une meilleure façon d'aller, mais j'aime bien m'appuyer sur Pure Java si possible. En voyant comment leurs filtres fonctionnent et lisent une grande affaire sur les filtres sur Tutor DSP , j'ai réussi à Gagnez un certain contrôle sur la quantité de bruit retirée et comment éliminer les hautes fréquences, etc.

quelques conseils:

  1. Gardez à l'esprit ce que vous retirez de l'endroit. Je devais passer cela autour de plusieurs fois.
  2. La variable la plus importante de cette méthode est le taux de convergence. Ceci est la variable appelée étamé dans le code de la liaison ci-dessus.
  3. J'ai pris les composants individuels une à la fois, a compris ce qu'ils ont fait, les ont construits et les ont testés séparément. Par exemple, j'ai pris le détecteur de double talk et l'a testé pour que cela fonctionne. Ensuite, j'ai suivi les filtres un par un et les a testés sur des fichiers audio pour vous assurer qu'ils ont fonctionné, puis j'ai pris la partie normalisée des moyens carrés et la testait avant de la mettre tous ensemble.

    J'espère que cela aide quelqu'un d'autre!


0 commentaires

4
votes

Utilisez le Speex aec . C'est une source ouverte, elle est écrite en C (utilisez-la avec JNI), et cela fonctionne. J'en ai utilisé avec succès dans 2 applications VoIP différentes et gagne la majeure partie de l'écho annulée.


3 commentaires

salut pouvez-vous me guider comment annuler echo .Je me lutter pour le faire fonctionner


Vous pouvez me contacter dans l'e-mail écrit dans mon profil. Ce n'est pas quelque chose à résumer dans un poste.


@Sirknigget Comment installer la vitesse?



5
votes

Ça fait des âges! J'espère que c'est même la bonne classe, mais vous y allez:

/**
 * This filter performs a pre-whitening Normalised Least Means Square on an
 * array of bytes. This does the actual echo cancelling.
 * 
 * Echo cancellation occurs with the following formula:
 * 
 * e = d - X' * W
 * 
 * e represents the echo-free signal. d represents the actual microphone signal
 * with the echo. X' is the transpose of the loudspeaker signal. W is an array
 * of adaptive weights.
 * 
 */
public class cNormalisedLeastMeansSquareFilter
  implements IFilter
{
  private byte[] m_ayEchoFreeSignal;// e
  private byte[] m_ayEchoSignal;// d
  private byte[] m_ayTransposeOfSpeakerSignal;// X'
  private double[] m_adWeights;// W

  /**
   * The transpose and the weights need to be updated before applying the filter
   * to an echo signal again.
   * 
   * @param ayEchoSignal
   * @param ayTransposeOfSpeakerSignal
   * @param adWeights
   */
  public cNormalisedLeastMeansSquareFilter(byte[] ayEchoSignal, byte[] ayTransposeOfSpeakerSignal, double[] adWeights)
  {
    m_ayEchoSignal = ayEchoSignal;
    m_ayTransposeOfSpeakerSignal = ayTransposeOfSpeakerSignal;
    m_adWeights = adWeights;
  }

  @Override
  public byte[] applyFilter(byte[] ayAudioBytes)
  {
    // e = d - X' * W
    m_ayEchoFreeSignal = new byte[ayAudioBytes.length];
    for (int i = 0; i < m_ayEchoFreeSignal.length; ++i)
    {
      m_ayEchoFreeSignal[i] = (byte) (m_ayEchoSignal[i] - m_ayTransposeOfSpeakerSignal[i] * m_adWeights[i]);
    }
    return m_ayEchoFreeSignal;
  }


2 commentaires

Vous auriez préférable d'ajouter ce code à votre réponse d'origine que de poster une nouvelle réponse.


Comment intégrer cette pièce de code avec mon projet existant dans lequel j'encore un fichier RAW aux données PCM, puis le fichier PCM est codé sur le fichier .spx. J'utilise jspeex.jar pour cela.