1 //////////////////////////////////////////////////////////////////////////////////////// 2 // 3 // Nestopia - NES/Famicom emulator written in C++ 4 // 5 // Copyright (C) 2003-2008 Martin Freij 6 // 7 // This file is part of Nestopia. 8 // 9 // Nestopia is free software; you can redistribute it and/or modify 10 // it under the terms of the GNU General Public License as published by 11 // the Free Software Foundation; either version 2 of the License, or 12 // (at your option) any later version. 13 // 14 // Nestopia is distributed in the hope that it will be useful, 15 // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 // GNU General Public License for more details. 18 // 19 // You should have received a copy of the GNU General Public License 20 // along with Nestopia; if not, write to the Free Software 21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 // 23 //////////////////////////////////////////////////////////////////////////////////////// 24 25 #ifndef NST_DIRECTX_DIRECTSOUND_H 26 #define NST_DIRECTX_DIRECTSOUND_H 27 28 #pragma once 29 30 #include <vector> 31 #include "NstObjectPod.hpp" 32 #include "NstDirectX.hpp" 33 34 #if NST_MSVC >= 1200 35 #pragma warning( push ) 36 #pragma warning( disable : 4201 ) 37 #endif 38 39 #include <MMSystem.h> 40 41 #if NST_MSVC >= 1200 42 #pragma warning( pop ) 43 #endif 44 45 #define DIRECTSOUND_VERSION 0x0800 46 #include <dsound.h> 47 48 namespace Nestopia 49 { 50 namespace DirectX 51 { 52 class DirectSound 53 { 54 public: 55 56 explicit DirectSound(HWND); 57 ~DirectSound(); 58 59 enum Channels 60 { 61 MONO = 1, 62 STEREO 63 }; 64 65 enum Pool 66 { 67 POOL_HARDWARE, 68 POOL_SYSTEM 69 }; 70 71 struct Adapter : BaseAdapter 72 { 73 Adapter(); 74 75 bool buggy; 76 }; 77 78 typedef std::vector<Adapter> Adapters; 79 80 cstring Update(uint,uint,uint,Channels,uint,Pool,bool); 81 void Destroy(); 82 void StopStream(); 83 84 private: 85 86 class SoundAdapters 87 { 88 static BOOL CALLBACK Enumerator(LPGUID,LPCTSTR,LPCTSTR,LPVOID); 89 90 public: 91 92 SoundAdapters(); 93 94 Adapters list; 95 }; 96 97 struct Device : ComInterface<IDirectSound8> 98 { 99 explicit Device(HWND); 100 101 HWND const hWnd; 102 ushort id; 103 bool priority; 104 bool buggy; 105 }; 106 107 class Buffer 108 { 109 public: 110 111 Buffer(); 112 ~Buffer(); 113 114 cstring Update(IDirectSound8&,bool,uint,uint,Channels,uint,Pool,bool); 115 void StartStream(); 116 void StopStream(IDirectSound8*,bool); 117 void Release(); 118 119 private: 120 121 cstring Create(IDirectSound8&,bool); 122 123 enum 124 { 125 DC_OFFSET_8 = 0x80, 126 DC_OFFSET_16 = 0x0000 127 }; 128 129 struct Com : ComInterface<IDirectSoundBuffer8> 130 { 131 Com(); 132 133 uint writePos; 134 }; 135 136 struct Settings 137 { 138 Settings(); 139 140 uint size; 141 Pool pool; 142 bool globalFocus; 143 }; 144 145 Com com; 146 Object::Pod<WAVEFORMATEX> waveFormat; 147 Settings settings; 148 149 public: 150 GetWaveFormat() const151 const WAVEFORMATEX& GetWaveFormat() const 152 { 153 return waveFormat; 154 } 155 GlobalFocus() const156 bool GlobalFocus() const 157 { 158 return settings.globalFocus; 159 } 160 LockStream(void ** data,uint * size)161 NST_FORCE_INLINE bool LockStream(void** data,uint* size) 162 { 163 DWORD pos; 164 165 if (SUCCEEDED(com->GetCurrentPosition( &pos, NULL ))) 166 { 167 pos = (pos > com.writePos ? pos - com.writePos : pos + settings.size - com.writePos); 168 169 DWORD bytes[2]; 170 171 if (SUCCEEDED(com->Lock( com.writePos, pos, data+0, bytes+0, data+1, bytes+1, 0 ))) 172 { 173 com.writePos = (com.writePos + pos) % settings.size; 174 175 size[0] = bytes[0] / waveFormat.nBlockAlign; 176 size[1] = bytes[1] / waveFormat.nBlockAlign; 177 178 return true; 179 } 180 } 181 182 com->Stop(); 183 184 NST_DEBUG_MSG("DirectSound::Buffer::Lock() failed!"); 185 186 return false; 187 } 188 UnlockStream(void ** data,uint * size) const189 NST_FORCE_INLINE void UnlockStream(void** data,uint* size) const 190 { 191 NST_ASSERT( data && com ); 192 com->Unlock( data[0], size[0]*waveFormat.nBlockAlign, data[1], size[1]*waveFormat.nBlockAlign ); 193 } 194 Streaming() const195 bool Streaming() const 196 { 197 DWORD status; 198 199 return 200 ( 201 com && SUCCEEDED(com->GetStatus( &status )) && 202 (status & (DSBSTATUS_BUFFERLOST|DSBSTATUS_PLAYING|DSBSTATUS_LOOPING)) == (DSBSTATUS_PLAYING|DSBSTATUS_LOOPING) 203 ); 204 } 205 }; 206 207 Device device; 208 Buffer buffer; 209 const SoundAdapters adapters; 210 211 public: 212 Streaming() const213 bool Streaming() const 214 { 215 return buffer.Streaming(); 216 } 217 StartStream()218 void StartStream() 219 { 220 buffer.StartStream(); 221 } 222 LockStream(void ** data,uint * size)223 NST_FORCE_INLINE bool LockStream(void** data,uint* size) 224 { 225 return buffer.LockStream( data, size ); 226 } 227 UnlockStream(void ** data,uint * size) const228 NST_FORCE_INLINE void UnlockStream(void** data,uint* size) const 229 { 230 buffer.UnlockStream( data, size ); 231 } 232 GetAdapters() const233 const Adapters& GetAdapters() const 234 { 235 return adapters.list; 236 } 237 GetWaveFormat() const238 const WAVEFORMATEX& GetWaveFormat() const 239 { 240 return buffer.GetWaveFormat(); 241 } 242 GlobalFocus() const243 bool GlobalFocus() const 244 { 245 return buffer.GlobalFocus(); 246 } 247 }; 248 } 249 } 250 251 #endif 252