Сообщение от
SAM style
Да, сфэйлил. Опытным путём проверил - даже 2 разных объекта не одновременно выполняют слоты.
Распараллеливание эмуляции не такая простая задача, как кажется.
Единственная идея была- все влияющие на звукогенерацию выводы в порт ставить в очередь вместе с временнОй меткой и рендерить либо в конце фрейма (для однопоточного режима) либо по мере поступления (для двухпоточного, но возможны затраты на синхронизацию).
Например, вот как делается рендеринг AY в ZXTune.
На вывод в порт зовется метод:
Код:
virtual void RenderData(const DataChunk& src)
{
BufferedData.Add(src);
}
Т.е. ничего не делаем, просто ставим в очередь.
Когда у нас конец фрейма, можно проанализировать очередь и выбросить всякие левые устройства (например, не было вывода в порт ковокса, нафига его микшировать?). Потом просто все элементы очереди обрабатываются:
Код:
void RenderChunks(Renderer& render)
{
for (const DataChunk* it = BufferedData.GetBegin(), *lim = BufferedData.GetEnd(); it != lim; ++it)
{
RenderSingleChunk(*it, render);
}
BufferedData.Reset();
}
где
Код:
void RenderSingleChunk(const DataChunk& src, Renderer& render)
{
render.SetNewData(src);
if (!Clock.HasOutputBefore(src.TimeStamp))
{
return;
}
Clock.SetFrameEnd(src.TimeStamp);
MultiSample result;
while (const uint_t toEnd = Clock.GetTicksToFrameEnd())
{
const uint_t toSound = Clock.GetTicksToSample();
const uint_t toTick = 1 + std::min(toSound, toEnd);
render.Tick(toTick);
if (Clock.Tick(toTick))
{
render.GetLevels(result);
Target->ApplyData(result);
}
}