Setting up OpenAL Soft 1.24.2 in Visual Studio 2022 using CMake
        
            - Install OpenAL Soft using this guide: How to install OpenAL Soft using CMake and Visual Studio 2022 for Desktop
 
            - Run Visual Studio
 
            - Click on the "Create a new project" button:
 
            
            - Click on the "CMake Project" and click on the "Next" button:
 
            
            - Type a project name, set a project location, check the "Place solution and project in the same directory" checkbox, and click on the "Create" button:
 
            
            - Wait a few seconds for configuration
 
            - Run the project by click on the empty green triangle (or Ctrl+F5):
 
            
            - The program prints "Hello CMake" to the console:
 
            
            - Download this audio file:
 
            
            
            
            - Cut the downloaded file, open your "hello-openal-soft" project in the file explorer, create the "assets/audio" folder, and paste the downloaded audio file in the "audio" folder like this:
 
            
            
            - Double click on the "CMakeLists.txt" file:
 
            
            - Add this code to the "CMakeLists.txt" file
 
target_link_libraries(hello-openal-soft PRIVATE
    "E:/libs/openal-soft-1.24.2-msvc/win/debug/lib/OpenAL32.lib")
# Copy the assets folder to the dist folder
add_custom_command(TARGET hello-openal-soft POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_directory
    ${CMAKE_SOURCE_DIR}/assets $<TARGET_FILE_DIR:hello-openal-soft>/assets)
            The "OpenAL32.dll" should be place in the same folder like EXE. You can find the debug version of "OpenAL32.dll" in this folder: "E:\libs\openal-soft-1.24.2-msvc\win\debug\bin"
            
            Copy and paste the "OpenAL32.dll" file to the "E:\projects\hello-openal-soft\out\build\x64-debug"
            Double click on the "hello-openal-soft.cpp" file:
            
            Copy the following content to the "hello-openal-soft.cpp" file:
#include <array>
#include <bit>
#include <iostream>
#include <fstream>
#include <AL/al.h>
#include <AL/alc.h>
struct WAVHEADER
{
    std::array<char, 4> chunkId;
    uint32_t chunkSize;
    std::array<char, 4> format;
    std::array<char, 4> subchunk1Id;
    uint32_t subchunk1Size;
    uint16_t audioFormat;
    uint16_t numChannels;
    uint32_t sampleRate;
    uint32_t byteRate;
    uint16_t blockAlign;
    uint16_t bitsPerSample;
    std::array<char, 4> subchunk2Id;
    uint32_t subchunk2Size;
};
static_assert(sizeof(WAVHEADER) == 44);
ALCdevice* audioDevice;
ALCcontext* audioContext;
ALuint coinAudioBuffer;
ALuint coinAudioSource;
void setListener()
{
    alListener3f(AL_POSITION, 0.0f, 0.0f, 0.0f);
    alListener3f(AL_VELOCITY, 0.0f, 0.0f, 0.0f);
    // Front vector and up vector:
    float orient[]{ 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f };
    alListenerfv(AL_ORIENTATION, orient);
    alListenerf(AL_GAIN, 1.0f);
}
ALuint createBuffer()
{
    ALuint audioBuffer;
    alGenBuffers(1, &audioBuffer);
    if (alGetError() != AL_NO_ERROR)
    {
        std::cout << "Cannot create an audio buffer" << std::endl;
    }
    return audioBuffer;
}
std::int32_t convert_to_int(char* buffer, std::size_t len)
{
    std::int32_t a = 0;
    if (std::endian::native == std::endian::little)
        std::memcpy(&a, buffer, len);
    else
        for (std::size_t i = 0; i < len; ++i)
            reinterpret_cast<char*>(&a)[3 - i] = buffer[i];
    return a;
}
bool load_wav_file_header(std::ifstream& file,
    std::uint8_t& channels,
    std::int32_t& sampleRate,
    std::uint8_t& bitsPerSample,
    ALsizei& size)
{
    char buffer[4];
    if (!file.is_open())
        return false;
    // the RIFF
    if (!file.read(buffer, 4))
    {
        std::cerr << "ERROR: could not read RIFF" << std::endl;
        return false;
    }
    if (std::strncmp(buffer, "RIFF", 4) != 0)
    {
        std::cerr << "ERROR: file is not a valid WAVE file (header doesn't begin with RIFF)" << std::endl;
        return false;
    }
    // the size of the file
    if (!file.read(buffer, 4))
    {
        std::cerr << "ERROR: could not read size of file" << std::endl;
        return false;
    }
    // the WAVE
    if (!file.read(buffer, 4))
    {
        std::cerr << "ERROR: could not read WAVE" << std::endl;
        return false;
    }
    if (std::strncmp(buffer, "WAVE", 4) != 0)
    {
        std::cerr << "ERROR: file is not a valid WAVE file (header doesn't contain WAVE)" << std::endl;
        return false;
    }
    // "fmt/0"
    if (!file.read(buffer, 4))
    {
        std::cerr << "ERROR: could not read fmt/0" << std::endl;
        return false;
    }
    // this is always 16, the size of the fmt data chunk
    if (!file.read(buffer, 4))
    {
        std::cerr << "ERROR: could not read the 16" << std::endl;
        return false;
    }
    // PCM should be 1?
    if (!file.read(buffer, 2))
    {
        std::cerr << "ERROR: could not read PCM" << std::endl;
        return false;
    }
    // the number of channels
    if (!file.read(buffer, 2))
    {
        std::cerr << "ERROR: could not read number of channels" << std::endl;
        return false;
    }
    channels = convert_to_int(buffer, 2);
    // sample rate
    if (!file.read(buffer, 4))
    {
        std::cerr << "ERROR: could not read sample rate" << std::endl;
        return false;
    }
    sampleRate = convert_to_int(buffer, 4);
    // (sampleRate * bitsPerSample * channels) / 8
    if (!file.read(buffer, 4))
    {
        std::cerr << "ERROR: could not read (sampleRate * bitsPerSample * channels) / 8" << std::endl;
        return false;
    }
    // ?? dafaq
    if (!file.read(buffer, 2))
    {
        std::cerr << "ERROR: could not read dafaq" << std::endl;
        return false;
    }
    // bitsPerSample
    if (!file.read(buffer, 2))
    {
        std::cerr << "ERROR: could not read bits per sample" << std::endl;
        return false;
    }
    bitsPerSample = convert_to_int(buffer, 2);
    // data chunk header "data"
    if (!file.read(buffer, 4))
    {
        std::cerr << "ERROR: could not read data chunk header" << std::endl;
        return false;
    }
    if (std::strncmp(buffer, "data", 4) != 0)
    {
        std::cerr << "ERROR: file is not a valid WAVE file (doesn't have 'data' tag)" << std::endl;
        return false;
    }
    // size of data
    if (!file.read(buffer, 4))
    {
        std::cerr << "ERROR: could not read data size" << std::endl;
        return false;
    }
    size = convert_to_int(buffer, 4);
    /* cannot be at the end of file */
    if (file.eof())
    {
        std::cerr << "ERROR: reached EOF on the file" << std::endl;
        return false;
    }
    if (file.fail())
    {
        std::cerr << "ERROR: fail state set on the file" << std::endl;
        return false;
    }
    return true;
}
char* load_wav(const std::string& filename,
    std::uint8_t& channels,
    std::int32_t& sampleRate,
    std::uint8_t& bitsPerSample,
    ALsizei& size)
{
    std::ifstream in(filename, std::ios::binary);
    if (!in.is_open())
    {
        std::cerr << "ERROR: Could not open \"" << filename << "\"" << std::endl;
        return nullptr;
    }
    if (!load_wav_file_header(in, channels, sampleRate, bitsPerSample, size))
    {
        std::cerr << "ERROR: Could not load wav header of \"" << filename << "\"" << std::endl;
        return nullptr;
    }
    char* data = new char[size];
    in.read(data, size);
    return data;
}
void fillBuffer(const std::string& path, ALuint audioBuffer, bool isStereo)
{
    std::uint8_t channels;
    std::int32_t sampleRate;
    std::uint8_t bitsPerSample;
    std::int32_t size;
    std::ifstream in(path, std::ios::binary);
    if (!in.is_open())
    {
        std::cerr << "ERROR: Could not open \"" << path << "\"" << std::endl;
        return;
    }
    WAVHEADER head{};
    in.read(reinterpret_cast<char*>(&head), sizeof(head));
    char* data = new char[head.subchunk2Size];
    in.read(data, head.subchunk2Size);
    in.close();
    if (isStereo)
    {
        alBufferData(audioBuffer, AL_FORMAT_STEREO16, data,
            static_cast<ALint>(head.subchunk2Size),
            static_cast<ALint>(head.sampleRate));
    }
    else
    {
        alBufferData(audioBuffer, AL_FORMAT_MONO8, data,
            static_cast<ALint>(head.subchunk2Size),
            static_cast<ALint>(head.sampleRate));
    }
}
ALuint createSource(ALuint audioBuffer, bool isLoop)
{
    ALuint audioSource;
    alGenSources(1, &audioSource);
    if (alGetError() != AL_NO_ERROR)
    {
        std::cout << "Cannot create an audio source" << std::endl;
    }
    alSource3f(audioSource, AL_POSITION, 0.0f, 0.0f, -2.0f);
    alSource3f(audioSource, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
    alSourcef(audioSource, AL_GAIN, 1.0f);
    alSourcef(audioSource, AL_PITCH, 1.0f);
    alSourcei(audioSource, AL_LOOPING, isLoop);
    alSourcei(audioSource, AL_BUFFER, static_cast<ALint>(audioBuffer));
    return audioSource;
}
int main()
{
    audioDevice = alcOpenDevice(nullptr);
    audioContext = alcCreateContext(audioDevice, nullptr);
    if (alcGetError(audioDevice) != ALC_NO_ERROR)
    {
        std::cout << "Cannot create an audio context" << std::endl;
    }
    alcMakeContextCurrent(audioContext);
    setListener();
    coinAudioBuffer = createBuffer();
    fillBuffer("./assets/audio/picked-coin-echo-2.wav", coinAudioBuffer, true);
    coinAudioSource = createSource(coinAudioBuffer, false);
    alSourcePlay(coinAudioSource);
    std::cout << "Press any key..." << std::endl;
    getchar();
    return 0;
}
            Press Ctrl+F5 to run the application
            You hear a sound