// numFrames is number of stereo frames. // This is called from *outside* the emulator thread. int __AudioMix(short *outstereo, int numFrames) { // TODO: if mixFrequency != the actual output frequency, resample! lock_guard guard(section); int underrun = -1; s16 sampleL = 0; s16 sampleR = 0; bool anythingToPlay = false; for (int i = 0; i < numFrames; i++) { if (outAudioQueue.size() >= 2) { sampleL = outAudioQueue.pop_front(); sampleR = outAudioQueue.pop_front(); outstereo[i * 2 + 0] = sampleL; outstereo[i * 2 + 1] = sampleR; anythingToPlay = true; } else { if (underrun == -1) underrun = i; outstereo[i * 2 + 0] = sampleL; // repeat last sample, can reduce clicking outstereo[i * 2 + 1] = sampleR; // repeat last sample, can reduce clicking } } if (anythingToPlay && underrun >= 0) { DEBUG_LOG(HLE, "Audio out buffer UNDERRUN at %i of %i", underrun, numFrames); } else { // DEBUG_LOG(HLE, "No underrun, mixed %i samples fine", numFrames); } return underrun >= 0 ? underrun : numFrames; }
void __AudioDoState(PointerWrap &p) { auto s = p.Section("sceAudio", 1); if (!s) return; p.Do(eventAudioUpdate); CoreTiming::RestoreRegisterEvent(eventAudioUpdate, "AudioUpdate", &hleAudioUpdate); p.Do(eventHostAudioUpdate); CoreTiming::RestoreRegisterEvent(eventHostAudioUpdate, "AudioUpdateHost", &hleHostAudioUpdate); p.Do(mixFrequency); if (s >= 2) { resampler.DoState(p); } else { // Only to preserve the previous file format. Might cause a slight audio glitch on upgrades? FixedSizeQueue<s16, 512 * 16> outAudioQueue; outAudioQueue.DoState(p); resampler.Clear(); } int chanCount = ARRAY_SIZE(chans); p.Do(chanCount); if (chanCount != ARRAY_SIZE(chans)) { ERROR_LOG(SCEAUDIO, "Savestate failure: different number of audio channels."); return; } for (int i = 0; i < chanCount; ++i) chans[i].DoState(p); __AudioCPUMHzChange(); }
// 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 {
// 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(); } }
// numFrames is number of stereo frames. // This is called from *outside* the emulator thread. int __AudioMix(short *outstereo, int numFrames) { // TODO: if mixFrequency != the actual output frequency, resample! int underrun = -1; s16 sampleL = 0; s16 sampleR = 0; const s16 *buf1 = 0, *buf2 = 0; size_t sz1, sz2; { lock_guard guard(section); outAudioQueue.popPointers(numFrames * 2, &buf1, &sz1, &buf2, &sz2); memcpy(outstereo, buf1, sz1 * sizeof(s16)); if (buf2) { memcpy(outstereo + sz1, buf2, sz2 * sizeof(s16)); } } int remains = (int)(numFrames * 2 - sz1 - sz2); if (remains > 0) memset(outstereo + numFrames * 2 - remains, 0, remains); if (sz1 + sz2 < (size_t)numFrames) { underrun = (int)(sz1 + sz2) / 2; VERBOSE_LOG(SCEAUDIO, "Audio out buffer UNDERRUN at %i of %i", underrun, numFrames); } return underrun >= 0 ? underrun : numFrames; }
void __AudioDoState(PointerWrap &p) { p.Do(eventAudioUpdate); CoreTiming::RestoreRegisterEvent(eventAudioUpdate, "AudioUpdate", &hleAudioUpdate); p.Do(eventHostAudioUpdate); CoreTiming::RestoreRegisterEvent(eventHostAudioUpdate, "AudioUpdateHost", &hleHostAudioUpdate); p.Do(mixFrequency); { lock_guard guard(section); outAudioQueue.DoState(p); } int chanCount = ARRAY_SIZE(chans); p.Do(chanCount); if (chanCount != ARRAY_SIZE(chans)) { ERROR_LOG(SCEAUDIO, "Savestate failure: different number of audio channels."); return; } for (int i = 0; i < chanCount; ++i) chans[i].DoState(p); p.DoMarker("sceAudio"); }
int main(){ FixedSizeQueue currentBuffer; int currentHigh; char dummyChar; std::ifstream dataFile; //open file dataFile.open("data/problem7Data.txt"); if(dataFile.is_open()){ //get first summation of 5 numbers for (int i=0; i<5; i++) { dataFile>>dummyChar; //convert char to integer value currentBuffer.insert((dummyChar - '0') % 48); } currentHigh=currentBuffer.product(); /*continue adding 1 number, and checking summation against * current high until end of file*/ while (!(dataFile.eof())) { dataFile>>dummyChar; currentBuffer.insert((dummyChar - '0') % 48); if ((currentBuffer.product()) > (currentHigh)) { currentHigh=currentBuffer.product(); } } dataFile.close(); }else{
// 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. } } }
int eventAudioUpdate = -1; int eventHostAudioUpdate = -1; int mixFrequency = 44100; const int hwSampleRate = 44100; const int hwBlockSize = 64; const int hostAttemptBlockSize = 256; const int audioIntervalUs = (int)(1000000ULL * hwBlockSize / hwSampleRate); const int audioHostIntervalUs = (int)(1000000ULL * hostAttemptBlockSize / hwSampleRate); // High and low watermarks, basically. const int chanQueueMaxSizeFactor = 4; const int chanQueueMinSizeFactor = 1; FixedSizeQueue<s16, hostAttemptBlockSize * 16> outAudioQueue; void hleAudioUpdate(u64 userdata, int cyclesLate) { __AudioUpdate(); CoreTiming::ScheduleEvent(usToCycles(audioIntervalUs) - cyclesLate, eventAudioUpdate, 0); } void hleHostAudioUpdate(u64 userdata, int cyclesLate) { host->UpdateSound(); CoreTiming::ScheduleEvent(usToCycles(audioHostIntervalUs) - cyclesLate, eventHostAudioUpdate, 0); }