flutter_echo 0.0.1
flutter_echo: ^0.0.1 copied to clipboard
A Flutter package to open Echo for just_audio. You can also create a custom Echo for Android.dart
example/example.dart
import 'package:audio_session/audio_session.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_echo/flutter_echo.dart';
import 'package:just_audio/just_audio.dart';
import 'package:rxdart/rxdart.dart';
class AudioPlayerScreen extends StatefulWidget {
final String? path;
const AudioPlayerScreen({Key? key, this.path}) : super(key: key);
@override
AudioPlayerScreenState createState() => AudioPlayerScreenState();
}
class AudioPlayerScreenState extends State<AudioPlayerScreen>
with WidgetsBindingObserver {
late final AudioPlayer _player = AudioPlayer( );
late final AudioPlayer _player2 = AudioPlayer();
late final AudioPlayer _player3 = AudioPlayer();
@override
void initState() {
super.initState();
ambiguate(WidgetsBinding.instance)!.addObserver(this);
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
statusBarColor: Colors.black,
));
_init();
}
Future<void> _init() async {
final session = await AudioSession.instance;
await session.configure(const AudioSessionConfiguration.speech());
try {
await _player.setFilePath(widget.path ?? "");
await _player2.setFilePath(widget.path ?? "");
if (showEcho == false) _player2.setVolume(0.0);
setState(() {});
await _player3.setFilePath(widget.path ?? "");
if (showEcho == false) _player3.setVolume(0.0);
setState(() {});
print("player 4 duration ..........${_player3.duration!.inMilliseconds.toString()}");
} catch (e) {
print("Error loading audio source: $e");
}
}
@override
void dispose() {
ambiguate(WidgetsBinding.instance)!.removeObserver(this);
_player.dispose();
_player2.dispose();
_player3.dispose();
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.paused) {
_player.stop();
_player2.stop();
_player3.stop();
}
}
///--- you need to install rxdart: ^0.27.7 for this seasion
Stream<PositionData> get _positionDataStream =>
Rx.combineLatest3<Duration, Duration, Duration?, PositionData>(
_player.positionStream,
_player.bufferedPositionStream,
_player3 .durationStream,
(position, bufferedPosition, duration) => PositionData(
position, bufferedPosition, duration ?? Duration.zero));
var showEqualizer = false;
var showLoudness = false;
var showEcho = false;
bool audio5Loading= false;
String audioAsset = "assets/audio/mixrobotic.mp3";
String audioAsset2 = "assets/audio/bip.mp3";
var audioOnePitch = 0.0;
var audioTwoPitch = 0.0;
var audioThreePitch = 0.0;
var audioFourPitch = 0.0;
var audioFivePitch = 0.0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Audio Player"),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
SwitchListTile(
title: const Text('Apply Echo'),
value: showEcho,
onChanged: (value) {
// _loudnessEnhancer.setEnabled(value);
showEcho = value;
setState(() {});
},
),
if (showEcho)
Column(
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Row(
children: [
Expanded(
child: StreamBuilder<double>(
stream: _player.speedStream,
builder: (context, snapshot) {
return GestureDetector(
onTap: () {
showSliderDialog(
context: context,
title: "Adjust speed",
divisions: 270,
min: 0.3,
max: 3.0,
value: _player.speed,
stream: _player.speedStream,
onChanged: (value) {
setState(() {
_player.setSpeed(value);
});
});
},
child: Column(
children: [
Text("${snapshot.data?.toStringAsFixed(1)}x",
style: const TextStyle(
fontWeight: FontWeight.bold)),
const Text("Audio 1 Speed",
style: TextStyle(
fontSize: 12, fontWeight: FontWeight.bold)),
],
),
);
}),
),
const SizedBox(
width: 10,
height: 30,
child: VerticalDivider(
color: Colors.red,
),
),
Expanded(
child: StreamBuilder<double>(
stream: _player.pitchStream,
builder: (context, snapshot) {
return GestureDetector(
onTap: () {
showSliderDialog(
context: context,
title: "Adjust pitch",
divisions: 47,
min: 0.3,
max: 5.0,
value: _player.pitch,
stream: _player.pitchStream,
onChanged: (value) {
setState(() {
_player.setPitch(value);
});
});
},
child: Column(
children: [
Text("${snapshot.data?.toStringAsFixed(1)}x",
style:
const TextStyle(fontWeight: FontWeight.bold)),
const Text("Audio 1 Pitch",
style: TextStyle(
fontSize: 12, fontWeight: FontWeight.bold)),
],
),
);
},
),
),
const SizedBox(
width: 10,
height: 30,
child: VerticalDivider(
color: Colors.red,
),
),
Expanded(
child: StreamBuilder<double>(
stream: _player.volumeStream,
builder: (context, snapshot) => IconButton(
icon: Text(
"v1 vol is ${snapshot.data?.toStringAsFixed(1)}x",
style: const TextStyle(fontWeight: FontWeight.bold)),
onPressed: () {
showSliderDialog(
context: context,
title: "v2 vol",
divisions: 10,
min: 0.0,
max: 1.0,
value: showEcho ? _player.volume : 0.0,
stream: _player.volumeStream,
onChanged: _player.setVolume,
);
},
),
),
),
///---vol
],
),
Row(
children: [
Expanded(
child: StreamBuilder<double>(
stream: _player2.speedStream,
builder: (context, snapshot) {
return GestureDetector(
onTap: () {
showSliderDialog(
context: context,
title: "Adjust speed",
divisions: 270,
min: 0.3,
max: 3.0,
value: _player2.speed,
stream: _player2.speedStream,
onChanged: (value) {
setState(() {
_player2.setSpeed(value);
});
});
},
child: Column(
children: [
Text("${snapshot.data?.toStringAsFixed(1)}x",
style: const TextStyle(
fontWeight: FontWeight.bold)),
const Text("Audio 2 Speed",
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold)),
],
),
);
}),
),
const SizedBox(
width: 10,
height: 30,
child: VerticalDivider(
color: Colors.red,
),
),
Expanded(
child: StreamBuilder<double>(
stream: _player2.pitchStream,
builder: (context, snapshot) {
return GestureDetector(
onTap: () {
showSliderDialog(
context: context,
title: "Adjust pitch",
divisions: 47,
min: 0.3,
max: 5.0,
value: _player2.pitch,
stream: _player2.pitchStream,
onChanged: (value) {
setState(() {
_player2.setPitch(value);
});
});
},
child: Column(
children: [
Text("${snapshot.data?.toStringAsFixed(1)}x",
style: const TextStyle(
fontWeight: FontWeight.bold)),
const Text("Audio 2 Pitch",
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold)),
],
),
);
},
),
),
const SizedBox(
width: 10,
height: 30,
child: VerticalDivider(
color: Colors.red,
),
),
Expanded(
child: StreamBuilder<double>(
stream: _player2.volumeStream,
builder: (context, snapshot) => IconButton(
icon: Text(
"v2 vol is ${snapshot.data?.toStringAsFixed(1)}x",
style:
const TextStyle(fontWeight: FontWeight.bold)),
onPressed: () {
showSliderDialog(
context: context,
title: "v2 vol",
divisions: 10,
min: 0.0,
max: 1.0,
value: showEcho ? _player2.volume : 0.0,
stream: _player2.volumeStream,
onChanged: _player2.setVolume,
);
},
),
),
),
///---vol
],
),
Row(
children: [
Expanded(
child: StreamBuilder<double>(
stream: _player3.speedStream,
builder: (context, snapshot) {
return GestureDetector(
onTap: () {
showSliderDialog(
context: context,
title: "Adjust speed",
divisions: 270,
min: 0.3,
max: 3.0,
value: _player3.speed,
stream: _player3.speedStream,
onChanged: (value) {
setState(() {
_player3.setSpeed(value);
});
});
},
child: Column(
children: [
Text("${snapshot.data?.toStringAsFixed(1)}x",
style: const TextStyle(
fontWeight: FontWeight.bold)),
const Text("Audio 3 Speed",
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold)),
],
),
);
}),
),
const SizedBox(
width: 10,
height: 30,
child: VerticalDivider(
color: Colors.red,
),
),
Expanded(
child: StreamBuilder<double>(
stream: _player3.pitchStream,
builder: (context, snapshot) {
return GestureDetector(
onTap: () {
showSliderDialog(
context: context,
title: "Adjust pitch",
divisions: 47,
min: 0.3,
max: 5.0,
value: _player3.pitch,
stream: _player3.pitchStream,
onChanged: (value) {
setState(() {
_player3.setPitch(value);
});
});
},
child: Column(
children: [
Text("${snapshot.data?.toStringAsFixed(1)}x",
style: const TextStyle(
fontWeight: FontWeight.bold)),
const Text("Audio 3 Pitch",
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold)),
],
),
);
},
),
),
const SizedBox(
width: 10,
height: 30,
child: VerticalDivider(
color: Colors.red,
),
),
Expanded(
child: StreamBuilder<double>(
stream: _player3.volumeStream,
builder: (context, snapshot) => IconButton(
icon: Text(
"v3 vol is ${snapshot.data?.toStringAsFixed(1)}x",
style:
const TextStyle(fontWeight: FontWeight.bold)),
onPressed: () {
showSliderDialog(
context: context,
title: "v3 vol",
divisions: 10,
min: 0.0,
max: 1.0,
value: showEcho ? _player3.volume : 0.0,
stream: _player3.volumeStream,
onChanged: _player3.setVolume,
);
},
),
),
),
],
),
],
),
Row(
children: [
ControlButtons(_player, _player2, _player3,
showEcho: showEcho),
Expanded(
child: StreamBuilder<PositionData>(
stream: _positionDataStream,
builder: (context, snapshot) {
final positionData = snapshot.data;
return SeekBar(
duration: positionData?.duration ?? Duration.zero,
position: positionData?.position ?? Duration.zero,
bufferedPosition:
positionData?.bufferedPosition ?? Duration.zero,
onChangeEnd: (duration) {
_player.seek(duration);
_player2.seek(duration);
_player3.seek(duration);
// _player5.seek(duration);
},
);
},
),
),
],
),
]),);
}
}
class ControlButtons extends StatelessWidget {
final AudioPlayer player;
final bool? showEcho;
final AudioPlayer player2;
final AudioPlayer player3;
const ControlButtons(
this.player,
this.player2,
this.player3,
{
Key? key,
this.showEcho = false,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
StreamBuilder<PlayerState>(
stream: player.playerStateStream,
builder: (context, snapshot) {
final playerState = snapshot.data;
final processingState = playerState?.processingState;
final playing = playerState?.playing;
if (processingState == ProcessingState.loading ||
processingState == ProcessingState.buffering) {
return Container(
margin: const EdgeInsets.all(8.0),
width: 64.0,
height: 64.0,
child: const CircularProgressIndicator(),
);
} else if (playing != true) {
return IconButton(
icon: const Icon(Icons.play_arrow),
iconSize: 64.0,
onPressed: () {
player.play();
// if (showEcho ?? false) {
player2.play();
player3.play();
// }
});
} else if (processingState != ProcessingState.completed) {
return IconButton(
icon: const Icon(Icons.pause),
iconSize: 64.0,
onPressed: () {
player.pause();
// if (showEcho ?? false) {
player2.pause();
player3.pause();
},
);
} else {
player.stop();
return IconButton(
icon: const Icon(Icons.replay),
iconSize: 64.0,
onPressed: () {
player.seek(Duration.zero);
// if (showEcho ?? false) {
player2.seek(Duration.zero);
player3.seek(Duration.zero);
player.play();
// }
},
);
}
},
),
],
);
}
}