/* ================== Sound::Init Initiates the file handles, sources and buffers. ================== */ bool Sound::Init(string file) { Clear(); if (pbMethod == PLAYBACK_STREAM) { if (!(oggFile = fopen(file.c_str(), "rb"))) { return false; } /* Attempt to read from the file as an Ogg-file */ oggStream = new OggVorbis_File; int result; if ((result = ov_open(oggFile, oggStream, NULL, 0)) < 0) { fclose(oggFile); delete oggStream; oggStream = NULL; return false; } /* Read format data from the file */ vorbisInfo = ov_info(oggStream, -1); if (vorbisInfo->channels == 1) { audioData.format = AL_FORMAT_MONO16; } else { audioData.format = AL_FORMAT_STEREO16; } audioData.frequency = vorbisInfo->rate; } else if (pbMethod == PLAYBACK_CACHE) { cacheBuffer = AudioManager::GetSingleton()->GetCacheBytes(file); PimAssert(cacheBuffer != NULL, "Failed to retrieve cache buffer"); audioData = AudioManager::GetSingleton()->GetCacheData(file); PimAssert(audioData.format != 0, "Failed to retrieve cache format"); PimAssert(audioData.frequency != 0, "Failed to retrieve cache frequency"); } else { PimAssert(0, "Init called on PLAYBACK_UNDEFINED Sound object"); return false; } alGenBuffers(2, buffers); alGenSources(1, &source); alSource3f(source, AL_POSITION, 0.f, 0.f, 0.f); alSource3f(source, AL_VELOCITY, 0.f, 0.f, 0.f); alSource3f(source, AL_DIRECTION, 0.f, 0.f, 0.f); alSourcef (source, AL_ROLLOFF_FACTOR, 0.f ); alSourcei (source, AL_SOURCE_RELATIVE, AL_TRUE ); return true; }
/* ================== Sound::Sound ================== */ Sound::Sound(string file, PlaybackMethod method) { oggFile = NULL; oggStream = NULL; vorbisInfo = NULL; bytePos = 0; cacheBuffer = NULL; buffers[0] = 0; buffers[1] = 0; source = 0; audioData.format = 0; audioData.frequency = 0; pbMethod = PLAYBACK_UNDEFINED; requiresInitialFill = true; loop = false; deleteWhenDone = true; AudioManager::GetSingleton()->AddSound(this); PimAssert(method != PLAYBACK_UNDEFINED, "Error: Must provide valid playback method!"); if (method == PLAYBACK_CACHE) { Cache(file); } else if (method == PLAYBACK_STREAM) { Stream(file); } }
/* ===================== Layer::Layer ===================== */ void Layer::AddLight(GameNode *node, LightDef *lDef) { PimAssert(node->parent != NULL, "ERROR: Orphan lights are not allowed"); if (lightSys) { lightSys->AddLight(node, lDef); } }
/* ===================== Layer::Layer The GameNode must have a ShadowShape prepared before it's added. use: GameNode::SetShadowShape(Vec2[], int) ===================== */ void Layer::AddShadowCaster(GameNode *caster) { if (lightSys) { PimAssert(caster->GetShadowShape() != NULL, "Error: Shadow Caster must have a defined shadow shape"); lightSys->casters.push_back(caster); } }
/* ================== Sound::FillBuffer Fills the buffer by streaming from an appropriate buffer. If PLAYBACK_CACHE: The vector<char> *cacheBuffer is used to fill the buffer. if PLAYBACK_STREAM: The OggVorbis_File *oggStream is used to fill the buffer. ================== */ bool Sound::FillBuffer(ALuint buffer) { char data[BUFFER_SIZE]; int size = 0; int section = 0; long result = 0; while (size < BUFFER_SIZE) { if (pbMethod == PLAYBACK_STREAM) { result = ov_read(oggStream, data+size, BUFFER_SIZE-size, 0, 2, 1, §ion); } else if (pbMethod == PLAYBACK_CACHE) { /* Calculate how much we can copy from the cache */ long remainding = cacheBuffer->size() - bytePos; result = min<long>(remainding, BUFFER_SIZE-size); /* Perform the copy */ if (result > 0) { copy(cacheBuffer->begin()+bytePos, cacheBuffer->begin()+bytePos+result, data+size); bytePos += result; } } else { PimAssert(false, "FillBuffer on PLAYBACK_UNDEFINED sound-object"); } if (result > 0) { size += result; } else if (result < 0) { /* An error occurred */ if (pbMethod == PLAYBACK_STREAM) { printf("OggVorbis error: %s\n", OggErrorString((int)result).c_str()); } return false; } else { /* We've reached the end of the buffer */ if (loop) { if (pbMethod == PLAYBACK_STREAM) { ov_pcm_seek(oggStream, 0); } else { bytePos = 0; } } else { /* We're not looping, and the end has beed reached */ if (!size) { return false; } else { /* Fill the buffer with what we've got */ break; } } } } /* Fill the OpenAL buffer with the retrieved data */ alBufferData(buffer, audioData.format, data, size, (int)audioData.frequency); return true; }
/* ===================== GameControl::SetScene ===================== */ void GameControl::SetScene(Scene *ns) { PimAssert(ns != NULL, "Error: Cannot set scene: NULL."); if (newScene) { delete newScene; } newScene = ns; }
/* ===================== GameNode::AddChild ===================== */ void GameNode::AddChild(GameNode *ch) { PimAssert(!ch->GetParent(), "Node already has a parent"); Layer *layer = dynamic_cast<Layer*>(ch); if (layer) { layer->LoadResources(); } ch->parent = this; children.push_back(ch); ch->OnParentChange(this); dirtyZOrder = true; }
/* ================== Sound::InitialFill When first starting playing, the buffers needs to be filled. ================== */ bool Sound::InitialFill() { PimAssert(requiresInitialFill, "Internal sound error"); if (!FillBuffer(buffers[0])) { return false; } if (!FillBuffer(buffers[1])) { return false; } alSourceQueueBuffers(source, 2, buffers); requiresInitialFill = false; return true; }
/* ===================== GameControl::GameControl ===================== */ GameControl::GameControl() { PimAssert(singleton == NULL, "Only one GameControl instance can exist at a time."); singleton = this; scene = NULL; newScene = NULL; paused = false; pauseLayer = NULL; maxDelta = 0.f; sleepNextFrame = false; sleepTime = 0.f; #ifdef WIN32 /* Windows specific initialization */ ticks = clock(); // Get the module path char path[260] = { '\0' }; GetModuleFileName(NULL, path, 260); int lastSlash = 0; for (int i=0; i<260; i++) { if (path[i] == '\\' || path[i] == '/') { lastSlash = i; } } for (int i=lastSlash+1; i<260; i++) { path[i] = '\0'; } modulePath = path; #elif defined __APPLE__ /* OSX specific initialization */ struct timeval time; gettimeofday(&time, NULL); ticks = Tick(time.tv_sec) + Tick(time.tv_usec / 1000000.0); modulePath = "."; #endif printf("Working directory:\n%s\n\n", modulePath.c_str()); }