inline void CalculateVolumeLevels(float *buffer, int totalFloats, float mulVal, float &RMS, float &MAX) { float sum = 0.0f; int totalFloatsStore = totalFloats; float Max = 0.0f; if((UPARAM(buffer) & 0xF) == 0) { UINT alignedFloats = totalFloats & 0xFFFFFFFC; __m128 sseMulVal = _mm_set_ps1(mulVal); for(UINT i=0; i<alignedFloats; i += 4) { __m128 sseScaledVals = _mm_mul_ps(_mm_load_ps(buffer+i), sseMulVal); /*compute squares and add them to the sum*/ __m128 sseSquares = _mm_mul_ps(sseScaledVals, sseScaledVals); sum += sseSquares.m128_f32[0] + sseSquares.m128_f32[1] + sseSquares.m128_f32[2] + sseSquares.m128_f32[3]; /* sse maximum of squared floats concept from: http://stackoverflow.com/questions/9795529/how-to-find-the-horizontal-maximum-in-a-256-bit-avx-vector */ __m128 sseSquaresP = _mm_shuffle_ps(sseSquares, sseSquares, _MM_SHUFFLE(1, 0, 3, 2)); __m128 halfmax = _mm_max_ps(sseSquares, sseSquaresP); __m128 halfmaxP = _mm_shuffle_ps(halfmax, halfmax, _MM_SHUFFLE(0,1,2,3)); __m128 maxs = _mm_max_ps(halfmax, halfmaxP); Max = max(Max, maxs.m128_f32[0]); } buffer += alignedFloats; totalFloats -= alignedFloats; } for(int i=0; i<totalFloats; i++) { float val = buffer[i] * mulVal; float pow2Val = val * val; sum += pow2Val; Max = max(Max, pow2Val); } RMS = sqrt(sum / totalFloatsStore); MAX = sqrt(Max); }
void MultiplyAudioBuffer(float *buffer, int totalFloats, float mulVal) { float sum = 0.0f; int totalFloatsStore = totalFloats; if((UPARAM(buffer) & 0xF) == 0) { UINT alignedFloats = totalFloats & 0xFFFFFFFC; __m128 sseMulVal = _mm_set_ps1(mulVal); for(UINT i=0; i<alignedFloats; i += 4) { __m128 sseScaledVals = _mm_mul_ps(_mm_load_ps(buffer+i), sseMulVal); _mm_store_ps(buffer+i, sseScaledVals); } buffer += alignedFloats; totalFloats -= alignedFloats; } for(int i=0; i<totalFloats; i++) buffer[i] *= mulVal; }
void UWidgetBlueprintLibrary::SetInputMode_GameOnly(APlayerController* Target) { if (Target != nullptr) { FInputModeGameOnly InputMode; Target->SetInputMode(InputMode); } } void UWidgetBlueprintLibrary::SetFocusToGameViewport() { FSlateApplication::Get().SetAllUserFocusToGameViewport(); } void UWidgetBlueprintLibrary::DrawBox(UPARAM(ref) FPaintContext& Context, FVector2D Position, FVector2D Size, USlateBrushAsset* Brush, FLinearColor Tint) { Context.MaxLayer++; if ( Brush ) { FSlateDrawElement::MakeBox( Context.OutDrawElements, Context.MaxLayer, Context.AllottedGeometry.ToPaintGeometry(Position, Size), &Brush->Brush, Context.MyClippingRect, ESlateDrawEffect::None, Tint); } }
UINT AudioSource::QueryAudio(float curVolume) { LPVOID buffer; UINT numAudioFrames; QWORD newTimestamp; if(GetNextBuffer((void**)&buffer, &numAudioFrames, &newTimestamp)) { //------------------------------------------------------------ // convert to float float *captureBuffer; if(!bFloat) { UINT totalSamples = numAudioFrames*inputChannels; if(convertBuffer.Num() < totalSamples) convertBuffer.SetSize(totalSamples); if(inputBitsPerSample == 8) { float *tempConvert = convertBuffer.Array(); char *tempSByte = (char*)buffer; while(totalSamples--) { *(tempConvert++) = float(*(tempSByte++))/127.0f; } } else if(inputBitsPerSample == 16) { float *tempConvert = convertBuffer.Array(); short *tempShort = (short*)buffer; while(totalSamples--) { *(tempConvert++) = float(*(tempShort++))/32767.0f; } } else if(inputBitsPerSample == 24) { float *tempConvert = convertBuffer.Array(); BYTE *tempTriple = (BYTE*)buffer; TripleToLong valOut; while(totalSamples--) { TripleToLong &valIn = (TripleToLong&)tempTriple; valOut.wVal = valIn.wVal; valOut.tripleVal = valIn.tripleVal; if(valOut.tripleVal > 0x7F) valOut.lastByte = 0xFF; *(tempConvert++) = float(double(valOut.val)/8388607.0); tempTriple += 3; } } else if(inputBitsPerSample == 32) { float *tempConvert = convertBuffer.Array(); long *tempShort = (long*)buffer; while(totalSamples--) { *(tempConvert++) = float(double(*(tempShort++))/2147483647.0); } } captureBuffer = convertBuffer.Array(); } else captureBuffer = (float*)buffer; //------------------------------------------------------------ // channel upmix/downmix if(tempBuffer.Num() < numAudioFrames*2) tempBuffer.SetSize(numAudioFrames*2); float *dataOutputBuffer = tempBuffer.Array(); float *tempOut = dataOutputBuffer; if(inputChannels == 1) { UINT numFloats = numAudioFrames; float *inputTemp = (float*)captureBuffer; float *outputTemp = dataOutputBuffer; if((UPARAM(inputTemp) & 0xF) == 0 && (UPARAM(outputTemp) & 0xF) == 0) { UINT alignedFloats = numFloats & 0xFFFFFFFC; for(UINT i=0; i<alignedFloats; i += 4) { __m128 inVal = _mm_load_ps(inputTemp+i); __m128 outVal1 = _mm_unpacklo_ps(inVal, inVal); __m128 outVal2 = _mm_unpackhi_ps(inVal, inVal); _mm_store_ps(outputTemp+(i*2), outVal1); _mm_store_ps(outputTemp+(i*2)+4, outVal2); } numFloats -= alignedFloats; inputTemp += alignedFloats; outputTemp += alignedFloats*2; } while(numFloats--) { float inputVal = *inputTemp; *(outputTemp++) = inputVal; *(outputTemp++) = inputVal; inputTemp++; } } else if(inputChannels == 2) //straight up copy { SSECopy(dataOutputBuffer, captureBuffer, numAudioFrames*2*sizeof(float)); } else { //todo: downmix optimization, also support for other speaker configurations than ones I can merely "think" of. ugh. float *inputTemp = (float*)captureBuffer; float *outputTemp = dataOutputBuffer; if(inputChannelMask == KSAUDIO_SPEAKER_QUAD) { UINT numFloats = numAudioFrames*4; float *endTemp = inputTemp+numFloats; while(inputTemp < endTemp) { float left = inputTemp[0]; float right = inputTemp[1]; float rearLeft = inputTemp[2]*surroundMix4; float rearRight = inputTemp[3]*surroundMix4; // When in doubt, use only left and right .... and rear left and rear right :) // Same idea as with 5.1 downmix *(outputTemp++) = (left + rearLeft) * attn4dotX; *(outputTemp++) = (right + rearRight) * attn4dotX; inputTemp += 4; } } else if(inputChannelMask == KSAUDIO_SPEAKER_2POINT1) { UINT numFloats = numAudioFrames*3; float *endTemp = inputTemp+numFloats; while(inputTemp < endTemp) { float left = inputTemp[0]; float right = inputTemp[1]; // Drop LFE since we don't need it //float lfe = inputTemp[2]*lowFreqMix; *(outputTemp++) = left; *(outputTemp++) = right; inputTemp += 3; } } else if(inputChannelMask == KSAUDIO_SPEAKER_4POINT1) { UINT numFloats = numAudioFrames*5; float *endTemp = inputTemp+numFloats; while(inputTemp < endTemp) { float left = inputTemp[0]; float right = inputTemp[1]; // Skip LFE , we don't really need it. //float lfe = inputTemp[2]; float rearLeft = inputTemp[3]*surroundMix4; float rearRight = inputTemp[4]*surroundMix4; // Same idea as with 5.1 downmix *(outputTemp++) = (left + rearLeft) * attn4dotX; *(outputTemp++) = (right + rearRight) * attn4dotX; inputTemp += 5; } } else if(inputChannelMask == KSAUDIO_SPEAKER_SURROUND) { UINT numFloats = numAudioFrames*4; float *endTemp = inputTemp+numFloats; while(inputTemp < endTemp) { float left = inputTemp[0]; float right = inputTemp[1]; float frontCenter = inputTemp[2]; float rearCenter = inputTemp[3]; // When in doubt, use only left and right :) Seriously. // THIS NEEDS TO BE PROPERLY IMPLEMENTED! *(outputTemp++) = left; *(outputTemp++) = right; inputTemp += 4; } } // Both speakers configs share the same format, the difference is in rear speakers position // See: http://msdn.microsoft.com/en-us/library/windows/hardware/ff537083(v=vs.85).aspx // Probably for KSAUDIO_SPEAKER_5POINT1_SURROUND we will need a different coefficient for rear left/right else if(inputChannelMask == KSAUDIO_SPEAKER_5POINT1 || inputChannelMask == KSAUDIO_SPEAKER_5POINT1_SURROUND) { UINT numFloats = numAudioFrames*6; float *endTemp = inputTemp+numFloats; while(inputTemp < endTemp) { float left = inputTemp[0]; float right = inputTemp[1]; float center = inputTemp[2]*centerMix; //We don't need LFE channel so skip it (see below) //float lowFreq = inputTemp[3]*lowFreqMix; float rearLeft = inputTemp[4]*surroundMix; float rearRight = inputTemp[5]*surroundMix; // According to ITU-R BS.775-1 recommendation, the downmix from a 3/2 source to stereo // is the following: // L = FL + k0*C + k1*RL // R = FR + k0*C + k1*RR // FL = front left // FR = front right // C = center // RL = rear left // RR = rear right // k0 = centerMix = dbMinus3 = 0.7071067811865476 [for k0 we can use dbMinus6 = 0.5 too, probably it's better] // k1 = surroundMix = dbMinus3 = 0.7071067811865476 // The output (L,R) can be out of (-1,1) domain so we attenuate it [ attn5dot1 = 1/(1 + centerMix + surroundMix) ] // Note: this method of downmixing is far from "perfect" (pretty sure it's not the correct way) but the resulting downmix is "okayish", at least no more bleeding ears. // (maybe have a look at http://forum.doom9.org/archive/index.php/t-148228.html too [ 5.1 -> stereo ] the approach seems almost the same [but different coefficients]) // http://acousticsfreq.com/blog/wp-content/uploads/2012/01/ITU-R-BS775-1.pdf // http://ir.lib.nctu.edu.tw/bitstream/987654321/22934/1/030104001.pdf *(outputTemp++) = (left + center + rearLeft) * attn5dot1; *(outputTemp++) = (right + center + rearRight) * attn5dot1; inputTemp += 6; } } // According to http://msdn.microsoft.com/en-us/library/windows/hardware/ff537083(v=vs.85).aspx // KSAUDIO_SPEAKER_7POINT1 is obsolete and no longer supported in Windows Vista and later versions of Windows // Not sure what to do about it, meh , drop front left of center/front right of center -> 5.1 -> stereo; else if(inputChannelMask == KSAUDIO_SPEAKER_7POINT1) { UINT numFloats = numAudioFrames*8; float *endTemp = inputTemp+numFloats; while(inputTemp < endTemp) { float left = inputTemp[0]; float right = inputTemp[1]; float center = inputTemp[2] * centerMix; // Drop LFE since we don't need it //float lowFreq = inputTemp[3]*lowFreqMix; float rearLeft = inputTemp[4] * surroundMix; float rearRight = inputTemp[5] * surroundMix; // Drop SPEAKER_FRONT_LEFT_OF_CENTER , SPEAKER_FRONT_RIGHT_OF_CENTER //float centerLeft = inputTemp[6]; //float centerRight = inputTemp[7]; // Downmix from 5.1 to stereo *(outputTemp++) = (left + center + rearLeft) * attn5dot1; *(outputTemp++) = (right + center + rearRight) * attn5dot1; inputTemp += 8; } } // Downmix to 5.1 (easy stuff) then downmix to stereo as done in KSAUDIO_SPEAKER_5POINT1 else if(inputChannelMask == KSAUDIO_SPEAKER_7POINT1_SURROUND) { UINT numFloats = numAudioFrames*8; float *endTemp = inputTemp+numFloats; while(inputTemp < endTemp) { float left = inputTemp[0]; float right = inputTemp[1]; float center = inputTemp[2] * centerMix; // Skip LFE we don't need it //float lowFreq = inputTemp[3]*lowFreqMix; float rearLeft = inputTemp[4]; float rearRight = inputTemp[5]; float sideLeft = inputTemp[6]; float sideRight = inputTemp[7]; // combine the rear/side channels first , baaam! 5.1 rearLeft = (rearLeft + sideLeft) * 0.5f; rearRight = (rearRight + sideRight) * 0.5f; // downmix to stereo as in 5.1 case *(outputTemp++) = (left + center + rearLeft * surroundMix) * attn5dot1; *(outputTemp++) = (right + center + rearRight * surroundMix) * attn5dot1; inputTemp += 8; } } } ReleaseBuffer(); //------------------------------------------------------------ // resample if(bResample) { UINT frameAdjust = UINT((double(numAudioFrames) * resampleRatio) + 1.0); UINT newFrameSize = frameAdjust*2; if(tempResampleBuffer.Num() < newFrameSize) tempResampleBuffer.SetSize(newFrameSize); SRC_DATA data; data.src_ratio = resampleRatio; data.data_in = tempBuffer.Array(); data.input_frames = numAudioFrames; data.data_out = tempResampleBuffer.Array(); data.output_frames = frameAdjust; data.end_of_input = 0; int err = src_process((SRC_STATE*)resampler, &data); if(err) { RUNONCE AppWarning(TEXT("AudioSource::QueryAudio: Was unable to resample audio for device '%s'"), GetDeviceName()); return NoAudioAvailable; } if(data.input_frames_used != numAudioFrames) { RUNONCE AppWarning(TEXT("AudioSource::QueryAudio: Failed to downsample buffer completely, which shouldn't actually happen because it should be using 10ms of samples")); return NoAudioAvailable; } numAudioFrames = data.output_frames_gen; } //----------------------------------------------------------------------------- // sort all audio frames into 10 millisecond increments (done because not all devices output in 10ms increments) // NOTE: 0.457+ - instead of using the timestamps from windows, just compare and make sure it stays within a 100ms of their timestamps if(!bFirstBaseFrameReceived) { lastUsedTimestamp = newTimestamp; bFirstBaseFrameReceived = true; } float *newBuffer = (bResample) ? tempResampleBuffer.Array() : tempBuffer.Array(); if (bSmoothTimestamps) { lastUsedTimestamp += 10; QWORD difVal = GetQWDif(newTimestamp, lastUsedTimestamp); if(difVal > 70) { //OSDebugOut(TEXT("----------------------------1\r\nlastUsedTimestamp before: %llu - device: %s\r\n"), lastUsedTimestamp, GetDeviceName()); lastUsedTimestamp = newTimestamp; //OSDebugOut(TEXT("lastUsedTimestamp after: %llu\r\n"), lastUsedTimestamp); } if(lastUsedTimestamp > lastSentTimestamp) { QWORD adjustVal = (lastUsedTimestamp-lastSentTimestamp); if(adjustVal < 10) lastUsedTimestamp += 10-adjustVal; AudioSegment *newSegment = new AudioSegment(newBuffer, numAudioFrames*2, lastUsedTimestamp); AddAudioSegment(newSegment, curVolume*sourceVolume); lastSentTimestamp = lastUsedTimestamp; } } else { // OSDebugOut(TEXT("newTimestamp: %llu\r\n"), newTimestamp); AudioSegment *newSegment = new AudioSegment(newBuffer, numAudioFrames*2, newTimestamp); AddAudioSegment(newSegment, curVolume*sourceVolume); } //----------------------------------------------------------------------------- return AudioAvailable; } return NoAudioAvailable; }
if (EventListener != nullptr) { UBTTask_ShowPhrases* Node = EventListener->ShowPhrasesNode; if (Node != nullptr) { Node->OwnerActor->GetWorldTimerManager().ClearTimer(Node->TimerHandle); Node->ShowNewDialoguePhrase(true); } } } ///////////////////////////////////////////////////// // Quests void UBTDialogueFunctionLibrary::AddQuest(UPARAM(ref) TArray<FQuest>& Quests, FQuest Quest) { Quests.AddUnique(Quest); } void UBTDialogueFunctionLibrary::DeleteQuest(UPARAM(ref) TArray<FQuest>& Quests, FQuest Quest) { Quests.Remove(Quest); } void UBTDialogueFunctionLibrary::UpdateTaskProgress(UPARAM(ref) FQuest& Quest, int32 TaskIndex) { if (!Quest.Tasks.IsValidIndex(TaskIndex)) return; FQuest_Task Task = Quest.Tasks[TaskIndex]; if (Task.TotalProgressNeeded == Task.Progress) return;
UINT MMDeviceAudioSource::GetNextBuffer(float curVolume) { UINT captureSize = 0; HRESULT err = mmCapture->GetNextPacketSize(&captureSize); if(FAILED(err)) { RUNONCE AppWarning(TEXT("MMDeviceAudioSource::GetBuffer: GetNextPacketSize failed")); return NoAudioAvailable; } float *outputBuffer = NULL; if(captureSize) { LPBYTE captureBuffer; DWORD dwFlags = 0; UINT numAudioFrames = 0; UINT64 devPosition; UINT64 qpcTimestamp; err = mmCapture->GetBuffer(&captureBuffer, &numAudioFrames, &dwFlags, &devPosition, &qpcTimestamp); if(FAILED(err)) { RUNONCE AppWarning(TEXT("MMDeviceAudioSource::GetBuffer: GetBuffer failed")); return NoAudioAvailable; } QWORD newTimestamp; if(dwFlags & AUDCLNT_BUFFERFLAGS_TIMESTAMP_ERROR) { RUNONCE AppWarning(TEXT("MMDeviceAudioSource::GetBuffer: woa woa woa, getting timestamp errors from the audio subsystem. device = %s"), GetDeviceName().Array()); if(!bBrokenTimestamp) newTimestamp = lastUsedTimestamp + numAudioFrames*1000/inputSamplesPerSec; } else { if(!bBrokenTimestamp) newTimestamp = qpcTimestamp/10000; /*UINT64 freq; mmClock->GetFrequency(&freq); Log(TEXT("position: %llu, numAudioFrames: %u, freq: %llu, newTimestamp: %llu, test: %llu"), devPosition, numAudioFrames, freq, newTimestamp, devPosition*8000/freq);*/ } //have to do this crap to account for broken devices or device drivers. absolutely unbelievable. if(!bFirstFrameReceived) { LARGE_INTEGER clockFreq; QueryPerformanceFrequency(&clockFreq); QWORD curTime = GetQPCTimeMS(clockFreq.QuadPart); if(newTimestamp < (curTime-1000) || newTimestamp > (curTime+1000)) { bBrokenTimestamp = true; Log(TEXT("MMDeviceAudioSource::GetNextBuffer: Got bad audio timestamp offset %lld from device: '%s', timestamps for this device will be calculated. curTime: %llu, newTimestamp: %llu"), (LONGLONG)(newTimestamp - curTime), GetDeviceName().Array(), curTime, newTimestamp); lastUsedTimestamp = newTimestamp = curTime; } else lastUsedTimestamp = newTimestamp; bFirstFrameReceived = true; } if(tempBuffer.Num() < numAudioFrames*2) tempBuffer.SetSize(numAudioFrames*2); outputBuffer = tempBuffer.Array(); float *tempOut = outputBuffer; //------------------------------------------------------------ // channel upmix/downmix if(inputChannels == 1) { UINT numFloats = numAudioFrames; float *inputTemp = (float*)captureBuffer; float *outputTemp = outputBuffer; if(App->SSE2Available() && (UPARAM(inputTemp) & 0xF) == 0 && (UPARAM(outputTemp) & 0xF) == 0) { UINT alignedFloats = numFloats & 0xFFFFFFFC; for(UINT i=0; i<alignedFloats; i += 4) { __m128 inVal = _mm_load_ps(inputTemp+i); __m128 outVal1 = _mm_unpacklo_ps(inVal, inVal); __m128 outVal2 = _mm_unpackhi_ps(inVal, inVal); _mm_store_ps(outputTemp+(i*2), outVal1); _mm_store_ps(outputTemp+(i*2)+4, outVal2); } numFloats -= alignedFloats; inputTemp += alignedFloats; outputTemp += alignedFloats*2; } while(numFloats--) { float inputVal = *inputTemp; *(outputTemp++) = inputVal; *(outputTemp++) = inputVal; inputTemp++; } } else if(inputChannels == 2) //straight up copy { if(App->SSE2Available()) SSECopy(outputBuffer, captureBuffer, numAudioFrames*2*sizeof(float)); else mcpy(outputBuffer, captureBuffer, numAudioFrames*2*sizeof(float)); } else { //todo: downmix optimization, also support for other speaker configurations than ones I can merely "think" of. ugh. float *inputTemp = (float*)captureBuffer; float *outputTemp = outputBuffer; if(inputChannelMask == KSAUDIO_SPEAKER_QUAD) { UINT numFloats = numAudioFrames*4; float *endTemp = inputTemp+numFloats; while(inputTemp < endTemp) { float left = inputTemp[0]; float right = inputTemp[1]; float rear = (inputTemp[2]+inputTemp[3])*surroundMix; *(outputTemp++) = left - rear; *(outputTemp++) = right + rear; inputTemp += 4; } } else if(inputChannelMask == KSAUDIO_SPEAKER_2POINT1) { UINT numFloats = numAudioFrames*3; float *endTemp = inputTemp+numFloats; while(inputTemp < endTemp) { float left = inputTemp[0]; float right = inputTemp[1]; float lfe = inputTemp[2]*lowFreqMix; *(outputTemp++) = left + lfe; *(outputTemp++) = right + lfe; inputTemp += 3; } } else if(inputChannelMask == KSAUDIO_SPEAKER_4POINT1) { UINT numFloats = numAudioFrames*5; float *endTemp = inputTemp+numFloats; while(inputTemp < endTemp) { float left = inputTemp[0]; float right = inputTemp[1]; float lfe = inputTemp[2]*lowFreqMix; float rear = (inputTemp[3]+inputTemp[4])*surroundMix; *(outputTemp++) = left + lfe - rear; *(outputTemp++) = right + lfe + rear; inputTemp += 5; } } else if(inputChannelMask == KSAUDIO_SPEAKER_SURROUND) { UINT numFloats = numAudioFrames*4; float *endTemp = inputTemp+numFloats; while(inputTemp < endTemp) { float left = inputTemp[0]; float right = inputTemp[1]; float center = inputTemp[2]*centerMix; float rear = inputTemp[3]*(surroundMix*dbMinus3); *(outputTemp++) = left + center - rear; *(outputTemp++) = right + center + rear; inputTemp += 4; } } //don't think this will work for both else if(inputChannelMask == KSAUDIO_SPEAKER_5POINT1) { UINT numFloats = numAudioFrames*6; float *endTemp = inputTemp+numFloats; while(inputTemp < endTemp) { float left = inputTemp[0]; float right = inputTemp[1]; float center = inputTemp[2]*centerMix; float lowFreq = inputTemp[3]*lowFreqMix; float rear = (inputTemp[4]+inputTemp[5])*surroundMix; *(outputTemp++) = left + center + lowFreq - rear; *(outputTemp++) = right + center + lowFreq + rear; inputTemp += 6; } } //todo ------------------ //not sure if my 5.1/7.1 downmixes are correct else if(inputChannelMask == KSAUDIO_SPEAKER_5POINT1_SURROUND) { UINT numFloats = numAudioFrames*6; float *endTemp = inputTemp+numFloats; while(inputTemp < endTemp) { float left = inputTemp[0]; float right = inputTemp[1]; float center = inputTemp[2]*centerMix; float lowFreq = inputTemp[3]*lowFreqMix; float sideLeft = inputTemp[4]*dbMinus3; float sideRight = inputTemp[5]*dbMinus3; *(outputTemp++) = left + center + sideLeft + lowFreq; *(outputTemp++) = right + center + sideRight + lowFreq; inputTemp += 6; } } else if(inputChannelMask == KSAUDIO_SPEAKER_7POINT1) { UINT numFloats = numAudioFrames*8; float *endTemp = inputTemp+numFloats; while(inputTemp < endTemp) { float left = inputTemp[0]; float right = inputTemp[1]; float center = inputTemp[2]*(centerMix*dbMinus3); float lowFreq = inputTemp[3]*lowFreqMix; float rear = (inputTemp[4]+inputTemp[5])*surroundMix; float centerLeft = inputTemp[6]*dbMinus6; float centerRight = inputTemp[7]*dbMinus6; *(outputTemp++) = left + centerLeft + center + lowFreq - rear; *(outputTemp++) = right + centerRight + center + lowFreq + rear; inputTemp += 8; } } else if(inputChannelMask == KSAUDIO_SPEAKER_7POINT1_SURROUND) { UINT numFloats = numAudioFrames*8; float *endTemp = inputTemp+numFloats; while(inputTemp < endTemp) { float left = inputTemp[0]; float right = inputTemp[1]; float center = inputTemp[2]*centerMix; float lowFreq = inputTemp[3]*lowFreqMix; float rear = (inputTemp[4]+inputTemp[5])*(surroundMix*dbMinus3); float sideLeft = inputTemp[6]*dbMinus6; float sideRight = inputTemp[7]*dbMinus6; *(outputTemp++) = left + sideLeft + center + lowFreq - rear; *(outputTemp++) = right + sideLeft + center + lowFreq + rear; inputTemp += 8; } } } mmCapture->ReleaseBuffer(numAudioFrames); //------------------------------------------------------------ // resample if(bResample) { UINT frameAdjust = UINT((double(numAudioFrames) * resampleRatio) + 1.0); UINT newFrameSize = frameAdjust*2; if(tempResampleBuffer.Num() < newFrameSize) tempResampleBuffer.SetSize(newFrameSize); SRC_DATA data; data.src_ratio = resampleRatio; data.data_in = tempBuffer.Array(); data.input_frames = numAudioFrames; data.data_out = tempResampleBuffer.Array(); data.output_frames = frameAdjust; data.end_of_input = 0; int err = src_process(resampler, &data); if(err) { RUNONCE AppWarning(TEXT("Was unable to resample audio")); return NoAudioAvailable; } if(data.input_frames_used != numAudioFrames) { RUNONCE AppWarning(TEXT("Failed to downsample buffer completely, which shouldn't actually happen because it should be using 10ms of samples")); return NoAudioAvailable; } numAudioFrames = data.output_frames_gen; } //----------------------------------------------------------------------------- // sort all audio frames into 10 millisecond increments (done because not all devices output in 10ms increments) // NOTE: 0.457+ - instead of using the timestamps from windows, just compare and make sure it stays within a 100ms of their timestamps float *newBuffer = (bResample) ? tempResampleBuffer.Array() : tempBuffer.Array(); if(storageBuffer.Num() == 0 && numAudioFrames == 441) { lastUsedTimestamp += 10; if(!bBrokenTimestamp) { QWORD difVal = GetQWDif(newTimestamp, lastUsedTimestamp); if(difVal > 70) lastUsedTimestamp = newTimestamp; } if(lastUsedTimestamp > lastSentTimestamp) { QWORD adjustVal = (lastUsedTimestamp-lastSentTimestamp); if(adjustVal < 10) lastUsedTimestamp += 10-adjustVal; AudioSegment &newSegment = *audioSegments.CreateNew(); newSegment.audioData.CopyArray(newBuffer, numAudioFrames*2); newSegment.timestamp = lastUsedTimestamp; MultiplyAudioBuffer(newSegment.audioData.Array(), numAudioFrames*2, curVolume); lastSentTimestamp = lastUsedTimestamp; } } else { UINT storedFrames = storageBuffer.Num(); storageBuffer.AppendArray(newBuffer, numAudioFrames*2); if(storageBuffer.Num() >= (441*2)) { lastUsedTimestamp += 10; if(!bBrokenTimestamp) { QWORD difVal = GetQWDif(newTimestamp, lastUsedTimestamp); if(difVal > 70) lastUsedTimestamp = newTimestamp - (QWORD(storedFrames)/2*1000/44100); } //------------------------ // add new data if(lastUsedTimestamp > lastSentTimestamp) { QWORD adjustVal = (lastUsedTimestamp-lastSentTimestamp); if(adjustVal < 10) lastUsedTimestamp += 10-adjustVal; AudioSegment &newSegment = *audioSegments.CreateNew(); newSegment.audioData.CopyArray(storageBuffer.Array(), (441*2)); newSegment.timestamp = lastUsedTimestamp; MultiplyAudioBuffer(newSegment.audioData.Array(), 441*2, curVolume); storageBuffer.RemoveRange(0, (441*2)); } //------------------------ // if still data pending (can happen) while(storageBuffer.Num() >= (441*2)) { lastUsedTimestamp += 10; if(lastUsedTimestamp > lastSentTimestamp) { QWORD adjustVal = (lastUsedTimestamp-lastSentTimestamp); if(adjustVal < 10) lastUsedTimestamp += 10-adjustVal; AudioSegment &newSegment = *audioSegments.CreateNew(); newSegment.audioData.CopyArray(storageBuffer.Array(), (441*2)); storageBuffer.RemoveRange(0, (441*2)); MultiplyAudioBuffer(newSegment.audioData.Array(), 441*2, curVolume); newSegment.timestamp = lastUsedTimestamp; lastSentTimestamp = lastUsedTimestamp; } } } } //----------------------------------------------------------------------------- return ContinueAudioRequest; } return NoAudioAvailable; }
void MixAudio(float *bufferDest, float *bufferSrc, UINT totalFloats, bool bForceMono) { UINT floatsLeft = totalFloats; float *destTemp = bufferDest; float *srcTemp = bufferSrc; if((UPARAM(destTemp) & 0xF) == 0 && (UPARAM(srcTemp) & 0xF) == 0) { UINT alignedFloats = floatsLeft & 0xFFFFFFFC; if(bForceMono) { __m128 halfVal = _mm_set_ps1(0.5f); for(UINT i=0; i<alignedFloats; i += 4) { float *micInput = srcTemp+i; __m128 val = _mm_load_ps(micInput); __m128 shufVal = _mm_shuffle_ps(val, val, _MM_SHUFFLE(2, 3, 0, 1)); _mm_store_ps(micInput, _mm_mul_ps(_mm_add_ps(val, shufVal), halfVal)); } } __m128 maxVal = _mm_set_ps1(1.0f); __m128 minVal = _mm_set_ps1(-1.0f); for(UINT i=0; i<alignedFloats; i += 4) { float *pos = destTemp+i; __m128 mix; mix = _mm_add_ps(_mm_load_ps(pos), _mm_load_ps(srcTemp+i)); mix = _mm_min_ps(mix, maxVal); mix = _mm_max_ps(mix, minVal); _mm_store_ps(pos, mix); } floatsLeft &= 0x3; destTemp += alignedFloats; srcTemp += alignedFloats; } if(floatsLeft) { if(bForceMono) { for(UINT i=0; i<floatsLeft; i += 2) { srcTemp[i] += srcTemp[i+1]; srcTemp[i] *= 0.5f; srcTemp[i+1] = srcTemp[i]; } } for(UINT i=0; i<floatsLeft; i++) { float val = destTemp[i]+srcTemp[i]; if(val < -1.0f) val = -1.0f; else if(val > 1.0f) val = 1.0f; destTemp[i] = val; } } }
#include "AdvancedSessionsLibrary.h" //General Log DEFINE_LOG_CATEGORY(AdvancedSessionsLog); void UAdvancedSessionsLibrary::GetCurrentUniqueBuildID(int32 &UniqueBuildId) { UniqueBuildId = GetBuildUniqueId(); } void UAdvancedSessionsLibrary::GetUniqueBuildID(FBlueprintSessionResult SessionResult, int32 &UniqueBuildId) { UniqueBuildId = SessionResult.OnlineResult.Session.SessionSettings.BuildUniqueId; } void UAdvancedSessionsLibrary::AddOrModifyExtraSettings(UPARAM(ref) TArray<FSessionPropertyKeyPair> & SettingsArray, UPARAM(ref) TArray<FSessionPropertyKeyPair> & NewOrChangedSettings, TArray<FSessionPropertyKeyPair> & ModifiedSettingsArray) { ModifiedSettingsArray = SettingsArray; bool bFoundSetting = false; // For each new setting for (const FSessionPropertyKeyPair& Setting : NewOrChangedSettings) { bFoundSetting = false; for (FSessionPropertyKeyPair & itr : ModifiedSettingsArray) { // Manually comparing the keys if (itr.Key == Setting.Key) { bFoundSetting = true;
bool InitDDrawCapture() { bool versionSupported = false; HMODULE hDDrawLib = NULL; if (hDDrawLib = GetModuleHandle(TEXT("ddraw.dll"))) { bool isWinVistaMin = IsWindowsVistaOrGreater(); bool isWin7min = IsWindows7OrGreater(); bool isWin8min = IsWindows8OrGreater(); UPARAM libBaseAddr = UPARAM(hDDrawLib); UPARAM surfCreateOffset; UPARAM surfUnlockOffset; UPARAM surfReleaseOffset; UPARAM surfRestoreOffset; UPARAM surfBltOffset; UPARAM surfFlipOffset; UPARAM surfSetPaletteOffset; UPARAM palSetEntriesOffset; if (isWinVistaMin) { if (!isWin7min) { RUNEVERYRESET logOutput << CurrentTimeString() << "Windows Vista not supported yet" << endl; } else if (isWin7min && !isWin8min) { surfCreateOffset = 0x617E; surfUnlockOffset = 0x4C40; surfReleaseOffset = 0x3239; surfRestoreOffset = 0x3E9CB; surfBltOffset = surfCreateOffset + 0x44F63; surfFlipOffset = surfCreateOffset + 0x37789; surfSetPaletteOffset = surfCreateOffset + 0x4D2D3; palSetEntriesOffset = surfCreateOffset + 0x4CE68; versionSupported = true; } else if (isWin8min) { surfCreateOffset = 0x9530 + 0xC00; surfUnlockOffset = surfCreateOffset + 0x2A1D0; surfReleaseOffset = surfCreateOffset - 0x1A80; surfRestoreOffset = surfCreateOffset + 0x36000; surfBltOffset = surfCreateOffset + 0x438DC; surfFlipOffset = surfCreateOffset + 0x33EF3; surfSetPaletteOffset = surfCreateOffset + 0x4D3B8; palSetEntriesOffset = surfCreateOffset + 0x4CF4C; versionSupported = false; // some crash bugs remaining RUNEVERYRESET logOutput << CurrentTimeString() << "Windows 8 not supported yet" << endl; } else { RUNEVERYRESET logOutput << CurrentTimeString() << "Unknown OS version" << endl; } } else { RUNEVERYRESET logOutput << CurrentTimeString() << "OS version not supported" << endl; } if (versionSupported) { ddrawSurfaceCreate.Hook((FARPROC)(libBaseAddr + surfCreateOffset), (FARPROC)CreateSurface); ddrawSurfaceRestore.Hook((FARPROC)(libBaseAddr + surfRestoreOffset), (FARPROC)Restore); ddrawSurfaceRelease.Hook((FARPROC)(libBaseAddr + surfReleaseOffset), (FARPROC)Release); ddrawSurfaceUnlock.Hook((FARPROC)(libBaseAddr + surfUnlockOffset), (FARPROC)Unlock); ddrawSurfaceBlt.Hook((FARPROC)(libBaseAddr + surfBltOffset), (FARPROC)Blt); ddrawSurfaceFlip.Hook((FARPROC)(libBaseAddr + surfFlipOffset), (FARPROC)Flip); ddrawSurfaceSetPalette.Hook((FARPROC)(libBaseAddr + surfSetPaletteOffset), (FARPROC)SetPalette); ddrawPaletteSetEntries.Hook((FARPROC)(libBaseAddr + palSetEntriesOffset), (FARPROC)PaletteSetEntries); ddrawSurfaceUnlock.Rehook(); ddrawSurfaceFlip.Rehook(); ddrawSurfaceBlt.Rehook(); /* ddrawSurfaceCreate.Rehook(); ddrawSurfaceRestore.Rehook(); ddrawSurfaceRelease.Rehook(); ddrawSurfaceSetPalette.Rehook(); ddrawPaletteSetEntries.Rehook(); */ } } return versionSupported; }