STDMETHODIMP MFStream::GetLength(QWORD *pqwLength) { if (!pqwLength) return E_INVALIDARG; QMutexLocker locker(&m_mutex); *pqwLength = QWORD(m_stream->size()); return S_OK; }
void StreamEventDemuxer::parseReferenceNPT( BYTE *section ) { BYTE descLen = GET_SE_LEN(section); bool postDiscontinuityIndicator = GET_BYTE(section+2) & 0x80 ? true : false; BYTE contentID = GET_BYTE(section+2) & 0x7F; QWORD stcReference = ((QWORD(GET_BYTE(section+3) & 0x1)) << 32) | (0x00000000FFFFFFFFLLU & (GET_DWORD(section+4))); QWORD nptReference = GET_QWORD(section+8) & 0x00000001FFFFFFFFLLU; WORD scaleNumerator = GET_WORD(section+16); WORD scaleDenominator = GET_WORD(section+18); printf( "[DSMCCDemuxer] Reference NPT: len=%d, post=%d, contentID=%d, stc=%llx, npt=%llx, nominator=%x, denominator=%x\n", descLen, postDiscontinuityIndicator, contentID, stcReference, nptReference, scaleNumerator, scaleDenominator ); }
BOOL CUploadTransferED2K::DispatchNextChunk() { ASSERT( m_nState == upsUploading ); if ( !m_pDiskFile ) return FALSE; ASSERT( m_nLength < SIZE_UNKNOWN ); ASSERT( m_nPosition < m_nLength ); QWORD nChunk = m_nLength - m_nPosition; nChunk = min( nChunk, QWORD(Settings.eDonkey.FrameSize) ); #if 0 // Use packet form CEDPacket* pPacket = CEDPacket::New( ED2K_C2C_SENDINGPART ); pPacket->Write( &m_pED2K, sizeof(MD4) ); pPacket->WriteLongLE( m_nOffset + m_nPosition ); pPacket->WriteLongLE( m_nOffset + m_nPosition + nChunk ); m_pDiskFile->Read( m_nFileBase + m_nOffset + m_nPosition, pPacket->GetWritePointer( nChunk ), nChunk, &nChunk ); // SetFilePointer( hFile, m_nFileBase + m_nOffset + m_nPosition, NULL, FILE_BEGIN ); // ReadFile( hFile, pPacket->WriteGetPointer( nChunk ), nChunk, &nChunk, NULL ); if ( nChunk == 0 ) { pPacket->Release(); return FALSE; } pPacket->m_nLength = sizeof(MD4) + 8 + nChunk; Send( pPacket ); #else // Raw write CBuffer* pBuffer = m_pClient->m_pOutput; pBuffer->EnsureBuffer( sizeof(ED2K_PART_HEADER) + (DWORD)nChunk ); ED2K_PART_HEADER* pHeader = (ED2K_PART_HEADER*)( pBuffer->m_pBuffer + pBuffer->m_nLength ); if ( ! m_pDiskFile->Read( m_nFileBase + m_nOffset + m_nPosition, &pHeader[1], nChunk, &nChunk ) ) return FALSE; // SetFilePointer( hFile, m_nFileBase + m_nOffset + m_nPosition, NULL, FILE_BEGIN ); // ReadFile( hFile, &pHeader[1], nChunk, &nChunk, NULL ); if ( nChunk == 0 ) return FALSE; pHeader->nProtocol = ED2K_PROTOCOL_EDONKEY; pHeader->nType = ED2K_C2C_SENDINGPART; pHeader->nLength = 1 + sizeof(MD4) + 8 + (DWORD)nChunk; pHeader->pMD4 = m_pED2K; pHeader->nOffset1 = (DWORD)( m_nOffset + m_nPosition ); pHeader->nOffset2 = (DWORD)( m_nOffset + m_nPosition + nChunk ); pBuffer->m_nLength += sizeof(ED2K_PART_HEADER) + (DWORD)nChunk; m_pClient->Send( NULL ); #endif m_nPosition += nChunk; m_nUploaded += nChunk; Statistics.Current.Uploads.Volume += ( nChunk / 1024 ); return TRUE; }
bool SyncCommand::HandleRegistryKey(const CString& regname, CSimpleIni& iniFile, bool bCloudIsNewer) { CAutoRegKey hKey; CAutoRegKey hKeyKey; DWORD regtype = 0; DWORD regsize = 0; CString sKeyPath = L"Software"; CString sValuePath = regname; CString sIniKeyName = regname; CString sRegname = regname; CString sValue; bool bHaveChanges = false; if (regname.Find('\\') >= 0) { // handle values in sub-keys sKeyPath = L"Software\\" + regname.Left(regname.ReverseFind('\\')); sValuePath = regname.Mid(regname.ReverseFind('\\') + 1); } if (RegOpenKeyEx(HKEY_CURRENT_USER, sKeyPath, 0, KEY_READ, hKey.GetPointer()) == ERROR_SUCCESS) { bool bEnum = false; bool bEnumKeys = false; int index = 0; int keyindex = 0; // an asterisk means: use all values inside the specified key if (sValuePath == L"*") bEnum = true; if (sValuePath == L"**") { bEnumKeys = true; bEnum = true; RegOpenKeyEx(HKEY_CURRENT_USER, sKeyPath, 0, KEY_READ, hKeyKey.GetPointer()); } do { if (bEnumKeys) { bEnum = true; index = 0; wchar_t cKeyName[MAX_PATH] = { 0 }; DWORD cLen = _countof(cKeyName); if (RegEnumKeyEx(hKeyKey, keyindex, cKeyName, &cLen, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) { bEnumKeys = false; break; } ++keyindex; sKeyPath = L"Software\\" + regname.Left(regname.ReverseFind('\\')) + L"\\" + cKeyName + L"\\"; sRegname = regname.Left(regname.ReverseFind('\\')) + L"\\" + cKeyName + L"\\"; hKey.CloseHandle(); if (RegOpenKeyEx(HKEY_CURRENT_USER, sKeyPath, 0, KEY_READ, hKey.GetPointer()) != ERROR_SUCCESS) { bEnumKeys = false; break; } } do { if (bEnum) { // start enumerating all values wchar_t cValueName[MAX_PATH] = { 0 }; DWORD cLen = _countof(cValueName); if (RegEnumValue(hKey, index, cValueName, &cLen, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) { bEnum = false; break; } ++index; sValuePath = cValueName; CString sValueLower = sValuePath; sValueLower.MakeLower(); bool bIgnore = false; for (const auto& ignore : regBlockArray) { if (wcswildcmp(ignore, sValueLower)) { bIgnore = true; break; } } if (bIgnore) continue; sIniKeyName = sRegname.Left(sRegname.ReverseFind('\\')); if (sIniKeyName.IsEmpty()) sIniKeyName = sValuePath; else sIniKeyName += L"\\" + sValuePath; } if (RegQueryValueEx(hKey, sValuePath, NULL, ®type, NULL, ®size) == ERROR_SUCCESS) { if (regtype != 0) { auto regbuf = std::make_unique<BYTE[]>(regsize); if (RegQueryValueEx(hKey, sValuePath, NULL, ®type, regbuf.get(), ®size) == ERROR_SUCCESS) { switch (regtype) { case REG_DWORD: { DWORD value = *(DWORD*)regbuf.get(); sValue = iniFile.GetValue(L"registry_dword", sIniKeyName); DWORD nValue = DWORD(_wtol(sValue)); if (nValue != value) { if (bCloudIsNewer) { RegSetValueEx(hKey, sValuePath, NULL, regtype, (BYTE *)&nValue, sizeof(nValue)); } else { bHaveChanges = true; sValue.Format(L"%lu", value); iniFile.SetValue(L"registry_dword", sIniKeyName, sValue); } } if (bCloudIsNewer) iniFile.Delete(L"registry_dword", sIniKeyName); } break; case REG_QWORD: { QWORD value = *(QWORD*)regbuf.get(); sValue = iniFile.GetValue(L"registry_qword", sIniKeyName); QWORD nValue = QWORD(_wtoi64(sValue)); if (nValue != value) { if (bCloudIsNewer) { RegSetValueEx(hKey, sValuePath, NULL, regtype, (BYTE *)&nValue, sizeof(nValue)); } else { bHaveChanges = true; sValue.Format(L"%I64d", value); iniFile.SetValue(L"registry_qword", sIniKeyName, sValue); } } if (bCloudIsNewer) iniFile.Delete(L"registry_qword", sIniKeyName); } break; case REG_EXPAND_SZ: case REG_MULTI_SZ: case REG_SZ: { sValue = (LPCWSTR)regbuf.get(); CString iniValue = iniFile.GetValue(L"registry_string", sIniKeyName); if (iniValue != sValue) { if (bCloudIsNewer) { RegSetValueEx(hKey, sValuePath, NULL, regtype, (BYTE *)(LPCWSTR)iniValue, (iniValue.GetLength() + 1)*sizeof(WCHAR)); } else { bHaveChanges = true; iniFile.SetValue(L"registry_string", sIniKeyName, sValue); } } if (bCloudIsNewer) iniFile.Delete(L"registry_string", sIniKeyName); } break; } } } } } while (bEnum); } while (bEnumKeys); } return bHaveChanges; }
BOOL CLocalSearch::AddHitG1(CLibraryFile* pFile, int nIndex) { // Check that the file is actually available. (We must not return ghost hits to G1!) if ( ! pFile->IsAvailable() ) return FALSE; // Check that a queue that can upload this file exists, and isn't insanely long. if ( UploadQueues.QueueRank( PROTOCOL_HTTP, pFile ) > Settings.Gnutella1.HitQueueLimit ) return FALSE; // Normally this isn't a problem- the default queue length is 8 to 10, so this check (50) will // never be activated. However, sometimes users configure bad settings, such as a 2000 user HTTP // queue. Although the remote client could/should handle this by itself, we really should give // Gnutella some protection against 'extreme' settings (if only to reduce un-necessary traffic.) m_pPacket->WriteLongLE( pFile->m_nIndex ); m_pPacket->WriteLongLE( (DWORD)min( pFile->GetSize(), QWORD(0xFFFFFFFF) ) ); if ( Settings.Gnutella1.QueryHitUTF8 ) //Support UTF-8 Query { m_pPacket->WriteStringUTF8( pFile->m_sName ); } else { m_pPacket->WriteString( pFile->m_sName ); } if ( pFile->m_bSHA1 ) { CString strHash = CSHA::HashToString( &pFile->m_pSHA1, TRUE ); m_pPacket->WriteString( strHash ); /* CGGEPBlock pBlock; CGGEPItem* pItem = pBlock.Add( _T("H") ); pItem->WriteByte( 1 ); pItem->Write( &pFile->m_pSHA1, 20 ); pBlock.Write( m_pPacket ); m_pPacket->WriteByte( 0 ); */ } else if ( pFile->m_bTiger ) { CString strHash = CTigerNode::HashToString( &pFile->m_pTiger, TRUE ); m_pPacket->WriteString( strHash ); } else if ( pFile->m_bED2K ) { CString strHash = CED2K::HashToString( &pFile->m_pED2K, TRUE ); m_pPacket->WriteString( strHash ); } else { m_pPacket->WriteByte( 0 ); } if ( pFile->m_pSchema != NULL && pFile->m_pMetadata != NULL && ( m_pSearch == NULL || m_pSearch->m_bWantXML ) ) { AddMetadata( pFile->m_pSchema, pFile->m_pMetadata, nIndex ); } return TRUE; }
bool CDownloadTransferED2K::SendFragmentRequests() { ASSUME_LOCK( Transfers.m_pSection ); ASSERT( m_pClient != NULL ); if ( m_nState != dtsDownloading ) return TRUE; if ( m_oRequested.size() >= (int)Settings.eDonkey.RequestPipe ) return TRUE; Fragments::List oPossible( m_pDownload->GetEmptyFragmentList() ); if ( ! m_pClient->m_bEmLargeFile && ( m_pDownload->m_nSize & 0xffffffff00000000 ) ) { Fragments::Fragment Selected( 0x100000000, m_pDownload->m_nSize - 1 ); oPossible.erase( Selected ); } if ( ! m_pDownload->m_bTorrentEndgame ) { for ( CDownloadTransfer* pTransfer = m_pDownload->GetFirstTransfer() ; pTransfer && ! oPossible.empty() ; pTransfer = pTransfer->m_pDlNext ) { pTransfer->SubtractRequested( oPossible ); } } typedef std::map< QWORD, Fragments::Fragment > _TRequest; typedef _TRequest::iterator _TRequestIndex; _TRequest oRequesting; while ( m_oRequested.size() < (int)Settings.eDonkey.RequestPipe ) { QWORD nOffset, nLength; if ( SelectFragment( oPossible, nOffset, nLength, m_pDownload->m_bTorrentEndgame ) ) { ChunkifyRequest( &nOffset, &nLength, Settings.eDonkey.RequestSize, FALSE ); Fragments::Fragment Selected( nOffset, nOffset + nLength ); oPossible.erase( Selected ); m_oRequested.push_back( Selected ); oRequesting.insert( _TRequest::value_type(nOffset, Selected) ); } else { break; } } while ( ! oRequesting.empty() ) { DWORD nCount = 0; QWORD nOffsetBegin[3] = {0,0,0}, nOffsetEnd[3] = {0,0,0}; bool bI64Offset = false; while ( nCount < 3 && ! oRequesting.empty() ) { _TRequestIndex iIndex = oRequesting.begin(); nOffsetBegin[nCount] = QWORD((*iIndex).second.begin()); nOffsetEnd[nCount] = QWORD((*iIndex).second.end()); bI64Offset |= ( ( ( nOffsetBegin[nCount] & 0xffffffff00000000 ) ) || ( ( nOffsetEnd[nCount] & 0xffffffff00000000 ) ) ); oRequesting.erase(iIndex); nCount++; } if ( bI64Offset ) { CEDPacket* pPacket = CEDPacket::New( ED2K_C2C_REQUESTPARTS, ED2K_PROTOCOL_EMULE ); pPacket->Write( m_pDownload->m_oED2K ); // This commented-out code is for BigEndian, only needed when ported to different platform. //pPacket->WriteLongLE( (DWORD)( nOffsetBegin[0] & 0x00000000ffffffff ) ); //pPacket->WriteLongLE( (DWORD)( ( nOffsetBegin[0] & 0xffffffff00000000 ) >> 32 ) ); //pPacket->WriteLongLE( (DWORD)( nOffsetBegin[1] & 0x00000000ffffffff ) ); //pPacket->WriteLongLE( (DWORD)( ( nOffsetBegin[1] & 0xffffffff00000000 ) >> 32 ) ); //pPacket->WriteLongLE( (DWORD)( nOffsetBegin[2] & 0x00000000ffffffff ) ); //pPacket->WriteLongLE( (DWORD)( ( nOffsetBegin[2] & 0xffffffff00000000 ) >> 32 ) ); //pPacket->WriteLongLE( (DWORD)( nOffsetEnd[0] & 0x00000000ffffffff ) ); //pPacket->WriteLongLE( (DWORD)( ( nOffsetEnd[0] & 0xffffffff00000000 ) >> 32 ) ); //pPacket->WriteLongLE( (DWORD)( nOffsetEnd[1] & 0x00000000ffffffff ) ); //pPacket->WriteLongLE( (DWORD)( ( nOffsetEnd[1] & 0xffffffff00000000 ) >> 32 ) ); //pPacket->WriteLongLE( (DWORD)( nOffsetEnd[2] & 0x00000000ffffffff ) ); //pPacket->WriteLongLE( (DWORD)( ( nOffsetEnd[2] & 0xffffffff00000000 ) >> 32 ) ); // If little Endian, no need to use above code pPacket->Write( &nOffsetBegin[0], 8 ); pPacket->Write( &nOffsetBegin[1], 8 ); pPacket->Write( &nOffsetBegin[2], 8 ); pPacket->Write( &nOffsetEnd[0], 8 ); pPacket->Write( &nOffsetEnd[1], 8 ); pPacket->Write( &nOffsetEnd[2], 8 ); Send( pPacket ); } else { CEDPacket* pPacket = CEDPacket::New( ED2K_C2C_REQUESTPARTS ); pPacket->Write( m_pDownload->m_oED2K ); // This commented-out code is for BigEndian, only needed when ported to different platform. //pPacket->WriteLongLE( (DWORD)( nOffsetBegin[0] & 0x00000000ffffffff ) ); //pPacket->WriteLongLE( (DWORD)( nOffsetBegin[1] & 0x00000000ffffffff ) ); //pPacket->WriteLongLE( (DWORD)( nOffsetBegin[2] & 0x00000000ffffffff ) ); //pPacket->WriteLongLE( (DWORD)( nOffsetEnd[0] & 0x00000000ffffffff ) ); //pPacket->WriteLongLE( (DWORD)( nOffsetEnd[1] & 0x00000000ffffffff ) ); //pPacket->WriteLongLE( (DWORD)( nOffsetEnd[2] & 0x00000000ffffffff ) ); pPacket->Write( &nOffsetBegin[0], 4 ); pPacket->Write( &nOffsetBegin[1], 4 ); pPacket->Write( &nOffsetBegin[2], 4 ); pPacket->Write( &nOffsetEnd[0], 4 ); pPacket->Write( &nOffsetEnd[1], 4 ); pPacket->Write( &nOffsetEnd[2], 4 ); Send( pPacket ); } while ( nCount-- ) { int nType = ( m_nDownloaded == 0 || ( nOffsetBegin[nCount] % ED2K_PART_SIZE ) == 0 ) ? MSG_INFO : MSG_DEBUG; theApp.Message( (WORD)nType, IDS_DOWNLOAD_FRAGMENT_REQUEST, nOffsetBegin[nCount], nOffsetEnd[nCount], (LPCTSTR)m_pDownload->GetDisplayName(), (LPCTSTR)m_sAddress ); } } // If there are no more possible chunks to request, and endgame is available but not active if ( oPossible.empty() && Settings.eDonkey.Endgame && ! m_pDownload->m_bTorrentEndgame ) { // And the file is at least 100MB, with less than 1MB to go if ( ( m_pDownload->GetVolumeComplete() > 100*1024*1024 ) && ( m_pDownload->GetVolumeRemaining() < 1*1024*1024 ) ) { // Then activate endgame m_pDownload->m_bTorrentEndgame = true; theApp.Message( MSG_DEBUG, _T("Activating endgame for ed2k transfer %s"), m_pDownload->m_sName ); } } if ( ! m_oRequested.empty() ) return true; Send( CEDPacket::New( ED2K_C2C_QUEUERELEASE ) ); theApp.Message( MSG_INFO, IDS_DOWNLOAD_FRAGMENT_END, (LPCTSTR)m_sAddress ); Close( TRI_TRUE ); return false; }
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 CDownloadWithTiger::FinishValidation() { FF::SimpleFragmentList oCorrupted( m_nSize ); if ( m_nVerifyHash == HASH_TIGERTREE ) { if ( m_pTigerTree.FinishBlockTest( m_nVerifyBlock ) ) { m_pTigerBlock[ m_nVerifyBlock ] = TS_TRUE; m_nTigerSuccess ++; } else { m_pTigerBlock[ m_nVerifyBlock ] = TS_FALSE; QWORD nOffset = QWORD(m_nVerifyBlock) * QWORD(m_nTigerSize); oCorrupted.insert( oCorrupted.end(), FF::SimpleFragment( nOffset, ::std::min( nOffset + m_nTigerSize, m_nSize ) ) ); } } else if ( m_nVerifyHash == HASH_ED2K ) { if ( m_pHashset.FinishBlockTest( m_nVerifyBlock ) ) { m_pHashsetBlock[ m_nVerifyBlock ] = TS_TRUE; m_nHashsetSuccess ++; } else { m_pHashsetBlock[ m_nVerifyBlock ] = TS_FALSE; QWORD nOffset = QWORD(m_nVerifyBlock) * QWORD(ED2K_PART_SIZE); oCorrupted.insert( oCorrupted.end(), FF::SimpleFragment( nOffset, ::std::min( nOffset + ED2K_PART_SIZE, m_nSize ) ) ); } } else if ( m_nVerifyHash == HASH_TORRENT ) { if ( m_pTorrent.FinishBlockTest( m_nVerifyBlock ) ) { m_pTorrentBlock[ m_nVerifyBlock ] = TS_TRUE; m_nTorrentSuccess ++; OnFinishedTorrentBlock( m_nVerifyBlock ); } else { m_pTorrentBlock[ m_nVerifyBlock ] = TS_FALSE; QWORD nOffset = QWORD(m_nVerifyBlock) * QWORD(m_nTorrentSize); oCorrupted.insert( oCorrupted.end(), FF::SimpleFragment( nOffset, ::std::min( nOffset + m_nTorrentSize, m_nSize ) ) ); } } if ( !oCorrupted.empty() && m_pFile != NULL ) { if ( m_pTigerBlock != NULL ) SubtractHelper( oCorrupted, m_pTigerBlock, m_nTigerBlock, m_nTigerSize ); if ( m_pHashsetBlock != NULL ) SubtractHelper( oCorrupted, m_pHashsetBlock, m_nHashsetBlock, ED2K_PART_SIZE ); if ( m_pTorrentBlock != NULL ) SubtractHelper( oCorrupted, m_pTorrentBlock, m_nTorrentBlock, m_nTorrentSize ); for ( FF::SimpleFragmentList::ConstIterator pRange = oCorrupted.begin(); pRange != oCorrupted.end(); ++pRange ) { m_pFile->InvalidateRange( pRange->begin(), pRange->length() ); RemoveOverlappingSources( pRange->begin(), pRange->length() ); } } m_nVerifyHash = HASH_NULL; m_nVerifyBlock = 0xFFFFFFFF; m_nVerifyCookie++; SetModified(); }