Skip to content

Commit

Permalink
[win32] implement resampling via IMFTransform (#85)
Browse files Browse the repository at this point in the history
* [win32] implement resampling via IMFTransform

This implements resampling with mix format WASAPI shared mode stream
uses via IMFTransform. Additionally, this contains fixes of render audio
thread crash due to buffer size difference.

* [win32] add MFSTARTUP_NOSOCKET to remove redundant initialization

* [docs] updates menu document

This contains following changes
* multi-channels audio ssource can load but differ playing by OS
* add play with audio source behavior note
  • Loading branch information
hkrn authored Oct 21, 2021
1 parent 1ab2b7a commit 45e3e7b
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 73 deletions.
20 changes: 16 additions & 4 deletions docs/menu.rst
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,11 @@ MikuMikuMoving が採用しているモーフ変形が追加された拡張形

音源をプロジェクトに読み込みます。

.. note::
プロジェクトに読み込める音源はひとつまでです。別の音源を読み込んだ場合以前の音源を削除してから読み込まれます
.. caution::
プロジェクトに読み込める音源はひとつまでです。別の音源を読み込んだ場合すでに利用している音源を削除してから読み込まれます

5.1ch または 7.1ch のマルチチャンネルを持つ音源も読み込むことは出来ますがその場合はフロントの左右のみ再生されます。
マルチチャンネルをすべて再生させたい場合は音源をステレオに合成する形で変換してください
.. note::
5.1ch や 7.1ch などのマルチチャンネルを持つ音源も読み込み可能ですが再生処理は利用している OS 及び再生デバイスに依存します

読み込み可能な音源ファイルは nanoem 自体のバージョン及び中に含まれるコーデックによって異なるため、実際に読み込みできるかを必ず確認してください。

Expand Down Expand Up @@ -841,6 +841,18 @@ OS に組み込まれているエンコーダを利用します。プラグイ
再生
==========================================

.. important::
音源が含まれている場合は再生デバイスの構成変更により再生中の挙動が変わります。構成変更の検知は OS の仕組みを利用するため場合によっては検知できないことがあります。また、この挙動を設定から変更することはできません。

* 新しい再生デバイス追加を検知した場合は再生を一時停止し、再生デバイスを変更してから再開して再生を続けます

* 例えばイヤフォンをイヤフォンジャックに差し込んだ場合が該当します

* 再生デバイスの離脱を検知した場合は再生を一時停止しますが、再生デバイスを変更した後の再開を行いません

* 例えばイヤフォンがイヤフォンジャックから外れて別の再生デバイスに切り替わる場合が該当します
* これについては別の再生デバイスで再生される際の時の意図しない音漏れを防ぐためです

現在のフレーム位置からプロジェクトを再生します。

停止(再生中の場合は「再開」)
Expand Down
2 changes: 1 addition & 1 deletion win32/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ if(TARGET sokol_glcore33)
endif()
nanoem_emapp_link_executable(${NANOEM_EXECUTABLE_NAME})

set(win32_api_libraries psapi winhttp shlwapi d3d11 dxgi dxguid mf mfplat mfreadwrite mfuuid evr pdh gdi32 shell32 comdlg32)
set(win32_api_libraries psapi winhttp shlwapi d3d11 dxgi dxguid mf mfplat mfreadwrite mfuuid evr pdh gdi32 shell32 comdlg32 wmcodecdspuuid)
target_link_libraries(${NANOEM_EXECUTABLE_NAME} ${win32_api_libraries})
target_include_directories(${NANOEM_EXECUTABLE_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include ${PROJECT_BINARY_DIR}/emapp/resources/include)
if(NANOEM_GA_TRACKING_ID)
Expand Down
9 changes: 6 additions & 3 deletions win32/include/WASAPIAudioPlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,13 @@ class WASAPIAudioPlayer : public BaseAudioPlayer {
void internalTransitStatePaused(Error &error) override;
void internalTransitStateResumed(Error &error) override;
void internalTransitStateStopped(Error &error) override;
bool initializeClient(IMMDevice *device, const WAVDescription &desc, Error &error);
bool initializeClient(IMMDevice *device, Error &error);
void destroyClient();
void resampleAllLinearPCMSamples(const nanoem_u8_t *data, size_t size, const WAVEFORMATEX *format, Error &error);
void createAudioRenderThread();
void createNullRenderThread();
void renderAudioBuffer(uint32_t numPaddingPackets, bool enableOffset);
void renderNullBuffer(uint32_t numPaddingPackets, bool enableOffset);
void renderAudioBuffer(nanoem_rsize_t bytesPerPacket, uint32_t numAvailablePackets, bool enableOffset);
void renderNullBuffer(nanoem_rsize_t bytesPerPacket, uint32_t numAvailablePackets, bool enableOffset);
void destroyRenderThread();

IEventPublisher *m_eventPublisher = nullptr;
Expand All @@ -98,6 +99,8 @@ class WASAPIAudioPlayer : public BaseAudioPlayer {
AudioSessionEventsHandler m_audioSessionEventsHandler;
NotificationClient m_notificationClient;
Clock m_clock;
ByteArray m_resampledAudioSamples;
WAVEFORMATEX m_nativeOutputDescription = {};
std::atomic<uint64_t> m_offset = 0;
std::atomic<uint64_t> m_numProceededPackets = 0;
std::atomic<RequestState> m_requestState = kRequestStateNone;
Expand Down
3 changes: 2 additions & 1 deletion win32/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ runMain(HINSTANCE hInstance, int argc, const char *const *argv)
Allocator::initialize();
ThreadedApplicationService::setup();
int exitCode = -1;
if (!FAILED(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED)) && !FAILED(MFStartup(MF_VERSION))) {
if (!FAILED(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED)) &&
!FAILED(MFStartup(MF_VERSION, MFSTARTUP_NOSOCKET))) {
GetModuleFileNameW(GetInstanceModule(hInstance), executablePath, ARRAYSIZE(executablePath));
exitCode = runApplication(hInstance, argc, argv, executablePath);
}
Expand Down
Loading

0 comments on commit 45e3e7b

Please sign in to comment.