September 02, 2025, 08:16:35 pm

The Gang Garrison 2 Forum

Please login or register.

Login with username, password and session length
Advanced search  

News:

NOTICE: Wondering where all the forums have gone?

Join the community Discord server!

Pages: [1] 2

Author Topic: Beta testing: Windows 10 audio fixes for Gang Garrison 2  (Read 2926 times)

PrOF

  • Full Member
  • ***
  • Karma: 43
  • Offline Offline
  • Posts: 593
  • Sometimes a dev. Only sometimes
Beta testing: Windows 10 audio fixes for Gang Garrison 2
« on: January 14, 2018, 11:22:40 am »

This is a beta branch to test if a bugfix for the next release works correctly
The changes are only noticeable on Windows 10 computers. Before Gang Garrison 2 automatically disabled some sound effects on Windows 8 and 8.1 machines to avoid crashing. It seems this is not an issue on Windows 10, but we need testers.

See the pull request here

You can either download the attachment, but lose all your settings, maps and music, or move the new executable in your old GG2 folder
Download here
Logged

AKVARI

  • Full Member
  • ***
  • Karma: 11
  • Offline Offline
  • Posts: 508
Re: Beta testing: Windows 10 audio fixes for Gang Garrison 2
« Reply #1 on: January 14, 2018, 01:34:25 pm »

Had no idea that Windows 10 also had audio bugs with GG2.

PrOF

  • Full Member
  • ***
  • Karma: 43
  • Offline Offline
  • Posts: 593
  • Sometimes a dev. Only sometimes
Re: Beta testing: Windows 10 audio fixes for Gang Garrison 2
« Reply #2 on: January 14, 2018, 01:49:14 pm »

Had no idea that Windows 10 also had audio bugs with GG2.
In the live version GG2 assumes it's going to have issues with the os and disables some features. But my testing revealed that it shouldn't, so I re-enabled them in this build. We have to be sure it also works on other PC though
Logged

Spazz

  • Seasoned Member
  • *****
  • Karma: 44
  • Offline Offline
  • Posts: 1910
  • Almost too much seasoning.
Re: Beta testing: Windows 10 audio fixes for Gang Garrison 2
« Reply #3 on: January 14, 2018, 02:49:03 pm »

PC is Win7 though I have (Actually the missy does) two Win10 laptops

If I was to participate, what am I looking for?
Logged

<3 Bustatunez

PrOF

  • Full Member
  • ***
  • Karma: 43
  • Offline Offline
  • Posts: 593
  • Sometimes a dev. Only sometimes
Re: Beta testing: Windows 10 audio fixes for Gang Garrison 2
« Reply #4 on: January 14, 2018, 03:24:03 pm »

PC is Win7 though I have (Actually the missy does) two Win10 laptops

If I was to participate, what am I looking for?
If it works you shouldn't be able to tell the difference, if it doesn't then "Gang Garrison 2 has stopped working"
Be sure to play for some time, we're looking for crashes triggered by intense gameplay
Logged

PrOF

  • Full Member
  • ***
  • Karma: 43
  • Offline Offline
  • Posts: 593
  • Sometimes a dev. Only sometimes
Re: Beta testing: Windows 10 audio fixes for Gang Garrison 2
« Reply #5 on: January 22, 2018, 01:34:11 am »

Has anyone using Windows 10 found any sound-related bugs with this build? Let me know please
Logged

Spazz

  • Seasoned Member
  • *****
  • Karma: 44
  • Offline Offline
  • Posts: 1910
  • Almost too much seasoning.
Re: Beta testing: Windows 10 audio fixes for Gang Garrison 2
« Reply #6 on: January 22, 2018, 01:25:00 pm »

Do no believe I placed enough time in this to verify or not, not that I have much to begin with. Apologies, will continue later.
Logged

<3 Bustatunez

Derpduck

  • 2011 Haxxy Finalist
  • *
  • Karma: 42
  • Offline Offline
  • Posts: 5752
Re: Beta testing: Windows 10 audio fixes for Gang Garrison 2
« Reply #7 on: January 22, 2018, 03:31:25 pm »

I think a bit more clarification on what people are actually looking for would help.

PrOF

  • Full Member
  • ***
  • Karma: 43
  • Offline Offline
  • Posts: 593
  • Sometimes a dev. Only sometimes
Re: Beta testing: Windows 10 audio fixes for Gang Garrison 2
« Reply #8 on: January 22, 2018, 04:07:15 pm »

I think a bit more clarification on what people are actually looking for would help.
Alright:
If you previously played GG2 on a Windows 10 machine, with this build you will be able to hear more sounds at the same time. Go play and have fun, if it crashes "Gang Garrison 2 stopped working, Windows is looking for a solution" then tell me. That's what we're looking for, and hopefully if I'm right that won't happen, because we're not looking for a bug, we're confirming that an audio fix doesn't crash the game.
Again, Windows 7/8 users will not notice a difference
Logged

Phantom Brave

  • All Hail Classicwell
  • Moderator
  • *****
  • Karma: 70
  • Offline Offline
  • Posts: 12524
  • Another one --
Re: Beta testing: Windows 10 audio fixes for Gang Garrison 2
« Reply #9 on: February 24, 2018, 12:20:18 am »

for mine/medo's reference:

WASAPI demo:
Code: [Select]
// -lavrt -lole32 -lksuser

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <initguid.h>
#include <avrt.h>
#include <mmdeviceapi.h>
#include <audioclient.h>
#include <stdio.h>
#include <stdint.h>

#include <thread> // for sleeping

IMMDeviceEnumerator* enumerator = nullptr;
IMMDevice* audioDevice = nullptr;
IPropertyStore* propertyStore = nullptr;
IAudioClient* audioClient = nullptr;
IAudioRenderClient* renderClient = nullptr;
WAVEFORMATEX* waveFormat = nullptr;
WAVEFORMATEXTENSIBLE* waveFormatEx = nullptr;
PROPVARIANT propVariant;
HANDLE taskHandle = nullptr;
REFERENCE_TIME devicePeriod = 0;
uint32_t bufferSize;

#include <math.h>
#ifndef M_PI
#define M_PI 3.141592653589793
#endif

#define max(x,y) ((x>y)?(x):(y))

int type = -1; // 0: 16-bit signed int; 1: 32-bit float; -1: unsupported

double freq = 100;
double volume = 0.2;

float mixbuffer[4096*256];
void mix_sine(float * buffer, uint64_t count, uint64_t samplerate, uint64_t channels, uint64_t time)
{
    double nyquist = samplerate/2.0;
    for(uint64_t i = 0; i < count; i++)
    {
        for(uint64_t c = 0; c < channels; c++)
        {
            buffer[i*channels + c] = sin((i+time)*M_PI*freq/nyquist)*volume;
        }
    }
}

int main()
{
    // initialize COM
    CoInitialize(nullptr);
    // load device enumerator
    if(CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&enumerator) != S_OK) return puts("a"), false;
    // get default output
    if(enumerator->GetDefaultAudioEndpoint(eRender, eConsole, &audioDevice) != S_OK) return false;
    // activate endpoint
    if(audioDevice->Activate(IID_IAudioClient, CLSCTX_ALL, nullptr, (void**)&audioClient) != S_OK) return puts("b"), false;
   
    // get format of endpoint
    if(audioClient->GetMixFormat(&waveFormat) != S_OK) return puts("c"), false;
    if(waveFormat->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
        waveFormatEx = (WAVEFORMATEXTENSIBLE*)waveFormat;
    if(waveFormat->wBitsPerSample == 16 and (!waveFormatEx or waveFormatEx->SubFormat == KSDATAFORMAT_SUBTYPE_PCM))
        type = 0;
    if(waveFormatEx and waveFormatEx->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT and waveFormat->wBitsPerSample == 32)
        type = 1;
    if(type == -1)
        return puts("Unsupported format"), 0;
   
    printf("Type: %d\n", type);
    printf("Channels: %d\n", waveFormat->nChannels);
   
    uint32_t samples = 512;
   
    uint32_t latency = double(samples)/waveFormat->nSamplesPerSec*10'000'000; // 10: 100ns -> 1us; 1000: us -> ms; 1000: ms -> s
    printf("asking for %fms buffer size\n", double(samples)/waveFormat->nSamplesPerSec*1000);
   
    // open endpoint
    if(audioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, latency, 0, waveFormat, nullptr) != S_OK) return puts("f"), false;
    DWORD taskIndex = 0;
    taskHandle = AvSetMmThreadCharacteristics("Faucet Mixer", &taskIndex);
   
    // set up render client
    if(audioClient->GetService(IID_IAudioRenderClient, (void**)&renderClient) != S_OK) return puts("g"), false;
    // needed metadata
    if(audioClient->GetBufferSize(&bufferSize) != S_OK) return puts("h"), false;
   
    // info
    REFERENCE_TIME default_period, min_period;
    if(audioClient->GetDevicePeriod(&default_period, &min_period) != S_OK) return puts("e"), false;
    printf("actual buffer size: %fms\n", double(bufferSize)/waveFormat->nSamplesPerSec*1000);
    printf("default period: %fms\n minimum period: %fms\n", double(default_period)/10'000, double(min_period)/10'000);

    // start
    if(audioClient->Start() != S_OK) return puts("d"), false;
   
    uint64_t t = 0;
   
    // reduce latency by memeing (note: terrible idea, just for example)
    //uint32_t padding_offset = bufferSize - double(default_period)/10'000'000*waveFormat->nSamplesPerSec;
    uint32_t padding_offset = 0;
   
    while(t < 100000)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
        uint32_t padding = 0;
        auto err = audioClient->GetCurrentPadding(&padding);
        if(err != S_OK)
            printf("GetCurrentPadding threw error: %ld\n", err);
       
        auto render = max(0, int64_t(bufferSize)-int64_t(padding+padding_offset));
        if(render > 0)
        {
            mix_sine(mixbuffer, render, waveFormat->nSamplesPerSec, waveFormat->nChannels, t);
            t += render;
           
            unsigned char * backend_buffer;
            err = renderClient->GetBuffer(render, &backend_buffer);
            if(err != S_OK)
                printf("GetBuffer threw error: %ld\n", err);
           
            for(uint32_t i = 0; i < render*waveFormat->nChannels; i++)
            {
                if(type == 1)
                    ((float*)(backend_buffer))[i] = mixbuffer[i];
                if(type == 0)
                    ((int16_t*)(backend_buffer))[i] = round(mixbuffer[i]*0x7FFF);
            }
           
            err = renderClient->ReleaseBuffer(render, 0);
            if(err != S_OK)
                printf("ReleaseBuffer threw error: %ld\n", err);
        }
    }
   
    return 0;
}


DirectSound demo:

Code: [Select]
// -lole32 -ldsound -ldxguid
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <mmsystem.h>
#include <dsound.h>
#include <stdio.h>
#include <stdint.h>

typedef HRESULT (WINAPI * t_DirectSoundCreate8) (LPGUID, LPDIRECTSOUND *, LPUNKNOWN);
t_DirectSoundCreate8 dyn_DirectSoundCreate8 = nullptr;

#include <thread> // for sleeping

#include <math.h>
#ifndef M_PI
#define M_PI 3.141592653589793
#endif

#define max(x,y) ((x>y)?(x):(y))

double freq = 100;
double volume = 0.2;

float mixbuffer[4096*256];
void mix_sine(float * buffer, uint64_t count, uint64_t samplerate, uint64_t channels, uint64_t time)
{
    double nyquist = samplerate/2.0;
    for(uint64_t i = 0; i < count; i++)
    {
        for(uint64_t c = 0; c < channels; c++)
        {
            buffer[i*channels + c] = sin((i+time)*M_PI*freq/nyquist)*volume;
        }
    }
}

int main()
{
    // initialize COM
    CoInitialize(nullptr);
   
    IDirectSound8 * device;
    // FIXME: docs show &CLSID_DirectSound8, but I need to drop the & to compile, and it runs properly. what's going on?
    auto err = CoCreateInstance(CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER, IID_IDirectSound8, (LPVOID*) &device);
    if(err != S_OK)
        return puts("could not initialize directsound via COM\n"), 0;
   
    err = device->Initialize(&DSDEVID_DefaultPlayback);
    if(err != S_OK)
        return puts("failed to initialize dsound device\n"), 0;
   
    err = device->SetCooperativeLevel(GetDesktopWindow(), DSSCL_PRIORITY);
    if(err != S_OK)
        return puts("SetCooperativeLevel failed\n"), 0;
   
    // open up primary (underlying) buffer
    DSBUFFERDESC bufferdesc;
    bufferdesc.dwSize = sizeof(bufferdesc);
    bufferdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
    bufferdesc.dwBufferBytes = 0;
    bufferdesc.dwReserved = 0;
    bufferdesc.lpwfxFormat = 0;
    memset(&(bufferdesc.guid3DAlgorithm), 0, sizeof(bufferdesc.guid3DAlgorithm));
   
    IDirectSoundBuffer * buffer_out;
   
    err = device->CreateSoundBuffer(&bufferdesc, &buffer_out, 0);
    if(err != S_OK)
        return printf("CreateSoundBuffer (for buffer_out) failed %ld\n", err), 0;
   
    // desired format of output device (what happens on pre-WDM windows? this is like the format of the mixing stage in WASAPI)
    const auto channels = 2;
    const auto nbits = 16;
    const auto nbytes = nbits/8;
    const auto freq = 48000;
    WAVEFORMATEX format;
    format.wFormatTag = WAVE_FORMAT_PCM;
    format.nChannels = channels;
    format.nSamplesPerSec = freq;
    format.nAvgBytesPerSec = freq * nbytes * channels;
    format.nBlockAlign = nbytes * channels;
    format.wBitsPerSample = nbits;
    format.cbSize = 0;
   
    err = buffer_out->SetFormat(&format);
    if(err != S_OK)
        return printf("SetFormat failed %ld\n", err), 0;
   
    // open up secondary (ring buffer) buffer
   
    const auto samples = 1024;
   
    const auto oversize = 8; // does not affect latency, just underflow behavior
   
    bufferdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLFREQUENCY | DSBCAPS_GLOBALFOCUS | DSBCAPS_LOCSOFTWARE;
    bufferdesc.dwBufferBytes = samples * nbytes * channels * oversize;
    bufferdesc.lpwfxFormat = &format;
   
    IDirectSoundBuffer * buffer_write;
   
    // looping ring buffer to use to output to dsound's primary buffer
    err = device->CreateSoundBuffer(&bufferdesc, &buffer_write, 0);
    if(err != S_OK)
        return printf("CreateSoundBuffer (for buffer_write) failed %ld\n", err), 0;
    err = buffer_write->SetCurrentPosition(0);
    if(err != S_OK)
        return printf("SetCurrentPosition failed %ld\n", err), 0;
   
    // initialize ring buffer to silence
    DWORD clear_size; // must be DWORD, not uint32_t or uint64_t, due to those resolving to "unsigned int" and "long long unsigned int" on 32-bit mingw-w64
    void * clear_output;
    err = buffer_write->Lock(0, bufferdesc.dwBufferBytes, &clear_output, &clear_size, 0, 0, 0);
    if(err != S_OK)
        return printf("Lock failed %ld\n", err), 0;
    memset(clear_output, 0, clear_size);
    buffer_write->Unlock(clear_output, clear_size, 0, 0);
    if(err != S_OK)
        return printf("Unlock failed %ld\n", err), 0;
   
    err = buffer_write->Play(0, 0, DSBPLAY_LOOPING);
    if(err != S_OK)
        return printf("Play failed %ld\n", err), 0;
   
    // demo output loop
    uint64_t t = 0;
    uint64_t c_write = 0;
    while(t < 100000)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
        DWORD c_out, c_read;
        auto err = buffer_write->GetCurrentPosition(&c_out, &c_read); // the docs name the cursors badly
        if(err != S_OK)
            printf("GetCurrentPosition threw error: %ld\n", err);
       
        // size of the whole ring buffer in bytes
        int64_t ringsize = bufferdesc.dwBufferBytes;
       
        int64_t badpad = int64_t(c_read) - int64_t(c_out);
        while(badpad < 0)
            badpad += ringsize;
       
        // write cursor's distance rightwards relative to read cursor
        int64_t rightwards = int64_t(c_write) - int64_t(c_read);
        while(rightwards < 0)
            rightwards += ringsize;
       
        int64_t write_ahead = int64_t(samples*nbytes*channels) - rightwards;
        // if we underflowed
        if(write_ahead < 0)
            write_ahead = int64_t(samples*nbytes*channels);
        // don't write more than half the ring buffer at once
        if(write_ahead > ringsize/2)
            write_ahead = ringsize/2;
        // mustn't write into this region of the ring buffer
        if(write_ahead > ringsize - badpad)
            write_ahead = ringsize - badpad;
       
        // how many sample frames to render
        uint64_t render = write_ahead/(nbytes*channels);
        if(render > 0)
        {
            mix_sine(mixbuffer, render, freq, channels, t);
            t += render;
           
            // directsound ring buffers loop at the end and it might give us two buffers to write into when we lock it
            unsigned char * backend_buffer_1 = 0;
            DWORD backend_amount_1 = 0;
            unsigned char * backend_buffer_2 = 0;
            DWORD backend_amount_2 = 0;
            err = buffer_write->Lock(c_write, write_ahead, (void**)&backend_buffer_1, &backend_amount_1, (void**)&backend_buffer_2, &backend_amount_2, 0);
            if(err != S_OK)
                printf("Lock threw error: %ld\n", err);
           
            // write into the buffer (or two)
            uint64_t i = 0;
            uint64_t actually_written_1 = 0;
            for(uint64_t j = 0; backend_buffer_1 and j < backend_amount_1/nbytes and i < render*channels; j++)
            {
                ((int16_t*)(backend_buffer_1))[j] = round(mixbuffer[i++]*0x7FFF);
                actually_written_1 += nbytes;
            }
            uint64_t actually_written_2 = 0;
            for(uint64_t j = 0; backend_buffer_2 and j < backend_amount_2/nbytes and i < render*channels; j++)
            {
                ((int16_t*)(backend_buffer_2))[j] = round(mixbuffer[i++]*0x7FFF);
                actually_written_2 += nbytes;
            }
           
            // commit
            err = buffer_write->Unlock((void*)backend_buffer_1, actually_written_1, (void*)backend_buffer_2, actually_written_2);
            if(err != S_OK)
                printf("Unlock threw error: %ld; %ld %ld %ld\n", err, DSERR_INVALIDCALL, DSERR_INVALIDPARAM, DSERR_PRIOLEVELNEEDED);
           
            // progress write cursor by how much we actually wrote
            c_write += i*nbytes;
            c_write = c_write%ringsize;
        }
    }
   
    CoUninitialize();
}


CC-0/MIT/ISC/WTFPL/w/e
« Last Edit: February 24, 2018, 12:36:09 am by Phantom Brave »
Logged

http://steamcommunity.com/id/wareya/
ladies and gentlemen i would like to announce that the fact of the matter is up that the fact of the matter is a fact and it matters

Phantom Brave

  • All Hail Classicwell
  • Moderator
  • *****
  • Karma: 70
  • Offline Offline
  • Posts: 12524
  • Another one --
Re: Beta testing: Windows 10 audio fixes for Gang Garrison 2
« Reply #10 on: February 24, 2018, 12:16:01 pm »

fixed WASAPI demo for 5.1 etc:

Code: [Select]
// -lavrt -lole32 -lksuser

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <initguid.h>
#include <avrt.h>
#include <mmdeviceapi.h>
#include <audioclient.h>
#include <stdio.h>
#include <stdint.h>

#include <thread> // for sleeping

IMMDeviceEnumerator* enumerator = nullptr;
IMMDevice* audioDevice = nullptr;
IPropertyStore* propertyStore = nullptr;
IAudioClient* audioClient = nullptr;
IAudioRenderClient* renderClient = nullptr;
WAVEFORMATEX* waveFormat = nullptr;
WAVEFORMATEXTENSIBLE* waveFormatEx = nullptr;
PROPVARIANT propVariant;
HANDLE taskHandle = nullptr;
REFERENCE_TIME devicePeriod = 0;
uint32_t bufferSize;
uint32_t numchannels = 2;

#include <math.h>
#ifndef M_PI
#define M_PI 3.141592653589793
#endif

#define max(x,y) ((x>y)?(x):(y))

int type = -1; // 0: 16-bit signed int; 1: 32-bit float; -1: unsupported

double freq = 100;
double volume = 0.2;

float mixbuffer[4096*256];
void mix_sine(float * buffer, uint64_t count, uint64_t samplerate, uint64_t channels, uint64_t time)
{
    double nyquist = samplerate/2.0;
    for(uint64_t i = 0; i < count; i++)
    {
        for(uint64_t c = 0; c < channels; c++)
        {
            buffer[i*channels + c] = sin((i+time)*M_PI*freq/nyquist)*volume;
        }
    }
}

int main()
{
    // initialize COM
    CoInitialize(nullptr);
    // load device enumerator
    if(CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&enumerator) != S_OK) return puts("a"), false;
    // get default output
    if(enumerator->GetDefaultAudioEndpoint(eRender, eConsole, &audioDevice) != S_OK) return false;
    // activate endpoint
    if(audioDevice->Activate(IID_IAudioClient, CLSCTX_ALL, nullptr, (void**)&audioClient) != S_OK) return puts("b"), false;
   
    // get format of endpoint
    if(audioClient->GetMixFormat(&waveFormat) != S_OK) return puts("c"), false;
    if(waveFormat->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
        waveFormatEx = (WAVEFORMATEXTENSIBLE*)waveFormat;
    if(waveFormat->wBitsPerSample == 16 and (!waveFormatEx or waveFormatEx->SubFormat == KSDATAFORMAT_SUBTYPE_PCM))
        type = 0;
    if(waveFormatEx and waveFormatEx->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT and waveFormat->wBitsPerSample == 32)
        type = 1;
    if(type == -1)
        return puts("Unsupported format"), 0;
   
    printf("Type: %d\n", type);
    printf("Channels: %d\n", waveFormat->nChannels);
    if(waveFormat->nChannels == 1)
        numchannels = 1;
    else
        numchannels = 2;
    printf("(rendering to %d channels)\n", numchannels);
   
   
    uint32_t samples = 512;
   
    uint32_t latency = double(samples)/waveFormat->nSamplesPerSec*10'000'000; // 10: 100ns -> 1us; 1000: us -> ms; 1000: ms -> s
    printf("asking for %fms buffer size\n", double(samples)/waveFormat->nSamplesPerSec*1000);
   
    // open endpoint
    if(audioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, latency, 0, waveFormat, nullptr) != S_OK) return puts("f"), false;
    DWORD taskIndex = 0;
    taskHandle = AvSetMmThreadCharacteristics("Faucet Mixer", &taskIndex);
   
    // set up render client
    if(audioClient->GetService(IID_IAudioRenderClient, (void**)&renderClient) != S_OK) return puts("g"), false;
    // needed metadata
    if(audioClient->GetBufferSize(&bufferSize) != S_OK) return puts("h"), false;
   
    // info
    REFERENCE_TIME default_period, min_period;
    if(audioClient->GetDevicePeriod(&default_period, &min_period) != S_OK) return puts("e"), false;
    printf("actual buffer size: %fms\n", double(bufferSize)/waveFormat->nSamplesPerSec*1000);
    printf("default period: %fms\n minimum period: %fms\n", double(default_period)/10'000, double(min_period)/10'000);

    // start
    if(audioClient->Start() != S_OK) return puts("d"), false;
   
    uint64_t t = 0;
   
    // reduce latency by memeing (note: terrible idea, just for example)
    //uint32_t padding_offset = bufferSize - double(default_period)/10'000'000*waveFormat->nSamplesPerSec;
    uint32_t padding_offset = 0;
   
    while(t < 100000)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
        uint32_t padding = 0;
        auto err = audioClient->GetCurrentPadding(&padding);
        if(err != S_OK)
            printf("GetCurrentPadding threw error: %ld\n", err);
       
        auto render = max(0, int64_t(bufferSize)-int64_t(padding+padding_offset));
        if(render > 0)
        {
            mix_sine(mixbuffer, render, waveFormat->nSamplesPerSec, numchannels, t);
            t += render;
           
            unsigned char * backend_buffer;
            err = renderClient->GetBuffer(render, &backend_buffer);
            if(err != S_OK)
                printf("GetBuffer threw error: %ld\n", err);
           
            uint64_t i = 0;
            for(uint64_t j = 0; j < render; j++)
            {
                for(uint64_t c = 0; c < waveFormat->nChannels; c++)
                {
                    if(c < numchannels)
                    {
                        if(type == 1)
                            ((float*)(backend_buffer))[j*waveFormat->nChannels+c] = mixbuffer[i++];
                        if(type == 0)
                            ((int16_t*)(backend_buffer))[j*waveFormat->nChannels+c] = round(mixbuffer[i++]*0x7FFF);
                    }
                    else
                    {
                        if(type == 1)
                            ((float*)(backend_buffer))[j*waveFormat->nChannels+c] = 0;
                        if(type == 0)
                            ((int16_t*)(backend_buffer))[j*waveFormat->nChannels+c] = 0;
                    }
                }
            }
           
            err = renderClient->ReleaseBuffer(render, 0);
            if(err != S_OK)
                printf("ReleaseBuffer threw error: %ld\n", err);
        }
    }
   
    return 0;
}


this just assumes that the first two channels are the stereo channels, which is almost certainly wrong, but it works on my PC

EDIT: nope, completely correct

Quote
The channels specified in dwChannelMask must be present in the prescribed order (from least significant bit up). For example, if only SPEAKER_FRONT_LEFT and SPEAKER_FRONT_RIGHT are specified, then the samples for the front left speaker must come first in the interleaved stream.
« Last Edit: February 24, 2018, 12:22:18 pm by Phantom Brave »
Logged

http://steamcommunity.com/id/wareya/
ladies and gentlemen i would like to announce that the fact of the matter is up that the fact of the matter is a fact and it matters

PrOF

  • Full Member
  • ***
  • Karma: 43
  • Offline Offline
  • Posts: 593
  • Sometimes a dev. Only sometimes
Re: Beta testing: Windows 10 audio fixes for Gang Garrison 2
« Reply #11 on: February 24, 2018, 02:25:26 pm »

Wasn't there a Faucet Audio project in the works some time ago hrdjdjxzbw years ago?
For forum users: this change was implemented in GG2 2.9, a sound extension might be coming
« Last Edit: February 24, 2018, 02:27:21 pm by PrOF »
Logged

Phantom Brave

  • All Hail Classicwell
  • Moderator
  • *****
  • Karma: 70
  • Offline Offline
  • Posts: 12524
  • Another one --
Re: Beta testing: Windows 10 audio fixes for Gang Garrison 2
« Reply #12 on: February 24, 2018, 03:24:13 pm »

OSS. Breaks the audio device until reboot on my archlinux VM with alsa-oss, but works fine in my freebsd VM.

Code: [Select]
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
#include <stdio.h>

#include <thread> // for sleeping

#include <math.h>
#ifndef M_PI
#define M_PI 3.141592653589793
#endif

#define max(x,y) (((x)>(y))?(x):(y))
#define min(x,y) (((x)<(y))?(x):(y))

double freq = 100;
double volume = 0.2;

float mixbuffer[4096*256];
void mix_sine(float * buffer, uint64_t count, uint64_t samplerate, uint64_t channels, uint64_t time)
{
    double nyquist = samplerate/2.0;
    for(uint64_t i = 0; i < count; i++)
    {
        for(uint64_t c = 0; c < channels; c++)
        {
            buffer[i*channels + c] = sin((i+time)*M_PI*freq/nyquist)*volume;
        }
    }
}

int main()
{
    auto device = open("/dev/dsp", O_WRONLY, O_NONBLOCK);
    if(device < 0) return puts("Failed to open device"), 0;
   
    int channels = 2;
    int format = AFMT_S16_LE;
    int frequency = 48000;
   
    int samples = 1024;
   
    ioctl(device, SNDCTL_DSP_CHANNELS, &channels);
    ioctl(device, SNDCTL_DSP_SETFMT, &format);
    ioctl(device, SNDCTL_DSP_SPEED, &frequency);
   
    audio_buf_info space;
    ioctl(device, SNDCTL_DSP_GETOSPACE, &space);
    printf("Space: %u\n", space.bytes);
   
    int buffer_size = space.bytes;
   
    uint64_t t = 0;
   
    while(t < 100000)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
        ioctl(device, SNDCTL_DSP_GETOSPACE, &space);
        int padding = buffer_size - space.bytes;
        int overhead = samples - padding/4;
       
        uint64_t render = max(0, overhead);
        if(render > 0)
        {
            mix_sine(mixbuffer, render, frequency, channels, t);
            t += render;
           
            for(uint64_t i = 0; i < render; i++)
            {
                int16_t left  = round(mixbuffer[i*channels + 0]*0x7FFF);
                int16_t right = round(mixbuffer[i*channels + 1]*0x7FFF);
                uint32_t frame = (uint16_t(right)<<16) | uint16_t(left);
               
                write(device, &frame, 4);
            }
        }
    }
   
    #ifdef SNDCTL_DSP_HALT
    ioctl(device, SNDCTL_DSP_HALT, nullptr);
    #else
    ioctl(device, SNDCTL_DSP_RESET, nullptr);
    #endif
    close(device);
    return 0;
}
Logged

http://steamcommunity.com/id/wareya/
ladies and gentlemen i would like to announce that the fact of the matter is up that the fact of the matter is a fact and it matters

Phantom Brave

  • All Hail Classicwell
  • Moderator
  • *****
  • Karma: 70
  • Offline Offline
  • Posts: 12524
  • Another one --
Re: Beta testing: Windows 10 audio fixes for Gang Garrison 2
« Reply #13 on: February 24, 2018, 05:20:49 pm »

ALSA

Code: [Select]
#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h>

#include <thread> // for sleep

#include <math.h>
#ifndef M_PI
#define M_PI 3.141592653589793
#endif

#define max(x,y) (((x)>(y))?(x):(y))
#define min(x,y) (((x)<(y))?(x):(y))

double freq = 100;
double volume = 0.2;

float mixbuffer[4096*256];
int16_t outbuffer[4096*256];
void mix_sine(float * buffer, uint64_t count, uint64_t samplerate, uint64_t channels, uint64_t time)
{
    double nyquist = samplerate/2.0;
    for(uint64_t i = 0; i < count; i++)
    {
        for(uint64_t c = 0; c < channels; c++)
        {
            buffer[i*channels + c] = sin((i+time)*M_PI/nyquist*freq)*volume;
        }
    }
}

int main()
{
    snd_pcm_t * device;
    snd_pcm_hw_params_t * parameters;

//    if(snd_pcm_open(&device, "default", SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) < 0)
    if(snd_pcm_open(&device, "default", SND_PCM_STREAM_PLAYBACK, 0) < 0)
        return puts("Failed to open ALSA device"), 0;
       
    if(snd_pcm_hw_params_malloc(&parameters) < 0)
        return puts("Failed to allocate device parameter structure"), 0;
             
    if(snd_pcm_hw_params_any(device, parameters) < 0)
        return puts("Failed to init device parameter structure"), 0;

    if(snd_pcm_hw_params_set_access(device, parameters, SND_PCM_ACCESS_RW_INTERLEAVED) < 0)
        return puts("Failed to set access type"), 0;

    if(snd_pcm_hw_params_set_format(device, parameters, SND_PCM_FORMAT_S16_LE) < 0)
        return puts("Failed to set sample format"), 0;

    unsigned int samplerate = 44100;
    if(snd_pcm_hw_params_set_rate_near(device, parameters, &samplerate, 0) < 0)
        return puts("Failed to set sample rate"), 0;

    int channels = 2;
    if(snd_pcm_hw_params_set_channels(device, parameters, channels) < 0)
        return puts("Failed to set channel count"), 0;
   
    printf("actual sample rate %d\n", samplerate);
   
    snd_pcm_uframes_t period;
    int dir;
   
    if(snd_pcm_hw_params_get_period_size_min(parameters, &period, &dir) < 0)
        return puts("Failed to get period size"), 0;
   
    printf("min period size: %lu\n", period);
   
    if(snd_pcm_hw_params_set_period_size(device, parameters, period, dir) < 0)
        return puts("Failed to set period size to the minimum provided by it"), 0;
   
    snd_pcm_uframes_t samples = max(period, 1024);
    printf("pretend buffer size is %lu\n", samples);
   
    if(snd_pcm_hw_params_set_buffer_size_near(device, parameters, &samples) < 0)
        return puts("Failed to set buffer size to something near our sample window"), 0;

    if(snd_pcm_hw_params(device, parameters) < 0)
        return puts("Failed to set device parameters"), 0;

    snd_pcm_hw_params_free(parameters);

    if (snd_pcm_prepare(device) < 0)
        return puts("Failed to prepare device"), 0;
   
    auto buffer_size = snd_pcm_avail_update(device);
    if(buffer_size < 0)
        return puts("Error when measuring approximate buffer size"), 0;
   
    printf("apparent buffer size is %lu\n", buffer_size);
   
    uint64_t t = 0;
    while(t < 100000)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
        auto avail = snd_pcm_avail_update(device);
        while(avail == -EPIPE or avail == -ESTRPIPE)
        {
            snd_pcm_recover(device, avail, 0);
            avail = snd_pcm_avail_update(device);
        }
        int padding = buffer_size - avail;
       
        int render = min(uint64_t(buffer_size), samples) - padding;
       
        if(render > 0)
        {
            mix_sine(mixbuffer, render, samplerate, 2, t);
            t += render;
           
            for(int i = 0; i < render*2; i++)
                outbuffer[i] = round(mixbuffer[i]*0x7FFF);
           
            auto written = snd_pcm_writei(device, outbuffer, render);
           
            while(written == -EPIPE or written == -ESTRPIPE)
            {
                snd_pcm_recover(device, written, 0);
                written = snd_pcm_writei(device, outbuffer, render);
            }
        }
    }

    snd_pcm_close(device);
    return 0;
}
Logged

http://steamcommunity.com/id/wareya/
ladies and gentlemen i would like to announce that the fact of the matter is up that the fact of the matter is a fact and it matters

#freeprime

  • Junior Member
  • **
  • Karma: 4
  • Offline Offline
  • Posts: 114
  • not arctic
Re: Beta testing: Windows 10 audio fixes for Gang Garrison 2
« Reply #14 on: February 25, 2018, 02:57:50 pm »

oh hey, i completely forgot about this bug 🤔
Logged
Pages: [1] 2
 

Page created in 0.03 seconds with 30 queries.