mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-30 13:21:04 +00:00
- fixed the sound in Exhumed's intro movie.
Taking a cue from GDX to properly synchronize it because PCExhumed's approach looked broken by design. It had no frame rate sync and solely depended on the low level audio stream for it.
This commit is contained in:
parent
3a5c0b30bb
commit
966cf5e262
4 changed files with 70 additions and 61 deletions
|
@ -100,11 +100,12 @@ static void S_AddBloodSFX(int lumpnum)
|
||||||
S_sfx[sfxnum].bLoadRAW = true;
|
S_sfx[sfxnum].bLoadRAW = true;
|
||||||
S_sfx[sfxnum].LoopStart = LittleLong(sfx->loopStart);
|
S_sfx[sfxnum].LoopStart = LittleLong(sfx->loopStart);
|
||||||
//S_sfx[sfxnum].Volume = sfx->relVol / 255.f; This cannot be done because this volume setting is optional.
|
//S_sfx[sfxnum].Volume = sfx->relVol / 255.f; This cannot be done because this volume setting is optional.
|
||||||
S_sfx[sfxnum].UserData.Resize(2);
|
S_sfx[sfxnum].UserData.Resize(3);
|
||||||
int* udata = (int*)S_sfx[sfxnum].UserData.Data();
|
int* udata = (int*)S_sfx[sfxnum].UserData.Data();
|
||||||
udata[0] = sfx->pitch;
|
udata[0] = sfx->pitch;
|
||||||
udata[1] = sfx->pitchRange;
|
udata[1] = sfx->pitchRange;
|
||||||
udata[2] = sfx->relVol; }
|
udata[2] = sfx->relVol;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sndInit(void)
|
void sndInit(void)
|
||||||
|
|
|
@ -26,6 +26,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
#include "v_2ddrawer.h"
|
#include "v_2ddrawer.h"
|
||||||
#include "animtexture.h"
|
#include "animtexture.h"
|
||||||
|
#include "s_music.h"
|
||||||
|
|
||||||
BEGIN_PS_NS
|
BEGIN_PS_NS
|
||||||
|
|
||||||
|
@ -43,15 +44,27 @@ uint8_t bankbuf[kSampleRate];
|
||||||
uint32_t bankptr = 0;
|
uint32_t bankptr = 0;
|
||||||
uint32_t banktail = 0;
|
uint32_t banktail = 0;
|
||||||
|
|
||||||
uint32_t lSoundBytesRead = 0;
|
|
||||||
uint32_t lSoundBytesUsed = 0;
|
|
||||||
|
|
||||||
uint8_t lh[32] = { 0 };
|
uint8_t lh[32] = { 0 };
|
||||||
|
|
||||||
static uint8_t* CurFrame = NULL;
|
static uint8_t* CurFrame = NULL;
|
||||||
|
|
||||||
bool bServedSample = false;
|
bool bServedSample = false;
|
||||||
palette_t moviepal[256];
|
palette_t moviepal[256];
|
||||||
|
const int numAudioBlocks = 20;
|
||||||
|
int sfxnum = -1;
|
||||||
|
|
||||||
|
struct AudioData
|
||||||
|
{
|
||||||
|
int16_t samples[2205 * numAudioBlocks]; // must be a multiple of the stream buffer size
|
||||||
|
int nWrite;
|
||||||
|
int nRead;
|
||||||
|
};
|
||||||
|
|
||||||
|
SoundStream* stream;
|
||||||
|
AudioData audio;
|
||||||
|
bool bAudioStarted;
|
||||||
|
|
||||||
|
SoundHandle shandle;
|
||||||
|
|
||||||
int ReadFrame(FileReader &fp, uint8_t *palette)
|
int ReadFrame(FileReader &fp, uint8_t *palette)
|
||||||
{
|
{
|
||||||
|
@ -94,32 +107,16 @@ int ReadFrame(FileReader &fp, uint8_t *palette)
|
||||||
}
|
}
|
||||||
case kFrameSound:
|
case kFrameSound:
|
||||||
{
|
{
|
||||||
Printf("Reading sound block size %d...\n", nSize);
|
auto sfxx = soundEngine->GetSounds();
|
||||||
|
auto buffer = fp.Read(nSize);
|
||||||
if (lSoundBytesRead - lSoundBytesUsed >= kSampleRate)
|
assert(buffer.Size() == 2205);
|
||||||
|
auto wbuffer = audio.samples + audio.nWrite * 2205;
|
||||||
|
for (int i = 0; i < 2205; i++)
|
||||||
{
|
{
|
||||||
//DebugOut("ReadFrame() - Sound buffer full\n");
|
wbuffer[i] = (buffer[i] - 128) << 8;
|
||||||
fp.Seek(nSize, FileReader::SeekCur);
|
|
||||||
}
|
}
|
||||||
else
|
audio.nWrite++;
|
||||||
{
|
if (audio.nWrite >= numAudioBlocks) audio.nWrite = 0;
|
||||||
//mutex_lock(&mutex);
|
|
||||||
|
|
||||||
int nRead = fp.Read((char*)bankbuf + bankptr, nSize);
|
|
||||||
|
|
||||||
lSoundBytesRead += nRead;
|
|
||||||
bankptr += nSize;
|
|
||||||
|
|
||||||
assert(nSize == nRead);
|
|
||||||
assert(bankptr <= kSampleRate);
|
|
||||||
|
|
||||||
if (bankptr >= kSampleRate) {
|
|
||||||
bankptr -= kSampleRate; // loop back to start
|
|
||||||
}
|
|
||||||
|
|
||||||
//mutex_unlock(&mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case kFrameImage:
|
case kFrameImage:
|
||||||
|
@ -183,6 +180,15 @@ static void ServeSample(const char** ptr, uint32_t* length)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static bool StreamCallbackFunc(SoundStream* stream, void* buff, int len, void* userdata)
|
||||||
|
{
|
||||||
|
memcpy(buff, &audio.samples[audio.nRead], len);
|
||||||
|
audio.nRead += len / 2;
|
||||||
|
if (audio.nRead >= countof(audio.samples)) audio.nRead = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void PlayMovie(const char* fileName)
|
void PlayMovie(const char* fileName)
|
||||||
{
|
{
|
||||||
uint8_t palette[768];
|
uint8_t palette[768];
|
||||||
|
@ -190,7 +196,6 @@ void PlayMovie(const char* fileName)
|
||||||
CurFrame = f.Data();
|
CurFrame = f.Data();
|
||||||
|
|
||||||
int bDoFade = true;
|
int bDoFade = true;
|
||||||
int hFx = -1;
|
|
||||||
auto fp = fileSystem.OpenFileReader(fileName);
|
auto fp = fileSystem.OpenFileReader(fileName);
|
||||||
if (!fp.isOpen())
|
if (!fp.isOpen())
|
||||||
{
|
{
|
||||||
|
@ -207,70 +212,76 @@ void PlayMovie(const char* fileName)
|
||||||
// clear keys
|
// clear keys
|
||||||
inputState.ClearAllInput();
|
inputState.ClearAllInput();
|
||||||
|
|
||||||
|
bAudioStarted = false;
|
||||||
if (bDoFade) {
|
if (bDoFade) {
|
||||||
StartFadeIn();
|
StartFadeIn();
|
||||||
}
|
}
|
||||||
|
memset(audio.samples, 0, sizeof(audio.samples));
|
||||||
|
audio.nWrite = 5; // play 5 blocks (i.e. half a second) of silence to get ahead of the stream. For this video it isn't necessary to sync it perfectly.
|
||||||
|
|
||||||
int angle = 1536;
|
double angle = 1536;
|
||||||
int z = 0;
|
double z = 0;
|
||||||
|
|
||||||
AnimTextures animtex;
|
AnimTextures animtex;
|
||||||
animtex.SetSize(AnimTexture::Paletted, 200, 320);
|
animtex.SetSize(AnimTexture::Paletted, 200, 320);
|
||||||
|
|
||||||
|
auto sfxx = soundEngine->GetSounds();
|
||||||
|
|
||||||
|
if (!bAudioStarted)
|
||||||
|
{
|
||||||
|
// start audio playback
|
||||||
|
stream = S_CreateCustomStream(4410, 22050, 1, StreamCallbackFunc, nullptr);
|
||||||
|
bAudioStarted = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Read a frame in first
|
// Read a frame in first
|
||||||
if (ReadFrame(fp, palette))
|
if (ReadFrame(fp, palette))
|
||||||
{
|
{
|
||||||
// start audio playback (fixme)
|
|
||||||
#if 0
|
|
||||||
hFx = FX_StartDemandFeedPlayback(ServeSample, kSampleRate, 0, snd_fxvolume, snd_fxvolume, snd_fxvolume, FX_MUSIC_PRIORITY, fix16_one, -1);
|
|
||||||
#else
|
|
||||||
hFx = -1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int fn = 0;
|
int fn = 0;
|
||||||
while (!inputState.keyBufferWaiting())
|
int ototalclock = totalclock + 12;
|
||||||
|
int lastclock = totalclock;
|
||||||
|
while (true)// !inputState.keyBufferWaiting())
|
||||||
{
|
{
|
||||||
HandleAsync();
|
HandleAsync();
|
||||||
|
|
||||||
// audio is king for sync - if the backend doesn't need any more samples yet,
|
|
||||||
// don't process any more movie file data.
|
|
||||||
if (!bServedSample && hFx > 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
bServedSample = false;
|
|
||||||
|
|
||||||
if (z < 65536) { // Zoom - normal zoom is 65536.
|
if (z < 65536) { // Zoom - normal zoom is 65536.
|
||||||
z += 2048;
|
z += 2048 * (totalclock - lastclock) / 8.;
|
||||||
}
|
}
|
||||||
|
if (z > 65536) z = 65536;
|
||||||
if (angle != 0) {
|
if (angle != 0) {
|
||||||
angle += 16;
|
angle += 16. * (totalclock-lastclock) / 8. ;
|
||||||
if (angle == 2048) {
|
if (angle >= 2048) {
|
||||||
angle = 0;
|
angle = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lastclock = totalclock;
|
||||||
|
|
||||||
// I have no idea why this needs double buffering now.
|
// I have no idea why this needs double buffering now.
|
||||||
fn ^= 1;
|
fn ^= 1;
|
||||||
animtex.SetFrame(palette, CurFrame);
|
animtex.SetFrame(palette, CurFrame);
|
||||||
rotatesprite(160 << 16, 100 << 16, z, angle+512, -1, 0, 1, RS_AUTO | RS_YFLIP, 0, 0, xdim - 1, ydim - 1, animtex.GetFrame());
|
|
||||||
|
|
||||||
|
|
||||||
|
rotatesprite(160 << 16, 100 << 16, int(z), int(angle+512), -1, 0, 1, RS_AUTO | RS_YFLIP, 0, 0, xdim - 1, ydim - 1, animtex.GetFrame());
|
||||||
|
|
||||||
|
#if 0
|
||||||
if (bDoFade) {
|
if (bDoFade) {
|
||||||
bDoFade = DoFadeIn();
|
bDoFade = DoFadeIn();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
videoNextPage();
|
videoNextPage();
|
||||||
|
|
||||||
if (ReadFrame(fp, palette) == 0) {
|
if (totalclock >= ototalclock)
|
||||||
break;
|
{
|
||||||
|
ototalclock += 12;
|
||||||
|
if (ReadFrame(fp, palette) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hFx > 0) {
|
S_StopCustomStream(stream);
|
||||||
//FX_StopSound(hFx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inputState.keyBufferWaiting()) {
|
if (inputState.keyBufferWaiting()) {
|
||||||
inputState.keyGetChar();
|
inputState.keyGetChar();
|
||||||
}
|
}
|
||||||
|
|
|
@ -722,7 +722,6 @@ private:
|
||||||
if (chunkFlag & 2) flags |= DI_MIRRORY;
|
if (chunkFlag & 2) flags |= DI_MIRRORY;
|
||||||
|
|
||||||
DrawGraphic(tileGetTexture(tile), x, y, flags, 1, -1, -1, 1, 1);
|
DrawGraphic(tileGetTexture(tile), x, y, flags, 1, -1, -1, 1, 1);
|
||||||
//overwritesprite(x, y, tile, 0, nStat, 0);
|
|
||||||
nFrameBase++;
|
nFrameBase++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -470,8 +470,6 @@ void DrawView(int smoothRatio, bool sceneonly)
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawMap();
|
DrawMap();
|
||||||
|
|
||||||
DrawSnakeCamStatus();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue