Flutter oyununuza ses ve müzik ekleyin

1. Başlamadan önce

Oyunlar görsel-işitsel deneyimlerdir. Flutter, güzel görseller ve etkileyici bir kullanıcı arayüzü oluşturmak için mükemmel bir araçtır. Bu nedenle, görsel açıdan çok iyi olmanızı sağlar. Kalan eksik malzeme ses. 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 kullanarak yalnızca oyunlara değil, uygulamalarınıza da ses ekleyebilirsiniz. Neredeyse tüm oyunlar ses ve müzik gerektirse de çoğu uygulama bunu gerektirmez. Bu nedenle, bu codelab'de oyunlara odaklanacağız.

Ön koşullar

  • Flutter'a temel düzeyde aşinalık.
  • Flutter uygulamalarını çalıştırma ve hata ayıklama hakkında bilgi sahibi olma.

Öğrenecekleriniz

  • Tek seferlik sesler nasıl çalınır?
  • Boşluksuz müzik döngüleri nasıl çalınır ve özelleştirilir?
  • Sesler nasıl açılır ve azaltılır?
  • Seslere çevre efektleri uygulama.
  • İstisnaları ele alma.
  • Tüm bu özellikleri tek bir ses denetleyicisinde birleş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 adla 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 yalnızca gelecekteki işlevler için iskelet. Bunların tümünü bu codelab 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 dizininde 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:

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

Dosyalar orada olduğuna göre Flutter'a bunları anlatmanız gerekir.

  1. pubspec.yaml dosyasını açın ve ardından dosyanın alt kısmındaki flutter: bölümünü şununla 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. Aşağıdaki bölümlerde işlevi 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 tarafından diğer oyunlarla birlikte kullanılan oyunlar için bir C++ ses motoru olan SoLoud projesine dayanmaktadı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 denetleyici, 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. Bunu üretim kodunda yapmak ve hataları kullanıcıya bildirmek istersiniz.
  1. dispose() yönteminde aşağıdaki kodu girin:

lib/audio/audio_controller.dart

...

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

...

Uygulamadan çıkış sırasında SoLoud'un kapatılması iyi bir uygulamadır. Ancak bunu ihmal etseniz bile her şey düzgün çalışır.

  1. AudioController.initialize() yönteminin zaten main() işlevinden ç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.

Soud, bir sesi tanımlamak için kullanılan veri ve meta veri olan ses kaynağı ile gerçekte çalınan sesleri içeren "ses örnekleri"ni birbirinden ayırır. 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 olsa pek çok kez oynatabilirsiniz.

Bir ses kaynağıyla işiniz bittiğinde SoLoud.disposeSource() yöntemini kullanarak bu kaynağı ortadan kaldırırsınız.

Bir öğeyi yükleyip 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, çalışırken yeniden yükleyin ve Ses çal'ı seçin. Komik bir eğim sesi duyacaksınız. Aşağıdakileri göz önünde bulundurun:
  • Sağlanan assetKey bağımsız değişkeni, assets/sounds/pew1.mp3 benzeri bir dizedir. Image.asset() widget'ı gibi öğe yükleyen diğer tüm Flutter API'lerine sağlayacağınız dizedir.
  • 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. Dosya sisteminden dosya yüklemek (loadFile() yöntemi) ve URL'den ağ üzerinden yüklemek (loadUrl() yöntemi) için eşdeğer yöntemler vardır.
  • Yeni edinilen AudioSource örneği, daha sonra SoLoud'un play() yöntemine iletilir. Bu yöntem, yeni çalınan sesi temsil eden SoundHandle türünün bir örneğini 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 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 eklentisine özgü olan, Dart kodu ile platform kodu arasındaki iletişimi bulmak hiçbir yerde yoktur. 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! ile _soloud alanının boş olmadığını kabul edersiniz. Bunları da kısa bir süre için tekrarlıyoruz. Üretim kodu, ses denetleyicisi tam olarak başlatılmadan önce geliştiricinin ses çalmaya çalıştığı durumu incelikle ele almalıdır.

İstisnalarla ilgilenin

Olası istisnaları bir kez daha göz ardı ettiğinizi fark etmiş olabilirsiniz. Öğrenme amacıyla 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 durumda istisnaları ele almak için playSound() yönteminin iki satırını bir try/catch bloğuna sarmalayı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);
    }
  }

  ...

Soud, SoLoudNotInitializedException veya SoLoudTemporaryFolderFailedException istisnaları gibi çeşitli istisnalar uygular. Her yöntemin API belgeleri, atılabilecek istisna türlerini listeler.

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 çalmanın kritik olmadığı durumlarda faydalıdır. Örneğin, yalnızca sıra seslerinden biri yüklenemediği için oyuncunun oyun oturumunun kilitlenmesini istemediğinizde.

Muhtemelen tahmin edeceğiniz gibi, var olmayan bir öğe anahtarı sağlarsanız loadAsset() yöntemi de FlutterError hatası verebilir. Oyunla birlikte sunulmayan öğeleri yüklemeye çalışmak genellikle ele almanız gereken bir sorundur, bu yüzden bu bir hatadır.

Farklı sesler çalma

Yalnızca pew1.mp3 dosyasını oynattığınızı ancak öğeler dizininde sesin başka iki sürümü olduğunu fark etmiş olabilirsiniz. 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 yöntem, örneğin ayak seslerinin ve silah fotoğraflarının fazla tek tip ve bu nedenle sahte sesler çıkarmasını önler.

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

Semboller için

5. Müzik döngüleri çalma

Uzun süren sesleri yönetin

Bazı sesler uzun süre çalmak için kullanılır. Bunun en bariz örneği müzik olsa da pek çok oyun, koridorlardan geçen rüzgarın uğultusu, keşişlerin uzaktan marşları, yüzlerce yıllık metallerin gıcırdaması veya hastaların uzaktan öksürmesi gibi bir ortam yaratır.

Bunlar, dakika cinsinden ölçülebilen çalma sürelerine sahip ses kaynaklarıdır. Gerektiğinde duraklatabilmek veya durdurabilmek için bu hedefleri takip etmeniz gerekir. Ayrıca genellikle büyük dosyalar tarafından desteklenir ve çok fazla bellek kullanabilir. 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 ürününe yeni bir özel alan sunacaksınız. 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

Esasında müzik çalmak, tek seferlik bir ses çalmaktan farklı değildir. Yine de öncelikle assets/music/looped-song.ogg dosyasını AudioSource sınıfının bir örneği olarak yüklemeniz, ardından dosyayı oynatmak için SoLoud'un play() yöntemini kullanmanız gerekir.

Ancak bu kez, ses çalarken sesi değiştirmek için play() yönteminin döndürdüğü ses tutma yerini tutarsınız.

  • İsterseniz AudioController.startMusic() yöntemini kendiniz uygulayabilirsiniz. Bazı ayrıntıları doğru bilemeyebilirsiniz. Ö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 sıralaması) yüklediğinize dikkat edin. Bu, dosyanın yalnızca gerektiği gibi parçalar halinde yükleneceği anlamına gelir. Daha uzun süren sesler için genellikle en iyi yükleme disk modunda yüklemedir. Kısa ses efektleri için bunları yükleyip belleğe (varsayılan LoadMode.memory sıralaması) yüklemek daha anlamlıdır.

Fakat bazı sorunlarınız var. Öncelikle müzik çok yüksek, ses fazla bastırıyor. Ç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 şeyle 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 çalan şarkının dışına geçmesi gerektiğinde, yalnızca şarkı yavaşça kaybolur.

Neyse ki SoLoud, döngü sesi çalmak için çeşitli yöntemler sunuyor. play() yöntemi, looping parametresi için boole değeri, ayrıca loopingStartAt parametresi olarak döngünün başlangıç noktası 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ı). Herhangi bir giriş olmadan mükemmel bir döngü oluşturabileceğiniz bir müzik parçanız varsa istediğiniz şey budur.

  • Çalınması bittiğinde ses kaynağının düzgün şekilde atıldığından emin olmak 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 pratik bir yanıp sönme yöntemleri sunuyor. Aşağıdaki adımları uygulayarak müziği beş saniye içinde azaltıp CPU kaynaklarını gereksiz yere kullanmaması 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

Uygun bir ses motoruna sahip olmanın en önemli avantajlarından biri ses işlemeyi (yankı, ekolayzır veya düşük geçiş filtresi aracılığıyla yönlendirme gibi) 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. Ormanda sesin yayılmasına ve emilmesine yardımcı olurken sığınağın sade duvarları ses dalgalarını yansıyarak yankı oluşturur. Benzer şekilde, insanların sesi bir duvardan duyulduğunda farklı geliyor. 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 farklı ses efektleri sunar.

  • Oynatıcınızın katedral veya mağara gibi büyük bir odada olduğu izlenimi oluşturmak için FilterType.freeverbFilter numaralandırmasını kullanın:

lib/audio/audio_controller.dart

...

  void applyFilter() {
    _soloud!.addGlobalFilter(FilterType.freeverbFilter);
    _soloud!.setFilterParameter(FilterType.freeverbFilter, 0, 0.2);
    _soloud!.setFilterParameter(FilterType.freeverbFilter, 2, 0.9);
  }

  void removeFilter() {
    _soloud!.removeGlobalFilter(FilterType.freeverbFilter);
  }

...

Gördüğünüz gibi, filtrelerle daha alt düzey bir bölgeyi keşfedersiniz. Filtre parametresinin ayarlanması, parametrenin dizini kullanılarak yapılır. Örneğin, serbest fiilin Islak parametresi 0 dizinine ve Oda Boyutu parametresi de 2 dizinine sahiptir.

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

  • Serbest fiil filtresini küresel olarak veya yalnızca tek bir sesi değil, tüm ses mix'i için etkinleştirin.
  • Wet parametresini 0.2 olarak ayarlayın. Bu işlem, elde edilen sesin% 80 orijinal, %20 yankı efekti çıkışının olacağı anlamına gelir. Bu parametreyi 1.0 olarak ayarlarsanız yalnızca odanın uzak duvarlarından gelen ses dalgalarını duymayı ve orijinal sesleri duymamayı tercih etmiş olursunuz.
  • Oda Boyutu parametresini 0.9 olarak ayarlayın. Bu parametreyi istediğiniz gibi veya dinamik olarak değiştirebilirsiniz. 1.0 dev bir mağaradır, 0.0 ise bir banyodur.
  • Gerekirse kodu değiştirin ve aşağıdaki filtrelerden birini veya aşağıdaki filtrelerin bir kombinasyonunu uygulayın:
  • FilterType.biquadResonantFilter (düşük geçiş filtresi olarak kullanılabilir)
  • FilterType.eqFilter
  • FilterType.echoFilter
  • FilterType.lofiFilter
  • FilterType.flangerFilter
  • FilterType.bassboostFilter
  • FilterType.waveShaperFilter
  • FilterType.robotizeFilter
  • FilterType.freeverbFilter

7. Tebrikler

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

Daha fazla bilgi

  • Başlangıçta sesleri önceden yükleme, şarkıları sırayla çalma veya zaman içinde kademeli olarak filtre uygulama gibi özelliklerle ses denetleyicisini geliştirmeyi deneyin.
  • flutter_soloud paket belgelerini okuyun.
  • Temel C++ kitaplığının ana sayfasını okuyun.
  • C++ kitaplığıyla arayüz oluşturmak için kullanılan Dart FFI hakkında daha fazla bilgi edinin.
  • İlham almak için Guy Somberg'in oyun ses programları hakkındaki konuşmasını izleyin. (Daha uzun bir yöntem de var.) Guy "ara yazılım"dan bahsettiğinde SoLoud ve FMOD gibi kütüphaneleri kastediyor. Kodun geri kalanı genellikle her oyuna özel olur.
  • Oyununuzu geliştirin ve yayınlayın.

Kulaklık resmi