Flutter oyununuza ses ve müzik ekleyin

1. Başlamadan önce

Oyunlar görsel-işitsel deneyimlerdir. Flutter, güzel görseller ve sağlam kullanıcı arayüzleri oluşturmak için mükemmel bir araçtır. Bu nedenle, görsel açıdan çok daha fazlasını yapmanıza olanak tanır. Geriye kalan eksik bileşen sestir. Bu codelab'de, projenize düşük gecikmeli ses ve müzik eklemek için flutter_soloud eklentisini nasıl kullanacağınızı öğreneceksiniz. Temel bir yapıyla başlar, böylece doğrudan ilgi çekici bölümlere atlayabilirsiniz.

Elle çizilmiş kulaklık çizimi.

Elbette burada öğrendiklerinizi yalnızca oyunlara değil, uygulamalarınıza da ses eklemek için kullanabilirsiniz. Ancak neredeyse tüm oyunlarda ses ve müzik gerekirken çoğu uygulamada bu gerekli değildir. Bu nedenle bu kod laboratuvarı oyunlara odaklanır.

Ön koşullar

  • Flutter'a aşina olmanız gerekir.
  • Flutter uygulamalarını çalıştırma ve hata ayıklama hakkında bilgi sahibi olma.

Öğrenecekleriniz

  • Tek seferlik sesleri çalma
  • Boşluksuz müzik döngüleri nasıl çalınır ve özelleştirilir?
  • Sesleri yavaşça artırma ve azaltma
  • Seslere çevre efektleri uygulama.
  • İstisnalar nasıl ele alınır?
  • Bu özelliklerin tümünü tek bir ses kontrol cihazına yerleştirme.

İhtiyacınız olanlar

  • Flutter SDK'sı
  • Tercih ettiğiniz bir kod düzenleyici

2. Kur

  1. Aşağıdaki dosyaları indirin. Bağlantınız yavaşsa endişelenmeyin. Dosyaları daha sonra indirmeniz gerekir. Dolayısıyla çalışırken indirmelerine izin verebilirsiniz.
  1. İstediğiniz adı kullanarak bir Flutter projesi oluşturun.
  1. Projede bir lib/audio/audio_controller.dart dosyası oluşturun.
  2. Dosyaya aşağıdaki kodu girin:

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
  }
}

Gördüğünüz gibi bu, gelecekteki işlevler için yalnızca bir iskelettir. Bunların hepsini bu kod laboratuvarının sırasında uygulayacağız.

  1. Sonra, lib/main.dart dosyasını açın ve içeriğini aşağıdaki kodla değiştirin:

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),
        useMaterial3: true,
      ),
      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();
                    }
                  },
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}
  1. Ses dosyaları indirildikten sonra projenizin kökünde assets adlı bir dizin oluşturun.
  2. assets dizininde biri music, diğeri sounds adlı iki alt dizin oluşturun.
  3. Şarkı dosyasının assets/music/looped-song.ogg dosyasında ve sıra seslerinin aşağıdaki dosyalarda olmasını sağlamak için indirilen dosyaları projenize taşıyın:
  • assets/sounds/pew1.mp3
  • assets/sounds/pew2.mp3
  • assets/sounds/pew3.mp3

Proje yapınız şu şekilde görünmelidir:

&quot;android&quot;, &quot;ios&quot; gibi klasörleri ve &quot;README.md&quot;, &quot;analysis_options.yaml&quot; gibi dosyaları içeren projenin ağaç görünümü.  Bunlar arasında &quot;music&quot; ve &quot;sounds&quot; alt dizinlerini içeren &quot;assets&quot; dizini, &quot;main.dart&quot; ve &quot;audio_controller.dart&quot; içeren &quot;audio&quot; alt dizini ve &quot;pubspec.yaml&quot; dosyasını görebiliriz.  Oklar yeni dizinleri ve şu ana kadar dokunduğunuz dosyaları gösterir.

Dosyalar artık orada olduğuna göre Flutter'a bu dosyaları bildirmeniz gerekir.

  1. pubspec.yaml dosyasını açın ve ardından dosyanın en altındaki flutter: bölümünü aşağıdakiyle değiştirin:

pubspec.yaml

...

flutter:
  uses-material-design: true

  assets:
    - assets/music/
    - assets/sounds/
  1. flutter_soloud paketine ve logging paketine bir bağımlılık ekleyin.

pubspec.yaml

...

dependencies:
  flutter:
    sdk: flutter

  flutter_soloud: ^2.0.0
  logging: ^1.2.0

...
  1. Projeyi çalıştırın. İşlevleri aşağıdaki bölümlere eklediğiniz için henüz hiçbir şey çalışmıyor.

10f0f751c9c47038.png

/flutter_soloud/src/filters/filters.cpp:21:24: warning: implicit conversion loses integer precision: 'decltype(__x.base() - __y.base())' (aka 'long') to 'int' [-Wshorten-64-to-32];

Bunlar, temel SoLoud C++ kitaplığından gelir. İşlevsellik üzerinde herhangi bir etkisi yoktur ve güvenli bir şekilde göz ardı edilebilir.

3. Başlatma ve kapatma

Ses çalmak için flutter_soloud eklentisini kullanırsınız. Bu eklenti, Nintendo SNES Classic'ın da aralarında bulunduğu oyunlar için C++ ses motoru olan SoLoud projesini temel alır.

7ce23849b6d0d09a.png

SoLoud ses motorunu başlatmak için şu adımları uygulayın:

  1. audio_controller.dart dosyasında flutter_soloud paketini içe aktarın ve sınıfa özel bir _soloud alanı ekleyin.

lib/audio/audio_controller.dart

import 'dart:ui';

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
  }

  ...

Ses denetleyicisi, temel SoLoud motorunu bu alan üzerinden yönetir ve tüm çağrıları bu motora yönlendirir.

  1. initialize() yönteminde aşağıdaki kodu girin:

lib/audio/audio_controller.dart

...

  Future<void> initialize() async {
    _soloud = SoLoud.instance;
    await _soloud!.init();
  }

...

Bu işlemle _soloud alanı doldurulur ve başlatma işlemi beklenir. Aşağıdakileri göz önünde bulundurun:

  • SoLoud, bir singleton instance alanı sağlar. Birden fazla SoLoud örneği oluşturmak mümkün değildir. C++ motorunun buna izin vermediği için Dart eklentisi de buna izin vermez.
  • Eklentinin başlatılması eşzamansızdır ve init() yöntemi döndürülene kadar tamamlanmaz.
  • Bu örneği kısaca açıklamak gerekirse bir try/catch bloğundaki hataları yakalamıyorsunuz. Üretim kodunda bunu yapmak ve hataları kullanıcıya bildirmek istersiniz.
  1. dispose() yöntemine aşağıdaki kodu girin:

lib/audio/audio_controller.dart

...

  void dispose() {
    _soloud?.deinit();
  }

...

Uygulamadan çıktığınızda SoLoud'u kapatmak iyi bir uygulamadır ancak bunu yapmasanız bile her şey sorunsuz şekilde çalışır.

  1. AudioController.initialize() yönteminin main() işlevinden zaten çağrıldığına dikkat edin. Yani proje çalışır durumda yeniden başlatıldığında arka planda SoLoud başlatılır, ancak siz bazı sesler çalmadan önce işe yaramaz.

4. Tek seferlik sesler çalın

Bir öğeyi yükleyip oynatma

Artık SoLoud'un başlatma sırasında başlatıldığını bildiğinize göre ses çalmasını isteyebilirsiniz.

SoLoud, bir sesi tanımlamak için kullanılan veriler ve meta veriler olan ses kaynağı ile aslında çalınan sesler olan "ses örnekleri" arasında ayrım yapar. Ses kaynağına örnek olarak belleğe yüklenmiş, çalınmaya hazır ve AudioSource sınıfının bir örneğiyle temsil edilen bir mp3 dosyası verilebilir. Bu ses kaynağını her çaldığınızda SoLoud bir "ses örneği" oluşturur Bu değer, SoundHandle türüyle temsil edilir.

Yükleyerek bir AudioSource örneği elde edersiniz. Örneğin, öğelerinizde bir mp3 dosyanız varsa bu dosyayı yükleyerek AudioSource elde edebilirsiniz. Ardından SoLoud'a bu AudioSource dosyasını çalmasını söylersiniz. Aynı anda bile birçok kez oynayabilirsiniz.

Kullanmadığınız ses kaynaklarını SoLoud.disposeSource() yöntemiyle imha edin.

Bir öğeyi yüklemek ve oynatmak için aşağıdaki adımları uygulayın:

  1. AudioController sınıfının playSound() yönteminde aşağıdaki kodu girin:

lib/audio/audio_controller.dart

  ...

  Future<void> playSound(String assetKey) async {
    final source = await _soloud!.loadAsset(assetKey);
    await _soloud!.play(source);
  }

  ...
  1. Dosyayı kaydedin, anında yeniden yükleyin ve ardından Ses çal'ı seçin. Aptalca bir "pew" sesi duyarsınız. Aşağıdakileri göz önünde bulundurun:
  • Sağlanan assetKey bağımsız değişkeni assets/sounds/pew1.mp3 gibidir. Image.asset() widget'ı gibi öğe yükleyen diğer Flutter API'lerine sağlayacağınız dizeyle aynıdır.
  • SoLoud örneği, Flutter projesinin öğelerinden ses dosyasını eşzamansız olarak yükleyen ve AudioSource sınıfının bir örneğini döndüren bir loadAsset() yöntemi sağlar. Bir dosyayı dosya sisteminden (loadFile() yöntemi) ve ağ üzerinden bir URL'den (loadUrl() yöntemi) yüklemek için eşdeğer yöntemler vardır.
  • Ardından yeni edinilen AudioSource örneği SoLoud'un play() yöntemine iletilir. Bu yöntem, yeni çalınan sesi temsil eden SoundHandle türündeki bir örnek döndürür. Bu herkese açık kullanıcı adı; sesi duraklatma, durdurma veya ses seviyesini değiştirme gibi işlemler için diğer SoLoud yöntemlerine iletilebilir.
  • play() eşzamansız bir yöntem olsa da oynatma işlemi temelde anında başlar. flutter_soloud paketi, C kodunu doğrudan ve eşzamanlı olarak çağırmak için Dart'ın yabancı işlev arayüzünü (FFI) kullanır. Çoğu Flutter eklentisinin özelliği olan Dart kodu ile platform kodu arasında gidip gelen mesajlaşmalar hiçbir yerde bulunamaz. Bazı yöntemlerin eşzamansız olmasının tek nedeni, eklenti kodunun bir kısmının kendi izolasyonunda çalışması ve Dart izoleleri arasındaki iletişimin eşzamansız olmasıdır.
  • _soloud alanının _soloud! ile boş olmadığını iddia etmeniz yeterlidir. Bu, yine kısalık içindir. Üretim kodu, geliştiricinin ses denetleyicisi tam olarak başlatılmadan önce ses çalmayı denediği durumları sorunsuz bir şekilde ele almalıdır.

İstisnalarla ilgilenin

Olası istisnaları bir kez daha göz ardı ettiğinizi fark etmiş olabilirsiniz. Öğrenme amacıyla kullanılan bu özel yöntem için bunu düzeltelim. (Kısaca ifade etmek gerekirse, codelab bu bölümden sonra istisnaları yoksayarak geri dönecektir.)

  • Bu durumdaki istisnalarla başa çıkmak için playSound() yönteminin iki satırını bir try/catch bloğuna sarın ve yalnızca SoLoudException örneklerini yakalayın.

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, SoLoudNotInitializedException veya SoLoudTemporaryFolderFailedException istisnaları gibi çeşitli istisnalar atar. Her yöntemin API dokümanlarında, atılabilen istisna türleri listelenir.

SoLoud, ses motorunun işleviyle ilgili tüm hataları yakalayabilmeniz için SoLoudException istisnası olmak üzere tüm istisnaları için bir üst sınıf da sağlar. Bu, özellikle ses oynatmanın kritik olmadığı durumlarda yararlıdır. Örneğin, yalnızca "pıt pıt" seslerinden biri yüklenemediği için oyuncunun oyun oturumunu kilitlemek istemediğinizde.

Muhtemelen tahmin edeceğiniz gibi, var olmayan bir öğe anahtarı sağlarsanız loadAsset() yöntemi de FlutterError hatası verebilir. Oyunla birlikte paketlenmemiş öğeleri yüklemeye çalışmak genellikle çözmeniz gereken bir sorundur. Bu nedenle hata olarak değerlendirilir.

Farklı sesler çalma

Yalnızca pew1.mp3 dosyasını çaldığınızı fark etmiş olabilirsiniz ancak öğeler dizininde sesin iki başka sürümü de vardır. Oyunlarda aynı sesin birkaç versiyonu varsa ve farklı versiyonlar rastgele sırayla ya da sırayla çalındığında kulağa daha doğal gelebilir. Bu sayede, örneğin ayak sesleri ve silah sesleri çok tekdüze ve yapay bir şekilde duyulmaz.

  • İsteğe bağlı bir alıştırma olarak, düğmeye her dokunulduğunda farklı bir bip sesi çalacağı şekilde kodu değiştirin.

Semboller için

5. Müzikleri döngü şeklinde çalma

Uzun süren sesleri yönetin

Bazı seslerin uzun süre boyunca çalınması amaçlanmıştır. Müzik en belirgin örnektir ancak birçok oyunda koridorlarda esen rüzgar, uzaktan gelen rahiplerin mantraları, yüzyıllık metalin gıcırtısı veya hastaların uzaktan gelen öksürmeleri gibi ambiyans sesleri de çalınır.

Bunlar, dakika cinsinden ölçülebilen çalma sürelerine sahip ses kaynaklarıdır. Gerektiğinde duraklatabilmeniz veya durdurabilmeniz için bunları takip etmeniz gerekir. Ayrıca genellikle büyük dosyalar tarafından yedeklenirler ve çok fazla bellek kullanabilirler. Bu nedenle, bunları takip etmeniz için bir başka neden de artık ihtiyaç olmadığında AudioSource örneğini kaldırabilmenizdir.

Bu nedenle, AudioController için yeni bir özel alan eklersiniz. Geçerli olarak çalınan şarkının (varsa) herkese açık kullanıcı adı olarak kullanılır. Aşağıdaki satırı ekleyin:

lib/audio/audio_controller.dart

...

class AudioController {
  static final Logger _log = Logger('AudioController');

  SoLoud? _soloud;

  SoundHandle? _musicHandle;    // ← Add this.

  ...

Müziği başlat

Esasen, müzik çalmak tek seferlik bir ses çalmaktan farklı değildir. Yine de önce assets/music/looped-song.ogg dosyasını AudioSource sınıfının bir örneği olarak yüklemeniz, ardından SoLoud'un play() yöntemini kullanarak çalabileceğiniz bir dosya oluşturmanız gerekir.

Ancak bu kez, play() yönteminin döndürdüğü ses mülkünü ele alarak ses çalırken ses üzerinde işlem yapabilirsiniz.

  • Dilerseniz AudioController.startMusic() yöntemini kendiniz uygulayabilirsiniz. Bazı ayrıntıları doğru aktaramasanız sorun olmaz. Önemli olan, Müziği başlat'ı seçtiğinizde müziğin başlamasıdır.

Aşağıda bir referans uygulaması verilmiştir:

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);
    _musicHandle = await _soloud!.play(musicSource);
  }

...

Müzik dosyasını disk modunda (LoadMode.disk enum) yüklediğinizi unutmayın. Bu, dosyanın yalnızca gerektiğinde parçalara ayrılarak yüklendiği anlamına gelir. Daha uzun süreli sesler için genellikle disk modunda yükleme yapmak en iyisidir. Kısa ses efektlerini belleğe yükleyip sıkıştırmak (varsayılan LoadMode.memory enum) daha mantıklıdır.

Ancak birkaç sorununuz var. Öncelikle müzik çok yüksek ve sesleri bastıracak kadar güçlü. Çoğu oyunda müzik çoğu zaman arka plandadır ve konuşma ve ses efektleri gibi daha bilgilendirici sesler merkezde yer alır. Bu sorunu, oynatma yönteminin ses düzeyi parametresini kullanarak kolayca düzeltebilirsiniz. Örneğin, şarkıyı% 60 ses düzeyinde çalmak için _soloud!.play(musicSource, volume: 0.6) hizmetini deneyebilirsiniz. Alternatif olarak, ses seviyesini daha sonra _soloud!.setVolume(_musicHandle, 0.6) gibi bir ifadeyle ayarlayabilirsiniz.

İkinci sorun ise şarkının aniden durması. Bunun nedeni, şarkının döngü hâlinde çalınması gereken bir şarkı olması ve döngünün başlangıç noktasının ses dosyasının başlangıcı olmamasıdır.

88d2c57fffdfe996.png

Şarkı doğal bir girişle başlayıp bariz bir döngü noktası olmadan gerektiği kadar oynatıldığından bu, oyun müziği için popüler bir seçimdir. Oyunun şu anda çalan şarkıdan çıkması gerektiğinde şarkının sesi yavaş yavaş azaltılır.

Neyse ki SoLoud, sesleri döngü şeklinde çalma yöntemleri sunuyor. play() yöntemi, looping parametresi için bir boole değeri ve loopingStartAt parametresi olarak da döngünün başlangıç noktasının değerini alır. Bu işlem sonucunda elde edilen kod aşağıdaki gibi görünür:

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),
);

...

loopingStartAt parametresini ayarlamazsanız varsayılan olarak Duration.zero olur (yani ses dosyasının başlangıcı). Girişsiz, mükemmel bir döngüye sahip bir müzik parçanız varsa bu seçeneği tercih edin.

  • Oynatma işlemi sona erdiğinde ses kaynağının uygun şekilde bertaraf edilmesini sağlamak için her ses kaynağının sağladığı allInstancesFinished akışını dinleyin. Ek günlük çağrılarıyla, startMusic() yöntemi aşağıdaki gibi görünür:

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),
    );
  }

...

Kararma sesi

Bir sonraki sorun müziğin hiç bitmemesi. Şeffaflaştırma yapalım.

Karartmayı uygulamanın bir yolu, Ticker veya Timer.periodic gibi saniyede birkaç kez çağrılan bir tür işlevi kullanmak ve müziğin ses düzeyini küçük azaltmalarla azaltmaktır. Bu işe yarar ama çok çaba gerektirir.

Neyse ki SoLoud, bunu sizin için yapan kullanışlı bir "kullan ve unut" yöntemi sunar. Aşağıdaki adımları uygulayarak müziğin sesini beş saniye içinde yavaş yavaş azaltabilir ve CPU kaynaklarını gereksiz yere tüketmemesi için ses örneğini durdurabilirsiniz. fadeOutMusic() yöntemini şu kodla değiştirin:

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. Efekt uygulama

Kullanabileceğiniz uygun bir ses motorunun en büyük avantajlarından biri, bazı sesleri yankı, ekolayzer veya düşük geçiş filtresi üzerinden yönlendirme gibi ses işleme işlemleri yapabilmenizdir.

Oyunlarda bu, konumları işitsel olarak farklılaştırmak için kullanılabilir. Örneğin, ormanda beton bir sığınaktakinden farklı bir alkış sesi duyulur. Ormanlar sesin dağılmasına ve emilmesine yardımcı olurken sığınağın çıplak duvarları ses dalgalarını geri yansıtarak yankıya neden olur. Benzer şekilde, insanların sesleri bir duvardan duyulduğunda farklı gelir. Bu seslerin yüksek frekansları, katı ortamda gezindikçe daha kolay azaltılır. Bu da düşük geçişli bir filtre etkisine neden olur.

Bir odada konuşan iki kişinin resmi. Ses dalgaları yalnızca bir kişiden diğerine doğrudan geçmekle kalmaz, aynı zamanda duvarlardan ve tavandan da yansır.

SoLoud, seslere uygulayabileceğiniz birkaç farklı ses efekti sunar.

  • Oyuncularınızın sesi katedral veya mağara gibi büyük bir odadaymış gibi duyulmasını sağlamak için SoLoud.filters alanını kullanın:

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();
  }

...

SoLoud.filters alanı, tüm filtre türlerine ve bunların parametrelerine erişmenizi sağlar. Her parametrenin kademeli olarak kararma ve salınım gibi yerleşik işlevleri de vardır.

Not: _soloud!.filters, genel filtreleri gösterir. Tek bir kaynağa filtre uygulamak istiyorsanız lütfen aynı işlemi yapan karşılık gelen AudioSource.filters kullanın.

Önceki kodla aşağıdakileri yaparsınız:

  • Freeverb filtresini global olarak etkinleştirin.
  • Wet (Sıcak) parametresini 0.2 olarak ayarlayın. Bu durumda, ortaya çıkan sesin %80'i orijinal, %20'si ise yankı efektinin çıkışı olur. Bu parametreyi 1.0 olarak ayarlarsanız yalnızca odanın uzak duvarlarından size gelen ses dalgalarını duyarsınız ve orijinal sesin hiçbirini duymazsınız.
  • Oda Boyutu parametresini 0.9 olarak ayarlayın. Bu parametreyi istediğiniz gibi ayarlayabilir veya dinamik olarak değiştirebilirsiniz. 1.0 dev bir mağaradır, 0.0 ise bir banyodur.
  • Kodu değiştirip aşağıdaki filtrelerden birini veya bunların bir kombinasyonunu uygulayabilirsiniz:
  • biquadFilter (düşük geçiş filtresi olarak kullanılabilir)
  • pitchShiftFilter
  • equalizerFilter
  • echoFilter
  • lofiFilter
  • flangerFilter
  • bassboostFilter
  • waveShaperFilter
  • robotizeFilter

7. Tebrikler

Ses çalan, müziği döngüye alan ve efekt uygulayan bir ses denetleyicisi uyguladınız.

Daha fazla bilgi

  • Ses kontrol cihazını, başlangıçta sesleri önceden yükleme, şarkıları sırayla çalma veya zaman içinde kademeli olarak filtre uygulama gibi özelliklerle daha da ileriye taşımayı deneyin.
  • flutter_soloud'nin paket belgelerini okuyun.
  • Temel C++ kitaplığının ana sayfasını okuyun.
  • C++ kitaplığıyla arayüz oluşturmak için kullanılan teknoloji olan Dart FFI hakkında daha fazla bilgi edinin.
  • İlham almak için Guy Somberg'in oyunda ses programları hakkındaki konuşmasını izleyin. (Daha uzun bir yöntem de var.) Guy, "ara katman"dan bahsederken SoLoud ve FMOD gibi kitaplıkları kastetmektedir. Kodun geri kalanı her oyuna özgüdür.
  • Oyununuzu geliştirin ve yayınlayın.

Kulaklık resmi