Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: AutoGain filter #12

Merged
merged 30 commits into from
Dec 21, 2024
Merged

feat: AutoGain filter #12

merged 30 commits into from
Dec 21, 2024

Conversation

alnitak
Copy link
Owner

@alnitak alnitak commented Nov 26, 2024

Description

New autoGain filter for #7

  • The loopback.dart example uses flutter_soloud to play audio back to the device from the microphone data stream. Please try it with a headset to prevent audio feedback.
  • I do not have much experience in testing filter efficiency. To start please read the filter doc to know parameters meanings.
  • No web support yet. Web supported.
  • The Echo Cancellation feat: Echo Cancellation #5 code is not yet ready and I don't know if it will be!

Breaking change:

  • the init method is now async
  • FilterType renamed to RecorderFilterType
  • an additional script must be added for the web platform. Now it looks like:
    <script src="assets/packages/flutter_recorder/web/libflutter_recorder_plugin.js" defer></script>
    <script src="assets/packages/flutter_recorder/web/init_recorder_module.dart.js" defer></script>
    

Closes #14

Type of Change

  • ✨ New feature (non-breaking change which adds functionality)
  • 🛠️ Bug fix (non-breaking change which fixes an issue)
  • ❌ Breaking change (fix or feature that would cause existing functionality to change)
  • 🧹 Code refactor
  • ✅ Build configuration change
  • 📝 Documentation
  • 🗑️ Chore

@alnitak alnitak self-assigned this Nov 26, 2024
@alnitak alnitak changed the title feat: AutoGain filter feat: AutoGain filter #7 Nov 26, 2024
@alnitak alnitak changed the title feat: AutoGain filter #7 feat: AutoGain filter Nov 26, 2024
@alnitak alnitak mentioned this pull request Nov 26, 2024
1 task
@CillianMyles
Copy link

@alnitak thanks for the web support, I'm looking into it. I have added you plugin to internal builds and I hope to have some feedback for you next week! 👍

@CillianMyles
Copy link

I got an exception on web checking if a device was initialised:

TypeError: Cannot read properties of undefined (reading '_isInited')
packages/flutter_recorder/src/bindings/recorder_web.dart 178:38                              isDeviceInitialized
packages/flutter_recorder/src/flutter_recorder.dart 239:38                                   isDeviceInitialized

These checks work fine on IO platforms. Here is the code for ref:

  void _initRecordingDevice() {
    if (!_flutterRecorder.isDeviceInitialized()) {
      _flutterRecorder.init(
        format: PCMFormat.s16le,
        sampleRate: 16000,
        channels: RecorderChannels.mono,
      );
    }
    _startRecordingDevice();
  }

  void _startRecordingDevice() {
    if (!_flutterRecorder.isDeviceStarted()) {
      _flutterRecorder.start();
    }
    if (!_flutterRecorder.filters.autoGainFilter.isActive) {
      _flutterRecorder.filters.autoGainFilter.activate();
    }
  }

  void _stopRecordingDevice() {
    if (_flutterRecorder.filters.autoGainFilter.isActive) {
      _flutterRecorder.filters.autoGainFilter.deactivate();
    }
    if (_flutterRecorder.isDeviceStarted()) {
      _flutterRecorder.stop();
    }
  }

  void _disposeRecordingDevice() {
    _stopRecordingDevice();
    if (_flutterRecorder.isDeviceInitialized()) {
      _flutterRecorder.deinit();
    }
  }

@alnitak
Copy link
Owner Author

alnitak commented Dec 13, 2024

Thanks @CillianMyles, I forgot some checks!

FYI now the init doesn't throw when already initialized. It just displays a log message. Ie the if (!_flutterRecorder.isDeviceStarted()) is no more needed.

Also, the logs are managed by package:logging, so you can initialize it like this:

import 'dart:developer' as dev;
import 'package:logging/logging.dart';

void main() async {
  // The `flutter_recorder` package logs everything
  // (from severe warnings to fine debug messages)
  // using the standard `package:logging`.
  // You can listen to the logs as shown below.
  Logger.root.level = kDebugMode ? Level.FINE : Level.INFO;
  Logger.root.onRecord.listen((record) {
    dev.log(
      record.message,
      time: record.time,
      level: record.level.value,
      name: record.loggerName,
      zone: record.zone,
      error: record.error,
      stackTrace: record.stackTrace,
    );
  });

  runApp(MyApp());
}

@CillianMyles
Copy link

Great news about the logging 🎉


I am now running into a number of other errors:

TypeError: Cannot read properties of undefined (reading '_isFilterActive')
packages/flutter_recorder/src/bindings/recorder_web.dart 290:12                              isFilterActive
packages/flutter_recorder/src/flutter_recorder.dart 429:28                                   isFilterActive
NoSuchMethodError: tried to call a non-function, such as null: 'dart.global.RecorderModule'
packages/flutter_recorder/src/bindings/js_extension.dart 21:21
TypeError: Cannot read properties of undefined (reading '_malloc')
packages/flutter_recorder/src/bindings/recorder_web.dart 113:22                 listCaptureDevices
packages/flutter_recorder/src/flutter_recorder.dart 188:33                      listCaptureDevices

@alnitak
Copy link
Owner Author

alnitak commented Dec 16, 2024

I am now running into a number of other errors:

I see. After changing the WASM module it must be initialized asynchronously somewhere. I chose to initialize it in the init method, so some other method calls don't work if the init has not yet been called.

I have to think about moving that initialization somewhere else! I'll update you

@alnitak
Copy link
Owner Author

alnitak commented Dec 17, 2024

The only safe way I found to initialize the WASM module is to do it in a JS script! So it should be added in the index.html alongside the recorder JS:

<script src="assets/packages/flutter_recorder/web/libflutter_recorder_plugin.js" defer></script>
<script src="assets/packages/flutter_recorder/web/init_recorder_module.dart.js" defer></script>

Two little breaking changes have been added also:

  • the init method is now async
  • FilterType renamed to RecorderFilterType

Hope it's all fine now and you can try the autogain also on the web and thanks for your patience!

@CillianMyles
Copy link

Thanks for the continued fixes 🙏

Latest:

TypeError: Cannot read properties of undefined (reading '_createWorkerInWasm')
packages/flutter_recorder/src/bindings/recorder_web.dart 41:5

Which is happening during init()

@alnitak
Copy link
Owner Author

alnitak commented Dec 17, 2024

Ouch! That should not happen after adding init_recorder_module.dart.js in the index.html. That .js should expose all the methods, _createWorkerInWasm included!

With Firefox and Chrome, it doesn't happen to me. Maybe moving those <script> in the <head> instead of the <body> tag?

@alnitak alnitak marked this pull request as ready for review December 21, 2024 09:54
@alnitak alnitak merged commit 6be4d32 into main Dec 21, 2024
1 check passed
@CillianMyles
Copy link

CillianMyles commented Jan 3, 2025

Hey @alnitak 👋

Happy new year 🎉

Apologies for the delay in getting back to you here.

The automatic gain seems to be working well. I will come back to you if I find any issues.

Thanks you for the great work 🙏

@alnitak
Copy link
Owner Author

alnitak commented Jan 3, 2025

I'm glad it worked, thanks for letting me know and happy new year to you too!

@alnitak alnitak deleted the autogain branch January 3, 2025 11:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Error (Xcode): Undefined symbol: _AVAudioSessionCategoryAmbient
2 participants