Perché i motori audio non elaborano l'audio in modo più realistico?

2

Generalmente i motori audio di gioco utilizzano un sistema piuttosto semplice per il rendering dell'audio: 1. posizionare una sorgente audio nello spazio 2. applica effetti sulla clip audio in base all'area in cui si trova l'oggetto 3. sposta il volume / fase / pan in base all'angolo e alla distanza dall'ascoltatore

Ma nella vita reale l'audio si propaga in onde attraverso ogni mezzo e si riflette anche. Per esempio: se urli contro un muro, sarai molto più strong di se urlerai all'orizzonte (esempio grezzo, lo so).

Quindi la mia idea è di creare un motore audio che funzioni piuttosto come il raytracing nella grafica: Ogni passaggio (100 volte al secondo - > 441 campioni)

  1. Hai una sorgente audio che invia il suono Dry (che significa non modificato) in una quantità fissa di direzioni, distribuite uniformemente sulla sfera dell'angolo.
  2. Ogni raggio si propaga per un periodo di tempo limitato nello spazio.
  3. Se si colpisce un muro, viene creato un nuovo (più piccolo) set di raggi e si propaga con meno ampiezza (a seconda delle proprietà impostate sul muro)
  4. Quando questo processo viene eseguito e tutti i raggi raggiungono la loro lunghezza massima, ciascun raggio viene trattato come una funzione lineare e viene calcolata la distanza minima tra il raggio e ciascun canale di ascolto (ad esempio L / R).
  5. Lo spostamento di fase e l'ampiezza di ciascun raggio ora sono calcolati nel modo seguente

L'ampiezza è anti-proporzionale e lo sfasamento è proporzionale alla distanza percorsa dal raggio e alla distanza tra il raggio e l'ascoltatore, mentre questa distanza diventa meno efficace più il raggio ha percorso.

Mi dispiace se non è stato abbastanza chiaro - forse questo pseudocodice può aiutarti a capire cosa intendo.

// Code example in C# style
// C++ would be more performant but this is easier to get

// Base classes for clarity
class AudioRay
{
    Vector3 Source;
    Vector3 Direction;
    float DistanceOffset;
    float MaxLength;
    float Volume = 1;

    public AudioRay(Vector3 src, Vector3 dir, float off, float maxLen, float vol);

    public struct Intersection
    {
        Vector3 Point;
        Vector3 InAngel;
        Vector3 OutAngle;
        float MaterialMuffling;
    }

    public Intersection GetIntersection()
    {
        // Todo - just concept - I don't really know how to calculate that
    }
}

static class RayCaster
{
    static Vector3 GetNearestPoint(Vector3 targetPoint, Vector3 source, Vector3 direction)
    {
        // Nearest point on a line to a point...
    }

    static List<AudiorRay> Cast(AudioRay ray, float maxLength)
    {
        List<AudiorRay> rays = new List<AudiorRay>();
        AudioRay.Intersection intersection = ray.GetIntersection();

        if(intersection!= null) // Only cast new rays when the old one intersected with a wall
        {
            float len = ray.DistanceOffset + (intersection.Point - ray.Source).Length;
            if(len < maxLength) // ... and if they are below the max length 
            {
                List<AudioRay> newRays = new List<AudioRay>();

                // Add the new rays --> This is only the central one but the others will be evenly distributed
                newRays.Add(new AudioRay(intersection.Point, interse.OutAngle, len, maxLenght, vol * intersection.MaterialMuffling));

                // Cast the new rays but
                newRays.ForEach(t => rays.AddRange(Cast(t))); 
            }
        } 
    }
}

// Main class
class AudioSource
{
    Vector3 Position = new Vector3(0, 0, 0);
    Vector3 ListenerPos = new Vector3(10, 20, 30);
    int StartRayCount = 162;
    int BounceRayCount = 11;
    float BounceRayAngle = 25;
    float MaxRayLength = 1000;

    // The dry wave parameter is not the buffer but the whole file so we can adress
    // every sample all over the file.
    // I suspect a 512 sample out buffer (~12 ms) 
    // wavePositionOffset = position in the track
    public float[] Pass(float[] dryWave, int wavePositionOffset)
    {
        List<AudioRay> rays = new List<AudioRay>();

        int samples = StartRayCount;
        float offset = 2.0f / (float)samples;
        float increment = Math.Pi * ( 3.0f - Math.Sqrt(5.0f));

        // Create source rays
        for(int i = 0; i < samples; i++)
        {
            float y = ((i * offset) - 1f) + (offset / 2f);
            float r = Math.Sqrt(1f - Math.Pow(y, 2f));
            float phi = (i % samples) * increment;
            float x = Math.Cos(phi) * r
            float z = Math.Sin(phi) * r

            AudioRay ray = new AudioRay();
            ray.Source = Position;
            ray.Direction = new Vector3(x, y, z).Normalized;
            ray.DistanceOffset = 0f;
            ray.MaxLength = MaxRayLength;

            rays.Add(ray);
            rays.AddRange(RayCaster.Cast(ray, MaxRayLength));
        }

        // Create the out buffer
        float[] oB = new float[512]();

        float distanceVolumeFalloff = -0.01;    // Complete silence after 100 m
        float phaseShift = 20;                   // 20 samples / m shift

        // calculate all rays phases and volumes
        foreach(AudioRay ray in rays)
        {
            for(int i = 0; i < 512; i++)
            {
                Vector3 nearestPoint = GetNearestPoint(ListenerPos, ray.Position, ray.Direction);
                float dist = ray.DistanceOffset + (nearestPoint - ray.Position);

                // vol can't go below 0
                // Respect the material properties stored in RayVolume
                float vol =  Math.Max(1 - dist * distanceVolumeFalloff, 0f) * ray.Volume;

                int sampleOffset = (int)(dist * phaseShift);

                int pos = wavePositionOffset-sampleOffset
                if(pos > 0 && pos < dryWave.Length)
                    oB[i] +=  dryWave[pos] * vol;
            }
        }

        return oB;
    }
}

La mia domanda qui è: perché i motori non supportano ancora questo modello audio? Non penso ci sarebbe troppo sovraccarico della CPU poiché il riverbero è essenzialmente lo stesso e ho "implementato" i valori delle prestazioni (ad esempio StartRayCount e MaxRayLenght). L'unica cosa che potrebbe essere (rendimento saggio) difficile da fare è il raycasting. Ma la tua GPU fa milioni di volte e parlava forse centinaia di volte dicono 100 volte al secondo. Questo è ancora molto meno di quello che fa una scena video 3D.

Pixel / secondo: 1920 x * 1080 y * 60 FPS = 124.416.000 solo Full HD - Quadrupel per 4K

Raggi / secondo: dì circa 200 a 1000? * 100 raggi / secondo = da 200.000 a 1.000.000

Prima che qualcuno gridi: ho fatto la mia ricerca e ho letto questo .

    
posta subbestionix 06.10.2016 - 16:46
fonte

2 risposte

8

Non ci sono motivi tecnici per cui nulla di ciò sia stato fatto. l'elaborazione di questa profondità è già stata effettuata sulle immagini visualizzate dal gioco (anche se non nello stesso modo).

Il problema non è tanto l'elaborazione ... è riprodurre il suono in un modo realistico e che il sistema nervoso umano interpreterà per essere autentico.

Considera un normale sistema audio. La teoria è che il suono dell'altoparlante sinistro va all'orecchio sinistro e il suono dell'altoparlante destro va all'orecchio destro:

Iltuosistemaègiàcompromessointerminidirealismo.Perché?Poichépartedelsuonoprovenientedall'altoparlantesinistroraggiungel'orecchiodestroepartedelsuonoprovenientedall'altoparlantedestroraggiungel'orecchiosinistro.

Quindideviusarelecuffie.Lecuffieisolanoisuonidiciascuntrasduttore,inmodochel'orecchiosinistroricevasoloisuonidalcanalesinistroel'orecchiodestroricevasoloisuonidalcanaledestro.

Orahaiunnuovoproblema:comemodelliicambiamentinell'orientamento?Conmonitorecuffie,nonpuoifarloinmodorealistico.Invecediruotarelatestaperincontrareilmondo,ilpaesaggiosonororuotaintornoate,mentreilpaesaggiovisivorimanestazionario.Iltuosistemanervosononlointerpreteràcomecompletamenteautentico.

SistemicomeOculusRifteMicrosoftHololensrisolvonoentrambiquestiproblemimettendoitrasduttori(ilmonitorelecuffie)sullatuatestaerilevandol'orientamento,inmodochequandomuovilatesta,ilpaesaggioeilpaesaggiosonororuotinorealisticamenteintornoate.

Eisuonidall'altoedalbasso?Letueorecchiepossonodiredadoveprovengonoquestisuoniacausadellaformadell'orecchioesterno.Quindi,perriprodurresuegiù,devitrovareunmodoperriprodurrematematicamenteicontornisonoridell'orecchioesternoocrearecuffiecheforniscanoilsuonodallagiustadirezione.Il Ossic X tenta di risolvere questo problema calibrandolo alla tua anatomia.

Quindi l'elaborazione non è il problema; stiamo aspettando la disponibilità diffusa di dispositivi che rende l'esperienza più coinvolgente e realistica (sia per audio che per video).

    
risposta data 06.10.2016 - 17:27
fonte
3

In realtà, ci sono motori audio di gioco che fanno ciò che proponi.

link

e un altro qui link

Includono direzionalità, riflessione e fondamentalmente un tracciamento del suono basato su vettori.

Molto chiaramente, l'attenzione su "una grafica liscia" è in genere molto più elevata dell'audio - Da un lato, non tutte le console hanno (e nel mondo PC, gli utenti non possiedono) l'hardware corretto per un vero suono surround ( vedi l'XBox nell'articolo collegato), d'altra parte, c'è una costante lotta tra i ragazzi del suono e della grafica per la CPU - E, la grafica apparentemente "paga meglio". I clienti sembrano ancora acquistare giochi di qualità visiva piuttosto che udibile.

    
risposta data 06.10.2016 - 18:18
fonte

Leggi altre domande sui tag