Kauguspõhine heli (distance-based audio)

Sissejuhatus

Kauguspõhine heli võimaldab mängusimulaatorites luua realistlikuma helikeskkonna, kus helitugevus sõltub mängija kaugusest heli allikast. See lähenemine aitab mängijal paremini tajuda ümbritsevat keskkonda.

Kauguspõhist heli kasutatakse olukordades, kus heliallikad paiknevad mängumaailmas kindlates kohtades ning mängija liikumine nende suhtes mõjutab helide tajumist. Näiteks võib see olla kasulik:

  • Taustamüra (nt elektriliinide sumin, veevulin) loomisel, mis muutub valjemaks, kui mängija läheneb allikale.

  • Hoiatussignaalide või ohtude märkamise hõlbustamiseks, kus heli tugevneb ohuallikale lähenedes.

  • Mängumaailma atmosfääri rikastamiseks, lisades dünaamilisi heliefekte vastavalt mängija asukohale.

Selles peatükis uurime kauguspõhise heli loomise põhimõtteid, tuginedes järgmisele näitele: Distance based sound example (libGDX)

Kauguspõhise heli rakendamine

1. Heliressursi laadimine

Esmalt tuleb laadida vajalik helifail, mida soovime mängus kasutada.

Siin loome Music objekti, mis esindab meie heliallikat. Fail electric-sound.mp3 peaks asuma projekti assets kaustas.

Music electricSound = Gdx.audio.newMusic(Gdx.files.internal("electric-sound.mp3"));

2. Heli esitamine ja peatamine sõltuvalt kaugusest

Järgmisena määrame loogika, mis otsustab, millal heli esitada või peatada, sõltuvalt mängija kaugusest heliallikast.

Funktsioon canPlaySound() kontrollib, kas mängija ei ole dialoogis, cutscene on lõppenud ja mäng ei ole MENU olekus. Kui kõik tingimused on täidetud ja heli ei mängi, alustatakse esitust. Kui tingimused enam ei kehti, peatatakse heli esitamine.

if (canPlaySound()) {
    if (!electricSound.isPlaying()) {
        electricSound.play();
    }
    updateElectricSoundVolume();
} else {
    if (electricSound.isPlaying()) {
        electricSound.pause();
    }
}

3. Helitugevuse dünaamiline muutmine

Helitugevuse sujuvaks muutmiseks vastavalt kaugusele:

Arvutame mängija ja heliallika vahelise kauguse ning määrame helitugevuse vastavalt sellele. Kui mängija on väga lähedal, mängib heli maksimaalse tugevusega; kui kaugel, siis heli ei mängi üldse. Vahepealsetel kaugustel muutub helitugevus sujuvalt.

private void updateElectricSoundVolume() {
    float maxDistance = 300f;  // kaugus, mille juures heli on vaevukuuldav
    float minDistance = 50f;   // kaugus, mille juures heli on maksimaalse tugevusega
    float maxVolume = 0.7f;

    float distance = characterPosition.dst(lightning.getPosition()); // eeldades, et lightning-l on meetod getPosition()

    if (distance < minDistance) {
        electricSound.setVolume(maxVolume);
    } else if (distance > maxDistance) {
        electricSound.setVolume(0f);
    } else {
        // Lineaarne interpolatsioon minimaalse ja maksimaalse kauguse vahel
        float volume = maxVolume * (1 - (distance - minDistance) / (maxDistance - minDistance));
        electricSound.setVolume(volume);
    }
}

4. Ressursside vabastamine

Ja muidugi ära unusta vabastada electricSound objekti poolt kasutatud ressursid.

electricSound.dispose();

Täiendavad võimalused ja optimeerimised

Helitugevuse muutmise sageduse piiramine

Helitugevuse pidev muutmine igal kaadril võib põhjustada jõudlusprobleeme. Selle vältimiseks võime piirata helitugevuse uuendamise sagedust, näiteks iga 200 millisekundi järel.

See lähenemine vähendab protsessori koormust, säilitades samas heli sujuvuse.

long lastUpdateTime = 0;
long updateInterval = 200; // millisekundites

public void update(float deltaTime) {
    long currentTime = TimeUtils.millis();
    if (currentTime - lastUpdateTime > updateInterval) {
        updateElectricSoundVolume();
        lastUpdateTime = currentTime;
    }
}

Realistlikum helitugevuse langus

Helitugevuse langust kauguse suurenedes võib modelleerida realistlikumalt, kasutades pöördvõrdelist ruutfunktsiooni.

See tagab, et helitugevus väheneb kiiremini kauguse suurenedes, imiteerides reaalse maailma heli käitumist.

float distance = characterPosition.dst(lightning.getPosition());
float volume = maxVolume / (1 + distance * distance);
electricSound.setVolume(volume);

Stereoefektide lisamine

Kui soovite lisada stereoefekte, kus heli suund sõltub mängija asukohast heliallikaga võrreldes, peate kasutama Sound klassi ja määrama vasaku ja parema kanali helitugevused eraldi. LibGDX-is saab seda teha järgmiselt:

Siin pan väärtus vahemikus -1 (vasak) kuni 1 (parem) määrab heli suuna.

Sound sound = Gdx.audio.newSound(Gdx.files.internal("sound.wav"));
long soundId = sound.play();
sound.setPan(soundId, pan, volume);

Lähtekood

  • Vaata näidisprojekti GitHubis: GitHub