StereoResampler::StereoResampler() : m_bufsize(MAX_SAMPLES_DEFAULT) , m_lowwatermark(LOW_WATERMARK_DEFAULT) , m_input_sample_rate(44100) , m_indexW(0) , m_indexR(0) , m_numLeftI(0.0f) , m_frac(0) , underrunCount_(0) , overrunCount_(0) , sample_rate_(0.0f) , lastBufSize_(0) { // Need to have space for the worst case in case it changes. m_buffer = new int16_t[MAX_SAMPLES_EXTRA * 2](); // Some Android devices are v-synced to non-60Hz framerates. We simply timestretch audio to fit. // TODO: should only do this if auto frameskip is off? float refresh = System_GetPropertyInt(SYSPROP_DISPLAY_REFRESH_RATE) / 1000.0f; // If framerate is "close"... if (refresh != 60.0f && refresh > 50.0f && refresh < 70.0f) { SetInputSampleRate((int)(44100 * (refresh / 60.0f))); } UpdateBufferSize(); }
void StereoResampler::PushSamples(const s32 *samples, unsigned int num_samples) { UpdateBufferSize(); const int INDEX_MASK = (m_bufsize * 2 - 1); // Cache access in non-volatile variable // indexR isn't allowed to cache in the audio throttling loop as it // needs to get updates to not deadlock. u32 indexW = Common::AtomicLoad(m_indexW); u32 cap = m_bufsize * 2; // If unthottling, no need to fill up the entire buffer, just screws up timing after releasing unthrottle. if (PSP_CoreParameter().unthrottle) cap = m_lowwatermark * 2; // Check if we have enough free space // indexW == m_indexR results in empty buffer, so indexR must always be smaller than indexW if (num_samples * 2 + ((indexW - Common::AtomicLoad(m_indexR)) & INDEX_MASK) >= cap) { if (!PSP_CoreParameter().unthrottle) overrunCount_++; // TODO: "Timestretch" by doing a windowed overlap with existing buffer content? return; } int over_bytes = num_samples * 4 - (m_bufsize * 2 - (indexW & INDEX_MASK)) * sizeof(short); if (over_bytes > 0) { ClampBufferToS16WithVolume(&m_buffer[indexW & INDEX_MASK], samples, (num_samples * 4 - over_bytes) / 2); ClampBufferToS16WithVolume(&m_buffer[0], samples + (num_samples * 4 - over_bytes) / sizeof(short), over_bytes / 2); } else { ClampBufferToS16WithVolume(&m_buffer[indexW & INDEX_MASK], samples, num_samples * 2); } Common::AtomicAdd(m_indexW, num_samples * 2); lastPushSize_ = num_samples; }
void Serializer::WriteData(const void *data, int data_size) { ASSERT(mode==SERIALIZE_WRITE); UpdateBufferSize(buffer_index+data_size); memcpy((unsigned char *)buffer+buffer_index,(const unsigned char *)data,data_size); buffer_index+=data_size; }
void BillboardSet::UpdateGeometry(const FrameInfo& frame) { if (bufferSizeDirty_ || indexBuffer_->IsDataLost()) UpdateBufferSize(); if (bufferDirty_ || vertexBuffer_->IsDataLost()) UpdateVertexBuffer(frame); }
void BaseVideoFilter::SendFrame(uint16_t *ppuOutputBuffer, bool isOddFrame) { _frameLock.Acquire(); _overscan = EmulationSettings::GetOverscanDimensions(); _isOddFrame = isOddFrame; UpdateBufferSize(); OnBeforeApplyFilter(); ApplyFilter(ppuOutputBuffer); _frameLock.Release(); }
void BillboardSet::UpdateGeometry(const FrameInfo& frame) { if (bufferSizeDirty_ || indexBuffer_->IsDataLost()) UpdateBufferSize(); if (bufferDirty_ || sortThisFrame_ || vertexBuffer_->IsDataLost()) UpdateVertexBuffer(frame); // If using camera facing, re-update the rotation for the current view now if (faceCameraMode_ != FC_NONE) { transforms_[1] = Matrix3x4(Vector3::ZERO, frame.camera_->GetFaceCameraRotation(node_->GetWorldPosition(), node_->GetWorldRotation(), faceCameraMode_), Vector3::ONE); } }
void BillboardSet::UpdateGeometry(const FrameInfo& frame) { // If rendering from multiple views and fixed screen size is in use, re-update scale factors before each render if (fixedScreenSize_ && viewCameras_.Size() > 1) CalculateFixedScreenSize(frame); // If using camera facing, re-update the rotation for the current view now if (faceCameraMode_ != FC_NONE) { transforms_[1] = Matrix3x4(Vector3::ZERO, frame.camera_->GetFaceCameraRotation(node_->GetWorldPosition(), node_->GetWorldRotation(), faceCameraMode_, minAngle_), Vector3::ONE); } if (bufferSizeDirty_ || indexBuffer_->IsDataLost()) UpdateBufferSize(); if (bufferDirty_ || sortThisFrame_ || vertexBuffer_->IsDataLost()) UpdateVertexBuffer(frame); }