1
0
mirror of https://github.com/jummy0/sb2-decomp synced 2025-03-15 04:24:48 +01:00
sb2-decomp/wave.cpp
2024-06-25 17:17:07 -04:00

271 lines
8.3 KiB
C++

/*****************************************************************
*
* Copyright (c) 1996 Microsoft Corporation
*
* File: wave.cpp
* Content: Routines for getting waves from resources
* Author: Dave Edson; modified by Peter Donnelly
*
******************************************************************/
#include <windows.h>
#include "wave.h"
typedef struct tagWAVEFILE
{
DWORD cbSize; // Size of file
LPWAVEFORMATEX pwfxInfo; // Wave Header
LPBYTE pbData; // Wave Bits
}
WAVEFILE, *LPWAVEFILE;
// Function Prototypes
BOOL wave_ParseWaveMemory(void *pvRes,
WAVEFORMATEX **ppWaveHeader,
BYTE **ppbWaveData,
DWORD *pcbWaveSize);
/////////////////////////////////////////////////////////////////
//
// WAVE_LoadResource: Gets a wave file into the memory pointed
// to by pWaveFile from a resource.
//
/////////////////////////////////////////////////////////////////
LPVOID WAVE_LoadResource
(int ID, // ID of resource
HMODULE hModule, // hInst of app with WAVE
LPWAVEFILE pWaveFile) // Points to the struct to fill
{
HRSRC hResInfo;
HGLOBAL hResData;
void *pvRes;
DWORD dwSize;
LPVOID lpMemory;
// Find the resource and load into memory
if (((hResInfo = FindResourceA(hModule, MAKEINTRESOURCEA(ID), "WAVE")) != NULL) &&
((hResData = LoadResource(hModule, hResInfo)) != NULL) &&
((pvRes = LockResource(hResData)) != NULL))
{
// If we found it, copy the bits from the resource into
// our own chunk of memory
dwSize = SizeofResource(hModule, hResInfo);
lpMemory = malloc (dwSize);
memcpy (lpMemory, pvRes, dwSize);
UnlockResource(hResData);
FreeResource(hResData);
// Parse it out
if (wave_ParseWaveMemory(lpMemory,
&(pWaveFile->pwfxInfo),
&(pWaveFile->pbData),
&(pWaveFile->cbSize)))
{
return lpMemory; // OK
}
}
return NULL;
}
//////////////////////////////////////////////////////////////////
//
// wave_ParseWaveMemory
// Parses a chunk of memory into the header and samples.
// This is done by looking for the "fmt " and "data"
// fields in the memory.
//
//////////////////////////////////////////////////////////////////
BOOL wave_ParseWaveMemory
(LPVOID lpChunkOfMemory, // Points to raw ram
LPWAVEFORMATEX *lplpWaveHeader, // Points to pointer to header
LPBYTE *lplpWaveSamples,// Points to pointer to samples
LPDWORD lpcbWaveSize) // Points to size
{
LPDWORD pdw;
LPDWORD pdwEnd;
DWORD dwRiff;
DWORD dwType;
DWORD dwLength;
// Set defaults to NULL or zero
if (lplpWaveHeader)
*lplpWaveHeader = NULL;
if (lplpWaveSamples)
*lplpWaveSamples = NULL;
if (lpcbWaveSize)
*lpcbWaveSize = 0;
// Set up DWORD pointers to the start of the chunk
// of memory.
pdw = (DWORD *)lpChunkOfMemory;
// Get the type and length of the chunk of memory
dwRiff = *pdw++;
dwLength = *pdw++;
dwType = *pdw++;
// Using the mmioFOURCC macro (part of Windows SDK), ensure
// that this is a RIFF WAVE chunk of memory
if (dwRiff != mmioFOURCC('R', 'I', 'F', 'F'))
return FALSE; // not even RIFF
if (dwType != mmioFOURCC('W', 'A', 'V', 'E'))
return FALSE; // not a WAV
// Find the pointer to the end of the chunk of memory
pdwEnd = (DWORD *)((BYTE *)pdw + dwLength-4);
// Run through the bytes looking for the tags
while (pdw < pdwEnd)
{
dwType = *pdw++;
dwLength = *pdw++;
switch (dwType)
{
// Found the format part
case mmioFOURCC('f', 'm', 't', ' '):
if (lplpWaveHeader && !*lplpWaveHeader)
{
if (dwLength < sizeof(WAVEFORMAT))
return FALSE; // something's wrong! Not a WAV
// Set the lplpWaveHeader to point to this part of
// the memory chunk
*lplpWaveHeader = (LPWAVEFORMATEX)pdw;
// Check to see if the other two items have been
// filled out yet (the bits and the size of the
// bits). If so, then this chunk of memory has
// been parsed out and we can exit
if ((!lplpWaveSamples || *lplpWaveSamples) &&
(!lpcbWaveSize || *lpcbWaveSize))
{
return TRUE;
}
}
break;
// Found the samples
case mmioFOURCC('d', 'a', 't', 'a'):
if ((lplpWaveSamples && !*lplpWaveSamples) ||
(lpcbWaveSize && !*lpcbWaveSize))
{
// Point the samples pointer to this part of the
// chunk of memory.
if (lplpWaveSamples) *lplpWaveSamples = (LPBYTE)pdw;
// Set the size of the wave
if (lpcbWaveSize) *lpcbWaveSize = dwLength;
// Make sure we have our header pointer set up.
// If we do, we can exit
if (!lplpWaveHeader || *lplpWaveHeader)
return TRUE;
}
break;
} // End case
// Move the pointer through the chunk of memory
pdw = (DWORD *)((BYTE *)pdw + ((dwLength+1)&~1));
}
// Failed! If we made it here, we did not get all the pieces
// of the wave
return FALSE;
} // wave_ParseWaveMemory
//////////////////////////////////////////////////////////////////
//
// LoadWave
// Gets the sound data and loads it into a DirectSound
// secondary buffer.
//
//
//////////////////////////////////////////////////////////////////
void LoadWave(HINSTANCE hinst, int ResourceID,
LPDIRECTSOUND lpds,
LPDIRECTSOUNDBUFFER &lpDSB)
{
// These variables are used in Steps 1 and 2
LPVOID lpWaveData;
WAVEFILE WaveFile;
DSBUFFERDESC dsbd;
// These variables are used in step 3, further down below
LPVOID pbData = NULL;
LPVOID pbData2 = NULL;
DWORD dwLength;
DWORD dwLength2;
lpWaveData = WAVE_LoadResource (ResourceID, hinst, &WaveFile );
// Step 1: Set up the direct sound buffer.
memset(&dsbd, 0, sizeof(DSBUFFERDESC));
dsbd.dwSize = sizeof(DSBUFFERDESC);
// We want a buffer that lives on the sound card's memory
// (DSBCAPS_STATIC) and can have the pan, volume, and
// frequency adjusted (DSBCAPS_CTRLDEFAULT)
dsbd.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_STATIC ;
// Set up the size and format
dsbd.dwBufferBytes = WaveFile.cbSize;
dsbd.lpwfxFormat = WaveFile.pwfxInfo; // Must be a PCM format!
// Step 2: Create the buffer
if (DS_OK != lpds->CreateSoundBuffer(&dsbd, &lpDSB, NULL))
{
OutputDebugStringA("Failed to create sound buffer\n");
return;
}
// Once this code succeeds, lpDSB will point to a DirectSoundBuffer.
// At this point, you can copy blocks of sound data into the buffer,
// using the Lock and Unlock interfaces on the DirectSoundBuffer:
// Lock down the DirectSound buffer
if (DS_OK == lpDSB->Lock
(0, // Offset into buffer to start writing
WaveFile.cbSize, // Size of wave file to copy in
&pbData, // Points to first block of sound data
&dwLength, // Length of first block of data
&pbData2, // Points to second block of sound data
&dwLength2, // Length of second block of data
0L)) // Flags
{
// Copy first chunk
memcpy(pbData, WaveFile.pbData, dwLength);
// Copy second chunk
if (dwLength2)
memcpy(pbData2, WaveFile.pbData+dwLength , dwLength2);
// Free up the memory allocated in the WAVE_LoadFile function, since we
// have copied it to the buffer
free (lpWaveData);
// Unlock the buffer
if (DS_OK != lpDSB->Unlock(pbData, dwLength, pbData2, dwLength2))
OutputDebugStringA("Unlock failed");
}
else
{
OutputDebugStringA("Lock failed");
}
} // LoadWave