Mercurial > mplayer.hg
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; |