xref: /qemu/audio/audio_win_int.c (revision b2a3cbb8)
1 /* public domain */
2 
3 #include "qemu/osdep.h"
4 
5 #define AUDIO_CAP "win-int"
6 #include <windows.h>
7 #include <mmreg.h>
8 #include <mmsystem.h>
9 
10 #include "audio.h"
11 #include "audio_int.h"
12 #include "audio_win_int.h"
13 
14 int waveformat_from_audio_settings (WAVEFORMATEX *wfx,
15                                     struct audsettings *as)
16 {
17     memset (wfx, 0, sizeof (*wfx));
18 
19     wfx->nChannels = as->nchannels;
20     wfx->nSamplesPerSec = as->freq;
21     wfx->nAvgBytesPerSec = as->freq << (as->nchannels == 2);
22     wfx->nBlockAlign = 1 << (as->nchannels == 2);
23     wfx->cbSize = 0;
24 
25     switch (as->fmt) {
26     case AUDIO_FORMAT_S8:
27     case AUDIO_FORMAT_U8:
28         wfx->wFormatTag = WAVE_FORMAT_PCM;
29         wfx->wBitsPerSample = 8;
30         break;
31 
32     case AUDIO_FORMAT_S16:
33     case AUDIO_FORMAT_U16:
34         wfx->wFormatTag = WAVE_FORMAT_PCM;
35         wfx->wBitsPerSample = 16;
36         wfx->nAvgBytesPerSec <<= 1;
37         wfx->nBlockAlign <<= 1;
38         break;
39 
40     case AUDIO_FORMAT_S32:
41     case AUDIO_FORMAT_U32:
42         wfx->wFormatTag = WAVE_FORMAT_PCM;
43         wfx->wBitsPerSample = 32;
44         wfx->nAvgBytesPerSec <<= 2;
45         wfx->nBlockAlign <<= 2;
46         break;
47 
48     case AUDIO_FORMAT_F32:
49         wfx->wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
50         wfx->wBitsPerSample = 32;
51         wfx->nAvgBytesPerSec <<= 2;
52         wfx->nBlockAlign <<= 2;
53         break;
54 
55     default:
56         dolog("Internal logic error: Bad audio format %d\n", as->fmt);
57         return -1;
58     }
59 
60     return 0;
61 }
62 
63 int waveformat_to_audio_settings (WAVEFORMATEX *wfx,
64                                   struct audsettings *as)
65 {
66     if (!wfx->nSamplesPerSec) {
67         dolog ("Invalid wave format, frequency is zero\n");
68         return -1;
69     }
70     as->freq = wfx->nSamplesPerSec;
71 
72     switch (wfx->nChannels) {
73     case 1:
74         as->nchannels = 1;
75         break;
76 
77     case 2:
78         as->nchannels = 2;
79         break;
80 
81     default:
82         dolog (
83             "Invalid wave format, number of channels is not 1 or 2, but %d\n",
84             wfx->nChannels
85             );
86         return -1;
87     }
88 
89     if (wfx->wFormatTag == WAVE_FORMAT_PCM) {
90         switch (wfx->wBitsPerSample) {
91         case 8:
92             as->fmt = AUDIO_FORMAT_U8;
93             break;
94 
95         case 16:
96             as->fmt = AUDIO_FORMAT_S16;
97             break;
98 
99         case 32:
100             as->fmt = AUDIO_FORMAT_S32;
101             break;
102 
103         default:
104             dolog("Invalid PCM wave format, bits per sample is not "
105                   "8, 16 or 32, but %d\n",
106                   wfx->wBitsPerSample);
107             return -1;
108         }
109     } else if (wfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) {
110         switch (wfx->wBitsPerSample) {
111         case 32:
112             as->fmt = AUDIO_FORMAT_F32;
113             break;
114 
115         default:
116             dolog("Invalid IEEE_FLOAT wave format, bits per sample is not "
117                   "32, but %d\n",
118                   wfx->wBitsPerSample);
119             return -1;
120         }
121     } else {
122         dolog("Invalid wave format, tag is not PCM and not IEEE_FLOAT, "
123               "but %d\n",
124               wfx->wFormatTag);
125         return -1;
126     }
127 
128     return 0;
129 }
130 
131