예제 #1
0
파일: sound.cpp 프로젝트: CytraL/MineTee
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
}
예제 #2
0
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
}
예제 #3
0
파일: sound.cpp 프로젝트: Bumble/teeworlds
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
}