nestopia/source/win32/NstDirectSound.hpp

251 lines
4.7 KiB
C++

////////////////////////////////////////////////////////////////////////////////////////
//
// Nestopia - NES/Famicom emulator written in C++
//
// Copyright (C) 2003-2008 Martin Freij
//
// This file is part of Nestopia.
//
// Nestopia is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// Nestopia is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Nestopia; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
////////////////////////////////////////////////////////////////////////////////////////
#ifndef NST_DIRECTX_DIRECTSOUND_H
#define NST_DIRECTX_DIRECTSOUND_H
#pragma once
#include <vector>
#include "NstObjectPod.hpp"
#include "NstDirectX.hpp"
#if NST_MSVC >= 1200
#pragma warning( push )
#pragma warning( disable : 4201 )
#endif
#include <MMSystem.h>
#if NST_MSVC >= 1200
#pragma warning( pop )
#endif
#define DIRECTSOUND_VERSION 0x0800
#include <dsound.h>
namespace Nestopia
{
namespace DirectX
{
class DirectSound
{
public:
explicit DirectSound(HWND);
~DirectSound();
enum Channels
{
MONO = 1,
STEREO
};
enum Pool
{
POOL_HARDWARE,
POOL_SYSTEM
};
struct Adapter : BaseAdapter
{
Adapter();
bool buggy;
};
typedef std::vector<Adapter> Adapters;
cstring Update(uint,uint,uint,Channels,uint,Pool,bool);
void Destroy();
void StopStream();
private:
class SoundAdapters
{
static BOOL CALLBACK Enumerator(LPGUID,LPCTSTR,LPCTSTR,LPVOID);
public:
SoundAdapters();
Adapters list;
};
struct Device : ComInterface<IDirectSound8>
{
explicit Device(HWND);
HWND const hWnd;
ushort id;
bool priority;
bool buggy;
};
class Buffer
{
public:
Buffer();
~Buffer();
cstring Update(IDirectSound8&,bool,uint,uint,Channels,uint,Pool,bool);
void StartStream();
void StopStream(IDirectSound8*,bool);
void Release();
private:
cstring Create(IDirectSound8&,bool);
enum
{
DC_OFFSET_8 = 0x80,
DC_OFFSET_16 = 0x0000
};
struct Com : ComInterface<IDirectSoundBuffer8>
{
Com();
uint writePos;
};
struct Settings
{
Settings();
uint size;
Pool pool;
bool globalFocus;
};
Com com;
Object::Pod<WAVEFORMATEX> waveFormat;
Settings settings;
public:
const WAVEFORMATEX& GetWaveFormat() const
{
return waveFormat;
}
bool GlobalFocus() const
{
return settings.globalFocus;
}
NST_FORCE_INLINE bool LockStream(void** data,uint* size)
{
DWORD pos;
if (SUCCEEDED(com->GetCurrentPosition( &pos, NULL )))
{
pos = (pos > com.writePos ? pos - com.writePos : pos + settings.size - com.writePos);
DWORD bytes[2];
if (SUCCEEDED(com->Lock( com.writePos, pos, data+0, bytes+0, data+1, bytes+1, 0 )))
{
com.writePos = (com.writePos + pos) % settings.size;
size[0] = bytes[0] / waveFormat.nBlockAlign;
size[1] = bytes[1] / waveFormat.nBlockAlign;
return true;
}
}
com->Stop();
NST_DEBUG_MSG("DirectSound::Buffer::Lock() failed!");
return false;
}
NST_FORCE_INLINE void UnlockStream(void** data,uint* size) const
{
NST_ASSERT( data && com );
com->Unlock( data[0], size[0]*waveFormat.nBlockAlign, data[1], size[1]*waveFormat.nBlockAlign );
}
bool Streaming() const
{
DWORD status;
return
(
com && SUCCEEDED(com->GetStatus( &status )) &&
(status & (DSBSTATUS_BUFFERLOST|DSBSTATUS_PLAYING|DSBSTATUS_LOOPING)) == (DSBSTATUS_PLAYING|DSBSTATUS_LOOPING)
);
}
};
Device device;
Buffer buffer;
const SoundAdapters adapters;
public:
bool Streaming() const
{
return buffer.Streaming();
}
void StartStream()
{
buffer.StartStream();
}
NST_FORCE_INLINE bool LockStream(void** data,uint* size)
{
return buffer.LockStream( data, size );
}
NST_FORCE_INLINE void UnlockStream(void** data,uint* size) const
{
buffer.UnlockStream( data, size );
}
const Adapters& GetAdapters() const
{
return adapters.list;
}
const WAVEFORMATEX& GetWaveFormat() const
{
return buffer.GetWaveFormat();
}
bool GlobalFocus() const
{
return buffer.GlobalFocus();
}
};
}
}
#endif