/* public domain */

#include "qemu/osdep.h"
#include "qemu-common.h"

#define AUDIO_CAP "win-int"
#include <windows.h>
#include <mmreg.h>
#include <mmsystem.h>

#include "audio.h"
#include "audio_int.h"
#include "audio_win_int.h"

int waveformat_from_audio_settings (WAVEFORMATEX *wfx,
                                    struct audsettings *as)
{
    memset (wfx, 0, sizeof (*wfx));

    wfx->nChannels = as->nchannels;
    wfx->nSamplesPerSec = as->freq;
    wfx->nAvgBytesPerSec = as->freq << (as->nchannels == 2);
    wfx->nBlockAlign = 1 << (as->nchannels == 2);
    wfx->cbSize = 0;

    switch (as->fmt) {
    case AUDIO_FORMAT_S8:
    case AUDIO_FORMAT_U8:
        wfx->wFormatTag = WAVE_FORMAT_PCM;
        wfx->wBitsPerSample = 8;
        break;

    case AUDIO_FORMAT_S16:
    case AUDIO_FORMAT_U16:
        wfx->wFormatTag = WAVE_FORMAT_PCM;
        wfx->wBitsPerSample = 16;
        wfx->nAvgBytesPerSec <<= 1;
        wfx->nBlockAlign <<= 1;
        break;

    case AUDIO_FORMAT_S32:
    case AUDIO_FORMAT_U32:
        wfx->wFormatTag = WAVE_FORMAT_PCM;
        wfx->wBitsPerSample = 32;
        wfx->nAvgBytesPerSec <<= 2;
        wfx->nBlockAlign <<= 2;
        break;

    case AUDIO_FORMAT_F32:
        wfx->wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
        wfx->wBitsPerSample = 32;
        wfx->nAvgBytesPerSec <<= 2;
        wfx->nBlockAlign <<= 2;
        break;

    default:
        dolog("Internal logic error: Bad audio format %d\n", as->fmt);
        return -1;
    }

    return 0;
}

int waveformat_to_audio_settings (WAVEFORMATEX *wfx,
                                  struct audsettings *as)
{
    if (!wfx->nSamplesPerSec) {
        dolog ("Invalid wave format, frequency is zero\n");
        return -1;
    }
    as->freq = wfx->nSamplesPerSec;

    switch (wfx->nChannels) {
    case 1:
        as->nchannels = 1;
        break;

    case 2:
        as->nchannels = 2;
        break;

    default:
        dolog (
            "Invalid wave format, number of channels is not 1 or 2, but %d\n",
            wfx->nChannels
            );
        return -1;
    }

    if (wfx->wFormatTag == WAVE_FORMAT_PCM) {
        switch (wfx->wBitsPerSample) {
        case 8:
            as->fmt = AUDIO_FORMAT_U8;
            break;

        case 16:
            as->fmt = AUDIO_FORMAT_S16;
            break;

        case 32:
            as->fmt = AUDIO_FORMAT_S32;
            break;

        default:
            dolog("Invalid PCM wave format, bits per sample is not "
                  "8, 16 or 32, but %d\n",
                  wfx->wBitsPerSample);
            return -1;
        }
    } else if (wfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) {
        switch (wfx->wBitsPerSample) {
        case 32:
            as->fmt = AUDIO_FORMAT_F32;
            break;

        default:
            dolog("Invalid IEEE_FLOAT wave format, bits per sample is not "
                  "32, but %d\n",
                  wfx->wBitsPerSample);
            return -1;
        }
    } else {
        dolog("Invalid wave format, tag is not PCM and not IEEE_FLOAT, "
              "but %d\n",
              wfx->wFormatTag);
        return -1;
    }

    return 0;
}

