Gemischte Aufnahme - wie Echo unterdrücken?



  • Ich habe ein mp3 via text-to-speech erzeugt, das programmierbare Pausen zum Nachsprechen lässt. Wenn dieses mp3 nun abgespielt wird, kann der Nutzer das Gesagte nachsprechen oder darauf antworten. Zur Kontrolle kann das Gesamte, also mp3 und eigene Mikrofonaufnahme als gemischte Aufnahme (auch mp3) aufgezeichnet werden. Das klappt auch alles prächtig. Nur hört man beim Sprechen die eigene Sprache als Echo. Ich habe bisher keinen funktionierenden Weg gefunden dieses Echo (Monitoring) zu unterdrücken. In Windows ist es beim Mikrophon ausgeschaltet. Hier sind die beiden Funktionen zum Starten und Stoppen:

    using NAudio.CoreAudioApi;
    using NAudio.Lame;
    using NAudio.Mixer;
    using NAudio.Wave;
    using NAudio.Wave.SampleProviders;
    
    private bool mp3Generated = false;
    private CheckBox chkRecord;
    private Label lblRecording;
    private WaveInEvent? micIn;
    private BufferedWaveProvider? micBuffer;
    private IWavePlayer? mixPlayer;                     // spielt das Gemisch ab
    private WaveFileWriter? repetitionWriter;
    private WasapiOut? ttsOutput;                       // Keine direkte Ausgabe mehr an Default Device
    private AudioFileReader? audioReader;
    private WaveOutEvent? player;
    
    private void StartRecording(string playbackFile, string repetitionFile)
    {
        try
        {
            StopRecording(); // Vorher aufräumen
    
            if (!File.Exists(playbackFile))
            {
                MessageBox.Show($"Playback file not found: {playbackFile}");
                return;
            }
    
            // --- TTS vorbereiten
            var reader = new AudioFileReader(playbackFile); // liest Output.mp3
            var ttsProvider = EnsureMono44100(reader);
    
            // --- Mikrofon vorbereiten
            micIn = new WaveInEvent
            {
                WaveFormat = new WaveFormat(44100, 16, 1),
                BufferMilliseconds = 50
            };
            micBuffer = new BufferedWaveProvider(micIn.WaveFormat)
            {
                DiscardOnBufferOverflow = true
            };
            micIn.DataAvailable += (s, a) => micBuffer.AddSamples(a.Buffer, 0, a.BytesRecorded);
            micIn.StartRecording();
    
            var micProvider = micBuffer.ToSampleProvider(); // Mono float 44.1k
    
            // --- Mixer aus TTS + Mikro
            var mixer = new MixingSampleProvider(new[] { ttsProvider, micProvider })
            {
                ReadFully = true
            };
    
            // --- WAV-Datei zum Schreiben
            repetitionWriter = new WaveFileWriter(repetitionFile, WaveFormat.CreateIeeeFloatWaveFormat(44100, 1));
    
            // --- Tap für gleichzeitiges Schreiben
            var tap = new TapSampleProvider(mixer, repetitionWriter);
    
            // --- TTS AUSGABE ohne Monitoring
            ttsOutput = new WasapiOut(AudioClientShareMode.Shared, false, 100); // false = kein Loopback
            ttsOutput.Init(tap);
            ttsOutput.Play();
    
            lblRecording.Visible = true;
            btnPause.Enabled = false;
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error during recording: " + ex.Message);
            StopRecording();
        }
    }
    
    private void StopRecording()
    {
        try
        {
            micIn?.StopRecording();
            micIn?.Dispose();
            micIn = null;
    
            mixPlayer?.Stop();
            mixPlayer?.Dispose();
            mixPlayer = null;
    
            repetitionWriter?.Flush();
            repetitionWriter?.Dispose();
            repetitionWriter = null;
    
            micBuffer = null;
    
            lblRecording.Visible = false;
            btnPause.Enabled = true;
    
            // WAV → MP3
            string wavPath = "Output_Repetition.wav";
            string mp3Path = "Output_Repetition.mp3";
            if (File.Exists(wavPath))
            {
                using (var reader = new AudioFileReader(wavPath))
                using (var writer = new LameMP3FileWriter(mp3Path, reader.WaveFormat, LAMEPreset.VBR_90))
                {
                    reader.CopyTo(writer);
                }
    
                File.Delete(wavPath); // WAV löschen
            }
    
            lblFertig.Text = "Recording finished: Output_Repetition.mp3";
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error stopping recording:\n" + ex);
        }
    }
    

    Ich habe es sogar mit ChatGPT-4o und -5 versucht. Dabei wird jedoch die gemischte Aufnahme kaputt gemacht. Offenbar nicht ganz trivial.



  • Hört man dieses Echo nur bei der gemischten Aufnahme oder auch, wenn nur vom Mikrofon aufgenommen wird?

    Edit: Ansonsten mal nach "acoustic echo cancellation (AEC)" suchen - ich selber habe bisher keine direkten C#-Komponenten im Netz gefunden.



  • @Th69 sagte in Gemischte Aufnahme - wie Echo unterdrücken?:

    Ohne vorhandenes Output.mp3 kann man nicht aufnehmen.

    Es gibt noch einen Micro-Test:

    private void BtnMicTest_Click(object? sender, EventArgs e)
    {
        var micTest = new WaveInEvent
        {
            WaveFormat = new WaveFormat(44100, 1),
            BufferMilliseconds = 100
        };
    
        var writer = new WaveFileWriter("MicOnly.wav", micTest.WaveFormat);
    
        micTest.DataAvailable += (s, args) =>
        {
            writer.Write(args.Buffer, 0, args.BytesRecorded);
        };
    
        micTest.RecordingStopped += (s, args) =>
        {
            writer.Dispose();
            micTest.Dispose();
            MessageBox.Show("Mic test finished. File saved: MicOnly.wav");
        };
    
        micTest.StartRecording();
    
        // nach 5 Sekunden automatisch stoppen
        Task.Delay(5000).ContinueWith(_ =>
        {
            micTest.StopRecording();
        });
    }
    

    Dabei gibt es kein Echo. Vielleicht eine Möglichkeit, wenn man es sauber synchronisiert.
    Das Problem ist wohl gleichzeitiges Abspielen und Aufnehmen.


Anmelden zum Antworten