startCapture method

Future<void> startCapture({
  1. MicAudioConfig? config,
})

Starts capturing audio from the microphone.

This method will request necessary permissions (microphone permission) and begin capturing audio from the default or configured microphone.

config is optional. If provided, it will update the current configuration before starting capture.

Throws an Exception if:

  • Permissions are not granted
  • No microphone is available
  • Capture fails to start

Example:

final capture = MicAudioCapture();

try {
  await capture.startCapture(
    config: MicAudioConfig(
      sampleRate: 44100,
      channels: 1,
      gainBoost: 2.5,
    ),
  );
  print('Microphone capture started');
} catch (e) {
  print('Failed to start: $e');
}

Implementation

Future<void> startCapture({MicAudioConfig? config}) async {
  if (_isRecording) {
    return;
  }

  if (config != null) {
    updateConfig(config);
  }

  try {
    await requestPermissions();

    try {
      final result = await _channel.invokeMethod<dynamic>(
        _MicAudioMethod.startCapture.name,
        _config.toMap(),
      );

      if (result is! bool || result != true) {
        final errorMsg = result is String
            ? result
            : 'Failed to start microphone capture. Returned: $result';
        throw Exception(errorMsg);
      }
    } on PlatformException catch (e) {
      throw Exception(
          'Failed to start microphone capture: ${e.message ?? e.code}');
    }

    // Create audio stream
    // Note: Stream will be subscribed by listeners, which triggers onListen on native side
    _audioStream = _audioStreamChannel.receiveBroadcastStream().map((
      dynamic event,
    ) {
      if (event is Uint8List) {
        return event;
      } else if (event is List<int>) {
        return Uint8List.fromList(event);
      }
      throw Exception('Unexpected audio data type: ${event.runtimeType}');
    });

    // Create decibel stream
    _decibelStream = _decibelStreamChannel.receiveBroadcastStream().map((
      dynamic event,
    ) {
      if (event is Map) {
        return DecibelData.fromMap(Map<String, dynamic>.from(event));
      }
      return DecibelData(
          decibel: -120.0,
          timestamp: DateTime.now().millisecondsSinceEpoch / 1000.0);
    });

    // Status stream is created lazily via getter, no need to recreate here

    _isRecording = true;
  } catch (e) {
    rethrow;
  }
}