oggstream.cpp

来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 167 行

CPP
167
字号
#include "OggStream.h"
#include "LogOutput.h"


COggStream::COggStream() {
	DS = 0;
	DSB = 0;
	oggFile = 0;
	vorbisInfo = 0;
	vorbisComment = 0;
	stopped = true;
	isLastSection = true;
	reachedEOS = true;
}


void COggStream::play(const std::string& path, float volume, const float3& position) {
	if (!stopped) {
		return;
	}

	int result = 0;

	if (!(oggFile = fopen(path.c_str(), "rb"))) {
		logOutput.Print("Could not open Ogg file.");
		return;
	}

	if ((result = ov_open(oggFile, &oggStream, NULL, 0)) < 0) {
		fclose(oggFile);
		logOutput.Print("Could not open Ogg stream.");
		return;
	}

	vorbisInfo = ov_info(&oggStream, -1);
	vorbisComment = ov_comment(&oggStream, -1);
	// display();

	// set the wave format
	WAVEFORMATEX wfm;
	memset(&wfm, 0, sizeof(wfm));

	// Ogg-Vorbis is always 16 bit
	wfm.cbSize			= sizeof(wfm);
	wfm.nChannels		= vorbisInfo->channels;
	wfm.wBitsPerSample	= 16;
	wfm.nSamplesPerSec	= vorbisInfo->rate;
	wfm.nAvgBytesPerSec	= wfm.nSamplesPerSec * wfm.nChannels * 2;
	wfm.nBlockAlign		= 2 * wfm.nChannels;
	wfm.wFormatTag		= 1;

	// set up the stream buffer
	DSBUFFERDESC desc;

	desc.dwSize         = sizeof(desc);
	desc.dwFlags        = 0;
	desc.lpwfxFormat    = &wfm;
	desc.dwReserved     = 0;

	desc.dwBufferBytes  = BUFSIZE * 2;
	DS->CreateSoundBuffer(&desc, &DSB, NULL);

	// fill the buffer
	DWORD pos = 0;
	int sec = 0;
	int ret = 1;
	DWORD size = BUFSIZE * 2;

	char* buf;
	// offset to lock start, lock size, address of first lock part, size of first part, 0, 0, flag
	DSB->Lock(0, size, (LPVOID*) &buf, &size, NULL, NULL, DSBLOCK_ENTIREBUFFER);
	DSB->SetVolume(int(DSBVOLUME_MIN * volume));

	// read in the stream bits
	while (ret && pos < size) {
		ret = ov_read(&oggStream, buf + pos, size - pos, 0, 2, 1, &sec);
		pos += ret;
	}

	DSB->Unlock(buf, size, NULL, 0);
	DSB->Play(0, 0, DSBPLAY_LOOPING);

	curSection = 0;
	lastSection = 0;
	stopped = false;
	isLastSection = false;
	reachedEOS = false;
}


// stops the currently playing stream
// and cleans up the associated buffer
void COggStream::stop() {
	if (!stopped) {
		stopped = true;
		DSB->Stop();
		DSB->Release();
	}
}


void COggStream::update() {
	if (stopped) {
		return;
	}

	DWORD pos;
	DSB->GetCurrentPosition(&pos, NULL);
	curSection = (pos < BUFSIZE)? 0: 1;

	// buffer section changed?
	if (curSection != lastSection) {
		if (reachedEOS) {
			stop();
			return;
		}
		if (isLastSection) {
			reachedEOS = true;
		}

		DWORD size = BUFSIZE;
		char* buf;

		// fill the section we switched from
		DSB->Lock(lastSection * BUFSIZE, size, (LPVOID*) &buf, &size, NULL, NULL, 0);

		DWORD pos = 0;
		int sec = 0;
		int ret = 1;

		while (ret && pos < size) {
			ret = ov_read(&oggStream, buf + pos, size - pos, 0, 2, 1, &sec);
			pos += ret;
		}

		if (!ret) {
			// EOS reached, zero rest of buffer
			while (pos < size) {
				*(buf + pos++) = 0;
			}

			// only this buffer section to go
			isLastSection = true;
		}

		DSB->Unlock(buf, size, NULL, 0);
		lastSection = curSection;
	}
}


// display Ogg info and comments
void COggStream::display() {
	logOutput.Print("version:           %d", vorbisInfo->version);
	logOutput.Print("channels:          %d", vorbisInfo->channels);
	logOutput.Print("rate (Hz):         %d", vorbisInfo->rate);
	logOutput.Print("bitrate (upper):   %d", vorbisInfo->bitrate_upper);
	logOutput.Print("bitrate (nominal): %d", vorbisInfo->bitrate_nominal);
	logOutput.Print("bitrate (lower):   %d", vorbisInfo->bitrate_lower);
	logOutput.Print("bitrate (window):  %d", vorbisInfo->bitrate_window);
	logOutput.Print("vendor:            %s", vorbisComment->vendor);

	for (int i = 0; i < vorbisComment->comments; i++) {
		logOutput.Print("%s", vorbisComment->user_comments[i]);
	}
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?