static void Mix(short *pFinalOut, unsigned Frames) { int MasterVol; mem_zero(m_pMixBuffer, m_MaxFrames*2*sizeof(int)); Frames = min(Frames, m_MaxFrames); // aquire lock while we are mixing lock_wait(m_SoundLock); MasterVol = m_SoundVolume; for(unsigned i = 0; i < NUM_VOICES; i++) { if(m_aVoices[i].m_pSample) { // mix voice CVoice *v = &m_aVoices[i]; int *pOut = m_pMixBuffer; int Step = v->m_pSample->m_Channels; // setup input sources short *pInL = &v->m_pSample->m_pData[v->m_Tick*Step]; short *pInR = &v->m_pSample->m_pData[v->m_Tick*Step+1]; unsigned End = v->m_pSample->m_NumFrames-v->m_Tick; int Rvol = v->m_pChannel->m_Vol; int Lvol = v->m_pChannel->m_Vol; // make sure that we don't go outside the sound data if(Frames < End) End = Frames; // check if we have a mono sound if(v->m_pSample->m_Channels == 1) pInR = pInL; // volume calculation if(v->m_Flags&ISound::FLAG_POS && v->m_pChannel->m_Pan) { // TODO: we should respect the channel panning value const int Range = 1500; // magic value, remove int dx = v->m_X - m_CenterX; int dy = v->m_Y - m_CenterY; int Dist = (int)sqrtf((float)dx*dx+dy*dy); // float here. nasty int p = IntAbs(dx); if(Dist >= 0 && Dist < Range) { // panning if(dx > 0) Lvol = ((Range-p)*Lvol)/Range; else Rvol = ((Range-p)*Rvol)/Range; // falloff Lvol = (Lvol*(Range-Dist))/Range; Rvol = (Rvol*(Range-Dist))/Range; } else { Lvol = 0; Rvol = 0; } } // process all frames for(unsigned s = 0; s < End; s++) { *pOut++ += (*pInL)*Lvol; *pOut++ += (*pInR)*Rvol; pInL += Step; pInR += Step; v->m_Tick++; } // free voice if not used any more if(v->m_Tick == v->m_pSample->m_NumFrames) { if(v->m_Flags&ISound::FLAG_LOOP) v->m_Tick = 0; else v->m_pSample = 0; } } } // release the lock lock_unlock(m_SoundLock); { // clamp accumulated values // TODO: this seams slow for(unsigned i = 0; i < Frames; i++) { int j = i<<1; int vl = ((m_pMixBuffer[j]*MasterVol)/101)>>8; int vr = ((m_pMixBuffer[j+1]*MasterVol)/101)>>8; pFinalOut[j] = Int2Short(vl); pFinalOut[j+1] = Int2Short(vr); } } #if defined(CONF_ARCH_ENDIAN_BIG) swap_endian(pFinalOut, sizeof(short), Frames * 2); #endif }
static void Mix(short *pFinalOut, unsigned Frames) { int MasterVol; mem_zero(m_pMixBuffer, m_MaxFrames*2*sizeof(int)); Frames = min(Frames, m_MaxFrames); // aquire lock while we are mixing lock_wait(m_SoundLock); MasterVol = m_SoundVolume; for(unsigned i = 0; i < NUM_VOICES; i++) { if(m_aVoices[i].m_pSample) { // mix voice CVoice *v = &m_aVoices[i]; int *pOut = m_pMixBuffer; int Step = v->m_pSample->m_Channels; // setup input sources short *pInL = &v->m_pSample->m_pData[v->m_Tick*Step]; short *pInR = &v->m_pSample->m_pData[v->m_Tick*Step+1]; unsigned End = v->m_pSample->m_NumFrames-v->m_Tick; int Rvol = (int)(v->m_pChannel->m_Vol*(v->m_Vol/255.0f)); int Lvol = (int)(v->m_pChannel->m_Vol*(v->m_Vol/255.0f)); // make sure that we don't go outside the sound data if(Frames < End) End = Frames; // check if we have a mono sound if(v->m_pSample->m_Channels == 1) pInR = pInL; // volume calculation if(v->m_Flags&ISound::FLAG_POS && v->m_pChannel->m_Pan) { // TODO: we should respect the channel panning value int dx = v->m_X - m_CenterX; int dy = v->m_Y - m_CenterY; // int p = IntAbs(dx); float FalloffX = 0.0f; float FalloffY = 0.0f; int RangeX = 0; // for panning bool InVoiceField = false; switch(v->m_Shape) { case ISound::SHAPE_CIRCLE: { float r = v->m_Circle.m_Radius; RangeX = r; int Dist = (int)sqrtf((float)dx*dx+dy*dy); // nasty float if(Dist < r) { InVoiceField = true; // falloff int FalloffDistance = r*v->m_Falloff; if(Dist > FalloffDistance) FalloffX = FalloffY = (r-Dist)/(r-FalloffDistance); else FalloffX = FalloffY = 1.0f; } else InVoiceField = false; break; } case ISound::SHAPE_RECTANGLE: { RangeX = v->m_Rectangle.m_Width/2.0f; int abs_dx = abs(dx); int abs_dy = abs(dy); int w = v->m_Rectangle.m_Width/2.0f; int h = v->m_Rectangle.m_Height/2.0f; if(abs_dx < w && abs_dy < h) { InVoiceField = true; // falloff int fx = v->m_Falloff * w; int fy = v->m_Falloff * h; FalloffX = abs_dx > fx ? (float)(w-abs_dx)/(w-fx) : 1.0f; FalloffY = abs_dy > fy ? (float)(h-abs_dy)/(h-fy) : 1.0f; } else InVoiceField = false; break; } }; if(InVoiceField) { // panning if(!(v->m_Flags&ISound::FLAG_NO_PANNING)) { if(dx > 0) Lvol = ((RangeX-p)*Lvol)/RangeX; else Rvol = ((RangeX-p)*Rvol)/RangeX; } { Lvol *= FalloffX; Rvol *= FalloffY; } } else { Lvol = 0; Rvol = 0; } } // process all frames for(unsigned s = 0; s < End; s++) { *pOut++ += (*pInL)*Lvol; *pOut++ += (*pInR)*Rvol; pInL += Step; pInR += Step; v->m_Tick++; } // free voice if not used any more if(v->m_Tick == v->m_pSample->m_NumFrames) { if(v->m_Flags&ISound::FLAG_LOOP) v->m_Tick = 0; else { v->m_pSample = 0; v->m_Age++; } } } } // release the lock lock_unlock(m_SoundLock); { // clamp accumulated values // TODO: this seams slow for(unsigned i = 0; i < Frames; i++) { int j = i<<1; int vl = ((m_pMixBuffer[j]*MasterVol)/101)>>8; int vr = ((m_pMixBuffer[j+1]*MasterVol)/101)>>8; pFinalOut[j] = Int2Short(vl); pFinalOut[j+1] = Int2Short(vr); } } #if defined(CONF_ARCH_ENDIAN_BIG) swap_endian(pFinalOut, sizeof(short), Frames * 2); #endif }
static void Mix(short *pFinalOut, unsigned Frames) { int MasterVol; mem_zero(m_pMixBuffer, m_MaxFrames*2*sizeof(int)); Frames = min(Frames, m_MaxFrames); // aquire lock while we are mixing lock_wait(m_SoundLock); MasterVol = m_SoundVolume; for(unsigned i = 0; i < NUM_VOICES; i++) { if(m_aVoices[i].m_pSample) { // mix voice CVoice *v = &m_aVoices[i]; int *pOut = m_pMixBuffer; int Step = v->m_pSample->m_Channels; // setup input sources short *pInL = &v->m_pSample->m_pData[v->m_Tick*Step]; short *pInR = &v->m_pSample->m_pData[v->m_Tick*Step+1]; unsigned End = v->m_pSample->m_NumFrames-v->m_Tick; int Rvol = v->m_pChannel->m_Vol; int Lvol = v->m_pChannel->m_Vol; // make sure that we don't go outside the sound data if(Frames < End) End = Frames; // check if we have a mono sound if(v->m_pSample->m_Channels == 1) pInR = pInL; // volume calculation if(v->m_Flags&ISound::FLAG_POS) { int dx = v->m_X - m_CenterX; int dy = v->m_Y - m_CenterY; float Dist = sqrtf((float)dx*dx+dy*dy); if(Dist >= 0.0f && Dist < m_MaxDistance) { // constant panning (-3dB center) float a = 0.5f; if(dx < 0) a -= (Dist/m_MaxDistance)/2.0f; else a += (Dist/m_MaxDistance)/2.0f; float Lgain = sinf((1-a)*pi/2.0f); float Rgain = sinf(a*pi/2.0f); // linear falloff float Falloff = 1.0f - Dist/m_MaxDistance; Lvol = Lvol*Lgain*Falloff; Rvol = Rvol*Rgain*Falloff; } else { Lvol = 0; Rvol = 0; } } // process all frames for(unsigned s = 0; s < End; s++) { *pOut++ += (*pInL)*Lvol; *pOut++ += (*pInR)*Rvol; pInL += Step; pInR += Step; v->m_Tick++; } // free voice if not used any more if(v->m_Tick == v->m_pSample->m_NumFrames) { if(v->m_Flags&ISound::FLAG_LOOP) v->m_Tick = 0; else v->m_pSample = 0; } } } // release the lock lock_unlock(m_SoundLock); { // clamp accumulated values // TODO: this seams slow for(unsigned i = 0; i < Frames; i++) { int j = i<<1; int vl = ((m_pMixBuffer[j]*MasterVol)/101)>>8; int vr = ((m_pMixBuffer[j+1]*MasterVol)/101)>>8; pFinalOut[j] = Int2Short(vl); pFinalOut[j+1] = Int2Short(vr); } } #if defined(CONF_ARCH_ENDIAN_BIG) swap_endian(pFinalOut, sizeof(short), Frames * 2); #endif }