int cacheSound (int f) { if (! soundOK) return -1; unsigned int chunkLength; int retval; bool loopy; loopy = cacheLoopySound; cacheLoopySound = false; setResourceForFatal (f); if (! soundOK) return 0; int a = findInSoundCache (f); if (a != -1) { if (soundCache[a].playing) { if (! alureStopSource(soundCache[a].playingOnSource, AL_TRUE)) { debugOut( "Failed to stop source: %s\n", alureGetErrorString()); } } if (! alureRewindStream (soundCache[a].stream)) { debugOut( "Failed to rewind stream: %s\n", alureGetErrorString()); } return a; } if (f == -2) return -1; a = findEmptySoundSlot (); freeSound (a); uint32_t length = openFileFromNum (f); if (! length) return -1; unsigned char * memImage; bool tryAgain = true; while (tryAgain) { memImage = (unsigned char*)loadEntireFileToMemory (bigDataFile, length); tryAgain = memImage == NULL; if (tryAgain) { if (! forceRemoveSound ()) { fatal (ERROR_SOUND_MEMORY_LOW); return -1; } } } chunkLength = 19200; // Small looping sounds need small chunklengths. if (loopy) { if (length < NUM_BUFS * chunkLength) { chunkLength = length / NUM_BUFS; } } else if (length < chunkLength) { chunkLength = length; } soundCache[a].stream = alureCreateStreamFromMemory(memImage, length, chunkLength, 0, NULL); delete memImage; if (soundCache[a].stream != NULL) { soundCache[a].fileLoaded = f; setResourceForFatal (-1); retval = a; } else { debugOut("Failed to create stream from sound: %s\n", alureGetErrorString()); warning (ERROR_SOUND_ODDNESS); soundCache[a].stream = NULL; soundCache[a].playing = false; soundCache[a].playingOnSource = 0; soundCache[a].fileLoaded = -1; soundCache[a].looping = false; retval = -1; } return retval; }
ALuint AsyncPlayFunc(ALvoid*) { while(1) { EnterCriticalSection(&cs_StreamPlay); if(AsyncPlayList.size() == 0) { StopThread(PlayThreadHandle); PlayThreadHandle = NULL; LeaveCriticalSection(&cs_StreamPlay); break; } std::list<AsyncPlayEntry>::iterator i = AsyncPlayList.begin(), end = AsyncPlayList.end(); while(i != end) { ALuint buf; ALint processed; ALint queued; ALint state; if(i->stream == NULL) { alGetSourcei(i->source, AL_SOURCE_STATE, &state); if(state != AL_PLAYING && state != AL_PAUSED) { i->eos_callback(i->user_data, i->source); i = AsyncPlayList.erase(i); } else i++; continue; } alGetSourcei(i->source, AL_SOURCE_STATE, &state); alGetSourcei(i->source, AL_BUFFERS_QUEUED, &queued); alGetSourcei(i->source, AL_BUFFERS_PROCESSED, &processed); while(processed > 0) { queued--; processed--; alSourceUnqueueBuffers(i->source, 1, &buf); ALint size, channels, bits; alGetBufferi(buf, AL_SIZE, &size); alGetBufferi(buf, AL_CHANNELS, &channels); alGetBufferi(buf, AL_BITS, &bits); i->base_time += size / channels * 8 / bits; i->base_time %= i->max_time; while(!i->finished) { ALint filled = alureBufferDataFromStream(i->stream, 1, &buf); if(filled > 0) { queued++; alSourceQueueBuffers(i->source, 1, &buf); if(i->loopcount == 0) { alGetBufferi(buf, AL_SIZE, &size); alGetBufferi(buf, AL_CHANNELS, &channels); alGetBufferi(buf, AL_BITS, &bits); i->max_time += size / channels * 8 / bits; } break; } if(i->loopcount == i->maxloops) { i->finished = true; break; } if(i->maxloops != -1) i->loopcount++; i->finished = !alureRewindStream(i->stream); } } if(state != AL_PLAYING && state != AL_PAUSED) { if(queued == 0) { alSourcei(i->source, AL_BUFFER, 0); alDeleteBuffers(i->buffers.size(), &i->buffers[0]); if(i->eos_callback) i->eos_callback(i->user_data, i->source); i = AsyncPlayList.erase(i); continue; } alSourcePlay(i->source); } i++; } LeaveCriticalSection(&cs_StreamPlay); alureSleep(0.0078125f); } return 0; }