1. Hinweis
Spiele sind audiovisuelle Erlebnisse. Flutter ist ein hervorragendes Tool zum Erstellen ansprechender visueller Elemente und einer soliden Benutzeroberfläche. Die fehlende Zutat ist Audio. In diesem Codelab erfahren Sie, wie Sie mit dem flutter_soloud
-Plug-in Ton und Musik mit niedriger Latenz in Ihr Projekt einbinden. Sie beginnen mit einem einfachen Gerüst, damit Sie direkt zu den interessanten Teilen springen können.
Sie können das Gelernte natürlich nicht nur für Spiele, sondern auch für Apps verwenden. Während fast alle Spiele Ton und Musik erfordern, ist das bei den meisten Apps nicht der Fall. Daher liegt der Schwerpunkt dieses Codelabs auf Spielen.
Vorbereitung
- Grundkenntnisse in Flutter
- Kenntnisse zum Ausführen und Entwickeln von Flutter-Apps
Lerninhalte
- Einmalig wiedergegebene Töne abspielen
- Musikschleifen ohne Pausen abspielen und anpassen
- So kannst du Geräusche ein- und ausblenden.
- So wenden Sie Umgebungseffekte auf Töne an.
- Umgang mit Ausnahmen
- Wie Sie alle diese Funktionen in einem einzigen Audiocontroller kapseln.
Voraussetzungen
- Das Flutter SDK
- Einen Code-Editor Ihrer Wahl
2. Einrichten
- Laden Sie die folgenden Dateien herunter. Keine Sorge, wenn Sie eine langsame Verbindung haben. Sie benötigen die Dateien später, sodass Sie sie während der Arbeit herunterladen können.
- Erstellen Sie ein Flutter-Projekt mit einem beliebigen Namen.
- Erstellen Sie im Projekt eine
lib/audio/audio_controller.dart
-Datei. - Geben Sie in die Datei den folgenden Code ein:
lib/audio/audio_controller.dart
import 'dart:async';
import 'package:logging/logging.dart';
class AudioController {
static final Logger _log = Logger('AudioController');
Future<void> initialize() async {
// TODO
}
void dispose() {
// TODO
}
Future<void> playSound(String assetKey) async {
_log.warning('Not implemented yet.');
}
Future<void> startMusic() async {
_log.warning('Not implemented yet.');
}
void fadeOutMusic() {
_log.warning('Not implemented yet.');
}
void applyFilter() {
// TODO
}
void removeFilter() {
// TODO
}
}
Wie Sie sehen, ist dies nur ein Skelett für zukünftige Funktionen. Wir werden das alles in diesem Codelab implementieren.
- Öffnen Sie als Nächstes die Datei
lib/main.dart
und ersetzen Sie den Inhalt durch den folgenden Code:
lib/main.dart
import 'dart:developer' as dev;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
import 'audio/audio_controller.dart';
void main() async {
// The `flutter_soloud` package logs everything
// (from severe warnings to fine debug messages)
// using the standard `package:logging`.
// You can listen to the logs as shown below.
Logger.root.level = kDebugMode ? Level.FINE : Level.INFO;
Logger.root.onRecord.listen((record) {
dev.log(
record.message,
time: record.time,
level: record.level.value,
name: record.loggerName,
zone: record.zone,
error: record.error,
stackTrace: record.stackTrace,
);
});
WidgetsFlutterBinding.ensureInitialized();
final audioController = AudioController();
await audioController.initialize();
runApp(MyApp(audioController: audioController));
}
class MyApp extends StatelessWidget {
const MyApp({required this.audioController, super.key});
final AudioController audioController;
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter SoLoud Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.brown),
),
home: MyHomePage(audioController: audioController),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.audioController});
final AudioController audioController;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
static const _gap = SizedBox(height: 16);
bool filterApplied = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Flutter SoLoud Demo')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
OutlinedButton(
onPressed: () {
widget.audioController.playSound('assets/sounds/pew1.mp3');
},
child: const Text('Play Sound'),
),
_gap,
OutlinedButton(
onPressed: () {
widget.audioController.startMusic();
},
child: const Text('Start Music'),
),
_gap,
OutlinedButton(
onPressed: () {
widget.audioController.fadeOutMusic();
},
child: const Text('Fade Out Music'),
),
_gap,
Row(
mainAxisSize: MainAxisSize.min,
children: [
const Text('Apply Filter'),
Checkbox(
value: filterApplied,
onChanged: (value) {
setState(() {
filterApplied = value!;
});
if (filterApplied) {
widget.audioController.applyFilter();
} else {
widget.audioController.removeFilter();
}
},
),
],
),
],
),
),
);
}
}
- Nachdem die Audiodateien heruntergeladen wurden, erstellen Sie im Stammverzeichnis Ihres Projekts ein Verzeichnis mit dem Namen
assets
. - Erstellen Sie im Verzeichnis
assets
zwei Unterverzeichnisse mit den Namenmusic
undsounds
. - Verschiebe die heruntergeladenen Dateien in dein Projekt, sodass sich die Songdatei in der Datei
assets/music/looped-song.ogg
und die Kirchenbänken-Sounds in den folgenden Dateien befinden:
assets/sounds/pew1.mp3
assets/sounds/pew2.mp3
assets/sounds/pew3.mp3
Die Projektstruktur sollte jetzt in etwa so aussehen:
Nachdem Sie die Dateien erstellt haben, müssen Sie Flutter darüber informieren.
- Öffnen Sie die Datei
pubspec.yaml
und ersetzen Sie den Abschnittflutter:
unten in der Datei durch Folgendes:
pubspec.yaml
...
flutter:
uses-material-design: true
assets:
- assets/music/
- assets/sounds/
- Fügen Sie eine Abhängigkeit vom Paket
flutter_soloud
und vom Paketlogging
hinzu.
flutter pub add flutter_soloud logging
Ihre pubspec.yaml
-Datei sollte jetzt zusätzliche Abhängigkeiten von den Paketen flutter_soloud
und logging
haben.
pubspec.yaml
...
dependencies:
flutter:
sdk: flutter
flutter_soloud: ^3.1.10
logging: ^1.3.0
...
- Führen Sie das Projekt aus. Noch funktioniert nichts, da Sie die Funktionen in den folgenden Abschnitten hinzufügen.
3. Initialisieren und Herunterfahren
Zum Abspielen von Audioinhalten verwenden Sie das Plug-in flutter_soloud
. Dieses Plug-in basiert auf dem SoLoud-Projekt, einer C++-Audio-Engine für Spiele, die unter anderem von Nintendo SNES Classic verwendet wird.
So initialisieren Sie die SoLoud-Audio-Engine:
- Importieren Sie in der Datei
audio_controller.dart
das Paketflutter_soloud
und fügen Sie der Klasse ein privates Feld vom Typ_soloud
hinzu.
lib/audio/audio_controller.dart
import 'dart:async';
import 'package:flutter_soloud/flutter_soloud.dart'; // ← Add this...
import 'package:logging/logging.dart';
class AudioController {
static final Logger _log = Logger('AudioController');
SoLoud? _soloud; // ← ... and this.
Future<void> initialize() async {
// TODO
}
...
Der Audiocontroller verwaltet die zugrunde liegende SoLoud-Engine über dieses Feld und leitet alle Aufrufe an sie weiter.
- Geben Sie in der
initialize()
-Methode den folgenden Code ein:
lib/audio/audio_controller.dart
...
Future<void> initialize() async {
_soloud = SoLoud.instance;
await _soloud!.init();
}
...
Dadurch wird das Feld _soloud
ausgefüllt und wartet auf die Initialisierung. Wichtige Hinweise:
- SoLoud bietet ein Singleton-Feld
instance
. Es ist nicht möglich, mehrere SoLoud-Instanzen zu erstellen. Das ist in der C++-Engine nicht zulässig und daher auch nicht im Dart-Plug-in. - Die Initialisierung des Plug-ins ist asynchron und wird erst abgeschlossen, wenn die
init()
-Methode zurückgegeben wird. - Der Übersichtlichkeit halber werden in diesem Beispiel keine Fehler in einem
try/catch
-Block abgefangen. Im Produktionscode sollten Sie dies tun und alle Fehler dem Nutzer melden.
- Geben Sie in der
dispose()
-Methode den folgenden Code ein:
lib/audio/audio_controller.dart
...
void dispose() {
_soloud?.deinit();
}
...
Es ist empfehlenswert, SoLoud beim Schließen der App zu beenden. Alles sollte jedoch auch dann einwandfrei funktionieren, wenn Sie das nicht tun.
- Die Methode
AudioController.initialize()
wird bereits von der Funktionmain()
aufgerufen. Das bedeutet, dass SoLoud beim Hot-Neustart des Projekts im Hintergrund initialisiert wird, aber erst funktioniert, wenn Sie tatsächlich Töne abspielen.
4. Einzeltöne abspielen
Asset laden und abspielen
Da Sie jetzt wissen, dass SoLoud beim Start initialisiert wird, können Sie es bitten, Töne abzuspielen.
SoLoud unterscheidet zwischen einer Audioquelle, also den Daten und Metadaten, die zum Beschreiben eines Tons verwendet werden, und den „Toninstanzen“, also den tatsächlich wiedergegebenen Tönen. Ein Beispiel für eine Audioquelle ist eine MP3-Datei, die in den Arbeitsspeicher geladen und zur Wiedergabe bereit ist und durch eine Instanz der Klasse AudioSource
dargestellt wird. Jedes Mal, wenn du diese Audioquelle abspielst, erstellt SoLoud eine „Toninstanz“, die durch den Typ SoundHandle
dargestellt wird.
Sie erhalten eine AudioSource
-Instanz, indem Sie sie laden. Wenn Sie beispielsweise eine MP3-Datei in Ihren Assets haben, können Sie sie laden, um eine AudioSource
zu erhalten. Dann bitten Sie SoLoud, diese AudioSource
abzuspielen. Sie können sie beliebig oft und sogar gleichzeitig abspielen.
Wenn Sie mit einer Audioquelle fertig sind, können Sie sie mit der Methode SoLoud.disposeSource()
entsorgen.
So laden Sie ein Asset und spielen es ab:
- Geben Sie in der
playSound()
-Methode derAudioController
-Klasse den folgenden Code ein:
lib/audio/audio_controller.dart
...
Future<void> playSound(String assetKey) async {
final source = await _soloud!.loadAsset(assetKey);
await _soloud!.play(source);
}
...
- Speichern Sie die Datei, führen Sie einen Hot-Reload durch und wählen Sie dann Ton wiedergeben aus. Sie sollten einen alberne Knall hören. Wichtige Hinweise:
- Das angegebene
assetKey
-Argument ist beispielsweiseassets/sounds/pew1.mp3
– derselbe String, den Sie für jede andere Flutter API zum Laden von Assets angeben würden, z. B. für dasImage.asset()
-Widget. - Die SoLoud-Instanz bietet eine
loadAsset()
-Methode, die eine Audiodatei asynchron aus den Assets des Flutter-Projekts lädt und eine Instanz der KlasseAudioSource
zurückgibt. Es gibt gleichwertige Methoden, eine Datei aus dem Dateisystem (loadFile()
-Methode) und über das Netzwerk von einer URL (loadUrl()
-Methode) zu laden. - Die neu gewonnene
AudioSource
-Instanz wird dann an dieplay()
-Methode von SoLoud übergeben. Diese Methode gibt eine Instanz des TypsSoundHandle
zurück, die den gerade wiedergegebenen Ton darstellt. Dieser Handle kann wiederum an andere SoLoud-Methoden übergeben werden, um den Ton beispielsweise zu pausieren, anzuhalten oder die Lautstärke zu ändern. - Obwohl
play()
eine asynchrone Methode ist, beginnt die Wiedergabe praktisch sofort. Dasflutter_soloud
-Paket verwendet die Foreign Function Interface (FFI) von Dart, um C-Code direkt und synchron aufzurufen. Die üblichen Nachrichten zwischen Dart-Code und Plattformcode, die für die meisten Flutter-Plug-ins charakteristisch sind, sind nirgends zu finden. Der einzige Grund, warum einige Methoden asynchron sind, ist, dass ein Teil des Codes des Plug-ins in einem eigenen Isolate ausgeführt wird und die Kommunikation zwischen Dart-Isolaten asynchron ist. - Sie stellen mit
_soloud!
fest, dass das Feld_soloud
nicht null ist. Dies dient der Kürze. Der Produktionscode sollte die Situation fehlerfrei bewältigen, wenn der Entwickler versucht, einen Ton abzuspielen, bevor der Audiocontroller vollständig initialisiert wurde.
Mit Ausnahmen umgehen
Sie haben vielleicht bemerkt, dass Sie wieder einmal mögliche Ausnahmen ignorieren. Es ist an der Zeit, das für diese Methode zu ändern. Der Kürze halber wird im Codelab nach diesem Abschnitt wieder darauf zurückgekommen, Ausnahmen zu ignorieren.
- Um in diesem Fall mit Ausnahmen umzugehen, können Sie die beiden Zeilen der
playSound()
-Methode in einentry/catch
-Block einschließen und nur Instanzen vonSoLoudException
abfangen.
lib/audio/audio_controller.dart
...
Future<void> playSound(String assetKey) async {
try {
final source = await _soloud!.loadAsset(assetKey);
await _soloud!.play(source);
} on SoLoudException catch (e) {
_log.severe("Cannot play sound '$assetKey'. Ignoring.", e);
}
}
...
SoLoud löst verschiedene Ausnahmen aus, z. B. die SoLoudNotInitializedException
- oder SoLoudTemporaryFolderFailedException
-Ausnahme. In den API-Dokumenten für jede Methode werden die Arten von Ausnahmen aufgeführt, die auftreten können.
SoLoud bietet auch eine übergeordnete Klasse für alle Ausnahmen, die SoLoudException
-Ausnahme, damit Sie alle Fehler im Zusammenhang mit der Funktionalität der Audio-Engine abfangen können. Das ist besonders hilfreich, wenn das Abspielen von Audio nicht kritisch ist. Beispiel: Sie möchten nicht, dass die Spielsitzung des Spielers nur deshalb abstürzt, weil einer der „Pew-Pew“-Sounds nicht geladen werden konnte.
Wie du dir wahrscheinlich vorstellen kannst, kann auch die loadAsset()
-Methode einen FlutterError
-Fehler auslösen, wenn du einen nicht vorhandenen Asset-Schlüssel angibst. Der Versuch, Assets zu laden, die nicht im Lieferumfang des Spiels enthalten sind, sollte in der Regel behoben werden. Daher ist dies ein Fehler.
Unterschiedliche Töne abspielen
Möglicherweise haben Sie bemerkt, dass nur die Datei pew1.mp3
wiedergegeben wird, obwohl sich im Assets-Verzeichnis zwei weitere Versionen des Tons befinden. Es klingt oft natürlicher, wenn Spiele mehrere Versionen desselben Tons haben und die verschiedenen Versionen nach dem Zufallsprinzip oder im Wechsel abspielen. So klingen beispielsweise Schritte und Schüsse nicht zu einheitlich und damit unecht.
- Optional können Sie den Code so ändern, dass jedes Mal, wenn auf die Schaltfläche getippt wird, ein anderer Glockenton abgespielt wird.
5. Musikschleifen abspielen
Länger laufende Töne verwalten
Einige Audioinhalte sind für eine längere Wiedergabe vorgesehen. Musik ist das offensichtliche Beispiel, aber in vielen Spielen wird auch Umgebungssound verwendet, z. B. der Wind, der durch die Gänge heult, das entfernte Singen von Mönchen, das Knarren von jahrhundertealtem Metall oder das entfernte Husten von Patienten.
Das sind Audioquellen mit einer Wiedergabezeit, die in Minuten gemessen werden kann. Sie müssen sie im Auge behalten, damit Sie sie bei Bedarf pausieren oder beenden können. Außerdem werden sie häufig von großen Dateien unterstützt und können viel Arbeitsspeicher verbrauchen. Ein weiterer Grund, sie zu überwachen, ist, dass Sie die AudioSource
-Instanz entsorgen können, wenn sie nicht mehr benötigt wird.
Aus diesem Grund fügen Sie AudioController
ein neues privates Feld hinzu. Ein Handle für den abgespielten Titel, falls zutreffend. Fügen Sie folgende Zeile hinzu:
lib/audio/audio_controller.dart
...
class AudioController {
static final Logger _log = Logger('AudioController');
SoLoud? _soloud;
SoundHandle? _musicHandle; // ← Add this.
...
Musik starten
Im Grunde unterscheidet sich das Abspielen von Musik nicht vom Abspielen eines einzelnen Tons. Du musst die assets/music/looped-song.ogg
-Datei zuerst als Instanz der AudioSource
-Klasse laden und dann mit der play()
-Methode von SoLoud wiedergeben.
Dieses Mal greifen Sie jedoch auf den Audio-Handle zu, den die play()
-Methode zurückgibt, um den Ton während der Wiedergabe zu manipulieren.
- Sie können die
AudioController.startMusic()
-Methode auch selbst implementieren. Es ist in Ordnung, wenn Sie einige Details nicht richtig wiedergeben. Wichtig ist, dass die Musik startet, wenn Sie Musik starten auswählen.
Hier eine Referenzimplementierung:
lib/audio/audio_controller.dart
...
Future<void> startMusic() async {
if (_musicHandle != null) {
if (_soloud!.getIsValidVoiceHandle(_musicHandle!)) {
_log.info('Music is already playing. Stopping first.');
await _soloud!.stop(_musicHandle!);
}
}
final musicSource = await _soloud!.loadAsset(
'assets/music/looped-song.ogg',
mode: LoadMode.disk,
);
}
...
Beachten Sie, dass Sie die Musikdatei im Laufwerkmodus (LoadMode.disk
-Enum) laden. Das bedeutet, dass die Datei nur bei Bedarf in Teilen geladen wird. Bei längeren Audioinhalten ist es im Allgemeinen am besten, sie im Laufwerkmodus zu laden. Bei kurzen Soundeffekten ist es sinnvoller, sie in den Arbeitsspeicher zu laden und dort zu dekomprimieren (das Standard-LoadMode.memory
-Enum).
Es gibt jedoch ein paar Probleme. Erstens: Die Musik ist zu laut und übertönt die Geräusche. In den meisten Spielen läuft die Musik meistens im Hintergrund, sodass die aussagekräftigeren Audioinhalte wie Sprache und Soundeffekte im Vordergrund stehen. Dies dient der Behebung von Problemen bei der Verwendung des Lautstärkeparameters der Wiedergabemethode. Sie können beispielsweise _soloud!.play(musicSource, volume: 0.6)
sagen, um den Titel mit 60% der Lautstärke abzuspielen. Alternativ können Sie die Lautstärke auch später mit einer Taste wie _soloud!.setVolume(_musicHandle, 0.6)
einstellen.
Das zweite Problem ist, dass der Song abrupt stoppt. Das liegt daran, dass der Song in einer Schleife abgespielt werden soll und der Startpunkt der Schleife nicht der Anfang der Audiodatei ist.
Dies ist eine beliebte Option für die Musik in Spielen, da der Song mit einem natürlichen Intro beginnt und dann so lange abgespielt wird, wie es erforderlich ist, ohne einen offensichtlichen Loop-Punkt. Wenn im Spiel ein Übergang zum nächsten Song erforderlich ist, wird der aktuelle Song ausgeblendet.
Glücklicherweise bietet SoLoud Möglichkeiten, Audioinhalte im Loop abzuspielen. Die Methode play()
nimmt einen booleschen Wert für den Parameter looping
und den Wert für den Startpunkt der Schleife als Parameter loopingStartAt
an. Der Code sieht dann so aus:
lib/audio/audio_controller.dart
...
_musicHandle = await _soloud!.play(
musicSource,
volume: 0.6,
looping: true,
// ↓ The exact timestamp of the start of the loop.
loopingStartAt: const Duration(seconds: 25, milliseconds: 43),
);
...
Wenn Sie den Parameter loopingStartAt
nicht festlegen, wird standardmäßig Duration.zero
verwendet, also der Anfang der Audiodatei. Wenn du einen Musiktitel hast, der sich perfekt ohne Einleitung in einem Loop abspielen lässt, ist das die richtige Option.
- Um zu prüfen, ob die Audioquelle nach der Wiedergabe ordnungsgemäß entsorgt wird, kannst du dir den
allInstancesFinished
-Stream anhören, den jede Audioquelle bereitstellt. Mit hinzugefügten Protokollaufrufen sieht diestartMusic()
-Methode so aus:
lib/audio/audio_controller.dart
...
Future<void> startMusic() async {
if (_musicHandle != null) {
if (_soloud!.getIsValidVoiceHandle(_musicHandle!)) {
_log.info('Music is already playing. Stopping first.');
await _soloud!.stop(_musicHandle!);
}
}
_log.info('Loading music');
final musicSource = await _soloud!.loadAsset(
'assets/music/looped-song.ogg',
mode: LoadMode.disk,
);
musicSource.allInstancesFinished.first.then((_) {
_soloud!.disposeSource(musicSource);
_log.info('Music source disposed');
_musicHandle = null;
});
_log.info('Playing music');
_musicHandle = await _soloud!.play(
musicSource,
volume: 0.6,
looping: true,
loopingStartAt: const Duration(seconds: 25, milliseconds: 43),
);
}
...
Ton ausblenden
Ihr nächstes Problem ist, dass die Musik nie endet. Jetzt ist es an der Zeit, einen Übergang zu implementieren.
Eine Möglichkeit, das Ausblenden zu implementieren, wäre eine Funktion, die mehrmals pro Sekunde aufgerufen wird, z. B. Ticker
oder Timer.periodic
, und die Lautstärke der Musik in kleinen Schritten senkt. Das würde funktionieren, ist aber mit viel Arbeit verbunden.
Glücklicherweise bietet SoLoud praktische „Fire-and-Forget“-Methoden, die das für Sie erledigen. So können Sie die Musik über einen Zeitraum von fünf Sekunden ausblenden und dann die Audioinstanz beenden, damit sie nicht unnötig CPU-Ressourcen verbraucht: Ersetzen Sie die fadeOutMusic()
-Methode durch diesen Code:
lib/audio/audio_controller.dart
...
void fadeOutMusic() {
if (_musicHandle == null) {
_log.info('Nothing to fade out');
return;
}
const length = Duration(seconds: 5);
_soloud!.fadeVolume(_musicHandle!, 0, length);
_soloud!.scheduleStop(_musicHandle!, length);
}
...
6. Effekte anwenden
Ein großer Vorteil einer richtigen Audio-Engine ist, dass du Audiosignale verarbeiten kannst, z. B. indem du einige Töne durch einen Hall, einen Equalizer oder einen Tiefpassfilter leitest.
In Spielen kann dies zur akustischen Unterscheidung von Orten verwendet werden. Ein Klatschen klingt beispielsweise in einem Wald anders als in einem Betonbunker. Während ein Wald dazu beiträgt, den Schall zu verteilen und zu absorbieren, reflektieren die kahlen Wände eines Bunkers die Schallwellen zurück, was zu einem Nachhall führt. Ähnlich klingen die Stimmen von Menschen anders, wenn sie durch eine Wand gehört werden. Die höheren Frequenzen dieser Töne werden beim Durchlaufen des festen Mediums stärker gedämpft, was zu einem Tiefpassfiltereffekt führt.
SoLoud bietet verschiedene Audioeffekte, die Sie auf Audio anwenden können.
- Wenn es so klingen soll, als befände sich der Spieler in einem großen Raum wie einer Kathedrale oder einer Höhle, verwende das Feld
SoLoud.filters
:
lib/audio/audio_controller.dart
...
void applyFilter() {
_soloud!.filters.freeverbFilter.activate();
_soloud!.filters.freeverbFilter.wet.value = 0.2;
_soloud!.filters.freeverbFilter.roomSize.value = 0.9;
}
void removeFilter() {
_soloud!.filters.freeverbFilter.deactivate();
}
...
Über das Feld SoLoud.filters
haben Sie Zugriff auf alle Filtertypen und ihre Parameter. Jeder Parameter hat außerdem integrierte Funktionen wie allmähliches Ausblenden und Oszillation.
Hinweis : _soloud!.filters
gibt globale Filter an. Wenn Sie Filter auf eine einzelne Quelle anwenden möchten, verwenden Sie das Pendant AudioSource.filters
, das genauso funktioniert.
Mit dem vorherigen Code geschieht Folgendes:
- Aktivieren Sie den Freeverb-Filter global.
- Lege den Parameter Wet auf
0.2
fest. Das bedeutet, dass das resultierende Audiosignal zu 80% aus dem Original und zu 20% aus der Ausgabe des Halleffekts besteht. Wenn Sie diesen Parameter auf1.0
festlegen, hören Sie nur die Schallwellen, die von den entfernten Wänden des Raums zu Ihnen zurückkommen, und nichts vom ursprünglichen Audiosignal. - Legen Sie für den Parameter Raumgröße den Wert
0.9
fest. Sie können diesen Parameter nach Belieben anpassen oder sogar dynamisch ändern.1.0
ist eine riesige Höhle, während0.0
ein Badezimmer ist.
- Wenn Sie möchten, können Sie den Code ändern und einen oder mehrere der folgenden Filter anwenden:
biquadFilter
(kann als Tiefpassfilter verwendet werden)pitchShiftFilter
equalizerFilter
echoFilter
lofiFilter
flangerFilter
bassboostFilter
waveShaperFilter
robotizeFilter
7. Glückwunsch
Sie haben einen Audiocontroller implementiert, der Töne abspielt, Musik in einem Loop wiedergibt und Effekte anwendet.
Weitere Informationen
- Mit Funktionen wie dem Vorladen von Tönen beim Starten, dem Abspielen von Songs in einer Sequenz oder dem schrittweisen Anwenden eines Filters können Sie den Audiocontroller noch weiter optimieren.
- Lesen Sie die Paketdokumentation von
flutter_soloud
. - Weitere Informationen finden Sie auf der Startseite der zugrunde liegenden C++-Bibliothek.
- Weitere Informationen zu Dart FFI, der Technologie, die für die Verknüpfung mit der C++-Bibliothek verwendet wird.
- Sehen Sie sich den Vortrag von Guy Somberg zum Programmieren von Game-Audio an, um sich inspirieren zu lassen. (Es gibt auch eine längere Version.) Wenn Guy von „Middleware“ spricht, meint er Bibliotheken wie SoLoud und FMOD. Der Rest des Codes ist in der Regel für jedes Spiel spezifisch.
- Erstellen Sie Ihr Spiel und veröffentlichen Sie es.