initialize method
Future<int>
initialize(
{ - required int outputSampleRate,
})
override
Implementation
@override
Future<int> initialize({required int outputSampleRate}) async {
if (_isInitialized) {
return _inputSampleRate!;
}
_outputSampleRate = outputSampleRate;
try {
_audioContext = AudioContext();
_inputSampleRate = _audioContext!.sampleRate.toInt();
// Use native AudioContext mixing with GainNodes for volume control.
// Echo canceller monitors destination output, so all audio mixed here
// is included in the echo cancellation reference signal.
_voiceGainNode = _audioContext!.createGain();
_voiceGainNode!.gain.value = 1.0;
_voiceGainNode!.connect(_audioContext!.destination);
_backgroundGainNode = _audioContext!.createGain();
_backgroundGainNode!.gain.value = 0.3;
_backgroundGainNode!.connect(_audioContext!.destination);
_soundGainNode = _audioContext!.createGain();
_soundGainNode!.gain.value = 0.5;
_soundGainNode!.connect(_audioContext!.destination);
final mediaDevices = window.navigator.mediaDevices;
final audioConstraints =
{
'echoCancellation': true,
'noiseSuppression': true,
'autoGainControl': true,
}.jsify()
as JSObject;
final constraints = MediaStreamConstraints(audio: audioConstraints);
_mediaStream = await mediaDevices.getUserMedia(constraints).toDart;
final audioTracks = _mediaStream!.getAudioTracks().toDart;
if (audioTracks.isEmpty) {
throw Exception('No audio track available');
}
final track = audioTracks.first;
final settings = track.getSettings();
final settingsObj = settings as JSObject;
final echoCancellation = settingsObj.getProperty('echoCancellation'.toJS);
final hasEchoCancellation =
echoCancellation != null && (echoCancellation as JSBoolean).toDart;
final sinkId = settingsObj.getProperty('sinkId'.toJS);
final hasSinkId =
sinkId != null && (sinkId as JSString).toDart.isNotEmpty;
final hasHeadphones = hasSinkId;
if (!hasEchoCancellation && !hasHeadphones) {
await _cleanup();
throw Exception(
'Echo cancellation not available and no headphones connected',
);
}
await _setupMediaRecorder();
_isInitialized = true;
return _inputSampleRate!;
} catch (e) {
await _cleanup();
if (e.toString().contains('NotAllowedError') ||
e.toString().contains('Permission')) {
throw Exception('PERMISSION_DENIED');
}
rethrow;
}
}