Skip to content

Commit

Permalink
Upgrade audio logic + fix subdivisions
Browse files Browse the repository at this point in the history
  • Loading branch information
SwadicalRag committed Jan 2, 2021
1 parent daadaf2 commit ab995b0
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 46 deletions.
1 change: 1 addition & 0 deletions lib/controllers/muonproject.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class MuonProjectController extends GetxController {
final selectedNotes = Map<MuonNoteController,bool>().obs;
final playheadTime = 0.0.obs;
List<MuonNote> copiedNotes = [];
final internalStatus = "idle".obs;

// subdivision manager
final currentSubdivision = 1.obs;
Expand Down
7 changes: 5 additions & 2 deletions lib/controllers/muonvoice.dart
Original file line number Diff line number Diff line change
Expand Up @@ -144,15 +144,18 @@ class MuonVoiceController extends GetxController {
}

AudioPlayer audioPlayer;
Future<AudioPlayer> getAudioPlayer() async {
int audioPlayerDuration = 0;
Future<AudioPlayer> getAudioPlayer([Duration playPos]) async {
final voiceID = project.voices.indexOf(this);
if(audioPlayer == null) {
audioPlayer = new AudioPlayer(id: voiceID);
}

await audioPlayer.unload();
final suc = await audioPlayer.load(project.getProjectFilePath("audio/" + voiceID.toString() + "_voice_world.wav"));

audioPlayer.setPosition(Duration(seconds: 2));
audioPlayerDuration = (await audioPlayer.getDuration()).inMilliseconds;
audioPlayer.setPosition(playPos ?? Duration(seconds: 2));

if(!suc) {
audioPlayer = null;
Expand Down
121 changes: 101 additions & 20 deletions lib/editor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,62 @@ class MuonEditor extends StatefulWidget {
class _MuonEditorState extends State<MuonEditor> {
bool _firstTimeSetupDone = false;

Future<void> _playAudio() async {
if(currentProject.internalStatus.value != "idle") {return;}

final playPos = Duration(
milliseconds: 2000 +
(
1000 *
(
currentProject.playheadTime.value /
(currentProject.bpm.value / 60)
)
).floor()
);
for(final voice in currentProject.voices) {
if(voice.audioPlayer != null) {
await voice.audioPlayer.unload();
}

currentProject.internalStatus.value = "compiling";
await voice.makeLabels();
await voice.runNeutrino();
await voice.vocodeWORLD();

final audioPlayer = await voice.getAudioPlayer(playPos);

await audioPlayer.setPosition(playPos);
final suc = await audioPlayer.play();

if(suc) {
currentProject.internalStatus.value = "playing";
}
else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(backgroundColor: Theme.of(context).errorColor,
content: new Text('Unable to play audio!'),
duration: new Duration(seconds: 5),
)
);
}
}
}

Future<void> _stopAudio() async {
for(final voice in currentProject.voices) {
if(voice.audioPlayer != null) {
voice.audioPlayer.unload();
if(currentProject.internalStatus.value == "playing") {
currentProject.internalStatus.value = "idle";
}
else {
currentProject.playheadTime.value = 0;
}
}
}
}

@override
Widget build(BuildContext context) {
final settings = getMuonSettings();
Expand All @@ -37,9 +93,17 @@ class _MuonEditorState extends State<MuonEditor> {

if(voice != null) {
if(voice.audioPlayer != null) {
if(voice.audioPlayer.isPlaying) {
int voicePos = (await voice.audioPlayer.getPosition()).inMilliseconds - 2000;
currentProject.playheadTime.value = voicePos / 1000 * (currentProject.bpm / 60);
if(currentProject.internalStatus.value == "playing") {
int curPos = (await voice.audioPlayer.getPosition()).inMilliseconds;

if(curPos >= voice.audioPlayerDuration) {
currentProject.playheadTime.value = 0;
currentProject.internalStatus.value = "idle";
}
else {
int voicePos = curPos - 2000;
currentProject.playheadTime.value = voicePos / 1000 * (currentProject.bpm / 60);
}
}
}
}
Expand Down Expand Up @@ -137,28 +201,37 @@ class _MuonEditorState extends State<MuonEditor> {
title: Text("Muon Editor"),
actions: [
IconButton(
icon: const Icon(Icons.exposure_plus_1),
tooltip: "Add subdivision",
onPressed: () {
currentProject.setSubdivision(currentProject.currentSubdivision.value + 1);
},
),
IconButton(
icon: const Icon(Icons.exposure_minus_1),
tooltip: "Subtract subdivision",
onPressed: () {
currentProject.setSubdivision(max(1,currentProject.currentSubdivision.value - 1));
},
),
SizedBox(width: 40,),
Obx(() => IconButton(
icon: const Icon(Icons.play_arrow),
tooltip: "Play",
onPressed: () async {
for(final voice in currentProject.voices) {
await voice.makeLabels();
await voice.runNeutrino();
await voice.vocodeWORLD();

final audioPlayer = await voice.getAudioPlayer();

final suc = await audioPlayer.play();

if(suc) {
}
}
color: currentProject.internalStatus.value == "compiling" ?
Colors.yellow :
currentProject.internalStatus.value == "playing" ?
Colors.green :
Colors.white,
onPressed: () {
_playAudio();
},
),
)),
IconButton(
icon: const Icon(Icons.stop),
tooltip: "Stop",
onPressed: () {

_stopAudio();
},
),
SizedBox(width: 40,),
Expand Down Expand Up @@ -379,8 +452,8 @@ class _MuonEditorState extends State<MuonEditor> {
final deltaSemiTones = (pianoRoll.painter.screenPixelsToSemitones(mousePos.y - mouseFirstPos.y) + fpDeltaSemiTones).floor();

final fpDeltaBeats = (pianoRoll.painter.getBeatNumAtCursor(mouseFirstPos.x) % 1);
final deltaBeats = pianoRoll.painter.screenPixelsToBeats(mousePos.x - mouseFirstPos.x) + fpDeltaBeats / currentProject.currentSubdivision.value;
final deltaSegments = deltaBeats * currentProject.currentSubdivision.value;
final deltaBeats = pianoRoll.painter.screenPixelsToBeats(mousePos.x - mouseFirstPos.x) + fpDeltaBeats / currentProject.timeUnitsPerBeat.value;
final deltaSegments = deltaBeats * currentProject.timeUnitsPerBeat.value;
final deltaSegmentsFixed = deltaSegments.floor();

for(final selectedNote in currentProject.selectedNotes.keys) {
Expand Down Expand Up @@ -537,6 +610,14 @@ class _MuonEditorState extends State<MuonEditor> {
// dumb hack to force repaint
pianoRoll.state.setState(() {});
}
else if(keyEvent.isKeyPressed(LogicalKeyboardKey.space)) {
if(currentProject.internalStatus.value == "playing") {
_stopAudio();
}
else {
_playAudio();
}
}
},
))
),
Expand Down
40 changes: 20 additions & 20 deletions lib/pianoroll.dart
Original file line number Diff line number Diff line change
Expand Up @@ -514,9 +514,9 @@ class PianoRollPainter extends CustomPainter {

for (final voice in project.voices) {
for (final note in voice.notes) {
var noteX = note.startAtTime * pixelsPerBeat / project.currentSubdivision.value;
var noteX = note.startAtTime * pixelsPerBeat / project.timeUnitsPerBeat.value;
var noteY = pitchToYAxis(note);
var noteW = note.duration * pixelsPerBeat / project.currentSubdivision.value;
var noteW = note.duration * pixelsPerBeat / project.timeUnitsPerBeat.value;
var noteH = 20;

if ((noteX < canvasPos.x) &&
Expand All @@ -532,9 +532,9 @@ class PianoRollPainter extends CustomPainter {
}

Rect getNoteRect(MuonNoteController note) {
var noteL = note.startAtTime * pixelsPerBeat / project.currentSubdivision.value;
var noteL = note.startAtTime * pixelsPerBeat / project.timeUnitsPerBeat.value;
var noteT = pitchToYAxis(note);
var noteR = noteL + (note.duration * pixelsPerBeat / project.currentSubdivision.value);
var noteR = noteL + (note.duration * pixelsPerBeat / project.timeUnitsPerBeat.value);
var noteB = noteT + 20;

return Rect.fromLTRB(noteL, noteT, noteR, noteB);
Expand Down Expand Up @@ -673,43 +673,43 @@ class PianoRollPainter extends CustomPainter {
if(themeData.brightness == Brightness.dark) {
canvas.drawRect(
Rect.fromLTWH(
note.startAtTime * pixelsPerBeat / project.currentSubdivision.value,
note.startAtTime * pixelsPerBeat / project.timeUnitsPerBeat.value,
pitchToYAxis(note),
note.duration * pixelsPerBeat / project.currentSubdivision.value,
note.duration * pixelsPerBeat / project.timeUnitsPerBeat.value,
20),
Paint()..color = Colors.white);
canvas.drawRect(
Rect.fromLTWH(
note.startAtTime * pixelsPerBeat / project.currentSubdivision.value,
note.startAtTime * pixelsPerBeat / project.timeUnitsPerBeat.value,
pitchToYAxis(note),
note.duration * pixelsPerBeat / project.currentSubdivision.value,
note.duration * pixelsPerBeat / project.timeUnitsPerBeat.value,
20),
Paint()..color = noteColor.withOpacity(0.75));
}
else {
canvas.drawRect(
Rect.fromLTWH(
note.startAtTime * pixelsPerBeat / project.currentSubdivision.value,
note.startAtTime * pixelsPerBeat / project.timeUnitsPerBeat.value,
pitchToYAxis(note),
note.duration * pixelsPerBeat / project.currentSubdivision.value,
note.duration * pixelsPerBeat / project.timeUnitsPerBeat.value,
20),
Paint()..color = noteColor.withOpacity(0.5));
}
canvas.drawRect(
Rect.fromLTWH(
note.startAtTime * pixelsPerBeat / project.currentSubdivision.value + xBorderThickness / xScale,
note.startAtTime * pixelsPerBeat / project.timeUnitsPerBeat.value + xBorderThickness / xScale,
pitchToYAxis(note) + yBorderThickness / yScale,
note.duration * pixelsPerBeat / project.currentSubdivision.value - xBorderThickness / xScale * 2,
note.duration * pixelsPerBeat / project.timeUnitsPerBeat.value - xBorderThickness / xScale * 2,
20 - yBorderThickness / yScale * 2),
Paint()..color = noteColor);
}
else {
if(themeData.brightness == Brightness.light) {
canvas.drawRect(
Rect.fromLTWH(
note.startAtTime * pixelsPerBeat / project.currentSubdivision.value,
note.startAtTime * pixelsPerBeat / project.timeUnitsPerBeat.value,
pitchToYAxis(note),
note.duration * pixelsPerBeat / project.currentSubdivision.value,
note.duration * pixelsPerBeat / project.timeUnitsPerBeat.value,
20),
Paint()..color = noteColor);
}
Expand All @@ -718,16 +718,16 @@ class PianoRollPainter extends CustomPainter {
final yBorderThickness = 0;
canvas.drawRect(
Rect.fromLTWH(
note.startAtTime * pixelsPerBeat / project.currentSubdivision.value,
note.startAtTime * pixelsPerBeat / project.timeUnitsPerBeat.value,
pitchToYAxis(note),
note.duration * pixelsPerBeat / project.currentSubdivision.value + xBorderThickness / xScale,
note.duration * pixelsPerBeat / project.timeUnitsPerBeat.value + xBorderThickness / xScale,
20),
Paint()..color = Colors.black);
canvas.drawRect(
Rect.fromLTWH(
note.startAtTime * pixelsPerBeat / project.currentSubdivision.value + xBorderThickness / xScale,
note.startAtTime * pixelsPerBeat / project.timeUnitsPerBeat.value + xBorderThickness / xScale,
pitchToYAxis(note) + yBorderThickness / yScale,
note.duration * pixelsPerBeat / project.currentSubdivision.value - xBorderThickness / xScale,
note.duration * pixelsPerBeat / project.timeUnitsPerBeat.value - xBorderThickness / xScale,
20 - (yBorderThickness / yScale * 2)),
Paint()..color = noteColor.withOpacity(0.95));
}
Expand All @@ -752,7 +752,7 @@ class PianoRollPainter extends CustomPainter {
tp.paint(
canvas,
new Offset(
(note.startAtTime * pixelsPerBeat / project.currentSubdivision.value +
(note.startAtTime * pixelsPerBeat / project.timeUnitsPerBeat.value +
xOffset +
pianoKeysWidth / xScale +
20) *
Expand Down Expand Up @@ -850,7 +850,7 @@ class PianoRollPainter extends CustomPainter {
// draw "what am i looking at?" (waila)
if(curMousePos != null) {
final mouseBeatNum = max(0,getBeatNumAtCursor(curMousePos.x));
final mouseBeatSubDivNum = (mouseBeatNum * project.currentSubdivision.value).floor() % project.currentSubdivision.value + 1;
final mouseBeatSubDivNum = (mouseBeatNum * project.timeUnitsPerBeat.value).floor() % project.timeUnitsPerBeat.value + 1;
final mouseMeasureNum = (mouseBeatNum / project.beatsPerMeasure.value).ceil();
final mousePitch = getPitchAtCursor(curMousePos.y);
var wailaLabelPainter = new TextPainter(
Expand Down
6 changes: 3 additions & 3 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -267,9 +267,9 @@ packages:
flutter_audio_desktop:
dependency: "direct main"
description:
name: flutter_audio_desktop
url: "https://pub.dartlang.org"
source: hosted
path: "../flutter_audio_desktop"
relative: true
source: path
version: "0.0.8"
flutter_driver:
dependency: transitive
Expand Down
3 changes: 2 additions & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ dependencies:
get: ^3.24.0
kana_kit: ^1.0.4
path: ^1.7.0
flutter_audio_desktop: ^0.0.8
flutter_audio_desktop:
path: ../flutter_audio_desktop

dev_dependencies:
flutter_test:
Expand Down

0 comments on commit ab995b0

Please sign in to comment.