about summary refs log tree commit diff
path: root/src/engine/client/sound.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/client/sound.cpp')
-rw-r--r--src/engine/client/sound.cpp84
1 files changed, 51 insertions, 33 deletions
diff --git a/src/engine/client/sound.cpp b/src/engine/client/sound.cpp
index 4678bb8a..45404d18 100644
--- a/src/engine/client/sound.cpp
+++ b/src/engine/client/sound.cpp
@@ -19,7 +19,7 @@ enum
 	NUM_SAMPLES = 512,
 	NUM_VOICES = 64,
 	NUM_CHANNELS = 16,
-	
+
 	MAX_FRAMES = 1024
 };
 
@@ -31,6 +31,7 @@ struct CSample
 	int m_Channels;
 	int m_LoopStart;
 	int m_LoopEnd;
+	int m_PausedAt;
 };
 
 struct CChannel
@@ -54,7 +55,6 @@ static CVoice m_aVoices[NUM_VOICES] = { {0} };
 static CChannel m_aChannels[NUM_CHANNELS] = { {255, 0} };
 
 static LOCK m_SoundLock = 0;
-static int m_SoundEnabled = 0;
 
 static int m_CenterX = 0;
 static int m_CenterY = 0;
@@ -89,9 +89,9 @@ static void Mix(short *pFinalOut, unsigned Frames)
 
 	// 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)
@@ -103,7 +103,7 @@ static void Mix(short *pFinalOut, unsigned Frames)
 			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;
@@ -112,7 +112,7 @@ static void Mix(short *pFinalOut, unsigned Frames)
 			// 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;
@@ -126,14 +126,14 @@ static void Mix(short *pFinalOut, unsigned Frames)
 				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 < Range)
+				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;
@@ -154,7 +154,7 @@ static void Mix(short *pFinalOut, unsigned Frames)
 				pInR += Step;
 				v->m_Tick++;
 			}
-			
+
 			// free voice if not used any more
 			if(v->m_Tick == v->m_pSample->m_NumFrames)
 			{
@@ -165,8 +165,8 @@ static void Mix(short *pFinalOut, unsigned Frames)
 			}
 		}
 	}
-	
-	
+
+
 	// release the lock
 	lock_release(m_SoundLock);
 
@@ -198,16 +198,17 @@ static void SdlCallback(void *pUnused, Uint8 *pStream, int Len)
 
 int CSound::Init()
 {
+	m_SoundEnabled = 0;
 	m_pGraphics = Kernel()->RequestInterface<IEngineGraphics>();
 	m_pStorage = Kernel()->RequestInterface<IStorage>();
-	
+
 	SDL_AudioSpec Format;
-	
+
 	m_SoundLock = lock_create();
-	
+
 	if(!g_Config.m_SndEnable)
 		return 0;
-	
+
 	m_MixingRate = g_Config.m_SndRate;
 
 	// Set 16-bit stereo audio at 22Khz
@@ -228,7 +229,7 @@ int CSound::Init()
 		dbg_msg("client/sound", "sound init successful");
 
 	SDL_PauseAudio(0);
-	
+
 	m_SoundEnabled = 1;
 	Update(); // update the volume
 	return 0;
@@ -238,17 +239,17 @@ int CSound::Update()
 {
 	// update volume
 	int WantedVolume = g_Config.m_SndVolume;
-	
+
 	if(!m_pGraphics->WindowActive() && g_Config.m_SndNonactiveMute)
 		WantedVolume = 0;
-	
+
 	if(WantedVolume != m_SoundVolume)
 	{
 		lock_wait(m_SoundLock);
 		m_SoundVolume = WantedVolume;
 		lock_release(m_SoundLock);
 	}
-	
+
 	return 0;
 }
 
@@ -276,7 +277,7 @@ void CSound::RateConvert(int SampleID)
 	CSample *pSample = &m_aSamples[SampleID];
 	int NumFrames = 0;
 	short *pNewData = 0;
-	
+
 	// make sure that we need to convert this sound
 	if(!pSample->m_pData || pSample->m_Rate == m_MixingRate)
 		return;
@@ -284,7 +285,7 @@ void CSound::RateConvert(int SampleID)
 	// allocate new data
 	NumFrames = (int)((pSample->m_NumFrames/(float)pSample->m_Rate)*m_MixingRate);
 	pNewData = (short *)mem_alloc(NumFrames*pSample->m_Channels*sizeof(short), 1);
-	
+
 	for(int i = 0; i < NumFrames; i++)
 	{
 		// resample TODO: this should be done better, like linear atleast
@@ -292,7 +293,7 @@ void CSound::RateConvert(int SampleID)
 		int f = (int)(a*pSample->m_NumFrames);
 		if(f >= pSample->m_NumFrames)
 			f = pSample->m_NumFrames-1;
-		
+
 		// set new data
 		if(pSample->m_Channels == 1)
 			pNewData[i] = pSample->m_pData[f];
@@ -302,7 +303,7 @@ void CSound::RateConvert(int SampleID)
 			pNewData[i*2+1] = pSample->m_pData[f*2+1];
 		}
 	}
-	
+
 	// free old data and apply new
 	mem_free(pSample->m_pData);
 	pSample->m_pData = pNewData;
@@ -320,15 +321,15 @@ int CSound::LoadWV(const char *pFilename)
 	int SampleID = -1;
 	char aError[100];
 	WavpackContext *pContext;
-	
+
 	// don't waste memory on sound when we are stress testing
 	if(g_Config.m_DbgStress)
 		return -1;
-		
+
 	// no need to load sound when we are running with no sound
 	if(!m_SoundEnabled)
 		return 1;
-		
+
 	if(!m_pStorage)
 		return -1;
 
@@ -371,7 +372,7 @@ int CSound::LoadWV(const char *pFilename)
 			dbg_msg("sound/wv", "file is %d Hz, not 44100 Hz. filename='%s'", snd->rate, filename);
 			return -1;
 		}*/
-		
+
 		if(BitsPerSample != 16)
 		{
 			dbg_msg("sound/wv", "bps is %d, not 16, filname='%s'", BitsPerSample, pFilename);
@@ -381,7 +382,7 @@ int CSound::LoadWV(const char *pFilename)
 		pData = (int *)mem_alloc(4*m_aSamples*m_aChannels, 1);
 		WavpackUnpackSamples(pContext, pData, m_aSamples); // TODO: check return value
 		pSrc = pData;
-		
+
 		pSample->m_pData = (short *)mem_alloc(2*m_aSamples*m_aChannels, 1);
 		pDst = pSample->m_pData;
 
@@ -393,6 +394,7 @@ int CSound::LoadWV(const char *pFilename)
 		pSample->m_NumFrames = m_aSamples;
 		pSample->m_LoopStart = -1;
 		pSample->m_LoopEnd = -1;
+		pSample->m_PausedAt = 0;
 	}
 	else
 	{
@@ -426,9 +428,9 @@ int CSound::Play(int ChannelID, int SampleID, int Flags, float x, float y)
 {
 	int VoiceID = -1;
 	int i;
-	
+
 	lock_wait(m_SoundLock);
-	
+
 	// search for voice
 	for(i = 0; i < NUM_VOICES; i++)
 	{
@@ -440,19 +442,22 @@ int CSound::Play(int ChannelID, int SampleID, int Flags, float x, float y)
 			break;
 		}
 	}
-	
+
 	// voice found, use it
 	if(VoiceID != -1)
 	{
 		m_aVoices[VoiceID].m_pSample = &m_aSamples[SampleID];
 		m_aVoices[VoiceID].m_pChannel = &m_aChannels[ChannelID];
-		m_aVoices[VoiceID].m_Tick = 0;
+		if(Flags & FLAG_LOOP)
+			m_aVoices[VoiceID].m_Tick = m_aSamples[SampleID].m_PausedAt;
+		else
+			m_aVoices[VoiceID].m_Tick = 0;
 		m_aVoices[VoiceID].m_Vol = 255;
 		m_aVoices[VoiceID].m_Flags = Flags;
 		m_aVoices[VoiceID].m_X = (int)x;
 		m_aVoices[VoiceID].m_Y = (int)y;
 	}
-	
+
 	lock_release(m_SoundLock);
 	return VoiceID;
 }
@@ -475,7 +480,13 @@ void CSound::Stop(int SampleID)
 	for(int i = 0; i < NUM_VOICES; i++)
 	{
 		if(m_aVoices[i].m_pSample == pSample)
+		{
+			if(m_aVoices[i].m_Flags & FLAG_LOOP)
+				m_aVoices[i].m_pSample->m_PausedAt = m_aVoices[i].m_Tick;
+			else
+				m_aVoices[i].m_pSample->m_PausedAt = 0;
 			m_aVoices[i].m_pSample = 0;
+		}
 	}
 	lock_release(m_SoundLock);
 }
@@ -486,6 +497,13 @@ void CSound::StopAll()
 	lock_wait(m_SoundLock);
 	for(int i = 0; i < NUM_VOICES; i++)
 	{
+		if(m_aVoices[i].m_pSample)
+		{
+			if(m_aVoices[i].m_Flags & FLAG_LOOP)
+				m_aVoices[i].m_pSample->m_PausedAt = m_aVoices[i].m_Tick;
+			else
+				m_aVoices[i].m_pSample->m_PausedAt = 0;
+		}
 		m_aVoices[i].m_pSample = 0;
 	}
 	lock_release(m_SoundLock);