I am making a hearing aid application in flutter for those who can't hear properly, idea is sound that microphone get user can change its frequency, pitch other settings using slider or something else, and the speaker play that audio with processed settings, issue i am facing is flutter first record audio then play it how i make it that it directly play audio from microphone to speaker, speaker could be of mobile/headset.
I am expecting to play audio along with microphone one.
import 'dart:async';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_sound/flutter_sound.dart';
import 'package:permission_handler/permission_handler.dart';
class VoiceChanger extends StatefulWidget {
@override
_VoiceChangerState createState() => _VoiceChangerState();
}
class _VoiceChangerState extends State<VoiceChanger> {
late final StreamController<Uint8List> _audioStreamController;
FlutterSoundRecorder? _recorder;
FlutterSoundPlayer? _player;
bool isRecording = false;
bool isPlayingBack = false;
@override
void initState() {
super.initState();
_recorder = FlutterSoundRecorder();
_player = FlutterSoundPlayer();
_audioStreamController = StreamController<Uint8List>();
initAudio();
}
Future<void> initAudio() async {
await _recorder!.openRecorder();
await _player!.openPlayer();
await _player!.setVolume(1.0);
}
Future<void> startRecording() async {
if (await Permission.microphone.request().isGranted) {
// Start recording to a stream
await _recorder!.startRecorder(
toStream: _audioStreamController.sink,
codec: Codec.pcm16,
);
// Listen to the stream and play audio data in real-time
_audioStreamController.stream.listen((data) async {
// Ensure playback continues smoothly
if (!isPlayingBack) {
isPlayingBack = true;
await _player!.startPlayer(
fromDataBuffer: data,
codec: Codec.pcm16,
whenFinished: () {
isPlayingBack = false; // Set playing flag to false when finished
},
);
} else {
// Feed the new audio data to the player without interruption
await _player!.feedFromStream(data);
}
});
setState(() {
isRecording = true;
});
} else {
print("Microphone permission is not granted");
}
}
Future<void> stopRecording() async {
await _recorder!.stopRecorder();
setState(() {
isRecording = false;
isPlayingBack = false; // Stop playback
});
}
@override
void dispose() {
_recorder?.closeRecorder();
_player?.closePlayer();
_audioStreamController.close(); // Ensure stream is closed
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Voice Changer'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: isRecording ? stopRecording : startRecording,
child: Text(isRecording ? 'Stop Recording' : 'Start Recording'),
),
],
),
),
);
}
}