comparison libao2/ao_win32.c @ 13017:5b9c594dc6e9

untested multichannel support
author faust3
date Sat, 14 Aug 2004 10:03:26 +0000
parents ab369fe35121
children 83c5f9888576
comparison
equal deleted inserted replaced
13016:61d0fd8411cc 13017:5b9c594dc6e9
29 #include "../mp_msg.h" 29 #include "../mp_msg.h"
30 #include "../libvo/fastmemcpy.h" 30 #include "../libvo/fastmemcpy.h"
31 #include "osdep/timer.h" 31 #include "osdep/timer.h"
32 32
33 #define WAVE_FORMAT_DOLBY_AC3_SPDIF 0x0092 33 #define WAVE_FORMAT_DOLBY_AC3_SPDIF 0x0092
34 #define WAVE_FORMAT_EXTENSIBLE 0xFFFE
35
36 static const GUID KSDATAFORMAT_SUBTYPE_PCM = {
37 0x1,0x0000,0x0010,{0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71}
38 };
39
40 typedef struct {
41 WAVEFORMATEX Format;
42 union {
43 WORD wValidBitsPerSample;
44 WORD wSamplesPerBlock;
45 WORD wReserved;
46 } Samples;
47 DWORD dwChannelMask;
48 GUID SubFormat;
49 } WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE;
50
51 #define SPEAKER_FRONT_LEFT 0x1
52 #define SPEAKER_FRONT_RIGHT 0x2
53 #define SPEAKER_FRONT_CENTER 0x4
54 #define SPEAKER_LOW_FREQUENCY 0x8
55 #define SPEAKER_BACK_LEFT 0x10
56 #define SPEAKER_BACK_RIGHT 0x20
57 #define SPEAKER_FRONT_LEFT_OF_CENTER 0x40
58 #define SPEAKER_FRONT_RIGHT_OF_CENTER 0x80
59 #define SPEAKER_BACK_CENTER 0x100
60 #define SPEAKER_SIDE_LEFT 0x200
61 #define SPEAKER_SIDE_RIGHT 0x400
62 #define SPEAKER_TOP_CENTER 0x800
63 #define SPEAKER_TOP_FRONT_LEFT 0x1000
64 #define SPEAKER_TOP_FRONT_CENTER 0x2000
65 #define SPEAKER_TOP_FRONT_RIGHT 0x4000
66 #define SPEAKER_TOP_BACK_LEFT 0x8000
67 #define SPEAKER_TOP_BACK_CENTER 0x10000
68 #define SPEAKER_TOP_BACK_RIGHT 0x20000
69
70 static const int channel_mask[] = {
71 SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY,
72 SPEAKER_FRONT_LEFT | SPEAKER_FRONT_CENTER | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY,
73 SPEAKER_FRONT_LEFT | SPEAKER_FRONT_CENTER | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_CENTER | SPEAKER_LOW_FREQUENCY,
74 SPEAKER_FRONT_LEFT | SPEAKER_FRONT_CENTER | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_LOW_FREQUENCY
75 };
76
77
34 78
35 #define SAMPLESIZE 1024 79 #define SAMPLESIZE 1024
36 #define BUFFER_SIZE 4096 80 #define BUFFER_SIZE 4096
37 #define BUFFER_COUNT 16 81 #define BUFFER_COUNT 16
38 82
96 140
97 // open & setup audio device 141 // open & setup audio device
98 // return: 1=success 0=fail 142 // return: 1=success 0=fail
99 static int init(int rate,int channels,int format,int flags) 143 static int init(int rate,int channels,int format,int flags)
100 { 144 {
101 WAVEFORMATEX wformat; 145 WAVEFORMATEXTENSIBLE wformat;
102 DWORD totalBufferSize = (BUFFER_SIZE + sizeof(WAVEHDR)) * BUFFER_COUNT; 146 DWORD totalBufferSize = (BUFFER_SIZE + sizeof(WAVEHDR)) * BUFFER_COUNT;
103 MMRESULT result; 147 MMRESULT result;
104 unsigned char* buffer; 148 unsigned char* buffer;
105 int i; 149 int i;
106 150
119 } 163 }
120 mp_msg(MSGT_AO, MSGL_V,"ao_win32: Samplerate:%iHz Channels:%i Format:%s\n",rate, channels, audio_out_format_name(format)); 164 mp_msg(MSGT_AO, MSGL_V,"ao_win32: Samplerate:%iHz Channels:%i Format:%s\n",rate, channels, audio_out_format_name(format));
121 mp_msg(MSGT_AO, MSGL_V,"ao_win32: Buffersize:%d\n",ao_data.buffersize); 165 mp_msg(MSGT_AO, MSGL_V,"ao_win32: Buffersize:%d\n",ao_data.buffersize);
122 166
123 //fill waveformatex 167 //fill waveformatex
124 ZeroMemory( &wformat, sizeof(WAVEFORMATEX)); 168 ZeroMemory( &wformat, sizeof(WAVEFORMATEXTENSIBLE));
125 wformat.cbSize = 0; /* size of _extra_ info */ 169 wformat.Format.cbSize = (channels>2)?sizeof(WAVEFORMATEXTENSIBLE):0;
126 wformat.nChannels = channels; 170 wformat.Format.nChannels = channels;
127 wformat.nSamplesPerSec = rate; 171 wformat.Format.nSamplesPerSec = rate;
128 if(format == AFMT_AC3) 172 if(format == AFMT_AC3)
129 { 173 {
130 wformat.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF; 174 wformat.Format.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF;
131 wformat.wBitsPerSample = 16; 175 wformat.Format.wBitsPerSample = 16;
132 wformat.nBlockAlign = 4; 176 wformat.Format.nBlockAlign = 4;
133 } 177 }
134 else 178 else
135 { 179 {
136 wformat.wFormatTag = WAVE_FORMAT_PCM; 180 wformat.Format.wFormatTag = (channels>2)?WAVE_FORMAT_EXTENSIBLE:WAVE_FORMAT_PCM;
137 wformat.wBitsPerSample = audio_out_format_bits(format); 181 wformat.Format.wBitsPerSample = audio_out_format_bits(format);
138 wformat.nBlockAlign = wformat.nChannels * (wformat.wBitsPerSample >> 3); 182 wformat.Format.nBlockAlign = wformat.Format.nChannels * (wformat.Format.wBitsPerSample >> 3);
139 } 183 }
140 wformat.nAvgBytesPerSec = wformat.nSamplesPerSec * wformat.nBlockAlign; 184 if(channels>2)
185 {
186 wformat.dwChannelMask = channel_mask[channels-3];
187 wformat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
188 wformat.Samples.wValidBitsPerSample=audio_out_format_bits(format);
189 }
190
191 wformat.Format.nAvgBytesPerSec = wformat.Format.nSamplesPerSec * wformat.Format.nBlockAlign;
141 192
142 //open sound device 193 //open sound device
143 //WAVE_MAPPER always points to the default wave device on the system 194 //WAVE_MAPPER always points to the default wave device on the system
144 result = waveOutOpen(&hWaveOut,WAVE_MAPPER,&wformat,(DWORD_PTR)waveOutProc,0,CALLBACK_FUNCTION); 195 result = waveOutOpen(&hWaveOut,WAVE_MAPPER,(WAVEFORMATEX*)&wformat,(DWORD_PTR)waveOutProc,0,CALLBACK_FUNCTION|WAVE_FORMAT_DIRECT);
145 if(result == WAVERR_BADFORMAT) 196 if(result == WAVERR_BADFORMAT)
146 { 197 {
147 mp_msg(MSGT_AO, MSGL_ERR,"ao_win32: format not supported switching to default\n"); 198 mp_msg(MSGT_AO, MSGL_ERR,"ao_win32: format not supported switching to default\n");
148 ao_data.channels = wformat.nChannels = 2; 199 ao_data.channels = wformat.Format.nChannels = 2;
149 ao_data.samplerate = wformat.nSamplesPerSec = 44100; 200 ao_data.samplerate = wformat.Format.nSamplesPerSec = 44100;
150 ao_data.format = AFMT_S16_LE; 201 ao_data.format = AFMT_S16_LE;
151 ao_data.bps=ao_data.channels * ao_data.samplerate*2; 202 ao_data.bps=ao_data.channels * ao_data.samplerate*2;
152 ao_data.buffersize=wformat.wBitsPerSample=16; 203 wformat.Format.wBitsPerSample=16;
153 wformat.nBlockAlign = wformat.nChannels * (wformat.wBitsPerSample >> 3); 204 wformat.Format.wFormatTag=WAVE_FORMAT_PCM;
154 wformat.nAvgBytesPerSec = wformat.nSamplesPerSec * wformat.nBlockAlign; 205 wformat.Format.nBlockAlign = wformat.Format.nChannels * (wformat.Format.wBitsPerSample >> 3);
155 ao_data.buffersize/=8; 206 wformat.Format.nAvgBytesPerSec = wformat.Format.nSamplesPerSec * wformat.Format.nBlockAlign;
156 ao_data.buffersize*= ao_data.channels; 207 ao_data.buffersize=(wformat.Format.wBitsPerSample>>3)*wformat.Format.nChannels*SAMPLESIZE;
157 ao_data.buffersize*= SAMPLESIZE; 208 result = waveOutOpen(&hWaveOut,WAVE_MAPPER,(WAVEFORMATEX*)&wformat,(DWORD_PTR)waveOutProc,0,CALLBACK_FUNCTION);
158 result = waveOutOpen(&hWaveOut,WAVE_MAPPER,&wformat,(DWORD_PTR)waveOutProc,0,CALLBACK_FUNCTION);
159 } 209 }
160 if(result != MMSYSERR_NOERROR) 210 if(result != MMSYSERR_NOERROR)
161 { 211 {
162 mp_msg(MSGT_AO, MSGL_ERR,"ao_win32: unable to open wave mapper device\n"); 212 mp_msg(MSGT_AO, MSGL_ERR,"ao_win32: unable to open wave mapper device\n");
163 return 0; 213 return 0;