コード例 #1
0
ファイル: AudioCommon.cpp プロジェクト: calmbrain/dolphin
	SoundStream* InitSoundStream()
	{
		CMixer *mixer = new CMixer(48000);

		// TODO: possible memleak with mixer

		std::string backend = SConfig::GetInstance().sBackend;
		if (backend == BACKEND_OPENAL           && OpenALStream::isValid())
			soundStream = new OpenALStream(mixer);
		else if (backend == BACKEND_NULLSOUND   && NullSound::isValid())
			soundStream = new NullSound(mixer);
		else if (backend == BACKEND_XAUDIO2)
		{
			if (XAudio2::isValid())
				soundStream = new XAudio2(mixer);
			else if (XAudio2_7::isValid())
				soundStream = new XAudio2_7(mixer);
		}
		else if (backend == BACKEND_AOSOUND     && AOSound::isValid())
			soundStream = new AOSound(mixer);
		else if (backend == BACKEND_ALSA        && AlsaSound::isValid())
			soundStream = new AlsaSound(mixer);
		else if (backend == BACKEND_COREAUDIO   && CoreAudioSound::isValid())
			soundStream = new CoreAudioSound(mixer);
		else if (backend == BACKEND_PULSEAUDIO  && PulseAudio::isValid())
			soundStream = new PulseAudio(mixer);
		else if (backend == BACKEND_OPENSLES && OpenSLESStream::isValid())
			soundStream = new OpenSLESStream(mixer);

		if (!soundStream && NullSound::isValid())
		{
			WARN_LOG(DSPHLE, "Could not initialize backend %s, using %s instead.",
				backend.c_str(), BACKEND_NULLSOUND);
			soundStream = new NullSound(mixer);
		}

		if (soundStream)
		{
			UpdateSoundStream();
			if (soundStream->Start())
			{
				if (SConfig::GetInstance().m_DumpAudio)
				{
					std::string audio_file_name = File::GetUserPath(D_DUMPAUDIO_IDX) + "audiodump.wav";
					File::CreateFullPath(audio_file_name);
					mixer->StartLogAudio(audio_file_name);
				}

				return soundStream;
			}
			PanicAlertT("Could not initialize backend %s.", backend.c_str());
		}

		PanicAlertT("Sound backend %s is not valid.", backend.c_str());

		delete soundStream;
		soundStream = nullptr;
		return nullptr;
	}
コード例 #2
0
ファイル: AudioCommon.cpp プロジェクト: calmbrain/dolphin
	void SendAIBuffer(short *samples, unsigned int num_samples)
	{
		if (!soundStream)
			return;

		CMixer* pMixer = soundStream->GetMixer();

		if (pMixer && samples)
		{
			pMixer->PushSamples(samples, num_samples);
		}

		soundStream->Update();
	}
コード例 #3
0
ファイル: DSPLLE.cpp プロジェクト: mbishop0051/dolphin
void DSPLLE::DSP_SendAIBuffer(unsigned int address, unsigned int num_samples)
{
	if (!soundStream)
		return;

	CMixer *pMixer = soundStream->GetMixer();

	if (pMixer && address)
	{
		address &= (address & 0x10000000) ? 0x13ffffff : 0x01ffffff;
		const short *samples = (const short *)&g_dsp.cpu_ram[address];
		pMixer->PushSamples(samples, num_samples);
	}

	soundStream->Update();
}
コード例 #4
0
ファイル: AudioCommon.cpp プロジェクト: calmbrain/dolphin
	void PauseAndLock(bool doLock, bool unpauseOnUnlock)
	{
		if (soundStream)
		{
			// audio typically doesn't maintain its own "paused" state
			// (that's already handled by the CPU and whatever else being paused)
			// so it should be good enough to only lock/unlock here.
			CMixer* pMixer = soundStream->GetMixer();
			if (pMixer)
			{
				std::mutex& csMixing = pMixer->MixerCritical();
				if (doLock)
					csMixing.lock();
				else
					csMixing.unlock();
			}
		}
	}
コード例 #5
0
ファイル: AudioCommon.cpp プロジェクト: Buddybenj/dolphin
	void SendAIBuffer(short *samples, unsigned int num_samples)
	{
		if (!g_sound_stream)
			return;

		if (SConfig::GetInstance().m_DumpAudio && !s_audio_dump_start)
			StartAudioDump();
		else if (!SConfig::GetInstance().m_DumpAudio && s_audio_dump_start)
			StopAudioDump();

		CMixer* pMixer = g_sound_stream->GetMixer();

		if (pMixer && samples)
		{
			pMixer->PushSamples(samples, num_samples);
		}

		g_sound_stream->Update();
	}
コード例 #6
0
void UpdateTitle()
{
	u32 ElapseTime = (u32)s_timer.GetTimeDifference();
	s_request_refresh_info = false;
	SCoreStartupParameter& _CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter;

	if (ElapseTime == 0)
		ElapseTime = 1;

	float FPS = (float) (Common::AtomicLoad(s_drawn_frame) * 1000.0 / ElapseTime);
	float VPS = (float) (s_drawn_video * 1000.0 / ElapseTime);
	float Speed = (float) (s_drawn_video * (100 * 1000.0) / (VideoInterface::TargetRefreshRate * ElapseTime));

	// Settings are shown the same for both extended and summary info
	std::string SSettings = StringFromFormat("%s %s | %s | %s", cpu_core_base->GetName(), _CoreParameter.bCPUThread ? "DC" : "SC",
		g_video_backend->GetDisplayName().c_str(), _CoreParameter.bDSPHLE ? "HLE" : "LLE");

	std::string SFPS;

	if (Movie::IsPlayingInput())
		SFPS = StringFromFormat("VI: %u/%u - Input: %u/%u - FPS: %.0f - VPS: %.0f - %.0f%%", (u32)Movie::g_currentFrame, (u32)Movie::g_totalFrames, (u32)Movie::g_currentInputCount, (u32)Movie::g_totalInputCount, FPS, VPS, Speed);
	else if (Movie::IsRecordingInput())
		SFPS = StringFromFormat("VI: %u - Input: %u - FPS: %.0f - VPS: %.0f - %.0f%%", (u32)Movie::g_currentFrame, (u32)Movie::g_currentInputCount, FPS, VPS, Speed);
	else
	{
		SFPS = StringFromFormat("FPS: %.0f - VPS: %.0f - %.0f%%", FPS, VPS, Speed);
		if (SConfig::GetInstance().m_InterfaceExtendedFPSInfo)
		{
			// Use extended or summary information. The summary information does not print the ticks data,
			// that's more of a debugging interest, it can always be optional of course if someone is interested.
			static u64 ticks = 0;
			static u64 idleTicks = 0;
			u64 newTicks = CoreTiming::GetTicks();
			u64 newIdleTicks = CoreTiming::GetIdleTicks();

			u64 diff = (newTicks - ticks) / 1000000;
			u64 idleDiff = (newIdleTicks - idleTicks) / 1000000;

			ticks = newTicks;
			idleTicks = newIdleTicks;

			float TicksPercentage = (float)diff / (float)(SystemTimers::GetTicksPerSecond() / 1000000) * 100;

			SFPS += StringFromFormat(" | CPU: %s%i MHz [Real: %i + IdleSkip: %i] / %i MHz (%s%3.0f%%)",
					_CoreParameter.bSkipIdle ? "~" : "",
					(int)(diff),
					(int)(diff - idleDiff),
					(int)(idleDiff),
					SystemTimers::GetTicksPerSecond() / 1000000,
					_CoreParameter.bSkipIdle ? "~" : "",
					TicksPercentage);
		}
	}
	// This is our final "frame counter" string
	std::string SMessage = StringFromFormat("%s | %s", SSettings.c_str(), SFPS.c_str());

	// Update the audio timestretcher with the current speed
	if (g_sound_stream)
	{
		CMixer* pMixer = g_sound_stream->GetMixer();
		pMixer->UpdateSpeed((float)Speed / 100);
	}

	Host_UpdateTitle(SMessage);
}
コード例 #7
0
// The audio thread.
void SoundStream::SoundLoop()
{
	Common::SetCurrentThreadName("Audio thread");
	InitializeSoundLoop();
	bool surroundSupported = SupportSurroundOutput() && SConfig::GetInstance().bDPL2Decoder;
	memset(realtimeBuffer, 0, SOUND_MAX_FRAME_SIZE * sizeof(u16));
	memset(dpl2buffer, 0, SOUND_MAX_FRAME_SIZE * sizeof(soundtouch::SAMPLETYPE));
	memset(samplebuffer, 0, SOUND_MAX_FRAME_SIZE * sizeof(soundtouch::SAMPLETYPE));
	u32 channelmultiplier = surroundSupported ? SOUND_SAMPLES_SURROUND : SOUND_SAMPLES_STEREO;
	CMixer* mixer = GetMixer();
	if (SConfig::GetInstance().bTimeStretching)
	{
		float ratemultiplier = 1.0f;
		soundtouch::SoundTouch sTouch;
		sTouch.setChannels(2);
		sTouch.setSampleRate(mixer->GetSampleRate());
		sTouch.setTempo(1.0);
		sTouch.setSetting(SETTING_USE_QUICKSEEK, 0);
		sTouch.setSetting(SETTING_USE_AA_FILTER, 1);
		while (threadData.load())
		{
			u32 availablesamples = mixer->AvailableSamples();
			u32 numsamples = std::min(availablesamples, 400u);
			if (numsamples == 400u)
			{
				float rate = mixer->GetCurrentSpeed();
				if (rate <= 0)
				{
					rate = 1.0f;
				}
				numsamples = mixer->Mix(samplebuffer, numsamples);
				rate *= ratemultiplier;
				rate = rate < 0.5f ? 0.5f : rate;
				rate = roundf(rate * 16.0f) / 16.0f;
				sTouch.setTempo(rate);
				sTouch.putSamples(samplebuffer, numsamples);
			}
			u32 samplesneeded = SamplesNeeded();
			availablesamples = sTouch.numSamples();
			if (samplesneeded >= SOUND_FRAME_SIZE && availablesamples > 0)
			{
				ratemultiplier = std::fmaxf(std::fminf((float)availablesamples / (float)samplesneeded, 1.1f), 0.9f);
				numsamples = std::min(availablesamples, SOUND_FRAME_SIZE);
				if (surroundSupported)
				{
					numsamples = sTouch.receiveSamples(dpl2buffer, numsamples);
					DPL2Decode(dpl2buffer, numsamples, samplebuffer);
				}
				else
				{
					numsamples = sTouch.receiveSamples(samplebuffer, numsamples);
				}
				floatTos16(realtimeBuffer, samplebuffer, numsamples, channelmultiplier);
				WriteSamples(realtimeBuffer, numsamples);
			}
			else
			{
				Common::SleepCurrentThread(1);
			}
		}
	}
	else
	{
		while (threadData.load())
		{
			u32 neededsamples = std::min(SamplesNeeded(), SOUND_FRAME_SIZE);
			u32 availablesamples = mixer->AvailableSamples() & (~(0xF));
			if (neededsamples == SOUND_FRAME_SIZE && availablesamples > 0)
			{
				u32 numsamples = std::min(availablesamples, neededsamples);
				if (surroundSupported)
				{
					numsamples = mixer->Mix(dpl2buffer, numsamples);
					DPL2Decode(dpl2buffer, numsamples, samplebuffer);
					floatTos16(realtimeBuffer, samplebuffer, numsamples, channelmultiplier);
				}
				else
				{
					numsamples = mixer->Mix(realtimeBuffer, numsamples);
				}
				WriteSamples(realtimeBuffer, numsamples);
			}
			else
			{
				Common::SleepCurrentThread(1);
			}
		}
	}
}
コード例 #8
0
ファイル: Core.cpp プロジェクト: Everscent/dolphin-emu
void UpdateTitle()
{
	u32 ElapseTime = (u32)Timer.GetTimeDifference();
	g_requestRefreshInfo = false;
	SCoreStartupParameter& _CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter;

	if (ElapseTime == 0)
		ElapseTime = 1;

	u32 FPS = Common::AtomicLoad(DrawnFrame) * 1000 / ElapseTime;
	u32 VPS = DrawnVideo * 1000 / ElapseTime;
	u32 Speed = DrawnVideo * (100 * 1000) / (VideoInterface::TargetRefreshRate * ElapseTime);

	// Settings are shown the same for both extended and summary info
	std::string SSettings = StringFromFormat("%s %s", cpu_core_base->GetName(),	_CoreParameter.bCPUThread ? "DC" : "SC");

	// Use extended or summary information. The summary information does not print the ticks data,
	// that's more of a debugging interest, it can always be optional of course if someone is interested.
	//#define EXTENDED_INFO
	#ifdef EXTENDED_INFO
		u64 newTicks = CoreTiming::GetTicks();
		u64 newIdleTicks = CoreTiming::GetIdleTicks();

		u64 diff = (newTicks - ticks) / 1000000;
		u64 idleDiff = (newIdleTicks - idleTicks) / 1000000;

		ticks = newTicks;
		idleTicks = newIdleTicks;

		float TicksPercentage = (float)diff / (float)(SystemTimers::GetTicksPerSecond() / 1000000) * 100;

		std::string SFPS = StringFromFormat("FPS: %u - VPS: %u - SPEED: %u%%", FPS, VPS, Speed);
		SFPS += StringFromFormat(" | CPU: %s%i MHz [Real: %i + IdleSkip: %i] / %i MHz (%s%3.0f%%)",
				_CoreParameter.bSkipIdle ? "~" : "",
				(int)(diff),
				(int)(diff - idleDiff),
				(int)(idleDiff),
				SystemTimers::GetTicksPerSecond() / 1000000,
				_CoreParameter.bSkipIdle ? "~" : "",
				TicksPercentage);

	#else	// Summary information
	std::string SFPS;
	if (Movie::IsPlayingInput())
		SFPS = StringFromFormat("VI: %u/%u - Frame: %u/%u - FPS: %u - VPS: %u - SPEED: %u%%", (u32)Movie::g_currentFrame, (u32)Movie::g_totalFrames, (u32)Movie::g_currentInputCount, (u32)Movie::g_totalInputCount, FPS, VPS, Speed);
	else if (Movie::IsRecordingInput())
		SFPS = StringFromFormat("VI: %u - Frame: %u - FPS: %u - VPS: %u - SPEED: %u%%", (u32)Movie::g_currentFrame, (u32)Movie::g_currentInputCount, FPS, VPS, Speed);
	else
		SFPS = StringFromFormat("FPS: %u - VPS: %u - SPEED: %u%%", FPS, VPS, Speed);
	#endif

	// This is our final "frame counter" string
	std::string SMessage = StringFromFormat("%s | %s",
		SSettings.c_str(), SFPS.c_str());
	std::string TMessage = StringFromFormat("%s | ", scm_rev_str) +
		SMessage;

	// Show message
	g_video_backend->UpdateFPSDisplay(SMessage.c_str());

	// Update the audio timestretcher with the current speed
	if (soundStream)
	{
		CMixer* pMixer = soundStream->GetMixer();
		pMixer->UpdateSpeed((float)Speed / 100);
	}

	if (_CoreParameter.bRenderToMain &&
		SConfig::GetInstance().m_InterfaceStatusbar) {
		Host_UpdateStatusBar(SMessage.c_str());
		Host_UpdateTitle(scm_rev_str);
	} else
		Host_UpdateTitle(TMessage.c_str());
	}