Ticket #6538: aowin_21fixes.patch
File aowin_21fixes.patch, 6.4 KB (added by , 15 years ago) |
---|
-
libs/libmyth/audiooutputwin.h
37 37 long m_nPkts; 38 38 int m_CurrentPkt; 39 39 unsigned char **m_OutPkts; 40 bool m_UseSPDIF; 40 41 41 42 static const uint kPacketCnt; 42 43 }; -
libs/libmyth/audiooutputwin.cpp
9 9 #include <windows.h> 10 10 #include <mmsystem.h> 11 11 12 /***************************************************************************** 13 * Useful macros 14 *****************************************************************************/ 15 #ifndef WAVE_FORMAT_IEEE_FLOAT 16 # define WAVE_FORMAT_IEEE_FLOAT 0x0003 17 #endif 18 19 #ifndef WAVE_FORMAT_DOLBY_AC3_SPDIF 20 # define WAVE_FORMAT_DOLBY_AC3_SPDIF 0x0092 21 #endif 22 23 #ifndef WAVE_FORMAT_EXTENSIBLE 24 #define WAVE_FORMAT_EXTENSIBLE 0xFFFE 25 #endif 26 27 #ifndef _WAVEFORMATEXTENSIBLE_ 28 typedef struct { 29 WAVEFORMATEX Format; 30 union { 31 WORD wValidBitsPerSample; /* bits of precision */ 32 WORD wSamplesPerBlock; /* valid if wBitsPerSample==0 */ 33 WORD wReserved; /* If neither applies, set to zero. */ 34 } Samples; 35 DWORD dwChannelMask; /* which channels are */ 36 /* present in stream */ 37 GUID SubFormat; 38 } WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE; 39 #endif 40 41 DEFINE_GUID( _KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, WAVE_FORMAT_IEEE_FLOAT, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 ); 42 DEFINE_GUID( _KSDATAFORMAT_SUBTYPE_PCM, WAVE_FORMAT_PCM, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 ); 43 DEFINE_GUID( _KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF, WAVE_FORMAT_DOLBY_AC3_SPDIF, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 ); 44 12 45 // even number, 42 ~= 1.008 sec @ 48000 with 1152 samples per packet 13 46 const uint AudioOutputWin::kPacketCnt = 16; 14 47 … … 16 49 { 17 50 public: 18 51 AudioOutputWinPrivate() : 19 m_ WaveHdrs(NULL), m_hEvent(NULL)52 m_hWaveOut(NULL), m_WaveHdrs(NULL), m_hEvent(NULL) 20 53 { 21 54 m_WaveHdrs = new WAVEHDR[AudioOutputWin::kPacketCnt]; 22 55 memset(m_WaveHdrs, 0, sizeof(WAVEHDR) * AudioOutputWin::kPacketCnt); … … 83 116 m_priv(new AudioOutputWinPrivate()), 84 117 m_nPkts(0), 85 118 m_CurrentPkt(0), 86 m_OutPkts(NULL) 119 m_OutPkts(NULL), 120 m_UseSPDIF(laudio_passthru) 87 121 { 88 122 Reconfigure(laudio_bits, laudio_channels, 89 123 laudio_samplerate, laudio_passthru); … … 119 153 // Set everything up 120 154 SetBlocking(true); 121 155 fragment_size = (AUDIOOUTPUT_TELEPHONY == source) ? 320 : 6144; 156 soundcard_buffer_size = kPacketCnt * fragment_size; 122 157 123 WAVEFORMATEX wf; 124 wf.wFormatTag = WAVE_FORMAT_PCM; 125 wf.nChannels = audio_channels; 126 wf.nSamplesPerSec = audio_samplerate; 127 wf.wBitsPerSample = audio_bits; 128 wf.nBlockAlign = wf.wBitsPerSample / 8 * wf.nChannels; 129 wf.nAvgBytesPerSec = wf.nBlockAlign * wf.nSamplesPerSec; 130 wf.cbSize = 0; 158 WAVEFORMATEXTENSIBLE wf; 159 wf.Format.wFormatTag = 160 (m_UseSPDIF) ? WAVE_FORMAT_DOLBY_AC3_SPDIF : WAVE_FORMAT_PCM; 161 wf.Format.nChannels = audio_channels; 162 wf.Format.nSamplesPerSec = audio_samplerate; 163 wf.Format.nBlockAlign = audio_bytes_per_sample; 164 wf.Format.nAvgBytesPerSec = 165 wf.Format.nSamplesPerSec * wf.Format.nBlockAlign; 166 wf.Format.wBitsPerSample = audio_bits; 167 wf.Samples.wValidBitsPerSample = wf.Format.wBitsPerSample; 168 wf.SubFormat = 169 (m_UseSPDIF) ? _KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF : _KSDATAFORMAT_SUBTYPE_PCM; 131 170 171 VERBOSE(VB_AUDIO, "New format: " << audio_bits << "bits, " 172 << audio_channels << "ch, " << audio_samplerate << "Hz"); 173 174 /* Only use the new WAVE_FORMAT_EXTENSIBLE format for multichannel audio */ 175 if (audio_channels <= 2) 176 { 177 wf.Format.cbSize = 0; 178 } 179 else 180 { 181 wf.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; 182 wf.dwChannelMask = 0x003F; // 0x003F = 5.1 channels 183 wf.Format.cbSize = 184 sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); 185 } 186 132 187 MMRESULT mmr = waveOutOpen( 133 188 &m_priv->m_hWaveOut, 134 189 WAVE_MAPPER, 135 &wf,190 (WAVEFORMATEX *)&wf, 136 191 (DWORD) AudioOutputWinPrivate::waveOutProc, 137 192 (DWORD) this, 138 193 CALLBACK_FUNCTION); … … 140 195 if (mmr == WAVERR_BADFORMAT) 141 196 { 142 197 Error(QString("Unable to set audio output parameters %1") 143 .arg(wf. nSamplesPerSec));198 .arg(wf.Format.nSamplesPerSec)); 144 199 return false; 145 200 } 146 201 … … 157 212 if (size == 0) 158 213 return; 159 214 160 if ( InterlockedIncrement(&m_nPkts) >= kPacketCnt)215 if (audio_channels == 6) 161 216 { 162 while (m_nPkts >= kPacketCnt) 217 // Linux and Windows have different 5.1 channel order conventions 218 const uint kReorder[6] = {0,1,4,5,2,3}; 219 int abytes = audio_bits / 8; 220 unsigned char p_tmp[24]; 221 unsigned char *obuf = buffer; 222 for(int i = 0; i < size / audio_channels / abytes; i++) 223 { 224 for(int j = 0; j < audio_channels; j++) 225 { 226 for(int k = 0; k < abytes; k++) 227 { 228 p_tmp[abytes * kReorder[j] + k] = buffer[abytes * j + k]; 229 } 230 } 231 memcpy(buffer, p_tmp, abytes * audio_channels); 232 buffer += abytes * audio_channels; 233 } 234 buffer = obuf; 235 } 236 237 if (InterlockedIncrement(&m_nPkts) > kPacketCnt) 238 { 239 while (m_nPkts > kPacketCnt) 163 240 WaitForSingleObject(m_priv->m_hEvent, INFINITE); 164 241 } 165 242 … … 193 270 m_CurrentPkt++; 194 271 } 195 272 196 in t AudioOutputWin::getSpaceOnSoundcard(void)273 inline int AudioOutputWin::getSpaceOnSoundcard(void) 197 274 { 198 return (kPacketCnt - m_nPkts) * 1536 * 4;275 return soundcard_buffer_size - getBufferedOnSoundcard(); 199 276 } 200 277 201 in t AudioOutputWin::getBufferedOnSoundcard(void)278 inline int AudioOutputWin::getBufferedOnSoundcard(void) 202 279 { 203 return m_nPkts * 1536 * 4;280 return m_nPkts * fragment_size; 204 281 } 205 282 206 283 int AudioOutputWin::GetVolumeChannel(int channel)