aboutsummaryrefslogtreecommitdiff
path: root/audio/audio_win_int.c
blob: 5ea8157dfcc8145a2bbbf49c86d8319c4e22386e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/* 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;
}