:drunk: Messing around werid stuff
This commit is contained in:
BIN
assets/midi/never-gonna-give-you-up.mid
Normal file
BIN
assets/midi/never-gonna-give-you-up.mid
Normal file
Binary file not shown.
@@ -1,7 +1,11 @@
|
|||||||
|
import 'dart:math' as math;
|
||||||
|
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:just_audio/just_audio.dart';
|
import 'package:just_audio/just_audio.dart';
|
||||||
import 'package:island/pods/config.dart';
|
import 'package:island/pods/config.dart';
|
||||||
import 'package:audio_session/audio_session.dart';
|
import 'package:audio_session/audio_session.dart';
|
||||||
|
import 'package:dart_midi_pro/dart_midi_pro.dart';
|
||||||
|
|
||||||
final sfxPlayerProvider = Provider<AudioPlayer>((ref) {
|
final sfxPlayerProvider = Provider<AudioPlayer>((ref) {
|
||||||
final player = AudioPlayer();
|
final player = AudioPlayer();
|
||||||
@@ -63,3 +67,110 @@ void playMessageSfx(WidgetRef ref) {
|
|||||||
if (!settings.soundEffects) return;
|
if (!settings.soundEffects) return;
|
||||||
_playSfx('assets/audio/messages.mp3', 0.75);
|
_playSfx('assets/audio/messages.mp3', 0.75);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MiniSampleSynth {
|
||||||
|
final String sampleAsset;
|
||||||
|
final int baseNote; // MIDI note of the sample (usually 72 = C5 for lower pitch playback)
|
||||||
|
|
||||||
|
AudioPlayer? currentPlayer;
|
||||||
|
|
||||||
|
MiniSampleSynth({required this.sampleAsset, this.baseNote = 72});
|
||||||
|
|
||||||
|
Future<void> playMidiAsset(String midiAsset) async {
|
||||||
|
final data = await rootBundle.load(midiAsset);
|
||||||
|
final midi = MidiParser().parseMidiFromBuffer(data.buffer.asUint8List());
|
||||||
|
|
||||||
|
for (final track in midi.tracks) {
|
||||||
|
int currentTick = 0;
|
||||||
|
|
||||||
|
for (final event in track) {
|
||||||
|
currentTick += event.deltaTime;
|
||||||
|
|
||||||
|
if (event is NoteOnEvent && event.velocity > 0) {
|
||||||
|
final note = event.noteNumber;
|
||||||
|
final durationTicks = _estimateDuration(track, event);
|
||||||
|
final durationMs = _ticksToMs(durationTicks, midi);
|
||||||
|
|
||||||
|
_scheduleNote(
|
||||||
|
note: note,
|
||||||
|
startMs: _ticksToMs(currentTick, midi),
|
||||||
|
durationMs: durationMs,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _scheduleNote({
|
||||||
|
required int note,
|
||||||
|
required int startMs,
|
||||||
|
required int durationMs,
|
||||||
|
}) {
|
||||||
|
Future.delayed(Duration(milliseconds: startMs), () async {
|
||||||
|
// Stop any currently playing note
|
||||||
|
if (currentPlayer != null) {
|
||||||
|
await currentPlayer!.stop();
|
||||||
|
await currentPlayer!.dispose();
|
||||||
|
currentPlayer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final player = AudioPlayer();
|
||||||
|
currentPlayer = player;
|
||||||
|
|
||||||
|
await player.setAudioSource(AudioSource.asset(sampleAsset));
|
||||||
|
final speed = _noteToSpeed(note);
|
||||||
|
await player.setSpeed(speed);
|
||||||
|
await player.play();
|
||||||
|
|
||||||
|
Future.delayed(Duration(milliseconds: durationMs), () async {
|
||||||
|
if (currentPlayer == player) {
|
||||||
|
await player.stop();
|
||||||
|
await player.dispose();
|
||||||
|
currentPlayer = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
double _noteToSpeed(int note) {
|
||||||
|
return math.pow(2, (note - baseNote) / 12).toDouble();
|
||||||
|
}
|
||||||
|
|
||||||
|
int _getTempo(MidiFile midi) {
|
||||||
|
for (var track in midi.tracks) {
|
||||||
|
for (var event in track) {
|
||||||
|
if (event is SetTempoEvent) {
|
||||||
|
return event.microsecondsPerBeat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 500000; // default 120 BPM
|
||||||
|
}
|
||||||
|
|
||||||
|
int _ticksToMs(int ticks, MidiFile midi) {
|
||||||
|
final tempo = _getTempo(midi);
|
||||||
|
final ticksPerBeat = midi.header.ticksPerBeat ?? 480;
|
||||||
|
|
||||||
|
return ((ticks * tempo) / ticksPerBeat / 1000).round();
|
||||||
|
}
|
||||||
|
|
||||||
|
int _estimateDuration(List<MidiEvent> track, NoteOnEvent on) {
|
||||||
|
int ticks = 0;
|
||||||
|
bool started = false;
|
||||||
|
|
||||||
|
for (final e in track) {
|
||||||
|
if (e == on) {
|
||||||
|
started = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!started) continue;
|
||||||
|
|
||||||
|
ticks += e.deltaTime;
|
||||||
|
|
||||||
|
if (e is NoteOffEvent && e.noteNumber == on.noteNumber) {
|
||||||
|
return ticks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 200; // fallback
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -204,9 +204,6 @@ PODS:
|
|||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- pasteboard (0.0.1):
|
- pasteboard (0.0.1):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- path_provider_foundation (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- FlutterMacOS
|
|
||||||
- PromisesObjC (2.4.0)
|
- PromisesObjC (2.4.0)
|
||||||
- PromisesSwift (2.4.0):
|
- PromisesSwift (2.4.0):
|
||||||
- PromisesObjC (= 2.4.0)
|
- PromisesObjC (= 2.4.0)
|
||||||
@@ -296,7 +293,6 @@ DEPENDENCIES:
|
|||||||
- media_kit_video (from `Flutter/ephemeral/.symlinks/plugins/media_kit_video/macos`)
|
- media_kit_video (from `Flutter/ephemeral/.symlinks/plugins/media_kit_video/macos`)
|
||||||
- package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`)
|
- package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`)
|
||||||
- pasteboard (from `Flutter/ephemeral/.symlinks/plugins/pasteboard/macos`)
|
- pasteboard (from `Flutter/ephemeral/.symlinks/plugins/pasteboard/macos`)
|
||||||
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
|
|
||||||
- protocol_handler_macos (from `Flutter/ephemeral/.symlinks/plugins/protocol_handler_macos/macos`)
|
- protocol_handler_macos (from `Flutter/ephemeral/.symlinks/plugins/protocol_handler_macos/macos`)
|
||||||
- record_macos (from `Flutter/ephemeral/.symlinks/plugins/record_macos/macos`)
|
- record_macos (from `Flutter/ephemeral/.symlinks/plugins/record_macos/macos`)
|
||||||
- screen_retriever_macos (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever_macos/macos`)
|
- screen_retriever_macos (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever_macos/macos`)
|
||||||
@@ -397,8 +393,6 @@ EXTERNAL SOURCES:
|
|||||||
:path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos
|
:path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos
|
||||||
pasteboard:
|
pasteboard:
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/pasteboard/macos
|
:path: Flutter/ephemeral/.symlinks/plugins/pasteboard/macos
|
||||||
path_provider_foundation:
|
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
|
|
||||||
protocol_handler_macos:
|
protocol_handler_macos:
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/protocol_handler_macos/macos
|
:path: Flutter/ephemeral/.symlinks/plugins/protocol_handler_macos/macos
|
||||||
record_macos:
|
record_macos:
|
||||||
@@ -476,7 +470,6 @@ SPEC CHECKSUMS:
|
|||||||
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
|
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
|
||||||
package_info_plus: f0052d280d17aa382b932f399edf32507174e870
|
package_info_plus: f0052d280d17aa382b932f399edf32507174e870
|
||||||
pasteboard: 278d8100149f940fb795d6b3a74f0720c890ecb7
|
pasteboard: 278d8100149f940fb795d6b3a74f0720c890ecb7
|
||||||
path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880
|
|
||||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||||
PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851
|
PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851
|
||||||
protocol_handler_macos: f9cd7b13bcaf6b0425f7410cbe52376cb843a936
|
protocol_handler_macos: f9cd7b13bcaf6b0425f7410cbe52376cb843a936
|
||||||
|
|||||||
@@ -417,6 +417,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.3.1"
|
version: "3.3.1"
|
||||||
|
dart_midi_pro:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: dart_midi_pro
|
||||||
|
sha256: "9a0273c92c0336e5694c7318fd936f64f06e938a936dd5fac6563c39954b7f6d"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.4+2"
|
||||||
dart_style:
|
dart_style:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -174,6 +174,7 @@ dependencies:
|
|||||||
video_thumbnail: ^0.5.6
|
video_thumbnail: ^0.5.6
|
||||||
just_audio: ^0.10.5
|
just_audio: ^0.10.5
|
||||||
audio_session: ^0.2.2
|
audio_session: ^0.2.2
|
||||||
|
dart_midi_pro: ^1.0.4+2
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
@@ -207,6 +208,7 @@ flutter:
|
|||||||
|
|
||||||
# To add assets to your application, add an assets section, like this:
|
# To add assets to your application, add an assets section, like this:
|
||||||
assets:
|
assets:
|
||||||
|
- assets/midi/
|
||||||
- assets/i18n/
|
- assets/i18n/
|
||||||
- assets/images/
|
- assets/images/
|
||||||
- assets/images/oidc/
|
- assets/images/oidc/
|
||||||
|
|||||||
Reference in New Issue
Block a user