Skip to content

Commit

Permalink
Fix (or at least work around) missing messages problem
Browse files Browse the repository at this point in the history
  • Loading branch information
Psychlist1972 committed Jan 18, 2024
1 parent 8567b38 commit 8b0a833
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 60 deletions.
2 changes: 1 addition & 1 deletion build/staging/version/BundleInfo.wxi
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Include>
<?define SetupVersionName="Developer Preview 4" ?>
<?define SetupVersionNumber="1.0.24018.1804" ?>
<?define SetupVersionNumber="1.0.24018.1827" ?>
</Include>
120 changes: 61 additions & 59 deletions src/api/Libs/MidiXProc/MidiXProc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,74 +271,76 @@ CMidiXProc::SendMidiMessage(
PMEMORY_MAPPED_DATA Data = &(m_MidiOut->Data);

do{
try
// the write position is the last position we have written,
// the read position is the last position the driver has read from
ULONG writePosition = InterlockedCompareExchange((LONG*)Registers->WritePosition, 0, 0);
ULONG readPosition = InterlockedCompareExchange((LONG*)Registers->ReadPosition, 0, 0);
ULONG newWritePosition = (writePosition + requiredBufferSize) % Data->BufferSize;
ULONG bytesAvailable{ 0 };

// Calculate the available space in the buffer.
if (readPosition <= writePosition)
{
// the write position is the last position we have written,
// the read position is the last position the driver has read from
ULONG writePosition = InterlockedCompareExchange((LONG*)Registers->WritePosition, 0, 0);
ULONG readPosition = InterlockedCompareExchange((LONG*)Registers->ReadPosition, 0, 0);
ULONG newWritePosition = (writePosition + requiredBufferSize) % Data->BufferSize;
ULONG bytesAvailable{ 0 };

// Calculate the available space in the buffer.
if (readPosition <= writePosition)
bytesAvailable = Data->BufferSize - (writePosition - readPosition);
}
else
{
bytesAvailable = (readPosition - writePosition);
}

// Note, if we fill the buffer up 100%, then write position == read position,
// which is the same as when the buffer is empty and everything in the buffer
// would be lost.
// Reserve 1 byte so that when the buffer is full the write position will trail
// the read position.
// Because of this reserve, and the above calculation, the true bytesAvailable
// count can never be 0.
assert(bytesAvailable != 0);
bytesAvailable--;

// if there is sufficient space to write the buffer, send it
if (bytesAvailable >= requiredBufferSize)
{
PLOOPEDDATAFORMAT header = (PLOOPEDDATAFORMAT)(((BYTE*)Data->BufferAddress) + writePosition);

header->ByteCount = Length;
CopyMemory((((BYTE*)header) + sizeof(LOOPEDDATAFORMAT)), MidiData, Length);

// if a position provided is nonzero, use it, otherwise use the current QPC
if (Position)
{
bytesAvailable = Data->BufferSize - (writePosition - readPosition);
header->Position = Position;
}
else
else if (m_OverwriteZeroTimestamp)
{
bytesAvailable = (readPosition - writePosition);
LARGE_INTEGER qpc{ 0 };
QueryPerformanceCounter(&qpc);
header->Position = qpc.QuadPart;
}

// Note, if we fill the buffer up 100%, then write position == read position,
// which is the same as when the buffer is empty and everything in the buffer
// would be lost.
// Reserve 1 byte so that when the buffer is full the write position will trail
// the read position.
// Because of this reserve, and the above calculation, the true bytesAvailable
// count can never be 0.
assert(bytesAvailable != 0);
bytesAvailable--;

// if there is sufficient space to write the buffer, send it
if (bytesAvailable >= requiredBufferSize)
{
PLOOPEDDATAFORMAT header = (PLOOPEDDATAFORMAT)(((BYTE*)Data->BufferAddress) + writePosition);

header->ByteCount = Length;
CopyMemory((((BYTE*)header) + sizeof(LOOPEDDATAFORMAT)), MidiData, Length);

// if a position provided is nonzero, use it, otherwise use the current QPC
if (Position)
{
header->Position = Position;
}
else if (m_OverwriteZeroTimestamp)
{
LARGE_INTEGER qpc{ 0 };
QueryPerformanceCounter(&qpc);
header->Position = qpc.QuadPart;
}

// update the write position and notify the other side that data is available.
InterlockedExchange((LONG*)Registers->WritePosition, newWritePosition);
RETURN_LAST_ERROR_IF(FALSE == SetEvent(m_MidiOut->WriteEvent.get()));
// update the write position and notify the other side that data is available.
InterlockedExchange((LONG*)Registers->WritePosition, newWritePosition);
RETURN_LAST_ERROR_IF(FALSE == SetEvent(m_MidiOut->WriteEvent.get()));

//if (!SetEvent(m_MidiOut->WriteEvent.get()))
//{
// LOG_LAST_ERROR();
// RETURN_LAST_ERROR_IF(true);
//}
//if (!SetEvent(m_MidiOut->WriteEvent.get()))
//{
// LOG_LAST_ERROR();
// RETURN_LAST_ERROR_IF(true);
//}

bufferSent = TRUE;
}
else
{
// relinquish the remainder of this processing slice and try again on the next
Sleep(0);
}
bufferSent = TRUE;
}
else
{
// relinquish the remainder of this processing slice and try again on the next
//Sleep(0);

// if you remove this line, you will get additional send *and* receive failures
// if you set it to Sleep(0), you will end up with missing messages if we're
// spammed heavily
// If you set it to Sleep(1), there's more jitter, but all messages arrive.
Sleep(1);
}
CATCH_LOG();

}while (!bufferSent && --maxRetries > 0);

Expand Down

0 comments on commit 8b0a833

Please sign in to comment.