Ticket #6538: aodx_21fixes.patch
File aodx_21fixes.patch, 38.0 KB (added by , 15 years ago) |
---|
-
libs/libmyth/audiooutputdx.h
1 1 #ifndef AUDIOOUTPUTDX 2 2 #define AUDIOOUTPUTDX 3 3 4 /* ACK! <windows.h> and <dsound.h> should only be in cpp's compiled5 * in windows only. Some of the variables in AudioOutputDX need to6 * be moved to a private class before removing these includes though.7 */8 #include <windows.h> // HACK HACK HACK9 #include <dsound.h> // HACK HACK HACK10 11 4 // Qt headers 12 5 #include <qstring.h> 13 6 14 7 // MythTV headers 15 8 #include "audiooutputbase.h" 16 9 10 class AudioOutputDXPrivate; 11 17 12 class AudioOutputDX : public AudioOutputBase 18 13 { 19 public: 14 friend class AudioOutputDXPrivate; 15 public: 20 16 AudioOutputDX(QString laudio_main_device, 21 17 QString laudio_passthru_device, 22 18 int laudio_bits, … … 25 21 bool lset_initial_vol, bool laudio_passthru); 26 22 virtual ~AudioOutputDX(); 27 23 28 /// BEGIN HACK HACK HACK HACK These need to actually be implemented!29 bool OpenDevice(void) { return false; }30 void CloseDevice(void) {}31 void WriteAudio(unsigned char*, int) {}32 virtual int getSpaceOnSoundcard(void) { return 0; }33 virtual int getBufferedOnSoundcard(void) { return 0; }34 #warning Several methods in AudioOutputDX need to be implemented...35 /// END HACK HACK HACK HACK36 37 virtual void Reset(void);38 virtual void Reconfigure(int audio_bits,39 int audio_channels,40 int audio_samplerate,41 bool audio_passthru);42 virtual void SetBlocking(bool blocking);43 44 virtual bool AddSamples(char *buffer, int samples, long long timecode);45 virtual bool AddSamples(char *buffers[], int samples, long long timecode);46 virtual void SetEffDsp(int dsprate);47 virtual void SetTimecode(long long timecode);48 49 virtual bool GetPause(void);50 virtual void Pause(bool paused);51 52 virtual void Drain(void);53 54 virtual int GetAudiotime(void);55 56 24 // Volume control 57 25 virtual int GetVolumeChannel(int channel); // Returns 0-100 58 26 virtual void SetVolumeChannel(int channel, int volume); // range 0-100 for vol 59 27 60 private: 61 HINSTANCE dsound_dll; /* handle of the opened dsound dll */ 62 LPDIRECTSOUND dsobject; 63 LPDIRECTSOUNDBUFFER dsbuffer; /* the sound buffer we use (direct sound 64 * takes care of mixing all the 65 * secondary buffers into the primary) */ 66 LPDIRECTSOUNDNOTIFY dsnotify; /* the position notify interface */ 67 DSBPOSITIONNOTIFY notif[4]; 28 protected: 29 virtual bool OpenDevice(void); 30 virtual void CloseDevice(void); 31 virtual void WriteAudio(unsigned char *aubuf, int size); 32 virtual void Pause(bool pause); 33 virtual inline int getSpaceOnSoundcard(void); 34 virtual inline int getBufferedOnSoundcard(void); 68 35 69 DWORD write_cursor; 70 DWORD buffer_size; 71 bool blocking; 72 73 bool awaiting_data; 74 75 int effdsp; // from the recorded stream 76 int audio_bytes_per_sample; 77 int audio_bits; 78 int audio_channels; 79 int audbuf_timecode; /* timecode of audio most recently placed into 80 buffer */ 81 bool can_hw_pause; 82 bool paused; 83 84 int InitDirectSound(); 85 int CreateDSBuffer(int audio_bits, int audio_channels, int audio_samplerate, bool b_probe); 86 void DestroyDSBuffer(); 87 int FillBuffer(int frames, char *buffer); 36 protected: 37 AudioOutputDXPrivate *m_priv; 38 bool m_PlayStarted; 39 DWORD m_WriteCursor; 40 bool m_UseSPDIF; 41 static const uint kFramesNum; 88 42 }; 89 43 90 44 #endif // AUDIOOUTPUTDX -
libs/libmyth/audiooutputdx.cpp
1 1 #include <iostream> 2 #include <cmath> 2 3 //#include <stdlib.h> 3 4 4 5 using namespace std; … … 10 11 #include <mmsystem.h> 11 12 #include <dsound.h> 12 13 13 #define FRAMES_NUM 65536 14 #define LOC QString("AODX: ") 15 #define LOC_ERR QString("AODX, ERROR: ") 14 16 17 const uint AudioOutputDX::kFramesNum = 32; 18 15 19 /***************************************************************************** 16 20 * DirectSound GUIDs. 17 21 * Defining them here allows us to get rid of the dxguid library during … … 23 27 /***************************************************************************** 24 28 * Useful macros 25 29 *****************************************************************************/ 26 #ifndef WAVE_FORMAT_IEEE_FLOAT27 # define WAVE_FORMAT_IEEE_FLOAT 0x000328 #endif29 30 30 #ifndef WAVE_FORMAT_DOLBY_AC3_SPDIF 31 31 # define WAVE_FORMAT_DOLBY_AC3_SPDIF 0x0092 32 32 #endif … … 35 35 #define WAVE_FORMAT_EXTENSIBLE 0xFFFE 36 36 #endif 37 37 38 #ifndef SPEAKER_FRONT_LEFT39 # define SPEAKER_FRONT_LEFT 0x140 # define SPEAKER_FRONT_RIGHT 0x241 # define SPEAKER_FRONT_CENTER 0x442 # define SPEAKER_LOW_FREQUENCY 0x843 # define SPEAKER_BACK_LEFT 0x1044 # define SPEAKER_BACK_RIGHT 0x2045 # define SPEAKER_FRONT_LEFT_OF_CENTER 0x4046 # define SPEAKER_FRONT_RIGHT_OF_CENTER 0x8047 # define SPEAKER_BACK_CENTER 0x10048 # define SPEAKER_SIDE_LEFT 0x20049 # define SPEAKER_SIDE_RIGHT 0x40050 # define SPEAKER_TOP_CENTER 0x80051 # define SPEAKER_TOP_FRONT_LEFT 0x100052 # define SPEAKER_TOP_FRONT_CENTER 0x200053 # define SPEAKER_TOP_FRONT_RIGHT 0x400054 # define SPEAKER_TOP_BACK_LEFT 0x800055 # define SPEAKER_TOP_BACK_CENTER 0x1000056 # define SPEAKER_TOP_BACK_RIGHT 0x2000057 # define SPEAKER_RESERVED 0x8000000058 #endif59 60 #ifndef DSSPEAKER_HEADPHONE61 # define DSSPEAKER_HEADPHONE 0x0000000162 #endif63 #ifndef DSSPEAKER_MONO64 # define DSSPEAKER_MONO 0x0000000265 #endif66 #ifndef DSSPEAKER_QUAD67 # define DSSPEAKER_QUAD 0x0000000368 #endif69 #ifndef DSSPEAKER_STEREO70 # define DSSPEAKER_STEREO 0x0000000471 #endif72 #ifndef DSSPEAKER_SURROUND73 # define DSSPEAKER_SURROUND 0x0000000574 #endif75 #ifndef DSSPEAKER_5POINT176 # define DSSPEAKER_5POINT1 0x0000000677 #endif78 79 38 #ifndef _WAVEFORMATEXTENSIBLE_ 80 39 typedef struct { 81 40 WAVEFORMATEX Format; … … 90 49 } WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE; 91 50 #endif 92 51 93 DEFINE_GUID( _KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, WAVE_FORMAT_IEEE_FLOAT, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );94 52 DEFINE_GUID( _KSDATAFORMAT_SUBTYPE_PCM, WAVE_FORMAT_PCM, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 ); 95 53 DEFINE_GUID( _KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF, WAVE_FORMAT_DOLBY_AC3_SPDIF, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 ); 96 54 55 class AudioOutputDXPrivate 56 { 57 public: 58 AudioOutputDXPrivate() : 59 dsound_dll(NULL), 60 dsobject(NULL), 61 dsbuffer(NULL) 62 { 63 InitDirectSound(); 64 } 97 65 66 ~AudioOutputDXPrivate() 67 { 68 DestroyDSBuffer(); 69 70 if (dsobject) 71 IDirectSound_Release(dsobject); 72 73 if (dsound_dll) 74 FreeLibrary(dsound_dll); 75 } 76 77 int InitDirectSound(void); 78 void DestroyDSBuffer(void); 79 bool StartPlayback(void); 80 81 public: 82 HINSTANCE dsound_dll; 83 LPDIRECTSOUND dsobject; 84 LPDIRECTSOUNDBUFFER dsbuffer; 85 }; 86 87 98 88 AudioOutputDX::AudioOutputDX( 99 89 QString laudio_main_device, QString laudio_passthru_device, 100 90 int laudio_bits, int laudio_channels, … … 104 94 laudio_bits, laudio_channels, 105 95 laudio_samplerate, lsource, 106 96 lset_initial_vol, laudio_passthru), 107 dsound_dll(NULL), 108 dsobject(NULL), 109 dsbuffer(NULL), 110 write_cursor(0), 111 buffer_size(0), 112 blocking(false), 113 awaiting_data(false), 114 effdsp(0), /* Should this be audio_bits ? */ 115 audio_bytes_per_sample(0), /* ACK! hides version in AudioOutputBase */ 116 audio_bits(0), /* ACK! hides version in AudioOutputBase */ 117 audio_channels(0), /* ACK! hides version in AudioOutputBase */ 118 audbuf_timecode(0), 119 can_hw_pause(false), 120 paused(false) 97 m_priv(new AudioOutputDXPrivate()), 98 m_PlayStarted(false), 99 m_WriteCursor(0), 100 m_UseSPDIF(laudio_passthru) 121 101 { 122 InitDirectSound();123 124 102 Reconfigure(laudio_bits, laudio_channels, 125 103 laudio_samplerate, laudio_passthru); 126 104 } 127 105 128 void AudioOutputDX::SetBlocking(bool blocking)129 {130 // FIXME: kedl: not sure what else could be required here?131 }132 133 void AudioOutputDX::Reconfigure(int audio_bits,134 int audio_channels,135 int audio_samplerate,136 bool audio_passthru)137 {138 if (dsbuffer)139 DestroyDSBuffer();140 141 CreateDSBuffer(audio_bits, audio_channels, audio_samplerate, false);142 143 awaiting_data = true;144 paused = true;145 146 effdsp = audio_samplerate;147 this->audio_bits = audio_bits;148 this->audio_channels = audio_channels;149 this->audio_passthru = audio_passthru;150 }151 152 106 AudioOutputDX::~AudioOutputDX() 153 107 { 154 DestroyDSBuffer();108 KillAudio(); 155 109 156 /* release the DirectSound object */ 157 if (dsobject) 158 IDirectSound_Release(dsobject); 159 160 /* free DSOUND.DLL */ 161 if (dsound_dll) 162 FreeLibrary(dsound_dll); 163 } 164 165 void AudioOutputDX::Reset(void) 166 { 167 audbuf_timecode = 0; 168 awaiting_data = true; 169 write_cursor = 0; 170 171 if (dsbuffer) 110 if (m_priv) 172 111 { 173 IDirectSoundBuffer_Stop(dsbuffer);174 IDirectSoundBuffer_SetCurrentPosition(dsbuffer, 0);112 delete m_priv; 113 m_priv = NULL; 175 114 } 176 177 115 } 178 116 179 bool AudioOutputDX::AddSamples(char *buffer, int frames, long long timecode)180 {181 FillBuffer(frames, buffer);182 183 HRESULT dsresult;184 185 if (awaiting_data)186 {187 // dsresult = IDirectSoundBuffer_Play(dsbuffer, 0, 0, DSBPLAY_LOOPING);188 // if (dsresult == DSERR_BUFFERLOST)189 // {190 // IDirectSoundBuffer_Restore(dsbuffer);191 // dsresult = IDirectSoundBuffer_Play(dsbuffer, 0, 0, DSBPLAY_LOOPING );192 // }193 // if (dsresult != DS_OK)194 // {195 // VERBOSE(VB_IMPORTANT, "cannot start playing buffer" );196 // }197 198 awaiting_data = false;199 }200 201 202 203 // VERBOSE(VB_IMPORTANT, "add_samples(a) " << frames << " " << timecode);204 205 if (timecode < 0)206 timecode = audbuf_timecode; // add to current timecode207 208 /* we want the time at the end -- but the file format stores209 time at the start of the chunk. */210 audbuf_timecode = timecode + (int)((frames*1000.0) / effdsp);211 212 return true;213 }214 215 216 bool AudioOutputDX::AddSamples(char *buffers[], int frames, long long timecode)217 {218 // VERBOSE(VB_IMPORTANT, "add_samples(b) " << frames << " " << timecode);219 220 /* int err;221 int waud=0;222 int audio_bytes = audio_bits / 8;223 int audbufsize = frames*audio_bytes*audio_channels;224 char *audiobuffer = (char *) calloc(1,audbufsize);225 226 if (audiobuffer==NULL)227 {228 fprintf(stderr, "couldn't get memory to write audio to artsd\n");229 return;230 }231 232 if (pcm_handle == NULL)233 {234 free(audiobuffer);235 return;236 }237 238 for (int itemp = 0; itemp < frames*audio_bytes; itemp+=audio_bytes)239 {240 for(int chan = 0; chan < audio_channels; chan++)241 {242 audiobuffer[waud++] = buffers[chan][itemp];243 if (audio_bits == 16)244 audiobuffer[waud++] = buffers[chan][itemp+1];245 if (waud >= audbufsize)246 waud -= audbufsize;247 }248 }249 250 err = arts_write(pcm_handle, audiobuffer, frames*4);251 free(audiobuffer);252 253 if (err < 0)254 {255 fprintf(stderr, "arts_write error: %s\n", arts_error_text(err));256 return;257 }258 259 if (timecode < 0)260 timecode = audbuf_timecode; // add to current timecode*/261 262 /* we want the time at the end -- but the file format stores263 time at the start of the chunk. */264 //audbuf_timecode = timecode + (int)((frames*100000.0) / effdsp);265 266 return true;267 }268 269 void AudioOutputDX::SetTimecode(long long timecode)270 {271 audbuf_timecode = timecode;272 }273 274 void AudioOutputDX::SetEffDsp(int dsprate)275 {276 VERBOSE(VB_IMPORTANT, "setting dsprate = " << dsprate);277 278 HRESULT dsresult;279 280 dsresult = IDirectSoundBuffer_SetFrequency(dsbuffer, dsprate / 100);281 282 if (dsresult != DS_OK)283 {284 VERBOSE(VB_IMPORTANT, "cannot set frequency");285 }286 287 effdsp = dsprate / 100;288 }289 290 bool AudioOutputDX::GetPause(void)291 {292 return paused;293 }294 295 void AudioOutputDX::Pause(bool pause)296 {297 HRESULT dsresult;298 299 VERBOSE(VB_IMPORTANT, "pause: " << pause);300 301 if (pause == paused)302 return;303 304 if (paused)305 {306 VERBOSE(VB_IMPORTANT, "unpausing");307 308 dsresult = IDirectSoundBuffer_Play(dsbuffer, 0, 0, DSBPLAY_LOOPING);309 if (dsresult == DSERR_BUFFERLOST)310 {311 IDirectSoundBuffer_Restore(dsbuffer);312 dsresult = IDirectSoundBuffer_Play(dsbuffer, 0, 0, DSBPLAY_LOOPING );313 }314 if (dsresult != DS_OK)315 {316 VERBOSE(VB_IMPORTANT, "cannot start playing buffer" );317 }318 }319 else320 {321 VERBOSE(VB_IMPORTANT, "pausing");322 323 IDirectSoundBuffer_Stop(dsbuffer);324 }325 326 paused = pause;327 }328 329 int AudioOutputDX::GetAudiotime(void)330 {331 DWORD play_pos;332 HRESULT dsresult;333 334 dsresult = IDirectSoundBuffer_GetCurrentPosition(dsbuffer, &play_pos, NULL);335 336 if (dsresult != DS_OK)337 {338 VERBOSE(VB_IMPORTANT, "cannot get current buffer positions");339 return -1;340 }341 342 int frames = (write_cursor - play_pos) / audio_bytes_per_sample;343 344 if (frames < 0)345 frames += buffer_size;346 347 return audbuf_timecode - (int)((frames*1000.0) / effdsp);348 }349 350 351 117 typedef HRESULT (WINAPI *LPFNDSC) (LPGUID, LPDIRECTSOUND *, LPUNKNOWN); 352 118 353 /***************************************************************************** 354 * InitDirectSound: handle all the gory details of DirectSound initialisation 355 *****************************************************************************/ 356 int AudioOutputDX::InitDirectSound() 119 int AudioOutputDXPrivate::InitDirectSound(void) 357 120 { 358 // HRESULT (WINAPI *OurDirectSoundCreate)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN); 121 359 122 LPFNDSC OurDirectSoundCreate; 360 123 361 VERBOSE(VB_ IMPORTANT,"initialising DirectSound");124 VERBOSE(VB_AUDIO, LOC + "initialising DirectSound"); 362 125 363 126 dsound_dll = LoadLibrary("DSOUND.DLL"); 364 127 if (dsound_dll == NULL ) 365 128 { 366 VERBOSE(VB_IMPORTANT, "cannot open DSOUND.DLL" );129 VERBOSE(VB_IMPORTANT, LOC_ERR + "cannot open DSOUND.DLL" ); 367 130 goto error; 368 131 } 369 132 370 OurDirectSoundCreate = (LPFNDSC)371 133 OurDirectSoundCreate = 134 (LPFNDSC)GetProcAddress(dsound_dll, "DirectSoundCreate"); 372 135 if (OurDirectSoundCreate == NULL) 373 136 { 374 VERBOSE(VB_IMPORTANT, "GetProcAddress FAILED" );137 VERBOSE(VB_IMPORTANT, LOC_ERR + "GetProcAddress FAILED" ); 375 138 goto error; 376 139 } 377 140 378 VERBOSE(VB_IMPORTANT, "create DS object");141 // VERBOSE(VB_IMPORTANT, "create DS object"); 379 142 380 143 /* Create the direct sound object */ 381 144 if FAILED(OurDirectSoundCreate(NULL, &dsobject, NULL)) 382 145 { 383 VERBOSE(VB_IMPORTANT, "cannot create a direct sound device" );146 VERBOSE(VB_IMPORTANT, LOC_ERR + "cannot create a direct sound device" ); 384 147 goto error; 385 148 } 386 149 387 VERBOSE(VB_IMPORTANT, "setting cooperative level");150 // VERBOSE(VB_IMPORTANT, "setting cooperative level"); 388 151 389 152 /* Set DirectSound Cooperative level, ie what control we want over Windows 390 153 * sound device. In our case, DSSCL_EXCLUSIVE means that we can modify the … … 396 159 * sound without any video, and so what window handle should we use ??? 397 160 * The hack for now is to use the Desktop window handle - it seems to be 398 161 * working */ 399 if (IDirectSound_SetCooperativeLevel(dsobject,162 if FAILED(IDirectSound_SetCooperativeLevel(dsobject, 400 163 GetDesktopWindow(), 401 164 DSSCL_EXCLUSIVE)) 402 165 { 403 VERBOSE(VB_IMPORTANT, "cannot set direct soundcooperative level" );166 VERBOSE(VB_IMPORTANT, LOC_ERR + "cannot set DS cooperative level" ); 404 167 } 405 168 406 VERBOSE(VB_ IMPORTANT, "creating notificatoin events");169 VERBOSE(VB_AUDIO, LOC + "initialised DirectSound"); 407 170 408 /* Then create the notification events */409 for (int i = 0; i < 4; i++)410 notif[i].hEventNotify = CreateEvent(NULL, FALSE, FALSE, NULL);411 412 VERBOSE(VB_IMPORTANT, "initialised DirectSound");413 414 171 return 0; 415 172 416 173 error: … … 421 178 dsound_dll = NULL; 422 179 } 423 180 return -1; 181 } 424 182 183 void AudioOutputDXPrivate::DestroyDSBuffer(void) 184 { 185 if (dsbuffer) 186 { 187 VERBOSE(VB_AUDIO, LOC + "destroying DirectSound buffer"); 188 IDirectSoundBuffer_Stop(dsbuffer); 189 IDirectSoundBuffer_Release(dsbuffer); 190 dsbuffer = NULL; 191 } 425 192 } 426 193 427 428 /***************************************************************************** 429 * CreateDSBuffer: Creates a direct sound buffer of the required format. 430 ***************************************************************************** 431 * This function creates the buffer we'll use to play audio. 432 * In DirectSound there are two kinds of buffers: 433 * - the primary buffer: which is the actual buffer that the soundcard plays 434 * - the secondary buffer(s): these buffers are the one actually used by 435 * applications and DirectSound takes care of mixing them into the primary. 436 * 437 * Once you create a secondary buffer, you cannot change its format anymore so 438 * you have to release the current one and create another. 439 *****************************************************************************/ 440 int AudioOutputDX::CreateDSBuffer(int audio_bits, int audio_channels, int audio_samplerate, bool b_probe) 194 bool AudioOutputDXPrivate::StartPlayback(void) 441 195 { 442 WAVEFORMATEXTENSIBLE waveformat; 443 DSBUFFERDESC dsbdesc; 444 unsigned int i; 196 HRESULT dsresult; 445 197 446 /* First set the sound buffer format */ 447 /* waveformat.dwChannelMask = 0; 448 for( i = 0; i < sizeof(pi_channels_in)/sizeof(uint32_t); i++ ) 198 dsresult = IDirectSoundBuffer_Play(dsbuffer, 0, 0, DSBPLAY_LOOPING); 199 if (dsresult == DSERR_BUFFERLOST) 449 200 { 450 if ( i_channels & pi_channels_in[i] ) 451 waveformat.dwChannelMask |= pi_channels_out[i]; 452 }*/ 453 454 /* switch( i_format ) 201 IDirectSoundBuffer_Restore(dsbuffer); 202 dsresult = IDirectSoundBuffer_Play(dsbuffer, 0, 0, DSBPLAY_LOOPING ); 203 } 204 if (dsresult != DS_OK) 455 205 { 456 case VLC_FOURCC('s','p','d','i'): 457 i_nb_channels = 2; 458 / * To prevent channel re-ordering * / 459 waveformat.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; 460 waveformat.Format.wBitsPerSample = 16; 461 waveformat.Samples.wValidBitsPerSample = 462 waveformat.Format.wBitsPerSample; 463 waveformat.Format.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF; 464 waveformat.SubFormat = _KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF; 465 break; 206 VERBOSE(VB_IMPORTANT, LOC_ERR + "cannot start playing buffer" ); 207 return false; 208 } 209 else 210 return true; 211 } 466 212 467 case VLC_FOURCC('f','l','3','2'): 468 waveformat.Format.wBitsPerSample = sizeof(float) * 8; 469 waveformat.Samples.wValidBitsPerSample = 470 waveformat.Format.wBitsPerSample; 471 waveformat.Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; 472 waveformat.SubFormat = _KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; 473 break; 213 bool AudioOutputDX::OpenDevice(void) 214 { 215 WAVEFORMATEXTENSIBLE wf; 216 DSBUFFERDESC dsbdesc; 474 217 475 case VLC_FOURCC('s','1','6','l'):*/ 476 waveformat.Format.wBitsPerSample = audio_bits; 477 waveformat.Samples.wValidBitsPerSample = 478 waveformat.Format.wBitsPerSample; 479 waveformat.Format.wFormatTag = WAVE_FORMAT_PCM; 480 waveformat.SubFormat = _KSDATAFORMAT_SUBTYPE_PCM; 481 /* break; 482 }*/ 218 if (!m_priv->dsobject || !m_priv->dsound_dll) 219 { 220 Error("DirectSound initialization failed"); 221 return false; 222 } 483 223 484 waveformat.Format.nChannels = audio_channels; 485 waveformat.Format.nSamplesPerSec = audio_samplerate; 486 waveformat.Format.nBlockAlign = 487 waveformat.Format.wBitsPerSample / 8 * audio_channels; 488 waveformat.Format.nAvgBytesPerSec = 489 waveformat.Format.nSamplesPerSec * waveformat.Format.nBlockAlign; 224 CloseDevice(); 490 225 491 audio_bytes_per_sample = waveformat.Format.wBitsPerSample / 8 * audio_channels; 226 SetBlocking(true); 227 fragment_size = (source == AUDIOOUTPUT_TELEPHONY) ? 320 : 6144; 228 if (audio_channels > 2) 229 fragment_size *= 2; 230 soundcard_buffer_size = kFramesNum * fragment_size; 231 audio_bytes_per_sample = audio_bits / 8 * audio_channels; 232 if (m_UseSPDIF && (audio_channels != 2)) 233 { 234 Error("SPDIF passthru requires 2 channel data"); 235 return false; 236 } 492 237 493 VERBOSE(VB_IMPORTANT, "New format: " << audio_bits << "bits, " << audio_channels << "ch, " << audio_samplerate << "Hz"); 238 /* First set the sound buffer format */ 239 wf.Format.wFormatTag = 240 (m_UseSPDIF) ? WAVE_FORMAT_DOLBY_AC3_SPDIF : WAVE_FORMAT_PCM; 241 wf.Format.nChannels = audio_channels; 242 wf.Format.nSamplesPerSec = audio_samplerate; 243 wf.Format.nBlockAlign = audio_bytes_per_sample; 244 wf.Format.nAvgBytesPerSec = 245 wf.Format.nSamplesPerSec * wf.Format.nBlockAlign; 246 wf.Format.wBitsPerSample = audio_bits; 247 wf.Samples.wValidBitsPerSample = wf.Format.wBitsPerSample; 248 wf.SubFormat = 249 (m_UseSPDIF) ? _KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF : _KSDATAFORMAT_SUBTYPE_PCM; 494 250 251 VERBOSE(VB_AUDIO, LOC + "New format: " << audio_bits << "bits, " 252 << audio_channels << "ch, " << audio_samplerate << "Hz"); 253 495 254 /* Only use the new WAVE_FORMAT_EXTENSIBLE format for multichannel audio */ 496 255 if (audio_channels <= 2) 497 256 { 498 w aveformat.Format.cbSize = 0;257 wf.Format.cbSize = 0; 499 258 } 500 259 else 501 260 { 502 waveformat.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; 503 waveformat.Format.cbSize = 261 wf.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; 262 wf.dwChannelMask = 0x003F; // 0x003F = 5.1 channels 263 wf.Format.cbSize = 504 264 sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); 505 265 } 506 266 507 508 267 /* Then fill in the direct sound descriptor */ 509 268 memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); 510 269 dsbdesc.dwSize = sizeof(DSBUFFERDESC); 511 270 dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2/* Better position accuracy */ 512 | DSBCAPS_CTRLPOSITIONNOTIFY /* We need notification */513 271 | DSBCAPS_GLOBALFOCUS /* Allows background playing */ 514 272 | DSBCAPS_LOCHARDWARE; /* Needed for 5.1 on emu101k */ 515 dsbdesc.dwBufferBytes = FRAMES_NUM * audio_bits/8 * audio_channels; /* buffer size */ 516 dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&waveformat; 273 if (!m_UseSPDIF) 274 dsbdesc.dwFlags |= DSBCAPS_CTRLVOLUME; /* Allow volume control */ 275 dsbdesc.dwBufferBytes = soundcard_buffer_size; /* buffer size */ 276 dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&wf; 517 277 518 if FAILED(IDirectSound_CreateSoundBuffer(dsobject, &dsbdesc, &dsbuffer, NULL)) 278 if FAILED(IDirectSound_CreateSoundBuffer( 279 m_priv->dsobject, &dsbdesc, &m_priv->dsbuffer, NULL)) 519 280 { 281 /* Vista does not support hardware mixing */ 520 282 /* Try without DSBCAPS_LOCHARDWARE */ 521 283 dsbdesc.dwFlags &= ~DSBCAPS_LOCHARDWARE; 522 if FAILED(IDirectSound_CreateSoundBuffer(dsobject, &dsbdesc, &dsbuffer, NULL)) 284 HRESULT dsresult = IDirectSound_CreateSoundBuffer( 285 m_priv->dsobject, &dsbdesc, &m_priv->dsbuffer, NULL); 286 if FAILED(dsresult) 523 287 { 524 return -1; 288 Error(QString("Failed to create DS buffer %1").arg((DWORD)dsresult)); 289 return false; 525 290 } 526 if ( !b_probe ) VERBOSE(VB_IMPORTANT, "couldn't use hardware sound buffer" );291 VERBOSE(VB_AUDIO, LOC + "Using software mixer" ); 527 292 } 293 VERBOSE(VB_AUDIO, LOC + "created DirectSound buffer"); 528 294 529 write_cursor = 0; 530 buffer_size = FRAMES_NUM * audio_bits/8 * audio_channels; 531 532 /* Stop here if we were just probing */ 533 if ( b_probe ) 534 { 535 IDirectSoundBuffer_Release(dsbuffer); 536 dsbuffer = NULL; 537 return 0; 538 } 539 540 /* Now the secondary buffer is created, we need to setup its position 541 * notification */ 542 for (i = 0; i < 4; i++) 543 { 544 notif[i].dwOffset = buffer_size / 4 * i; 545 } 546 547 /* Get the IDirectSoundNotify interface */ 548 if FAILED(IDirectSoundBuffer_QueryInterface(dsbuffer, IID_IDirectSoundNotify, (LPVOID*) &dsnotify)) 549 { 550 VERBOSE(VB_IMPORTANT, "cannot get IDirectSoundNotify interface" ); 551 goto error; 552 } 553 554 if FAILED(IDirectSoundNotify_SetNotificationPositions(dsnotify, 4, notif)) 555 { 556 VERBOSE(VB_IMPORTANT, "cannot set position notification" ); 557 goto error; 558 } 559 560 // p_aout->output.p_sys->i_channel_mask = waveformat.dwChannelMask; 561 // CheckReordering( p_aout, i_nb_channels ); 562 563 VERBOSE(VB_IMPORTANT, "created DirectSound buffer"); 564 565 return 0; 566 567 error: 568 DestroyDSBuffer(); 569 return -1; 295 return true; 570 296 } 571 297 572 573 /***************************************************************************** 574 * DestroyDSBuffer 575 ***************************************************************************** 576 * This function destroys the secondary buffer. 577 *****************************************************************************/ 578 void AudioOutputDX::DestroyDSBuffer() 298 void AudioOutputDX::CloseDevice(void) 579 299 { 580 if (dsnotify) 581 { 582 IDirectSoundNotify_Release(dsnotify); 583 dsnotify = NULL; 584 } 585 586 VERBOSE(VB_IMPORTANT, "destroying DirectSound buffer"); 587 588 if (dsbuffer) 589 { 590 IDirectSoundBuffer_Stop(dsbuffer); 591 IDirectSoundBuffer_Release(dsbuffer); 592 dsbuffer = NULL; 593 } 300 if (m_priv->dsbuffer) 301 m_priv->DestroyDSBuffer(); 302 m_WriteCursor = 0; 303 m_PlayStarted = false; 594 304 } 595 305 596 /***************************************************************************** 597 * FillBuffer: Fill in one of the direct sound frame buffers. 598 ***************************************************************************** 599 * Returns VLC_SUCCESS on success. 600 *****************************************************************************/ 601 int AudioOutputDX::FillBuffer(int frames, char *buffer) 306 void AudioOutputDX::WriteAudio(unsigned char * buffer, int size) 602 307 { 603 DWORD play_pos, write_pos, end_write; 604 void *p_write_position, *p_wrap_around; 605 DWORD l_bytes1, l_bytes2; 606 HRESULT dsresult; 308 if (size == 0) 309 return; 607 310 608 if ( !awaiting_data && !paused)311 if (audio_channels == 6) 609 312 { 610 611 // VERBOSE(VB_IMPORTANT, "checking buffer positions");612 613 dsresult = IDirectSoundBuffer_GetCurrentPosition(dsbuffer, &play_pos, &write_pos);614 615 if (dsresult != DS_OK)313 // Linux and Windows have different 5.1 channel order conventions 314 const uint kReorder[6] = {0,1,4,5,2,3}; 315 int abytes = audio_bits / 8; 316 unsigned char p_tmp[24]; 317 unsigned char *obuf = buffer; 318 for(int i = 0; i < size / audio_channels / abytes; i++) 616 319 { 617 VERBOSE(VB_IMPORTANT, "cannot get current buffer positions"); 618 return -1; 619 } 620 621 end_write = write_cursor + (frames + FRAMES_NUM/4) * audio_bytes_per_sample; 622 623 while (!(((play_pos < write_pos) && (write_cursor >= write_pos || write_cursor < play_pos) && 624 (end_write >= write_pos || end_write < play_pos)) || 625 ((play_pos < write_pos) && (write_cursor >= write_pos && write_cursor < play_pos) && 626 (end_write >= write_pos && end_write < play_pos)))) 627 { 628 // VERBOSE(VB_IMPORTANT, "cannot write audio data: " << write_cursor << " " << write_pos << " " << play_pos << " sleeping"); 629 630 HANDLE notification_events[4]; 631 632 for(int i = 0; i < 4; i++) 633 notification_events[i] = notif[i].hEventNotify; 634 635 WaitForMultipleObjects(4, notification_events, 0, INFINITE ); 636 637 // VERBOSE(VB_IMPORTANT, "woken"); 638 639 dsresult = IDirectSoundBuffer_GetCurrentPosition(dsbuffer, &play_pos, &write_pos); 640 641 if (dsresult != DS_OK) 320 for(int j = 0; j < audio_channels; j++) 642 321 { 643 VERBOSE(VB_IMPORTANT, "cannot get current buffer positions"); 644 return -1; 322 for(int k = 0; k < abytes; k++) 323 { 324 p_tmp[abytes * kReorder[j] + k] = buffer[abytes * j + k]; 325 } 645 326 } 646 647 end_write = write_cursor + (frames + FRAMES_NUM/4) * audio_bytes_per_sample;327 memcpy(buffer, p_tmp, abytes * audio_channels); 328 buffer += abytes * audio_channels; 648 329 } 330 buffer = obuf; 649 331 } 650 651 332 652 // VERBOSE(VB_IMPORTANT, "Locking buffer"); 333 void *p_write_position, *p_wrap_around; 334 DWORD l_bytes1, l_bytes2; 335 HRESULT dsresult; 653 336 654 337 /* Before copying anything, we have to lock the buffer */ 655 338 dsresult = IDirectSoundBuffer_Lock( 656 dsbuffer,/* DS buffer */657 write_cursor,/* Start offset */658 frames * audio_bytes_per_sample,/* Number of bytes */339 m_priv->dsbuffer, /* DS buffer */ 340 m_WriteCursor, /* Start offset */ 341 size, /* Number of bytes */ 659 342 &p_write_position, /* Address of lock start */ 660 343 &l_bytes1, /* Count of bytes locked before wrap around */ 661 344 &p_wrap_around, /* Buffer adress (if wrap around) */ 662 345 &l_bytes2, /* Count of bytes after wrap around */ 663 0); 346 0); /* Flags */ 664 347 if (dsresult == DSERR_BUFFERLOST) 665 348 { 666 IDirectSoundBuffer_Restore( dsbuffer);349 IDirectSoundBuffer_Restore(m_priv->dsbuffer); 667 350 dsresult = IDirectSoundBuffer_Lock( 668 dsbuffer,669 write_cursor,670 frames * audio_bytes_per_sample,351 m_priv->dsbuffer, 352 m_WriteCursor, 353 size, 671 354 &p_write_position, 672 355 &l_bytes1, 673 356 &p_wrap_around, … … 676 359 } 677 360 if (dsresult != DS_OK) 678 361 { 679 VERBOSE(VB_IMPORTANT, "cannot lock buffer");680 return -1;362 VERBOSE(VB_IMPORTANT, LOC_ERR + "cannot lock buffer, audio dropped"); 363 return; 681 364 } 682 365 683 366 if (buffer == NULL) 684 367 { 685 VERBOSE(VB_ IMPORTANT,"Writing null bytes");368 VERBOSE(VB_AUDIO, LOC + "Writing null bytes"); 686 369 687 370 memset(p_write_position, 0, l_bytes1); 688 371 if (p_wrap_around) 689 372 memset(p_wrap_around, 0, l_bytes2); 690 373 691 write_cursor += l_bytes1 + l_bytes2;374 m_WriteCursor += l_bytes1 + l_bytes2; 692 375 693 while (write_cursor >=buffer_size)694 write_cursor -=buffer_size;376 while (m_WriteCursor >= (DWORD)soundcard_buffer_size) 377 m_WriteCursor -= soundcard_buffer_size; 695 378 } 696 /* else if ( p_aout->output.p_sys->b_chan_reorder )697 {698 /* Do the channel reordering here * /699 700 if ( p_aout->output.output.i_format == VLC_FOURCC('s','1','6','l') )701 InterleaveS16( (int16_t *)p_buffer->p_buffer,702 (int16_t *)p_write_position,703 p_aout->output.p_sys->pi_chan_table,704 aout_FormatNbChannels( &p_aout->output.output ) );705 else706 InterleaveFloat32( (float *)p_buffer->p_buffer,707 (float *)p_write_position,708 p_aout->output.p_sys->pi_chan_table,709 aout_FormatNbChannels( &p_aout->output.output ) );710 711 aout_BufferFree( p_buffer );712 }*/713 379 else 714 380 { 715 // VERBOSE(VB_IMPORTANT, "filling buffer");716 717 381 memcpy(p_write_position, buffer, l_bytes1); 718 // VERBOSE(VB_IMPORTANT, "buf_fill: " << l_bytes1 << " bytes, " << p_write_position << "-" << ((int)p_write_position + l_bytes1));719 382 if (p_wrap_around) { 720 383 memcpy(p_wrap_around, buffer + l_bytes1, l_bytes2); 721 // VERBOSE(VB_IMPORTANT, "buf_fill2: " << l_bytes2 << " bytes, " << p_wrap_around << "-" << ((int)p_wrap_around + l_bytes2));722 384 } 723 385 724 write_cursor += l_bytes1 + l_bytes2;386 m_WriteCursor += l_bytes1 + l_bytes2; 725 387 726 while (write_cursor >=buffer_size)727 write_cursor -=buffer_size;388 while (m_WriteCursor >= (DWORD)soundcard_buffer_size) 389 m_WriteCursor -= soundcard_buffer_size; 728 390 } 729 391 730 // VERBOSE(VB_IMPORTANT, "unlocking buffer");731 732 392 /* Now the data has been copied, unlock the buffer */ 733 IDirectSoundBuffer_Unlock( dsbuffer, p_write_position, l_bytes1,393 IDirectSoundBuffer_Unlock(m_priv->dsbuffer, p_write_position, l_bytes1, 734 394 p_wrap_around, l_bytes2 ); 735 395 396 m_PlayStarted = m_priv->StartPlayback(); 397 } 736 398 737 // VERBOSE(VB_IMPORTANT, "finished fillbuffer"); 399 void AudioOutputDX::Pause(bool pause) 400 { 401 if (m_priv->dsbuffer) 402 { 403 if (pause) 404 { 405 IDirectSoundBuffer_Stop(m_priv->dsbuffer); 406 VERBOSE(VB_AUDIO, LOC + "buffer paused"); 407 } 408 else 409 { 410 if (! m_priv->StartPlayback()) 411 VERBOSE(VB_IMPORTANT, LOC_ERR + "unpause failed" ); 412 VERBOSE(VB_AUDIO, LOC + "buffer unpaused"); 413 } 414 } 738 415 739 return 0;416 AudioOutputBase::Pause(pause); 740 417 } 741 418 742 // Wait for all data to finish playing 743 void AudioOutputDX::Drain() 419 inline int AudioOutputDX::getSpaceOnSoundcard(void) 744 420 { 745 // TODO: Wait until all data has been played... 421 HRESULT dsresult; 422 DWORD play_pos, write_pos; 746 423 424 dsresult = IDirectSoundBuffer_GetCurrentPosition( 425 m_priv->dsbuffer, &play_pos, &write_pos); 426 if (dsresult != DS_OK) 427 { 428 VERBOSE(VB_IMPORTANT, LOC_ERR + "cannot get current buffer position"); 429 return 0; 430 } 431 432 if (!m_PlayStarted) 433 return soundcard_buffer_size; 434 else 435 { 436 int buffer_free = (int)play_pos - (int)m_WriteCursor; 437 if ( buffer_free < 0 ) 438 buffer_free += soundcard_buffer_size; 439 440 if (((write_pos > play_pos) && (m_WriteCursor <= write_pos) 441 && (m_WriteCursor > play_pos)) 442 || ((write_pos < play_pos) && ((m_WriteCursor <= write_pos) 443 || (play_pos < m_WriteCursor)))) 444 { 445 VERBOSE (VB_AUDIO, LOC + "buffer underrun " 446 << play_pos << " " << write_pos << " " << m_WriteCursor); 447 // WriteCursor is in unsafe zone - stop playback for now 448 // Next call to WriteAudio will restart the buffer 449 IDirectSoundBuffer_Stop(m_priv->dsbuffer); 450 } 451 return buffer_free; 452 } 747 453 } 748 454 455 inline int AudioOutputDX::getBufferedOnSoundcard(void) 456 { 457 HRESULT dsresult; 458 DWORD play_pos; 459 460 dsresult = IDirectSoundBuffer_GetCurrentPosition(m_priv->dsbuffer, &play_pos, NULL); 461 if (dsresult != DS_OK) 462 { 463 VERBOSE(VB_IMPORTANT, LOC_ERR + "cannot get current buffer position"); 464 return 0; 465 } 466 467 int buffered = (int)m_WriteCursor - (int)play_pos; 468 if ( buffered < 0 ) 469 buffered += soundcard_buffer_size; 470 return buffered; 471 } 472 749 473 int AudioOutputDX::GetVolumeChannel(int channel) 750 474 { 751 // Do nothing 752 return 100; 475 HRESULT dsresult; 476 long dxVolume = 0; 477 int volume; 478 479 if (m_UseSPDIF) 480 return 100; 481 482 dsresult = IDirectSoundBuffer_GetVolume(m_priv->dsbuffer, &dxVolume); 483 if (dsresult != DS_OK) 484 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to get volume " << dxVolume ); 485 486 volume = (int)(pow(10,(float)dxVolume/20)*100); 487 VERBOSE(VB_AUDIO, LOC + "got volume " << volume ); 488 489 return volume; 753 490 } 491 754 492 void AudioOutputDX::SetVolumeChannel(int channel, int volume) 755 493 { 756 // Do nothing 494 HRESULT dsresult; 495 float dbAtten = 20 * log10((float)volume/100); 496 long dxVolume = (volume == 0) ? DSBVOLUME_MIN : 100 * dbAtten; 497 498 if (m_UseSPDIF) 499 return; 500 501 // dxVolume is attenuation in 100ths of a decibel 502 dsresult = IDirectSoundBuffer_SetVolume(m_priv->dsbuffer, dxVolume); 503 504 if (dsresult != DS_OK) 505 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to set volume " << dxVolume ); 506 507 VERBOSE(VB_AUDIO, LOC + "set volume " << dxVolume ); 757 508 } 758 509 510 /* vim: set expandtab tabstop=4 shiftwidth=4: */ -
libs/libmythtv/NuppelVideoPlayer.cpp
4194 4194 if (audioOutput) 4195 4195 { 4196 4196 audioOutput->SetStretchFactor(play_speed); 4197 #ifdef USING_DIRECTX4198 audioOutput->Reset();4199 #endif4200 4197 } 4201 4198 } 4202 4199