int Soloud::play(AudioSource &aSound, float aVolume, float aPan, int aPaused, int aBus) { if (aSound.mFlags & AudioSource::SINGLE_INSTANCE) { // Only one instance allowed, stop others stopSound(aSound); } if (mLockMutexFunc) mLockMutexFunc(mMutex); int ch = findFreeVoice(); if (ch < 0) { if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); return -1; } if (!aSound.mAudioSourceID) { aSound.mAudioSourceID = mAudioSourceID; mAudioSourceID++; aSound.mSoloud = this; } mVoice[ch] = aSound.createInstance(); mVoice[ch]->mAudioSourceID = aSound.mAudioSourceID; mVoice[ch]->mBusHandle = aBus; mVoice[ch]->init(mPlayIndex, aSound.mBaseSamplerate, aSound.mChannels, aSound.mFlags); mPlayIndex++; if (aPaused) { mVoice[ch]->mFlags |= AudioSourceInstance::PAUSED; } setVoicePan(ch, aPan); setVoiceVolume(ch, aVolume); setVoiceRelativePlaySpeed(ch, 1); int i; for (i = 0; i < FILTERS_PER_STREAM; i++) { if (aSound.mFilter[i]) { mVoice[ch]->mFilter[i] = aSound.mFilter[i]->createInstance(); } } int scratchneeded = SAMPLE_GRANULARITY * mVoice[ch]->mChannels; mVoice[ch]->mResampleData[0]->mBuffer = new float[scratchneeded]; mVoice[ch]->mResampleData[1]->mBuffer = new float[scratchneeded]; // First buffer will be overwritten anyway; the second may be referenced by resampler memset(mVoice[ch]->mResampleData[0]->mBuffer, 0, sizeof(float) * scratchneeded); memset(mVoice[ch]->mResampleData[1]->mBuffer, 0, sizeof(float) * scratchneeded); if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); int handle = getHandleFromVoice(ch); return handle; }
// Remove all non-active voices from group void Soloud::trimVoiceGroup(handle aVoiceGroupHandle) { if (!isVoiceGroup(aVoiceGroupHandle)) return; int c = aVoiceGroupHandle & 0xfff; if (mLockMutexFunc) mLockMutexFunc(mMutex); // empty group if (mVoiceGroup[c][1] == 0) { if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); return; } unsigned int i; for (i = 1; i < mVoiceGroup[c][0]; i++) { if (mVoiceGroup[c][i] == 0) { if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); return; } if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); while (!isValidVoiceHandle(mVoiceGroup[c][i])) // function locks mutex, so we need to unlock it before the call { if (mLockMutexFunc) mLockMutexFunc(mMutex); unsigned int j; for (j = i; j < mVoiceGroup[c][0] - 1; j++) { mVoiceGroup[c][j] = mVoiceGroup[c][j + 1]; if (mVoiceGroup[c][j] == 0) break; } mVoiceGroup[c][mVoiceGroup[c][0] - 1] = 0; if (mVoiceGroup[c][i] == 0) { if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); return; } } } if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); }
void Soloud::stopAll() { int i; if (mLockMutexFunc) mLockMutexFunc(mMutex); for (i = 0; i < VOICE_COUNT; i++) { stopVoice(i); } if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); }
void Soloud::stop(int aVoiceHandle) { int ch = getVoiceFromHandle(aVoiceHandle); if (ch == -1) { return; } if (mLockMutexFunc) mLockMutexFunc(mMutex); stopVoice(ch); if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); }
// Destroy a voice group. result Soloud::destroyVoiceGroup(handle aVoiceGroupHandle) { if (!isVoiceGroup(aVoiceGroupHandle)) return INVALID_PARAMETER; int c = aVoiceGroupHandle & 0xfff; if (mLockMutexFunc) mLockMutexFunc(mMutex); delete[] mVoiceGroup[c]; mVoiceGroup[c] = NULL; if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); return SO_NO_ERROR; }
void Soloud::seek(int aVoiceHandle, float aSeconds) { if (mLockMutexFunc) mLockMutexFunc(mMutex); int ch = getVoiceFromHandle(aVoiceHandle); if (ch == -1) { if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); return; } mVoice[ch]->seek(aSeconds, mScratch, mScratchSize); if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); }
// Add a voice handle to a voice group result Soloud::addVoiceToGroup(handle aVoiceGroupHandle, handle aVoiceHandle) { if (!isVoiceGroup(aVoiceGroupHandle)) return INVALID_PARAMETER; // Don't consider adding invalid voice handles as an error, since the voice may just have ended. if (!isValidVoiceHandle(aVoiceHandle)) return SO_NO_ERROR; trimVoiceGroup(aVoiceGroupHandle); int c = aVoiceGroupHandle & 0xfff; unsigned int i; if (mLockMutexFunc) mLockMutexFunc(mMutex); for (i = 1; i < mVoiceGroup[c][0]; i++) { if (mVoiceGroup[c][i] == aVoiceHandle) { if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); return SO_NO_ERROR; // already there } if (mVoiceGroup[c][i] == 0) { mVoiceGroup[c][i] = aVoiceHandle; mVoiceGroup[c][i + 1] = 0; if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); return SO_NO_ERROR; } } // Full group, allocate more memory unsigned int * n = new unsigned int[mVoiceGroup[c][0] * 2 + 1]; if (n == NULL) { if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); return OUT_OF_MEMORY; } for (i = 0; i < mVoiceGroup[c][0]; i++) n[i] = mVoiceGroup[c][i]; n[n[0]] = aVoiceHandle; n[n[0]+1] = 0; n[0] *= 2; delete[] mVoiceGroup[c]; mVoiceGroup[c] = n; if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); return SO_NO_ERROR; }
// Is this voice group empty? bool Soloud::isVoiceGroupEmpty(handle aVoiceGroupHandle) { // If not a voice group, yeah, we're empty alright.. if (!isVoiceGroup(aVoiceGroupHandle)) return 1; trimVoiceGroup(aVoiceGroupHandle); int c = aVoiceGroupHandle & 0xfff; if (mLockMutexFunc) mLockMutexFunc(mMutex); bool res = mVoiceGroup[c][1] == 0; if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); return res; }
// Is this handle a valid voice group? bool Soloud::isVoiceGroup(handle aVoiceGroupHandle) { if ((aVoiceGroupHandle & 0xfffff000) != 0xfffff000) return 0; unsigned int c = aVoiceGroupHandle & 0xfff; if (c >= mVoiceGroupCount) return 0; if (mLockMutexFunc) mLockMutexFunc(mMutex); bool res = mVoiceGroup[c] != NULL; if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); return res; }
void Soloud::stopAudioSource(AudioSource &aSound) { if (aSound.mAudioSourceID) { if (mLockMutexFunc) mLockMutexFunc(mMutex); int i; for (i = 0; i < VOICE_COUNT; i++) { if (mVoice && mVoice[i] && mVoice[i]->mAudioSourceID == aSound.mAudioSourceID) { stopVoice(i); } } if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); } }
void Soloud::scheduleStop(handle aVoiceHandle, time aTime) { if (aTime <= 0) { stop(aVoiceHandle); return; } if (mLockMutexFunc) mLockMutexFunc(mMutex); int ch = getVoiceFromHandle(aVoiceHandle); if (ch == -1) { if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); return; } mVoice[ch]->mStopScheduler.set(1, 0, aTime, mVoice[ch]->mStreamTime); if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); }
void Soloud::oscillateRelativePlaySpeed(handle aVoiceHandle, float aFrom, float aTo, time aTime) { if (aTime <= 0 || aTo == aFrom) { setRelativePlaySpeed(aVoiceHandle, aTo); return; } if (mLockMutexFunc) mLockMutexFunc(mMutex); int ch = getVoiceFromHandle(aVoiceHandle); if (ch == -1) { if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); return; } mVoice[ch]->mRelativePlaySpeedFader.setLFO(aFrom, aTo, aTime, mVoice[ch]->mStreamTime); if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); }
void Soloud::schedulePause(int aVoiceHandle, float aTime) { if (aTime <= 0) { setPause(aVoiceHandle, 1); return; } if (mLockMutexFunc) mLockMutexFunc(mMutex); int ch = getVoiceFromHandle(aVoiceHandle); if (ch == -1) { if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); return; } mVoice[ch]->mPauseScheduler.set(1, 0, aTime, mVoice[ch]->mStreamTime); if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); }
void Soloud::oscillatePan(int aVoiceHandle, float aFrom, float aTo, float aTime) { if (aTime <= 0 || aTo == aFrom) { setPan(aVoiceHandle, aTo); return; } if (mLockMutexFunc) mLockMutexFunc(mMutex); int ch = getVoiceFromHandle(aVoiceHandle); if (ch == -1) { if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); return; } mVoice[ch]->mPanFader.setLFO(aFrom, aTo, aTime, mVoice[ch]->mStreamTime); if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); }
void Soloud::fadeRelativePlaySpeed(int aVoiceHandle, float aTo, float aTime) { float from = getRelativePlaySpeed(aVoiceHandle); if (aTime <= 0 || aTo == from) { setRelativePlaySpeed(aVoiceHandle, aTo); return; } if (mLockMutexFunc) mLockMutexFunc(mMutex); int ch = getVoiceFromHandle(aVoiceHandle); if (ch == -1) { if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); return; } mVoice[ch]->mRelativePlaySpeedFader.set(from, aTo, aTime, mVoice[ch]->mStreamTime); if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); }
void Soloud::fadePan(handle aVoiceHandle, float aTo, time aTime) { float from = getPan(aVoiceHandle); if (aTime <= 0 || aTo == from) { setPan(aVoiceHandle, aTo); return; } if (mLockMutexFunc) mLockMutexFunc(mMutex); int ch = getVoiceFromHandle(aVoiceHandle); if (ch == -1) { if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); return; } mVoice[ch]->mPanFader.set(from, aTo, aTime, mVoice[ch]->mStreamTime); if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); }
// Create a voice group. Returns 0 if unable (out of voice groups / out of memory) handle Soloud::createVoiceGroup() { if (mLockMutexFunc) mLockMutexFunc(mMutex); unsigned int i; // Check if there's any deleted voice groups and re-use if found for (i = 0; i < mVoiceGroupCount; i++) { if (mVoiceGroup[i] == NULL) { mVoiceGroup[i] = new unsigned int[16]; if (mVoiceGroup[i] == NULL) { if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); return 0; } mVoiceGroup[i][0] = 16; mVoiceGroup[i][1] = 0; if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); return 0xfffff000 | i; } } if (mVoiceGroupCount == 4096) { if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); return 0; } unsigned int oldcount = mVoiceGroupCount; if (mVoiceGroupCount == 0) { mVoiceGroupCount = 4; } mVoiceGroupCount *= 2; unsigned int **vg = new unsigned int * [mVoiceGroupCount]; if (vg == NULL) { mVoiceGroupCount = oldcount; if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); return 0; } for (i = 0; i < oldcount; i++) { vg[i] = mVoiceGroup[i]; } for (; i < mVoiceGroupCount; i++) { vg[i] = NULL; } delete[] mVoiceGroup; mVoiceGroup = vg; i = oldcount; mVoiceGroup[i] = new unsigned int[17]; if (mVoiceGroup[i] == NULL) { if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); return 0; } mVoiceGroup[i][0] = 16; mVoiceGroup[i][1] = 0; if (mUnlockMutexFunc) mUnlockMutexFunc(mMutex); return 0xfffff000 | i; }