mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-26 07:35:41 +00:00
Qt: Implement audio output
This commit is contained in:
parent
207c75e6eb
commit
1b7be01507
|
@ -123,6 +123,18 @@ void AudioStream::EndWrite(u32 num_samples)
|
||||||
m_buffer_mutex.unlock();
|
m_buffer_mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 AudioStream::GetSamplesAvailable() const
|
||||||
|
{
|
||||||
|
// TODO: Use atomic loads
|
||||||
|
u32 available_buffers;
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(m_buffer_mutex);
|
||||||
|
available_buffers = m_num_available_buffers;
|
||||||
|
}
|
||||||
|
|
||||||
|
return available_buffers * m_buffer_size;
|
||||||
|
}
|
||||||
|
|
||||||
u32 AudioStream::ReadSamples(SampleType* samples, u32 num_samples)
|
u32 AudioStream::ReadSamples(SampleType* samples, u32 num_samples)
|
||||||
{
|
{
|
||||||
u32 remaining_samples = num_samples;
|
u32 remaining_samples = num_samples;
|
||||||
|
|
|
@ -49,6 +49,7 @@ protected:
|
||||||
|
|
||||||
bool IsDeviceOpen() const { return (m_output_sample_rate > 0); }
|
bool IsDeviceOpen() const { return (m_output_sample_rate > 0); }
|
||||||
|
|
||||||
|
u32 GetSamplesAvailable() const;
|
||||||
u32 ReadSamples(SampleType* samples, u32 num_samples);
|
u32 ReadSamples(SampleType* samples, u32 num_samples);
|
||||||
|
|
||||||
void DropBuffer();
|
void DropBuffer();
|
||||||
|
@ -69,7 +70,7 @@ private:
|
||||||
void EnsureBuffer();
|
void EnsureBuffer();
|
||||||
|
|
||||||
std::vector<Buffer> m_buffers;
|
std::vector<Buffer> m_buffers;
|
||||||
std::mutex m_buffer_mutex;
|
mutable std::mutex m_buffer_mutex;
|
||||||
|
|
||||||
// For input.
|
// For input.
|
||||||
u32 m_first_free_buffer = 0;
|
u32 m_first_free_buffer = 0;
|
||||||
|
|
|
@ -53,6 +53,14 @@ public:
|
||||||
protected:
|
protected:
|
||||||
using ThrottleClock = std::chrono::steady_clock;
|
using ThrottleClock = std::chrono::steady_clock;
|
||||||
|
|
||||||
|
enum : u32
|
||||||
|
{
|
||||||
|
AUDIO_SAMPLE_RATE = 44100,
|
||||||
|
AUDIO_CHANNELS = 2,
|
||||||
|
AUDIO_BUFFER_SIZE = 2048,
|
||||||
|
AUDIO_BUFFERS = 2
|
||||||
|
};
|
||||||
|
|
||||||
struct OSDMessage
|
struct OSDMessage
|
||||||
{
|
{
|
||||||
std::string text;
|
std::string text;
|
||||||
|
|
|
@ -24,6 +24,8 @@ add_executable(duckstation-qt
|
||||||
opengldisplaywindow.h
|
opengldisplaywindow.h
|
||||||
portsettingswidget.cpp
|
portsettingswidget.cpp
|
||||||
portsettingswidget.h
|
portsettingswidget.h
|
||||||
|
qtaudiostream.cpp
|
||||||
|
qtaudiostream.h
|
||||||
qtdisplaywindow.cpp
|
qtdisplaywindow.cpp
|
||||||
qtdisplaywindow.h
|
qtdisplaywindow.h
|
||||||
qthostinterface.cpp
|
qthostinterface.cpp
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
<ClCompile Include="gpusettingswidget.cpp" />
|
<ClCompile Include="gpusettingswidget.cpp" />
|
||||||
<ClCompile Include="hotkeysettingswidget.cpp" />
|
<ClCompile Include="hotkeysettingswidget.cpp" />
|
||||||
<ClCompile Include="inputbindingwidgets.cpp" />
|
<ClCompile Include="inputbindingwidgets.cpp" />
|
||||||
|
<ClCompile Include="qtaudiostream.cpp" />
|
||||||
<ClCompile Include="qtdisplaywindow.cpp" />
|
<ClCompile Include="qtdisplaywindow.cpp" />
|
||||||
<ClCompile Include="gamelistsettingswidget.cpp" />
|
<ClCompile Include="gamelistsettingswidget.cpp" />
|
||||||
<ClCompile Include="gamelistwidget.cpp" />
|
<ClCompile Include="gamelistwidget.cpp" />
|
||||||
|
@ -57,6 +58,7 @@
|
||||||
<QtMoc Include="gpusettingswidget.h" />
|
<QtMoc Include="gpusettingswidget.h" />
|
||||||
<QtMoc Include="hotkeysettingswidget.h" />
|
<QtMoc Include="hotkeysettingswidget.h" />
|
||||||
<QtMoc Include="inputbindingwidgets.h" />
|
<QtMoc Include="inputbindingwidgets.h" />
|
||||||
|
<ClInclude Include="qtaudiostream.h" />
|
||||||
<ClInclude Include="settingwidgetbinder.h" />
|
<ClInclude Include="settingwidgetbinder.h" />
|
||||||
<QtMoc Include="consolesettingswidget.h" />
|
<QtMoc Include="consolesettingswidget.h" />
|
||||||
<QtMoc Include="gamelistsettingswidget.h" />
|
<QtMoc Include="gamelistsettingswidget.h" />
|
||||||
|
@ -281,7 +283,7 @@
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)dep\msvc\lib32-debug;$(SolutionDir)dep\msvc\qt5-x86\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>$(SolutionDir)dep\msvc\lib32-debug;$(SolutionDir)dep\msvc\qt5-x86\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<AdditionalDependencies>Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;Qt5Multimediad.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
@ -302,7 +304,7 @@
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)dep\msvc\lib64-debug;$(SolutionDir)dep\msvc\qt5-x64\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>$(SolutionDir)dep\msvc\lib64-debug;$(SolutionDir)dep\msvc\qt5-x64\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<AdditionalDependencies>Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;Qt5Multimediad.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'">
|
||||||
|
@ -325,7 +327,7 @@
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)dep\msvc\lib32-debug;$(SolutionDir)dep\msvc\qt5-x86\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>$(SolutionDir)dep\msvc\lib32-debug;$(SolutionDir)dep\msvc\qt5-x86\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<AdditionalDependencies>Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;Qt5Multimediad.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'">
|
||||||
|
@ -348,7 +350,7 @@
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)dep\msvc\lib64-debug;$(SolutionDir)dep\msvc\qt5-x64\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>$(SolutionDir)dep\msvc\lib64-debug;$(SolutionDir)dep\msvc\qt5-x64\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<AdditionalDependencies>Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;Qt5Multimediad.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
@ -370,7 +372,7 @@
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)dep\msvc\lib32;$(SolutionDir)dep\msvc\qt5-x86\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>$(SolutionDir)dep\msvc\lib32;$(SolutionDir)dep\msvc\qt5-x86\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<AdditionalDependencies>Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;Qt5Multimedia.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseLTCG|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseLTCG|Win32'">
|
||||||
|
@ -393,7 +395,7 @@
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)dep\msvc\lib32;$(SolutionDir)dep\msvc\qt5-x86\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>$(SolutionDir)dep\msvc\lib32;$(SolutionDir)dep\msvc\qt5-x86\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<AdditionalDependencies>Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;Qt5Multimedia.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
|
@ -416,7 +418,7 @@
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)dep\msvc\lib64;$(SolutionDir)dep\msvc\qt5-x64\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>$(SolutionDir)dep\msvc\lib64;$(SolutionDir)dep\msvc\qt5-x64\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<AdditionalDependencies>Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;Qt5Multimedia.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseLTCG|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseLTCG|x64'">
|
||||||
|
@ -439,7 +441,7 @@
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)dep\msvc\lib64;$(SolutionDir)dep\msvc\qt5-x64\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>$(SolutionDir)dep\msvc\lib64;$(SolutionDir)dep\msvc\qt5-x64\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<AdditionalDependencies>Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;Qt5Multimedia.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
|
|
|
@ -27,13 +27,15 @@
|
||||||
<ClCompile Include="$(IntDir)moc_gpusettingswidget.cpp" />
|
<ClCompile Include="$(IntDir)moc_gpusettingswidget.cpp" />
|
||||||
<ClCompile Include="inputbindingwidgets.cpp" />
|
<ClCompile Include="inputbindingwidgets.cpp" />
|
||||||
<ClCompile Include="hotkeysettingswidget.cpp" />
|
<ClCompile Include="hotkeysettingswidget.cpp" />
|
||||||
|
<ClCompile Include="$(IntDir)moc_hotkeysettingswidget.cpp" />
|
||||||
|
<ClCompile Include="$(IntDir)moc_inputbindingwidgets.cpp" />
|
||||||
|
<ClCompile Include="qtaudiostream.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="qtsettingsinterface.h" />
|
<ClInclude Include="qtsettingsinterface.h" />
|
||||||
<ClInclude Include="qtutils.h" />
|
<ClInclude Include="qtutils.h" />
|
||||||
<ClInclude Include="settingwidgetbinder.h" />
|
<ClInclude Include="settingwidgetbinder.h" />
|
||||||
<ClInclude Include="inputbindingwidgets.h" />
|
<ClInclude Include="qtaudiostream.h" />
|
||||||
<ClInclude Include="hotkeysettingswidget.h" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="resources">
|
<Filter Include="resources">
|
||||||
|
@ -54,6 +56,8 @@
|
||||||
<QtMoc Include="portsettingswidget.h" />
|
<QtMoc Include="portsettingswidget.h" />
|
||||||
<QtMoc Include="qtdisplaywindow.h" />
|
<QtMoc Include="qtdisplaywindow.h" />
|
||||||
<QtMoc Include="gpusettingswidget.h" />
|
<QtMoc Include="gpusettingswidget.h" />
|
||||||
|
<QtMoc Include="hotkeysettingswidget.h" />
|
||||||
|
<QtMoc Include="inputbindingwidgets.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<QtUi Include="consolesettingswidget.ui" />
|
<QtUi Include="consolesettingswidget.ui" />
|
||||||
|
|
84
src/duckstation-qt/qtaudiostream.cpp
Normal file
84
src/duckstation-qt/qtaudiostream.cpp
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
#include "qtaudiostream.h"
|
||||||
|
#include <QtCore/QDebug>
|
||||||
|
#include <QtMultimedia/QAudioOutput>
|
||||||
|
|
||||||
|
QtAudioStream::QtAudioStream()
|
||||||
|
{
|
||||||
|
QIODevice::open(QIODevice::ReadOnly);
|
||||||
|
}
|
||||||
|
|
||||||
|
QtAudioStream::~QtAudioStream() = default;
|
||||||
|
|
||||||
|
std::unique_ptr<AudioStream> QtAudioStream::Create()
|
||||||
|
{
|
||||||
|
return std::make_unique<QtAudioStream>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QtAudioStream::OpenDevice()
|
||||||
|
{
|
||||||
|
QAudioFormat format;
|
||||||
|
format.setSampleRate(m_output_sample_rate);
|
||||||
|
format.setChannelCount(m_channels);
|
||||||
|
format.setSampleSize(sizeof(SampleType) * 8);
|
||||||
|
format.setCodec("audio/pcm");
|
||||||
|
format.setByteOrder(QAudioFormat::LittleEndian);
|
||||||
|
format.setSampleType(QAudioFormat::SignedInt);
|
||||||
|
|
||||||
|
QAudioDeviceInfo adi = QAudioDeviceInfo::defaultOutputDevice();
|
||||||
|
if (!adi.isFormatSupported(format))
|
||||||
|
{
|
||||||
|
qWarning() << "Audio format not supported by device";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_output = std::make_unique<QAudioOutput>(format);
|
||||||
|
m_output->setBufferSize(sizeof(SampleType) * m_channels * m_buffer_size);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtAudioStream::PauseDevice(bool paused)
|
||||||
|
{
|
||||||
|
if (paused)
|
||||||
|
{
|
||||||
|
m_output->stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_output->start(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtAudioStream::CloseDevice()
|
||||||
|
{
|
||||||
|
m_output.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtAudioStream::BufferAvailable() {}
|
||||||
|
|
||||||
|
bool QtAudioStream::isSequential() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 QtAudioStream::bytesAvailable() const
|
||||||
|
{
|
||||||
|
return GetSamplesAvailable() * m_channels * sizeof(SampleType);
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 QtAudioStream::readData(char* data, qint64 maxlen)
|
||||||
|
{
|
||||||
|
const u32 num_samples = static_cast<u32>(maxlen) / sizeof(SampleType) / m_channels;
|
||||||
|
const u32 read_samples = ReadSamples(reinterpret_cast<SampleType*>(data), num_samples);
|
||||||
|
const u32 silence_samples = num_samples - read_samples;
|
||||||
|
if (silence_samples > 0)
|
||||||
|
{
|
||||||
|
std::memset(reinterpret_cast<SampleType*>(data) + (read_samples * m_channels), 0,
|
||||||
|
silence_samples * m_channels * sizeof(SampleType));
|
||||||
|
}
|
||||||
|
|
||||||
|
return num_samples * m_channels * sizeof(SampleType);
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 QtAudioStream::writeData(const char* data, qint64 len)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
29
src/duckstation-qt/qtaudiostream.h
Normal file
29
src/duckstation-qt/qtaudiostream.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#pragma once
|
||||||
|
#include "common/audio_stream.h"
|
||||||
|
#include <QtCore/QIODevice>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class QAudioOutput;
|
||||||
|
|
||||||
|
class QtAudioStream final : public AudioStream, private QIODevice
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QtAudioStream();
|
||||||
|
~QtAudioStream();
|
||||||
|
|
||||||
|
static std::unique_ptr<AudioStream> Create();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool OpenDevice() override;
|
||||||
|
void PauseDevice(bool paused) override;
|
||||||
|
void CloseDevice() override;
|
||||||
|
void BufferAvailable() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isSequential() const override;
|
||||||
|
qint64 bytesAvailable() const override;
|
||||||
|
qint64 readData(char* data, qint64 maxlen) override;
|
||||||
|
qint64 writeData(const char* data, qint64 len) override;
|
||||||
|
|
||||||
|
std::unique_ptr<QAudioOutput> m_output;
|
||||||
|
};
|
|
@ -6,6 +6,7 @@
|
||||||
#include "core/game_list.h"
|
#include "core/game_list.h"
|
||||||
#include "core/gpu.h"
|
#include "core/gpu.h"
|
||||||
#include "core/system.h"
|
#include "core/system.h"
|
||||||
|
#include "qtaudiostream.h"
|
||||||
#include "qtsettingsinterface.h"
|
#include "qtsettingsinterface.h"
|
||||||
#include "qtutils.h"
|
#include "qtutils.h"
|
||||||
#include <QtCore/QCoreApplication>
|
#include <QtCore/QCoreApplication>
|
||||||
|
@ -20,6 +21,7 @@ QtHostInterface::QtHostInterface(QObject* parent)
|
||||||
checkSettings();
|
checkSettings();
|
||||||
createGameList();
|
createGameList();
|
||||||
doUpdateInputMap();
|
doUpdateInputMap();
|
||||||
|
createAudioStream();
|
||||||
createThread();
|
createThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,6 +330,8 @@ void QtHostInterface::powerOffSystem()
|
||||||
}
|
}
|
||||||
|
|
||||||
m_system.reset();
|
m_system.reset();
|
||||||
|
m_audio_stream->PauseOutput(true);
|
||||||
|
m_audio_stream->EmptyBuffers();
|
||||||
m_display_window->destroyDeviceContext();
|
m_display_window->destroyDeviceContext();
|
||||||
|
|
||||||
emit emulationStopped();
|
emit emulationStopped();
|
||||||
|
@ -359,6 +363,7 @@ void QtHostInterface::pauseSystem(bool paused)
|
||||||
}
|
}
|
||||||
|
|
||||||
m_paused = paused;
|
m_paused = paused;
|
||||||
|
m_audio_stream->PauseOutput(paused);
|
||||||
emit emulationPaused(paused);
|
emit emulationPaused(paused);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,9 +377,6 @@ void QtHostInterface::doBootSystem(QString initial_filename, QString initial_sav
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_audio_stream = NullAudioStream::Create();
|
|
||||||
m_audio_stream->Reconfigure();
|
|
||||||
|
|
||||||
std::string initial_filename_str = initial_filename.toStdString();
|
std::string initial_filename_str = initial_filename.toStdString();
|
||||||
std::string initial_save_state_filename_str = initial_save_state_filename.toStdString();
|
std::string initial_save_state_filename_str = initial_save_state_filename.toStdString();
|
||||||
if (!CreateSystem() ||
|
if (!CreateSystem() ||
|
||||||
|
@ -386,9 +388,25 @@ void QtHostInterface::doBootSystem(QString initial_filename, QString initial_sav
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_audio_stream->PauseOutput(false);
|
||||||
emit emulationStarted();
|
emit emulationStarted();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QtHostInterface::createAudioStream()
|
||||||
|
{
|
||||||
|
// Qt at least on Windows seems to want a buffer size of at least 8KB.
|
||||||
|
m_audio_stream = QtAudioStream::Create();
|
||||||
|
if (!m_audio_stream->Reconfigure(AUDIO_SAMPLE_RATE, AUDIO_CHANNELS, AUDIO_BUFFER_SIZE, 4))
|
||||||
|
{
|
||||||
|
qWarning() << "Failed to configure audio stream, falling back to null output";
|
||||||
|
|
||||||
|
// fall back to null output
|
||||||
|
m_audio_stream.reset();
|
||||||
|
m_audio_stream = NullAudioStream::Create();
|
||||||
|
m_audio_stream->Reconfigure(AUDIO_SAMPLE_RATE, AUDIO_CHANNELS, AUDIO_BUFFER_SIZE, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void QtHostInterface::createThread()
|
void QtHostInterface::createThread()
|
||||||
{
|
{
|
||||||
m_original_thread = QThread::currentThread();
|
m_original_thread = QThread::currentThread();
|
||||||
|
|
|
@ -106,6 +106,7 @@ private:
|
||||||
void updateControllerInputMap();
|
void updateControllerInputMap();
|
||||||
void updateHotkeyInputMap();
|
void updateHotkeyInputMap();
|
||||||
void addButtonToInputMap(const QString& binding, InputButtonHandler handler);
|
void addButtonToInputMap(const QString& binding, InputButtonHandler handler);
|
||||||
|
void createAudioStream();
|
||||||
void createThread();
|
void createThread();
|
||||||
void stopThread();
|
void stopThread();
|
||||||
void threadEntryPoint();
|
void threadEntryPoint();
|
||||||
|
|
|
@ -135,12 +135,12 @@ void SDLHostInterface::CreateAudioStream()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_audio_stream->Reconfigure(44100, 2))
|
if (!m_audio_stream->Reconfigure(AUDIO_SAMPLE_RATE, AUDIO_CHANNELS))
|
||||||
{
|
{
|
||||||
ReportError("Failed to recreate audio stream, falling back to null");
|
ReportError("Failed to recreate audio stream, falling back to null");
|
||||||
m_audio_stream.reset();
|
m_audio_stream.reset();
|
||||||
m_audio_stream = NullAudioStream::Create();
|
m_audio_stream = NullAudioStream::Create();
|
||||||
if (!m_audio_stream->Reconfigure(44100, 2))
|
if (!m_audio_stream->Reconfigure(AUDIO_SAMPLE_RATE, AUDIO_CHANNELS))
|
||||||
Panic("Failed to reconfigure null audio stream");
|
Panic("Failed to reconfigure null audio stream");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue