예제 #1
0
// Mix samples from the various audio channels into a single sample queue.
// This single sample queue is where __AudioMix should read from. If the sample queue is full, we should
// just sleep the main emulator thread a little.
void __AudioUpdate()
{
	// Audio throttle doesn't really work on the PSP since the mixing intervals are so closely tied
	// to the CPU. Much better to throttle the frame rate on frame display and just throw away audio
	// if the buffer somehow gets full.

	s32 mixBuffer[hwBlockSize * 2];
	memset(mixBuffer, 0, sizeof(mixBuffer));

	for (u32 i = 0; i < PSP_AUDIO_CHANNEL_MAX + 1; i++)
	{
		if (!chans[i].reserved)
			continue;
		__AudioWakeThreads(chans[i], hwBlockSize);

		if (!chans[i].sampleQueue.size()) {
			// ERROR_LOG(HLE, "No queued samples, skipping channel %i", i);
			continue;
		}

		for (int s = 0; s < hwBlockSize; s++)
		{
			if (chans[i].sampleQueue.size() >= 2)
			{
				s16 sampleL = chans[i].sampleQueue.pop_front();
				s16 sampleR = chans[i].sampleQueue.pop_front();
				mixBuffer[s * 2 + 0] += sampleL;
				mixBuffer[s * 2 + 1] += sampleR;
			} 
			else
			{
				ERROR_LOG(HLE, "Channel %i buffer underrun at %i of %i", i, s, hwBlockSize);
				break;
			}
		}
	}

	if (g_Config.bEnableSound) {
		section.lock();
		if (outAudioQueue.room() >= hwBlockSize * 2) {
			// Push the mixed samples onto the output audio queue.
			for (int i = 0; i < hwBlockSize; i++) {
				s16 sampleL = clamp_s16(mixBuffer[i * 2 + 0]);
				s16 sampleR = clamp_s16(mixBuffer[i * 2 + 1]);

				outAudioQueue.push((s16)sampleL);
				outAudioQueue.push((s16)sampleR);
			}
		} else {
			// This happens quite a lot. There's still something slightly off
			// about the amount of audio we produce.
			DEBUG_LOG(HLE, "Audio outbuffer overrun! room = %i / %i", outAudioQueue.room(), (u32)outAudioQueue.capacity());
		}
		section.unlock();
	}
	
}
예제 #2
0
// Mix samples from the various audio channels into a single sample queue.
// This single sample queue is where __AudioMix should read from. If the sample queue is full, we should
// just sleep the main emulator thread a little.
void __AudioUpdate()
{
	// Audio throttle doesn't really work on the PSP since the mixing intervals are so closely tied
	// to the CPU. Much better to throttle the frame rate on frame display and just throw away audio
	// if the buffer somehow gets full.

	s32 mixBuffer[hwBlockSize * 2];
	memset(mixBuffer, 0, sizeof(mixBuffer));

	for (int i = 0; i < PSP_AUDIO_CHANNEL_MAX; i++)
	{
		if (!chans[i].reserved)
			continue;
		if (!chans[i].sampleQueue.size()) {
			// ERROR_LOG(HLE, "No queued samples, skipping channel %i", i);
			continue;
		}

		for (int s = 0; s < hwBlockSize; s++)
		{
			if (chans[i].sampleQueue.size() >= 2)
			{
				s16 sampleL = chans[i].sampleQueue.pop_front();
				s16 sampleR = chans[i].sampleQueue.pop_front();
				mixBuffer[s * 2 + 0] += sampleL;
				mixBuffer[s * 2 + 1] += sampleR;
			} 
			else
			{
				ERROR_LOG(HLE, "Channel %i buffer underrun at %i of %i", i, s, hwBlockSize);
				break;
			}
		}

		if (chans[i].sampleQueue.size() < chans[i].sampleCount * 2 * chanQueueMinSizeFactor)
		{
			// Ask the thread to send more samples until next time, queue is being drained.
			if (chans[i].waitingThread) {
				SceUID waitingThread = chans[i].waitingThread;
				chans[i].waitingThread = 0;
				// DEBUG_LOG(HLE, "Woke thread %i for some buffer filling", waitingThread);
				__KernelResumeThreadFromWait(waitingThread, chans[i].sampleCount);
			}
		}
	}

	if (g_Config.bEnableSound) {
		section.lock();
		if (outAudioQueue.room() >= hwBlockSize * 2) {
			// Push the mixed samples onto the output audio queue.
			for (int i = 0; i < hwBlockSize; i++) {
				s32 sampleL = mixBuffer[i * 2 + 0] >> 2;  // TODO - what factor?
				s32 sampleR = mixBuffer[i * 2 + 1] >> 2;

				outAudioQueue.push((s16)sampleL);
				outAudioQueue.push((s16)sampleR);
			}
		} else {
예제 #3
0
// Mix samples from the various audio channels into a single sample queue.
// This single sample queue is where __AudioMix should read from. If the sample queue is full, we should
// just sleep the main emulator thread a little.
void __AudioUpdate() {
	// Audio throttle doesn't really work on the PSP since the mixing intervals are so closely tied
	// to the CPU. Much better to throttle the frame rate on frame display and just throw away audio
	// if the buffer somehow gets full.
	bool firstChannel = true;

	for (u32 i = 0; i < PSP_AUDIO_CHANNEL_MAX + 1; i++)	{
		if (!chans[i].reserved)
			continue;

		__AudioWakeThreads(chans[i], 0, hwBlockSize);

		if (!chans[i].sampleQueue.size()) {
			continue;
		}

		if (hwBlockSize * 2 > chans[i].sampleQueue.size()) {
			ERROR_LOG(SCEAUDIO, "Channel %i buffer underrun at %i of %i", i, (int)chans[i].sampleQueue.size() / 2, hwBlockSize);
		}

		const s16 *buf1 = 0, *buf2 = 0;
		size_t sz1, sz2;

		chans[i].sampleQueue.popPointers(hwBlockSize * 2, &buf1, &sz1, &buf2, &sz2);

		if (firstChannel) {
			for (size_t s = 0; s < sz1; s++)
				mixBuffer[s] = buf1[s];
			if (buf2) {
				for (size_t s = 0; s < sz2; s++)
					mixBuffer[s + sz1] = buf2[s];
			}
			firstChannel = false;
		} else {
			for (size_t s = 0; s < sz1; s++)
				mixBuffer[s] += buf1[s];
			if (buf2) {
				for (size_t s = 0; s < sz2; s++)
					mixBuffer[s + sz1] += buf2[s];
			}
		}
	}

	if (firstChannel) {
		memset(mixBuffer, 0, hwBlockSize * 2 * sizeof(s32));
	}

	if (g_Config.bEnableSound) {
		lock_guard guard(section);
		if (outAudioQueue.room() >= hwBlockSize * 2) {
			s16 *buf1 = 0, *buf2 = 0;
			size_t sz1, sz2;
			outAudioQueue.pushPointers(hwBlockSize * 2, &buf1, &sz1, &buf2, &sz2);
			for (size_t s = 0; s < sz1; s++)
				buf1[s] = clamp_s16(mixBuffer[s]);
			if (buf2) {
				for (size_t s = 0; s < sz2; s++)
					buf2[s] = clamp_s16(mixBuffer[s + sz1]);
			}
		} else {
			// This happens quite a lot. There's still something slightly off
			// about the amount of audio we produce.
		}
	}
}
예제 #4
0
	if (g_Config.bEnableSound) {
		section.lock();
		if (outAudioQueue.room() >= hwBlockSize * 2) {
			// Push the mixed samples onto the output audio queue.
			for (int i = 0; i < hwBlockSize; i++) {
				s32 sampleL = mixBuffer[i * 2 + 0] >> 2;  // TODO - what factor?
				s32 sampleR = mixBuffer[i * 2 + 1] >> 2;

				outAudioQueue.push((s16)sampleL);
				outAudioQueue.push((s16)sampleR);
			}
		} else {
			// This happens quite a lot. There's still something slightly off
			// about the amount of audio we produce.
			DEBUG_LOG(HLE, "Audio outbuffer overrun! room = %i / %i", outAudioQueue.room(), (u32)outAudioQueue.capacity());
		}
		section.unlock();
	}
	
}

void __AudioSetOutputFrequency(int freq)
{
	WARN_LOG(HLE, "Switching audio frequency to %i", freq);
	mixFrequency = freq;
}

// numFrames is number of stereo frames.
int __AudioMix(short *outstereo, int numFrames)
{