112 lines
3.2 KiB
Dart
112 lines
3.2 KiB
Dart
// lib/services/audio_handler.dart
|
|
|
|
import 'dart:async';
|
|
import 'dart:typed_data';
|
|
import 'package:flutter_audio_capture/flutter_audio_capture.dart';
|
|
import 'package:encrypt/encrypt.dart' as encrypt;
|
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
|
|
|
class AudioHandler {
|
|
final FlutterAudioCapture _audioCapture = FlutterAudioCapture();
|
|
final FlutterSecureStorage _secureStorage = FlutterSecureStorage();
|
|
StreamController<Uint8List> _audioStreamController = StreamController.broadcast();
|
|
Timer? _delayTimer;
|
|
final int delaySeconds = 3;
|
|
|
|
// Encryption variables
|
|
encrypt.Encrypter? _encrypter;
|
|
encrypt.Key? _key;
|
|
bool _isEncryptionEnabled = false;
|
|
|
|
// Buffer for delay
|
|
List<Uint8List> _buffer = [];
|
|
|
|
// Constructor
|
|
AudioHandler();
|
|
|
|
// Start listening to the microphone
|
|
Future<void> startListening() async {
|
|
await _audioCapture.start(_onAudioData, _onError, sampleRate: 44100, bufferSize: 3000);
|
|
|
|
// Initialize the delay timer
|
|
_delayTimer = Timer.periodic(Duration(seconds: delaySeconds), (_) {
|
|
if (_buffer.isNotEmpty) {
|
|
// Replay the audio
|
|
Uint8List replayData = _buffer.removeAt(0);
|
|
_audioStreamController.add(replayData);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Stop listening
|
|
Future<void> stopListening() async {
|
|
await _audioCapture.stop();
|
|
_delayTimer?.cancel();
|
|
_buffer.clear();
|
|
}
|
|
|
|
// Stream for UI to listen and replay audio
|
|
Stream<Uint8List> get audioStream => _audioStreamController.stream;
|
|
|
|
// Callback for audio data
|
|
void _onAudioData(dynamic obj) async {
|
|
Uint8List data = Uint8List.fromList(obj.cast<int>());
|
|
|
|
// Encrypt the data if encryption is enabled
|
|
if (_isEncryptionEnabled && _encrypter != null) {
|
|
final iv = encrypt.IV.fromSecureRandom(12); // Use a proper IV in production
|
|
final encrypted = _encrypter!.encryptBytes(data, iv: iv);
|
|
data = encrypted.bytes;
|
|
}
|
|
|
|
// Add data to buffer for delayed replay
|
|
_buffer.add(data);
|
|
|
|
// Optionally, you can handle encrypted data here
|
|
// For example, send it over the network or save to a file
|
|
}
|
|
|
|
// Error handling
|
|
void _onError(Object e) {
|
|
print('Audio Capture Error: $e');
|
|
}
|
|
|
|
// Enable encryption
|
|
Future<void> enableEncryption() async {
|
|
if (_isEncryptionEnabled) return;
|
|
|
|
// Check if key exists
|
|
String? storedKey = await _secureStorage.read(key: 'encryption_key');
|
|
if (storedKey == null) {
|
|
// Generate a new key
|
|
final newKey = _generateSecureKey();
|
|
await _secureStorage.write(key: 'encryption_key', value: newKey);
|
|
_key = encrypt.Key.fromUtf8(newKey);
|
|
} else {
|
|
_key = encrypt.Key.fromUtf8(storedKey);
|
|
}
|
|
|
|
_encrypter = encrypt.Encrypter(
|
|
encrypt.AES(
|
|
_key!,
|
|
mode: encrypt.AESMode.gcm,
|
|
padding: null,
|
|
),
|
|
);
|
|
_isEncryptionEnabled = true;
|
|
}
|
|
|
|
// Disable encryption
|
|
void disableEncryption() {
|
|
_encrypter = null;
|
|
_isEncryptionEnabled = false;
|
|
}
|
|
|
|
// Generate a secure key
|
|
String _generateSecureKey() {
|
|
// Implement a secure random key generator
|
|
// For demonstration, using a fixed key (DO NOT use in production)
|
|
return 'my32lengthsupersecretnooneknows1'; // 32 chars for AES-256
|
|
}
|
|
}
|