uvmac/src/UI/_deprecated/WIN32/SOUND.c

293 lines
6.2 KiB
C

/* --- sound --- */
#include "OSGLUWIN.h"
#if SoundEnabled
#include "UI/WIN32/SOUND.h"
tpSoundSamp TheSoundBuffer = nullpr;
HWAVEOUT hWaveOut = NULL;
void FillWithSilence(tpSoundSamp p, int n, trSoundSamp v)
{
int i;
for (i = n; --i >= 0; ) {
*p++ = v;
}
}
void Sound_BeginPlaying(void)
{
#if dbglog_SoundStuff
fprintf(stderr, "Sound_BeginPlaying\n");
#endif
}
void Sound_Start(void)
{
if (hWaveOut == NULL) {
WAVEFORMATEX wfex;
MMRESULT mmr;
int i;
tpSoundSamp p;
WAVEHDR *pwh;
wfex.wFormatTag = WAVE_FORMAT_PCM;
wfex.nChannels = 1;
wfex.nSamplesPerSec = SOUND_SAMPLERATE;
wfex.nAvgBytesPerSec = SOUND_SAMPLERATE;
#if 3 == kLn2SoundSampSz
wfex.nBlockAlign = 1;
wfex.wBitsPerSample = 8;
#elif 4 == kLn2SoundSampSz
wfex.nBlockAlign = 2;
wfex.wBitsPerSample = 16;
#else
#error "unsupported audio format"
#endif
wfex.cbSize = 0;
mmr = waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfex, 0,
0 /* (DWORD) AppInstance */, CALLBACK_NULL);
if (mmr != MMSYSERR_NOERROR) {
/*
not recursive:
MacMsg("waveOutOpen failed",
"Sorry, Mini vMac encountered errors"
" and cannot continue.", true);
*/
} else {
p = TheSoundBuffer;
pwh = whdr;
for (i = 0; i < kSoundBuffers; ++i) {
pwh->lpData = (LPSTR)p;
pwh->dwBufferLength = kOneBuffSz;
pwh->dwBytesRecorded = 0;
pwh->dwUser = 0;
pwh->dwFlags = 0;
pwh->dwLoops = 0;
mmr = waveOutPrepareHeader(hWaveOut, pwh,
sizeof(WAVEHDR));
if (mmr != MMSYSERR_NOERROR) {
/*
not recursive:
MacMsg("waveOutPrepareHeader failed",
"Sorry, Mini vMac encountered errors"
" and cannot continue.", true);
*/
} else {
pwh->dwFlags |= WHDR_DONE;
}
p += kOneBuffLen;
++pwh;
}
TheFillOffset = 0;
ThePlayOffset = 0;
TheWriteOffset = 0;
MinFilledSoundBuffs = kSoundBuffers;
wantplaying = false;
}
}
}
void Sound_Stop(void)
{
MMRESULT mmr;
int i;
wantplaying = false;
if (hWaveOut != NULL) {
DWORD StartTime = GetTickCount();
for (i = 0; i < kSoundBuffers; ++i) {
while (((whdr[i].dwFlags & WHDR_DONE) == 0)
&& ((uint32_t)(GetTickCount() - StartTime) < 1000))
{
Sleep(1);
}
mmr = waveOutUnprepareHeader(hWaveOut, &whdr[i],
sizeof(WAVEHDR));
if (mmr != MMSYSERR_NOERROR) {
/*
not recursive:
MacMsg("waveOutUnprepareHeader failed",
"Sorry, Mini vMac encountered errors"
" and cannot continue.", true);
*/
}
}
mmr = waveOutClose(hWaveOut);
if (mmr != MMSYSERR_NOERROR) {
/*
MacMsg("waveOutClose failed",
"Sorry, Mini vMac encountered errors"
" and cannot continue.", true);
*/
}
hWaveOut = NULL;
}
}
void SoundCheckVeryOften(void)
{
if ((hWaveOut != NULL) && (wantplaying)) {
label_retry:
{
uint16_t FilledSoundBuffs;
uint16_t ToPlaySize = TheFillOffset - ThePlayOffset;
uint16_t CurPlayBuffer =
(ThePlayOffset >> kLnOneBuffLen) & kSoundBuffMask;
if ((ToPlaySize > kOneBuffLen)
&& ((whdr[CurPlayBuffer].dwFlags & WHDR_DONE) != 0))
{
ThePlayOffset += kOneBuffLen;
goto label_retry;
}
FilledSoundBuffs = ToPlaySize >> kLnOneBuffLen;
if (FilledSoundBuffs < MinFilledSoundBuffs) {
MinFilledSoundBuffs = FilledSoundBuffs;
}
if (FilledSoundBuffs < 2) {
MMRESULT mmr;
uint16_t PrevPlayOffset = ThePlayOffset - kOneBuffLen;
uint16_t PrevPlayBuffer =
(PrevPlayOffset >> kLnOneBuffLen) & kSoundBuffMask;
uint16_t LastPlayedOffset =
((TheFillOffset >> kLnOneBuffLen) << kLnOneBuffLen)
- 1;
FillWithSilence(
TheSoundBuffer + (PrevPlayOffset & kAllBuffMask),
kOneBuffLen,
*(TheSoundBuffer
+ (LastPlayedOffset & kAllBuffMask)));
mmr = waveOutWrite(
hWaveOut, &whdr[PrevPlayBuffer], sizeof(WAVEHDR));
if (mmr != MMSYSERR_NOERROR) {
whdr[PrevPlayBuffer].dwFlags |= WHDR_DONE;
/*
not recursive:
MacMsg("waveOutWrite failed",
"Sorry, Mini vMac encountered errors"
" and cannot continue.", true);
*/
}
ThePlayOffset = PrevPlayOffset;
goto label_retry;
}
}
}
}
#if 4 == kLn2SoundSampSz
void ConvertSoundBlockToNative(tpSoundSamp p)
{
int i;
for (i = kOneBuffLen; --i >= 0; ) {
*p++ -= 0x8000;
}
}
#else
#define ConvertSoundBlockToNative(p)
#endif
void Sound_FilledBlocks(void)
{
while (0 != ((TheWriteOffset - TheFillOffset) >> kLnOneBuffLen)) {
uint16_t CurFillBuffer =
(TheFillOffset >> kLnOneBuffLen) & kSoundBuffMask;
bool IsOk = false;
ConvertSoundBlockToNative((tpSoundSamp)
whdr[CurFillBuffer].lpData);
if (hWaveOut != NULL) {
MMRESULT mmr = waveOutWrite(hWaveOut,
&whdr[CurFillBuffer], sizeof(WAVEHDR));
if (mmr == MMSYSERR_NOERROR) {
IsOk = true;
}
}
if (! IsOk) {
/*
not recursive:
MacMsg("waveOutWrite failed",
"Sorry, Mini vMac encountered errors"
" and cannot continue.", true);
*/
whdr[CurFillBuffer].dwFlags |= WHDR_DONE;
}
TheFillOffset += kOneBuffLen;
}
}
void Sound_WroteABlock(void)
{
if (wantplaying) {
Sound_FilledBlocks();
} else if (((TheWriteOffset - ThePlayOffset) >> kLnOneBuffLen) < 12)
{
/* just wait */
} else {
Sound_FilledBlocks();
wantplaying = true;
Sound_BeginPlaying();
}
}
void Sound_EndWrite(uint16_t actL)
{
TheWriteOffset += actL;
if (0 == (TheWriteOffset & kOneBuffMask)) {
/* just finished a block */
Sound_WroteABlock();
}
}
tpSoundSamp Sound_BeginWrite(uint16_t n, uint16_t *actL)
{
uint16_t ToFillLen = kAllBuffLen - (TheWriteOffset - ThePlayOffset);
uint16_t WriteBuffContig =
kOneBuffLen - (TheWriteOffset & kOneBuffMask);
if (WriteBuffContig < n) {
n = WriteBuffContig;
}
if (ToFillLen < n) {
/* overwrite previous buffer */
TheWriteOffset -= kOneBuffLen;
}
*actL = n;
return TheSoundBuffer + (TheWriteOffset & kAllBuffMask);
}
void Sound_SecondNotify(void)
{
if (hWaveOut != NULL) {
if (MinFilledSoundBuffs > DesiredMinFilledSoundBuffs) {
#if dbglog_SoundStuff
dbglog_writeln("MinFilledSoundBuffs too high");
#endif
IncrNextTime();
} else if (MinFilledSoundBuffs < DesiredMinFilledSoundBuffs) {
#if dbglog_SoundStuff
dbglog_writeln("MinFilledSoundBuffs too low");
#endif
++TrueEmulatedTime;
}
MinFilledSoundBuffs = kSoundBuffers;
}
}
#endif