Cómo no desarrollar motores de sonido



Cuando programaba sonido en aplicaciones y juegos, a menudo tenía que reescribir todo el código base de los módulos de sonido, ya que muchos de ellos tenían una arquitectura demasiado complicada o, por el contrario, no podían hacer nada más que reproducir sonidos.



La analogía con la renderización de imágenes en juegos funciona bien con motores de sonido: si tiene una tubería demasiado simple con una gran cantidad de abstracciones, entonces difícilmente puede programar adecuadamente algo más complicado que un cubo con engranajes. Por otro lado, si su código completo consiste en llamadas directas OpenGL o D3D, entonces no puede escalar su código espagueti sin dolor.



¿Qué tan relevante es la comparación con la representación gráfica?



En el renderizado de sonido, tienen lugar los mismos procesos que en el renderizado de gráficos: actualización de recursos de la lógica del juego, procesamiento de datos en una forma digerible, posprocesamiento y salida del resultado final. Todo esto puede llevar bastante tiempo, así que por el bien de la ilustración, utilizo mi biblioteca de audio para probar el rendimiento del renderizado.



SSD , Opus , , DSP (, ), . , : Inte Core i9 9900 4.5GHz, 32GB RAM, SSD 480GB SATA. 48000 44100.



    FRESPONZE_BEGIN_TEST
    if (!pFirstListener) return false;
    //      - 
    if (RingBuffer.GetLeftBuffers()) return false;
    RingBuffer.SetBuffersCount(RING_BUFFERS_COUNT);
    RingBuffer.Resize(Frames * Channels);
    OutputBuffer.Resize(Frames * Channels);
    tempBuffer.Resize(Channels, Frames);
    mixBuffer.Resize(Channels, Frames);

    for (size_t i = 0; i < RING_BUFFERS_COUNT; i++) {
        tempBuffer.Clear();
        mixBuffer.Clear();
        pListNode = pFirstListener;
        while (pListNode) {
            /*       */
            EmittersNode* pEmittersNode = nullptr;
            if (!pListNode->pListener) break;
            pListNode->pListener->GetFirstEmitter(&pEmittersNode);
            while (pEmittersNode) {
                tempBuffer.Clear();
                pEmittersNode->pEmitter->Process(tempBuffer.GetBuffers(), Frames);
                //  
                for (size_t o = 0; o < Channels; o++) {
                    MixerAddToBuffer(mixBuffer.GetBufferData((fr_i32)o), tempBuffer.GetBufferData((fr_i32)o), Frames);
                }

                pEmittersNode = pEmittersNode->pNext;
            }

            pListNode = pListNode->pNext;
        }

        /*         */
        PlanarToLinear(mixBuffer.GetBuffers(), OutputBuffer.Data(), Frames * Channels, Channels);
        RingBuffer.PushBuffer(OutputBuffer.Data(), Frames * Channels);
        RingBuffer.NextBuffer();
    }
    FRESPONZE_END_TEST("Audio render")


[00:00:59:703]: 'Audio render' operation passed: 551 microseconds
[00:00:59:797]: 'Audio render' operation passed: 512 microseconds
[00:00:59:906]: 'Audio render' operation passed: 541 microseconds
[00:01:00:000]: 'Audio render' operation passed: 583 microseconds


, , , . , , .



?



, . — -, C++, SoLoud OpenAL. , — . API , OpenAL Wwise.



. — ref_sound ISoundManager, , , , , . — , UAudioComponent Unreal Engine.



void Class::Function()
{
    //        
    snd.play_at_pos(0, Position(), false);

    //  
    if (IsHappened())
    {
        // ...
    }

    // ...
}


, — CSoundRender_Target, API OpenAL DirectSound, CSoundRender_Cache — Vorbis . target — , source + emitter.







, Core (FMOD Wwise), API (PortAudio).





,





, — (hardware) (mixer). , , API. .



:



void GameScheduler::Update() {
    // ...    

    // ,     .
    //    ,    
    //    .
    SoundManager::StopSound(id);

    // ...
}

// ...

void AudioHardware::Update() {
    // ...    

    //     : 
    //   ,    
    //      .
    AudioMixer::Render(input, frames);
    memcpy(output, input, frames * channels * frame_size);

    // ...
}


- . AudioHardware PortAudio, Windows Audio Session API. SoundManager — FMOD Wwise. AudioHardware , .



: routing emitters-source . DAW, , . , side-chain , . , - .







emitters-source. 2 — (source), , , (emitter) — , , -. emitters-source ( Wwise FMOD virtual emitters), .



emitters-source . miniaudio, .




All Articles