mirror of
https://github.com/AppleWin/AppleWin.git
synced 2025-08-12 13:25:24 +00:00
SoundBuffer: move Windows only flags to DXSoundBuffer. Remove out of date _MSC_VER checks (pre-VS2019).
261 lines
6.5 KiB
C++
261 lines
6.5 KiB
C++
/*
|
|
AppleWin : An Apple //e emulator for Windows
|
|
|
|
Copyright (C) 1994-1996, Michael O'Brien
|
|
Copyright (C) 1999-2001, Oliver Schmidt
|
|
Copyright (C) 2002-2005, Tom Charlesworth
|
|
Copyright (C) 2006-2007, Tom Charlesworth, Michael Pohoreski
|
|
|
|
AppleWin 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.
|
|
|
|
AppleWin 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 AppleWin; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
/* Description: DirectX implementation of SoundBuffer
|
|
*
|
|
* Author: Tom Charlesworth
|
|
*/
|
|
|
|
#include "StdAfx.h"
|
|
|
|
#include "DXSoundBuffer.h"
|
|
|
|
#include "Core.h" // for g_fh
|
|
#include "Interface.h"
|
|
#include "SoundCore.h"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#define MAX_SOUND_DEVICES 10
|
|
|
|
static std::string sound_devices[MAX_SOUND_DEVICES];
|
|
static GUID sound_device_guid[MAX_SOUND_DEVICES];
|
|
static int num_sound_devices = 0;
|
|
|
|
static LPDIRECTSOUND g_lpDS = NULL;
|
|
static bool g_bDSAvailable = false;
|
|
static UINT g_uDSInitRefCount = 0;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
std::shared_ptr<SoundBuffer> DXSoundBuffer::create(uint32_t dwBufferSize, uint32_t nSampleRate, int nChannels)
|
|
{
|
|
if (!g_lpDS)
|
|
return NULL;
|
|
|
|
WAVEFORMATEX wavfmt;
|
|
DSBUFFERDESC dsbdesc;
|
|
|
|
wavfmt.wFormatTag = WAVE_FORMAT_PCM;
|
|
wavfmt.nChannels = nChannels;
|
|
wavfmt.nSamplesPerSec = nSampleRate;
|
|
wavfmt.wBitsPerSample = 16;
|
|
wavfmt.nBlockAlign = wavfmt.nChannels == 1 ? 2 : 4;
|
|
wavfmt.nAvgBytesPerSec = wavfmt.nBlockAlign * wavfmt.nSamplesPerSec;
|
|
|
|
memset(&dsbdesc, 0, sizeof(dsbdesc));
|
|
dsbdesc.dwSize = sizeof(dsbdesc);
|
|
dsbdesc.dwBufferBytes = dwBufferSize;
|
|
dsbdesc.lpwfxFormat = &wavfmt;
|
|
dsbdesc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STICKYFOCUS;
|
|
|
|
LPDIRECTSOUNDBUFFER pBuffer;
|
|
|
|
// Are buffers released when g_lpDS OR m_pBuffer is released?
|
|
// . From DirectX doc:
|
|
// "Buffer objects are owned by the device object that created them. When the
|
|
// device object is released, all buffers created by that object are also released..."
|
|
HRESULT hr = g_lpDS->CreateSoundBuffer(&dsbdesc, &pBuffer, NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
LogFileOutput("DXSoundBuffer: CreateSoundBuffer(), hr=0x%08X\n", (uint32_t)hr);
|
|
return NULL;
|
|
}
|
|
|
|
return std::make_shared<DXSoundBuffer>(pBuffer);
|
|
}
|
|
|
|
DXSoundBuffer::DXSoundBuffer(LPDIRECTSOUNDBUFFER pBuffer) : m_pBuffer(pBuffer)
|
|
{
|
|
_ASSERT(m_pBuffer);
|
|
}
|
|
|
|
DXSoundBuffer::~DXSoundBuffer()
|
|
{
|
|
HRESULT hr = m_pBuffer->Release();
|
|
}
|
|
|
|
HRESULT DXSoundBuffer::SetCurrentPosition(DWORD dwNewPosition)
|
|
{
|
|
return m_pBuffer->SetCurrentPosition(dwNewPosition);
|
|
}
|
|
|
|
HRESULT DXSoundBuffer::GetCurrentPosition(LPDWORD lpdwCurrentPlayCursor, LPDWORD lpdwCurrentWriteCursor)
|
|
{
|
|
return m_pBuffer->GetCurrentPosition(lpdwCurrentPlayCursor, lpdwCurrentWriteCursor);
|
|
}
|
|
|
|
HRESULT DXSoundBuffer::Lock(DWORD dwWriteCursor, DWORD dwWriteBytes, LPVOID* lplpvAudioPtr1, DWORD* lpdwAudioBytes1, LPVOID* lplpvAudioPtr2, DWORD* lpdwAudioBytes2, DWORD dwFlags)
|
|
{
|
|
return m_pBuffer->Lock(dwWriteCursor, dwWriteBytes, lplpvAudioPtr1, lpdwAudioBytes1, lplpvAudioPtr2, lpdwAudioBytes2, dwFlags);
|
|
}
|
|
|
|
HRESULT DXSoundBuffer::Unlock(LPVOID lpvAudioPtr1, DWORD dwAudioBytes1, LPVOID lpvAudioPtr2, DWORD dwAudioBytes2)
|
|
{
|
|
return m_pBuffer->Unlock(lpvAudioPtr1, dwAudioBytes1, lpvAudioPtr2, dwAudioBytes2);
|
|
}
|
|
|
|
HRESULT DXSoundBuffer::Stop()
|
|
{
|
|
return m_pBuffer->Stop();
|
|
}
|
|
|
|
HRESULT DXSoundBuffer::Play(DWORD dwReserved1, DWORD dwReserved2, DWORD dwFlags)
|
|
{
|
|
return m_pBuffer->Play(dwReserved1, dwReserved2, dwFlags);
|
|
}
|
|
|
|
HRESULT DXSoundBuffer::SetVolume(LONG lVolume)
|
|
{
|
|
return m_pBuffer->SetVolume(lVolume);
|
|
}
|
|
|
|
HRESULT DXSoundBuffer::GetVolume(LONG* lplVolume)
|
|
{
|
|
return m_pBuffer->GetVolume(lplVolume);
|
|
}
|
|
|
|
HRESULT DXSoundBuffer::GetStatus(LPDWORD lpdwStatus)
|
|
{
|
|
return m_pBuffer->GetStatus(lpdwStatus);
|
|
}
|
|
|
|
HRESULT DXSoundBuffer::Restore()
|
|
{
|
|
return m_pBuffer->Restore();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool DSAvailable()
|
|
{
|
|
return g_bDSAvailable;
|
|
}
|
|
|
|
static BOOL CALLBACK DSEnumProc(LPGUID lpGUID, LPCTSTR lpszDesc, LPCTSTR lpszDrvName, LPVOID lpContext)
|
|
{
|
|
int i = num_sound_devices;
|
|
if (i == MAX_SOUND_DEVICES)
|
|
return TRUE;
|
|
if (lpGUID != NULL)
|
|
memcpy(&sound_device_guid[i], lpGUID, sizeof(GUID));
|
|
else
|
|
memset(&sound_device_guid[i], 0, sizeof(GUID));
|
|
sound_devices[i] = lpszDesc;
|
|
|
|
if (g_fh) fprintf(g_fh, "%d: %s - %s\n", i, lpszDesc, lpszDrvName);
|
|
|
|
num_sound_devices++;
|
|
return TRUE;
|
|
}
|
|
|
|
bool DSInit()
|
|
{
|
|
if (g_bDSAvailable)
|
|
{
|
|
g_uDSInitRefCount++;
|
|
return true; // Already initialised successfully
|
|
}
|
|
|
|
num_sound_devices = 0;
|
|
HRESULT hr = DirectSoundEnumerate((LPDSENUMCALLBACK)DSEnumProc, NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
if (g_fh) fprintf(g_fh, "DSEnumerate failed (%08X)\n", (uint32_t)hr);
|
|
return false;
|
|
}
|
|
|
|
if (g_fh)
|
|
{
|
|
fprintf(g_fh, "Number of sound devices = %d\n", num_sound_devices);
|
|
}
|
|
|
|
bool bCreatedOK = false;
|
|
for (int x = 0; x < num_sound_devices; x++)
|
|
{
|
|
hr = DirectSoundCreate(&sound_device_guid[x], &g_lpDS, NULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (g_fh) fprintf(g_fh, "DSCreate succeeded for sound device #%d\n", x);
|
|
bCreatedOK = true;
|
|
break;
|
|
}
|
|
|
|
if (g_fh) fprintf(g_fh, "DSCreate failed for sound device #%d (%08X)\n", x, (uint32_t)hr);
|
|
}
|
|
if (!bCreatedOK)
|
|
{
|
|
if (g_fh) fprintf(g_fh, "DSCreate failed for all sound devices\n");
|
|
return false;
|
|
}
|
|
|
|
HWND hwnd = GetFrame().g_hFrameWindow;
|
|
_ASSERT(hwnd);
|
|
hr = g_lpDS->SetCooperativeLevel(hwnd, DSSCL_NORMAL);
|
|
if (FAILED(hr))
|
|
{
|
|
if (g_fh) fprintf(g_fh, "SetCooperativeLevel failed (%08X)\n", (uint32_t)hr);
|
|
return false;
|
|
}
|
|
|
|
DSCAPS DSCaps;
|
|
memset(&DSCaps, 0, sizeof(DSCAPS));
|
|
DSCaps.dwSize = sizeof(DSCAPS);
|
|
hr = g_lpDS->GetCaps(&DSCaps);
|
|
if (FAILED(hr))
|
|
{
|
|
if (g_fh) fprintf(g_fh, "GetCaps failed (%08X)\n", (uint32_t)hr);
|
|
// Not fatal: so continue...
|
|
}
|
|
|
|
g_bDSAvailable = true;
|
|
|
|
g_uDSInitRefCount = 1;
|
|
|
|
return true;
|
|
}
|
|
|
|
void DSUninit()
|
|
{
|
|
if (!g_bDSAvailable)
|
|
return;
|
|
|
|
_ASSERT(g_uDSInitRefCount);
|
|
|
|
if (g_uDSInitRefCount == 0)
|
|
return;
|
|
|
|
g_uDSInitRefCount--;
|
|
|
|
if (g_uDSInitRefCount)
|
|
return;
|
|
|
|
//
|
|
|
|
_ASSERT(g_uNumVoices == 0);
|
|
|
|
SAFE_RELEASE(g_lpDS);
|
|
g_bDSAvailable = false;
|
|
|
|
SoundCore_StopTimer();
|
|
} |