RNNoiseをOBS Studio以外でも使う

目的

Equalizer APOまたは,VSTホストとVoiceMeeterを使って,RNNoise*1によるマイクのノイズ抑制をWindows上で使う方法を紹介する.

ふだん,配信においてOBS Studio(以下,OBS)でノイズ抑制RNNoiseを使っていたが,そもそもこれはOBS使用時以外にも使えるのではないかと(今ごろ)思い,なんとか適用までに至ることができた.VSTプラグインEqualizer APOも,VSTホストとしてLight Host,VoiceMeeter Bananaも今回,初めて使用した.

OBSでのRNNoise設定画面

名称 規格 製造会社 備考
オペレーティングシステム Windows 10 Pro 64ビット,バージョン22H2 マイクロソフト インターナショナル版
配信ソフト OBS Studio 30.0.0 OBSプロジェクト 2023/11/25時点最新版
USBマイク HyperX SoloCast HP
VST Noise Suppressionプラグイン Real-time Noise Suppression Plugin 1.03 werman
イコライザーソフト Equalizer APO 1.3 Jonas Thedering
仮想ソフトウェアミキサー VoiceMeeter Banana 2.0.6.8 VB-AUDIO Software 上位機種にPotatoがある
VSTホスト Light Host 1.2.1 Rolando Islas クロスプラットフォーム

結論

まず最初に,VST Noise Suppressionプラグインをダウンロードして,C:\Program Files\VSTPluginswin-rnnoiseフォルダーごとコピーする*2

VST Noise Suppressionプラグインのダウンロード

Equalizer APOで使う

この方法では,とりあえず,該当のデバイスに適用できるため,特に考えることなくシステム全体に設定が反映できる.また,Equalizer APOはWindows起動時に自動的に裏で起動するようなので,一度設定してしまえば何も手間がかからない.

  1. Equalizer APOのインストールの最後に,Configuratorウィンドウが表示されるので,とりあえず使用するマイクのチェックを入れてCloseする
    対応デバイスのインストール(画面は既にインストール済のもの)
  2. スタートメニューからEqualizer APOのConfigurator Editorを起動する
    Equalizer APOの起動
  3. Equalizer APO起動後,警告が出るが,対応するマイクに対してインストールはしているのでNoを押す
    Equalizer APO起動時の警告画面
  4. 起動後,Device:の欄から対応するデバイス(今回はHyperX Solocast)を選ぶ
    バイス選択
  5. 緑色の+を押してPlugins→VST pluginを選択する.上部の1~3は今回使用しないので赤色の-を押して削除するか,パワーボタンを押して無効にする
    VSTプラグインの追加
  6. VST pluginの行が表示されたら,あらかじめコピーしておいたVSTプラグインのrnnoise_stereo.dllを開く
    VSTプラグインの指定
  7. この状態で,システム全体でノイズ抑制が効いた状態になる*3.Open panelをクリックすると,パラメーター設定画面が表示され,それらが調節できる.
    VST Noise Suppressionプラグイン設定完了

明示的に適用するデバイスを指定したい場合

  1. 緑色の+を押して→Control→Device (Select device)を選択する
    バイスの選択
  2. Change...→Select all devicesのアンチェックをして,使用したいデバイスを選んでOKを押す
    具体的なデバイス選択画面
  3. バイス設定の順番をノイズ抑制の前に移動し,対応するデバイスに対してのみノイズ抑制を実施するように変更
    バイス設定の適用順序変更

Light Hostを使用してVoiceMeeter Bananaで使う

VSTホストには,さまざまなものが提供されているが,Light Hostを使う.使用理由は,インストール不要で使うできるから.ほかには,Cantabile Liteが有名なもよう.

VoiceMeeter Bananaについては割愛するが,使用したいチャンネル数の違いなので,VoiceMeeterまたはVoiceMeeter Potatoでも大きな違いはないと思われる.

なお,この設定では,Equalizer APOと異なり, Light HostおよびVoiceMeeter Bananaが起動しているときのみ,ノイズ抑制が効くようになる.VoiceMeeter Bananaは,左上Menu内のRun on Windows Startupにチェックを入れることで常時起動できるが,Light Hostは常時起動させる設定がないため,別途,その設定が必要となる.

VoiceMeeter Banana側の設定

  1. HARDWARE INPUT 1にマイクを指定しておく.
    HARDWARE INPUT 1にマイクを割り当て
  2. 右上のMenu→System Settings / Options...を選択する
    VoiceMeeter Bananaでのメニュー内のシステム設定
  3. 表示されたSystem settings /Options...の画面にて,左下のPATCH INSERT欄からin1 Leftおよびin1 Rightをクリックして青い状態(挿入可能状態)にしてウィンドウを閉じる
    PATCH INSERT有効化

Light Host側の設定

  1. https://github.com/rolandoislas/LightHost/releasesから,対応するzipをダウンロードする
    Light Hostのダウンロード
  2. 任意の場所に解凍*4して,Light Host.exeを実行する.実行後,ウィンドウが立ち上がるわけではなくて,タスクバーに起動することに注意
    Light Hostはタスクバーに起動する
  3. 左クリックするとメニューが表示されるので,Preferencesを選択する
    設定メニューの選択
  4. デフォルト設定ではAudio device type:がWindows Audioで,規定のデバイスが選択されているが,すべての欄を以下の設定して閉じる*5
    Audio Settingsの変更内容
  5. 次に,Edit Pluginsを選択する
    Edit Pluginsの選択
  6. 表示されるAvailable Pluginsウィンドウ左下のOptions...を押して,Scan for new or updated VST plug-insを選択する
    VSTプラグインのスキャンウィンドウ表示
  7. スキャン先がC:\Program Files\VSTPluginsになっていることを確認し,Scanを押す
    VSTプラグインのスキャン実行
  8. スキャン完了後,以下のウィンドウが表示されるので,rnnoise_stereo.dllが含まれていることを確認してOKを押す
    スキャン完了画面
  9. Available Pluginsウィンドウに利用可能なVSTプラグインが表示されたことを確認し,このウィンドウを閉じる
    利用可能なプラグインにNoise Suppressionプラグインが追加された
  10. 再度,タスクバーのLight Hostを左クリックしてAvailable Pluginsのwerman→rnnoise_stereoを押す
    Available Pluginsからrnnoise_stereoを選択
  11. Active Pluginsの中にrnnoise_stereoが含まれていれば,既に有効となっており,VoiceMeeter Bananaで聞こえるマイク音に適用される.必要に応じてEditを選択してパラメーター設定を実施できる
    Active Plugins内にrnnoise_stereoが追加された
  12. 最後に,Windowsの再起動後も自動でLight Hostが起動できるように,%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startupのフォルダー内にLight Host.exeのショートカットキーを置く

その他

VSTプラグインについて

いくらかバージョンがあるようで,今回はVSTを使用しているが,VST2,VST3がある.イマドキはVST3のようで,各社が販売しているVSTプラグインは,VST3のみの提供に移行しつつあるらしい.また

に置くのが業界標準(?)のよう.

Equalizer APOについて

システム全体にVSTプラグインを適用できる一方で,調べた限りでは,VST2または3は取り扱えない.そのため,最近のVSTプラグイン(≒VST2または3)を取り扱いたい場合は,今回のようにVSTホストを使用するしか方法がない.Audio Stream Input Output(ASIO)に触ってみていて気づいたが,ASIOの場合はWindowsの標準(正しい表現か不明)ドライバーを通らないので,Equalizer APOでのVSTプラグインが適用されない.

VSTホストについて

正直なところ,いろいろありすぎてよくわからない.楽曲製作するわけではないので,無料でなるべく簡単なもの,ということで今回はLight Hostを使用してみた.もっとかんたんなものがあれば,別のものを使用したい.

OBSとVSTプラグインについて

今回は,OBS内部で使用するのではなく,OBSの外でそれらVSTプラグインを使いたかったのでOBSの設定にはふれていないが,OBSではVST2のプラグインは使用できるらしい.さらに,VST3のプラグインについてもWaves社のStudioRackというソフトウェアを使用すると,OBSでもVST3のプラグインが使用できるようである.

全般的な感想

VoiceMeeter Bananaを導入しようとしていて,やっぱり単純にマイク入力をするとノイズがしっかり聞こえるなぁと思ったところより,この対策にたどり着いた.

Twitterを見る限りでは,RNNoise否定派もいるし,確かに歌うVTuberさんのRNNoise適用で高音が消える問題もあるようなので,一概にRNNoiseがよいとも言えないところは納得した.カラオケ配信をする予定はまったくないが,RX 10 Elementsに少し興味がわいた.

改訂履歴

# 日付 内容
1 2023/11/26 Equalizer APOでの適用方法を一部修正
Light Hostを使用したVoiceMeeter Bananaの使用方法を追加,その他を追加
2 2023/12/27 ASIOドライバー利用の場合は適用されない一文を追加

参考サイト

  1. RNNoise for Voicemeter (added to OBS studio V26 beta)
  2. Real-time Noise Suppression Plugin
  3. Free and Open Source Software Noise Cancelling for Working from Home
  4. How To Setup VST Plugins with VoiceMeeter (Light Host)
  5. Light Host

*1:正確にはどうやらまったく同じものではなく,VST Noise Suppressionプラグインというもの

*2:正確には使用するプラグインだけでよい.また,Equalizer APOを使用する場合,C:\Program Files\EqualizerAPO\VSTPluginsも存在するが,通常,VSTプラグインはこのディレクトリーに配置する慣習のためここにコピーする

*3:この時点でconfig.txtに保存されるため,明示的に保存操作をしなくてもOK

*4:フォルダー名Light Host 1.2.1 Win64をLight Hostに変更して,C:\Program Filesの中に配置するのがオススメ

*5:必要に応じて,Show advanced settings...にてサンプルレートとバッファーサイズを変更する

RL78マイコンのセキュリティIDを一意に決めたい

目的

RL78の開発環境において,セキュリティID設定というものがある(下図参照).16進数10バイトで設定できるものではあるが,その値を完全な乱数ではなくて,一意に決める方法のひとつを紹介する.

RL78のセキュリティID設定(画面はe2studioの英語版)

上記のセキュリティID設定では,不一致だった場合にフラッシュメモリーのデータ(コード領域およびデータフラッシュ領域両方)を消去するかどうか選択できる.

結論

ファイルのハッシュ値計算と同じ方法で,これを10ケタに区切ることで,特定の文字列に対して一意の16進数10バイト(20ケタ)が得られる:

$ echo -n 0x; echo -n foo-bar | md5sum | cut -c 1-20
0xe5f9ec048d1dbe19c70f

文字列foo-barに対する32ケタのMD5の計算結果の内,先頭の20ケタを切り出して,0xを先頭に付加したものが0xe5f9ec048d1dbe19c70f.これをセキュリティIDの値として使う.PowerShellコマンドプロンプトでは通常実施できないが,近頃はGitを使うことが大半であるため,Git Bashを使うことでWindows環境下でも上記コマンドが実行できる.

その他

セキュリティIDについて

セキュリティIDは,あくまでデバッグ(オンチップデバッグ)開始時のセキュリティ設定であって,RL78のチップへの不正アクセスというよりは,RL78のチップへ不正にアクセスしてデバッグを開始しようとしたときに,有効な機能である.既に書き込まれているセキュリティIDの値と,デバッグしようとしている側のセキュリティIDが異なっていた場合にデバッグを開始できなくするという動作をする.

開発環境におけるデバッグセッション構成

デフォルトでは,デバッグ開始時にフラッシュROMを消去してからデバッグという設定となっている.そのため,セキュリティIDの照合に失敗しても,結局フラッシュROMを消去してからデバッグを開始するので,あまり影響はないと考えられる(e2studioにて確認).

Windowsの録音デバイス設定:サンプルレートとビットの深さを別プログラムで設定したい

目的

レトロフリーク(音声出力サンプリングレートが44.1[kHz]固定)でのゲームキャプチャーをしている関係で,キャプチャー側音声のサンプリングレート(サンプルレート)と量子化ビット数(ビットの深さ)を都度,手動で変更している.手動で設定する場合,マウスで3,4クリックが必要となる:

サンプルレートとビットの深さの設定の場所

そもそも,私の使用しているHDMIキャプチャーボードは,48[kHz]の取り込みしかできないことも問題ではある*1

結論

MMDevice APIとIPolicyConfigというものを用いて,所望の動作である特定の録音インターフェースに対して,44.1[kHz]⇔48[kHz]を切り替えることができた(以下のGitHubソースコード参照):

github.com

ざっくり言うと

  1. MMDevice APIで録音インターフェースを取得
  2. サウンド設定に表示される名前で該当する録音インターフェースを特定
  3. IPolicyConfigのGetDeviceFormatとGetMixFormatで現在のフォーマットを取得
  4. それぞれのフォーマットを所望のサンプルレートに設定および関連する設定値を計算
  5. IPolicyConfigのSetDeviceFormatでそれらを反映

という流れとなる.GetMixFormatで得られた値のほうだけ変更すると,まったく音が出なくなるので注意.実行してしまった場合は,デバイスの無効→有効にすると元に戻る.また,逆に,GetDeviceFormatで得られた値のほうだけ変更したらどうなるかは未確認.

現状2023/11/23では,一覧を表示すると見せかけて,録音インターフェースSPDIF-In (USB Sound Blaster HD)が存在したら,サンプルレートをトグルで切り替える動作となっている.もうちょっと改良したい.

#include <wchar.h>
#include "mmdeviceapi.h"
#include "Propidl.h"
#include "functiondiscoverykeys_devpkey.h"
#include "initguid.h"

/* refer to the following article: */
/* https://learn.microsoft.com/en-us/answers/questions/669471/how-to-control-enable-audio-enhancements-with-code */
DEFINE_GUID(CLSID_PolicyConfig, 0x870af99c, 0x171d, 0x4f9e, 0xaf, 0x0d, 0xe6, 0x3d, 0xf4, 0x0c, 0x2b, 0xc9);
MIDL_INTERFACE("f8679f50-850a-41cf-9c72-430f290290c8")
IPolicyConfig : public IUnknown
{
public:
    virtual HRESULT STDMETHODCALLTYPE GetMixFormat(PCWSTR pszDeviceName, WAVEFORMATEX * *ppFormat) = 0;
    virtual HRESULT STDMETHODCALLTYPE GetDeviceFormat(PCWSTR pszDeviceName, bool bDefault, WAVEFORMATEX** ppFormat) = 0;
    virtual HRESULT STDMETHODCALLTYPE ResetDeviceFormat(PCWSTR pszDeviceName) = 0;
    virtual HRESULT STDMETHODCALLTYPE SetDeviceFormat(PCWSTR pszDeviceName, WAVEFORMATEX* ppEndpointFormatFormat, WAVEFORMATEX* pMixFormat) = 0;
    virtual HRESULT STDMETHODCALLTYPE GetProcessingPeriod(PCWSTR pszDeviceName, bool bDefault, PINT64 pmftDefaultPeriod, PINT64 pmftMinimumPeriod) = 0;
    virtual HRESULT STDMETHODCALLTYPE SetProcessingPeriod(PCWSTR pszDeviceName, PINT64 pmftPeriod) = 0;
    virtual HRESULT STDMETHODCALLTYPE GetShareMode(PCWSTR pszDeviceName, struct DeviceShareMode* pMode) = 0;
    virtual HRESULT STDMETHODCALLTYPE SetShareMode(PCWSTR pszDeviceName, struct DeviceShareMode* pMode) = 0;
    virtual HRESULT STDMETHODCALLTYPE GetPropertyValue(PCWSTR pszDeviceName, BOOL bFxStore, const PROPERTYKEY& pKey, PROPVARIANT* pv) = 0;
    virtual HRESULT STDMETHODCALLTYPE SetPropertyValue(PCWSTR pszDeviceName, BOOL bFxStore, const PROPERTYKEY& pKey, PROPVARIANT* pv) = 0;
    virtual HRESULT STDMETHODCALLTYPE SetDefaultEndpoint(PCWSTR pszDeviceName, ERole eRole) = 0;
    virtual HRESULT STDMETHODCALLTYPE SetEndpointVisibility(PCWSTR pszDeviceName, bool bVisible) = 0;
};

#define TARGET_DEV_NAME (L"SPDIF-In (USB Sound Blaster HD)")

int main()
{
    HRESULT hRes = NULL;
    IMMDeviceEnumerator *pDevEnum = NULL;
    IMMDeviceCollection *pDev = NULL;
    UINT nCount = 0;
    IMMDevice *pDevId = NULL;
    LPWSTR wstrEndpointId = NULL;
    IPropertyStore *pPropStore = NULL;
    PROPVARIANT friendlyName;
    IPolicyConfig *pPolicyConfig = NULL;
    WAVEFORMATEX *pDevFormat = NULL, *pMixFormat = NULL;

    hRes = CoInitialize(NULL);
    if (FAILED(hRes))
    {
        return -1;   /* TODO: refactor error proc */
    }

    hRes = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL,
        CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (LPVOID*)&pDevEnum);
    if (FAILED(hRes))
    {
        CoUninitialize();
        return -1;   /* TODO: refactor error proc */
    }

    /* get list of active input audio devices */
    hRes = pDevEnum->EnumAudioEndpoints(eCapture/* eRender: output, eCapture: input */,
        DEVICE_STATE_ACTIVE, &pDev);
    if (FAILED(hRes))
    {
        pDevEnum->Release();
        CoUninitialize();
        return -1;   /* TODO: refactor error proc */
    }

    hRes = pDev->GetCount(&nCount);
    if (FAILED(hRes))
    {
        pDev->Release();
        pDevEnum->Release();
        CoUninitialize();
        return -1;   /* TODO: refactor error proc */
    }
    for (UINT i = 0; i < nCount; i++)
    {
        hRes = pDev->Item(i, &pDevId);
        if (FAILED(hRes))
        {
            pDev->Release();
            pDevEnum->Release();
            CoUninitialize();
            return -1;   /* TODO: refactor error proc */
        }

        hRes = pDevId->GetId(&wstrEndpointId);
        if (FAILED(hRes))
        {
            pDevId->Release();
            pDev->Release();
            pDevEnum->Release();
            CoUninitialize();
            return -1;   /* TODO: refactor error proc */
        }

        hRes = pDevId->OpenPropertyStore(STGM_READ, &pPropStore);
        if (FAILED(hRes))
        {
            pDevId->Release();
            pDev->Release();
            pDevEnum->Release();
            CoUninitialize();
            return -1;   /* TODO: refactor error proc */
        }

        /* get friendly names on Sound settings */
        PropVariantInit(&friendlyName);
        hRes = pPropStore->GetValue(PKEY_Device_FriendlyName, &friendlyName);
        if (FAILED(hRes))
        {
            pPropStore->Release();
            pDevId->Release();
            pDev->Release();
            pDevEnum->Release();
            CoUninitialize();
            return -1;   /* TODO: refactor error proc */
        }
        wprintf(L"Device No. %d: %ls\n", i, friendlyName.pwszVal);  /* FIXME: show multi-byte letters properly */

        hRes = CoCreateInstance(CLSID_PolicyConfig, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pPolicyConfig));
        if (FAILED(hRes))
        {
            pPropStore->Release();
            pDevId->Release();
            pDev->Release();
            pDevEnum->Release();
            CoUninitialize();
            return -1;   /* TODO: refactor error proc */
        }

        hRes = pPolicyConfig->GetDeviceFormat(wstrEndpointId,
            FALSE/* if TRUE, get Default Format on Restore Default click */,
            &pDevFormat);
        if (FAILED(hRes))
        {
            pPolicyConfig->Release();
            pPropStore->Release();
            pDevId->Release();
            pDev->Release();
            pDevEnum->Release();
            CoUninitialize();
            return -1;   /* TODO: refactor error proc */
        }
        wprintf(L"\tWAVEFORMATEX Data from GetDeviceFormat\n");
        wprintf(L"\t\twFormatTag: %d\n", pDevFormat->wFormatTag);
        wprintf(L"\t\tnChannels: %d\n", pDevFormat->nChannels);
        wprintf(L"\t\tnSamplesPerSec: %ld\n", pDevFormat->nSamplesPerSec);
        wprintf(L"\t\tnAvgBytesPerSec: %ld\n", pDevFormat->nAvgBytesPerSec);
        wprintf(L"\t\tnBlockAlign: %ld\n", pDevFormat->nBlockAlign);
        wprintf(L"\t\twBitsPerSample: %d\n", pDevFormat->wBitsPerSample);
        wprintf(L"\t\tcbSize: %d\n", pDevFormat->cbSize);

        hRes = pPolicyConfig->GetMixFormat(wstrEndpointId, &pMixFormat);
        if (FAILED(hRes))
        {
            pPolicyConfig->Release();
            pPropStore->Release();
            pDevId->Release();
            pDev->Release();
            pDevEnum->Release();
            CoUninitialize();
            return -1;   /* TODO: refactor error proc */
        }
        wprintf(L"\tWAVEFORMATEX Data from GetMixFormat\n");
        wprintf(L"\t\twFormatTag: %d\n", pMixFormat->wFormatTag);
        wprintf(L"\t\tnChannels: %d\n", pMixFormat->nChannels);
        wprintf(L"\t\tnSamplesPerSec: %ld\n", pMixFormat->nSamplesPerSec);
        wprintf(L"\t\tnAvgBytesPerSec: %ld\n", pMixFormat->nAvgBytesPerSec);
        wprintf(L"\t\tnBlockAlign: %ld\n", pMixFormat->nBlockAlign);
        wprintf(L"\t\twBitsPerSample: %d\n", pMixFormat->wBitsPerSample);
        wprintf(L"\t\tcbSize: %d\n", pMixFormat->cbSize);

        wprintf(L"\n");

        /* if corresponding device found, set desired sample rate and calculate value(s) with it */
        if (0 == _wcsicmp(friendlyName.pwszVal, TARGET_DEV_NAME))
        {
            /* NOTE: if change wBitsPerSample, calculate nBlockAlign with it */
            pDevFormat->nSamplesPerSec = (44100 == pDevFormat->nSamplesPerSec) ? 48000 : 44100;
            pDevFormat->nAvgBytesPerSec = pDevFormat->nSamplesPerSec * pDevFormat->nBlockAlign;
            pMixFormat->nSamplesPerSec = (44100 == pMixFormat->nSamplesPerSec) ? 48000 : 44100;
            pMixFormat->nAvgBytesPerSec = pMixFormat->nSamplesPerSec * pMixFormat->nBlockAlign;
            hRes = pPolicyConfig->SetDeviceFormat(wstrEndpointId, pDevFormat, pMixFormat);
            if (FAILED(hRes))
            {
                wprintf(L"*** FAILED to change into your desired format...\n");
                pPolicyConfig->Release();
                pPropStore->Release();
                pDevId->Release();
                pDev->Release();
                pDevEnum->Release();
                CoUninitialize();
                return -1;   /* TODO: refactor error proc */
            }
            else
            {
                wprintf(L"*** succeeded to change into your desired format as follows:\n");
                wprintf(L"Device No. %d: %ls\n", i, friendlyName.pwszVal);  /* FIXME: show multi-byte letters properly */
                wprintf(L"\tWAVEFORMATEX Data from GetDeviceFormat\n");
                wprintf(L"\t\twFormatTag: %d\n", pDevFormat->wFormatTag);
                wprintf(L"\t\tnChannels: %d\n", pDevFormat->nChannels);
                wprintf(L"\t\tnSamplesPerSec: %ld\n", pDevFormat->nSamplesPerSec);
                wprintf(L"\t\tnAvgBytesPerSec: %ld\n", pDevFormat->nAvgBytesPerSec);
                wprintf(L"\t\tnBlockAlign: %ld\n", pDevFormat->nBlockAlign);
                wprintf(L"\t\twBitsPerSample: %d\n", pDevFormat->wBitsPerSample);
                wprintf(L"\t\tcbSize: %d\n", pDevFormat->cbSize);
                wprintf(L"\tWAVEFORMATEX Data from GetMixFormat\n");
                wprintf(L"\t\twFormatTag: %d\n", pMixFormat->wFormatTag);
                wprintf(L"\t\tnChannels: %d\n", pMixFormat->nChannels);
                wprintf(L"\t\tnSamplesPerSec: %ld\n", pMixFormat->nSamplesPerSec);
                wprintf(L"\t\tnAvgBytesPerSec: %ld\n", pMixFormat->nAvgBytesPerSec);
                wprintf(L"\t\tnBlockAlign: %ld\n", pMixFormat->nBlockAlign);
                wprintf(L"\t\twBitsPerSample: %d\n", pMixFormat->wBitsPerSample);
                wprintf(L"\t\tcbSize: %d\n", pMixFormat->cbSize);
                wprintf(L"***\n\n");
            }
        }

        PropVariantClear(&friendlyName);
    }

    pPropStore->Release();
    pDevId->Release();
    pDev->Release();
    pDevEnum->Release();
    CoUninitialize();

    return 0;
}

その他(感想)

最初にたどり着いたWASAPI(Windows Audio Session API)周りの情報では,どうもフォーマットが変更できなかった(以下twitter参照):

いろいろ方法はあるようで,そのうちのひとつが今回のMMDevice APIとIPolicyConfigを使う方法となった.MMDevice APIはまだしも,IPolicyConfigを使うという発想はどこから得ることができるのか,先人の知恵はすごい.

今日2023/11/23時点では,開発できる人以外は,まったく同じ録音インターフェースを使用している人にしか使えないものとなってしまっているため,mono-to-stereoを参考に

  1. インターフェース一覧表示
  2. 該当のインターフェース選択
  3. サンプルレート変更実行

というようにしたい.

改訂履歴

# 日付 内容
1 2023/11/23 とりあえずコマンドラインプログラム完成につき,情報まとめ!

参考サイト

  1. how to control enable audio enhancements with code
  2. Windowsの音声出力先を変えるショートカット作成
  3. Tauri + windows-rsでオーディオスイッチャーを作った話またはMicrosoftのRustへの本気度をCOM対応から見る的な何か
  4. C++&Win32 API MMDevice API (Core Audio APIs)によるデバイス情報の取得
  5. mono-to-stereo
  6. mono-to-stereo-gui
  7. WASAPIをプログラムしてみる

*1:PS3の映像・音声をキャプチャーできるので変更したくない

PYTHONPATHを設定するとOBSが起動しなくなる問題の一時回避策

目的

今日(2023/10/29)の23時くらいに,急にOBS(正確にはOBS 29.1.3)が起動しなくなってしまった.起動しなくなった度合いは,1秒程度マウスが読み込み中になる,かつタスクマネージャに1秒程度表示されたのちに消える状態.Googleで検索して見つけた

  • Windowsの再起動
  • Windowsのシャットダウン→電源断(ACケーブルを抜く)→Windowsの再起動
  • 再インストール
  • アンインストール→再インストール

のいずれでも解決しなかったが,あることが問題で解決できた(根本対策はできていない)ので備忘録として残しておく.

☞何か解決策をお持ちの方,いらっしゃいましたらコメントお願いします!

名称 規格 製造会社 備考
オペレーティングシステム Windows 10 Pro 64ビット,バージョン22H2 マイクロソフト インターナショナル版
グラフィックボード AMD Radeon RX 6650 XT AMD
配信ソフト OBS Studio 29.1.3 OBSプロジェクト 2023/10/29時点最新版
統合開発環境 e2studio 2023-07 (23.7.0) ルネサスエレクトロニクス 2023/10/29時点最新版
Python2 Python 2.7.12 --- (e2studio 2023-07にバンドル)

結論

環境変数PYTHONPATHを新規に追加して設定したことが原因で,起動しなくなっていた:

PYTHONPATHの設定

この環境変数PYTHONPATHを削除すると,問題なくOBSが起動できた.

詳細

ふだんOBSは,管理者権限で起動しているため,権限の設定ではないことは明確だった.OBSの動作ログは%APPDATA%\obs-studio\logsYYY-MM-DD HH-MM-SS.txtのファイル名書式のテキストファイルで格納されている.

それぞれ起動に失敗していたログおよび正常に起動するようになったときのログを以下に示す(一番左のコロン区切りの数字は,コンピューターの時刻を表す)が,明示的な差分がなかった(2023/10/30追記).確かにFailedが複数存在するが,起動成功時(後述)との違いはパッと見わからない.

起動失敗ログ

23:20:32.964: CPU Name: AMD Ryzen 7 3700X 8-Core Processor             
23:20:32.964: CPU Speed: 3593MHz
23:20:32.964: Physical Cores: 8, Logical Cores: 16
23:20:32.964: Physical Memory: 32694MB Total, 25618MB Free
23:20:32.964: Windows Version: 10.0 Build 19045 (release: 22H2; revision: 3570; 64-bit)
23:20:32.964: Running as administrator: true
23:20:32.964: Windows 10/11 Gaming Features:
23:20:32.964:   Game Bar: Off
23:20:32.964:   Game DVR: Off
23:20:32.964:   Game DVR Background Recording: Off
23:20:32.964:   Game Mode: Probably On (no reg key set)
23:20:32.966: Sec. Software Status:
23:20:32.967:   Microsoft Defender Antivirus: disabled (AV)
23:20:32.967:   ウイルスバスター クラウド: enabled (AV)
23:20:32.967:   Windows Firewall: enabled (FW)
23:20:32.967: Current Date/Time: 2023-10-29, 23:20:32
23:20:32.967: Browser Hardware Acceleration: true
23:20:32.967: Hide OBS windows from screen capture: false
23:20:32.967: Qt Version: 6.4.3 (runtime), 6.4.3 (compiled)
23:20:32.967: Portable mode: false
23:20:33.804: OBS 29.1.3 (64-bit, windows)
23:20:33.804: ---------------------------------
23:20:33.805: ---------------------------------
23:20:33.805: audio settings reset:
23:20:33.805:   samples per sec: 48000
23:20:33.805:   speakers:        2
23:20:33.805:   max buffering:   960 milliseconds
23:20:33.805:   buffering type:  dynamically increasing
23:20:33.806: ---------------------------------
23:20:33.806: Initializing D3D11...
23:20:33.806: Available Video Adapters: 
23:20:33.808:   Adapter 0: AMD Radeon RX 6650 XT
23:20:33.808:     Dedicated VRAM: 8541921280
23:20:33.808:     Shared VRAM:    17141098496
23:20:33.808:     PCI ID:         1002:73ef
23:20:33.809:     Driver Version: 31.0.22017.3004
23:20:33.811:     output 0:
23:20:33.811:       name=EV2450
23:20:33.811:       pos={0, 0}
23:20:33.811:       size={1920, 1080}
23:20:33.811:       attached=true
23:20:33.811:       refresh=60
23:20:33.811:       bits_per_color=8
23:20:33.811:       space=RGB_FULL_G22_NONE_P709
23:20:33.811:       sdr_white_nits=80
23:20:33.811:       nit_range=[min=0.500000, max=270.000000, max_full_frame=270.000000]
23:20:33.811:       dpi=96 (100%)
23:20:33.811:       id=\\?\DISPLAY#ENC2530#7&120d150d&1&UID256#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}
23:20:33.811:       alt_id=\\.\DISPLAY1
23:20:33.813:     output 1:
23:20:33.813:       name=EV2450
23:20:33.813:       pos={1920, 0}
23:20:33.813:       size={1920, 1080}
23:20:33.813:       attached=true
23:20:33.813:       refresh=60
23:20:33.813:       bits_per_color=8
23:20:33.813:       space=RGB_FULL_G22_NONE_P709
23:20:33.813:       sdr_white_nits=80
23:20:33.813:       nit_range=[min=0.500000, max=270.000000, max_full_frame=270.000000]
23:20:33.813:       dpi=96 (100%)
23:20:33.813:       id=\\?\DISPLAY#ENC2530#7&120d150d&1&UID260#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}
23:20:33.813:       alt_id=\\.\DISPLAY2
23:20:33.814:     output 2:
23:20:33.814:       name=K3818U
23:20:33.814:       pos={0, 1080}
23:20:33.814:       size={3840, 1100}
23:20:33.814:       attached=true
23:20:33.814:       refresh=60
23:20:33.814:       bits_per_color=10
23:20:33.814:       space=RGB_FULL_G2084_NONE_P2020
23:20:33.814:       sdr_white_nits=240
23:20:33.814:       nit_range=[min=0.000000, max=400.000000, max_full_frame=282.000000]
23:20:33.814:       dpi=96 (100%)
23:20:33.814:       id=\\?\DISPLAY#QJF3750#7&120d150d&1&UID268#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}
23:20:33.814:       alt_id=\\.\DISPLAY3
23:20:33.831: Loading up D3D11 on adapter AMD Radeon RX 6650 XT (0)
23:20:33.892: D3D11 loaded successfully, feature level used: b000
23:20:33.892: DXGI increase maximum frame latency success
23:20:33.892: D3D11 GPU priority setup success
23:20:35.259: ---------------------------------
23:20:35.259: video settings reset:
23:20:35.259:   base resolution:   1920x1080
23:20:35.259:   output resolution: 1920x1080
23:20:35.259:   downscale filter:  Lanczos
23:20:35.259:   fps:               60/1
23:20:35.259:   format:            NV12
23:20:35.259:   YUV mode:          Rec. 709/Partial
23:20:35.259: NV12 texture support enabled
23:20:35.259: P010 texture support not available
23:20:35.260: Audio monitoring device:
23:20:35.260:   name: Speakers (Realtek(R) Audio)
23:20:35.260:   id: {0.0.0.00000000}.{bf2e86d4-01b9-438e-b832-6e8088daaf62}
23:20:35.260: ---------------------------------
23:20:35.263: Failed to load 'en-GB' text for module: 'aja-output-ui.dll'
23:20:35.264: No AJA devices found, skipping loading AJA UI plugin
23:20:35.264: Failed to initialize module 'aja-output-ui.dll'
23:20:35.265: Failed to load 'en-GB' text for module: 'aja.dll'
23:20:35.266: No AJA devices found, skipping loading AJA plugin
23:20:35.266: Failed to initialize module 'aja.dll'
23:20:35.266: Skipping module '../../obs-plugins/64bit/chrome_elf.dll', not an OBS plugin
23:20:35.267: Failed to load 'en-GB' text for module: 'coreaudio-encoder.dll'
23:20:35.298: [CoreAudio encoder]: Adding CoreAudio AAC encoder
23:20:35.299: Failed to load 'en-US' text for module: 'decklink-captions.dll'
23:20:35.300: Failed to load 'en-US' text for module: 'decklink-output-ui.dll'
23:20:35.303: A DeckLink iterator could not be created.  The DeckLink drivers may not be installed
23:20:35.303: Failed to initialize module 'decklink.dll'
23:20:35.503: [AMF] Version 2.8.0 loaded (Compiled: 1.4.14.0, Runtime: 1.4.31.0, Library: 1;4;31;0;23.20.11.01;202309112318;AMD-Radeon-Driver/drivers:5e3e684246a316aa078d698f83c84101f5bce7eb).
23:20:35.559: [AMF] <Id: 1> Unable to set converter transfer characteristic, error AMF_NOT_FOUND (code 11)
23:20:35.616: [AMF] <Id: 2> Unable to set converter transfer characteristic, error AMF_NOT_FOUND (code 11)
23:20:35.617: [AMF] [Capability Manager] Testing Direct3D 11 Adapter 'AMD Radeon RX 6650 XT (VEN_1002/DEV_73ef/SUB_452e1da2/REV_00c1)':
23:20:35.617:   H264/AVC: Supported
23:20:35.617:   H265/HEVC: Supported
23:20:35.617: 
23:20:35.620: Failed to load 'en-GB' text for module: 'frontend-tools.dll'

起動成功ログ

起動成功時は具体的にStartup completeが表示される

23:24:06.913: CPU Name: AMD Ryzen 7 3700X 8-Core Processor             
23:24:06.913: CPU Speed: 3593MHz
23:24:06.913: Physical Cores: 8, Logical Cores: 16
23:24:06.913: Physical Memory: 32694MB Total, 25603MB Free
23:24:06.913: Windows Version: 10.0 Build 19045 (release: 22H2; revision: 3570; 64-bit)
23:24:06.913: Running as administrator: true
23:24:06.913: Windows 10/11 Gaming Features:
23:24:06.913:   Game Bar: Off
23:24:06.913:   Game DVR: Off
23:24:06.913:   Game DVR Background Recording: Off
23:24:06.913:   Game Mode: Probably On (no reg key set)
23:24:06.914: Sec. Software Status:
23:24:06.916:   Microsoft Defender Antivirus: disabled (AV)
23:24:06.916:   ウイルスバスター クラウド: enabled (AV)
23:24:06.916:   Windows Firewall: enabled (FW)
23:24:06.916: Current Date/Time: 2023-10-29, 23:24:06
23:24:06.916: Browser Hardware Acceleration: true
23:24:06.916: Hide OBS windows from screen capture: false
23:24:06.916: Qt Version: 6.4.3 (runtime), 6.4.3 (compiled)
23:24:06.916: Portable mode: false
23:24:07.749: OBS 29.1.3 (64-bit, windows)
23:24:07.749: ---------------------------------
23:24:07.750: ---------------------------------
23:24:07.750: audio settings reset:
23:24:07.750:   samples per sec: 48000
23:24:07.750:   speakers:        2
23:24:07.750:   max buffering:   960 milliseconds
23:24:07.750:   buffering type:  dynamically increasing
23:24:07.751: ---------------------------------
23:24:07.751: Initializing D3D11...
23:24:07.751: Available Video Adapters: 
23:24:07.753:   Adapter 0: AMD Radeon RX 6650 XT
23:24:07.753:     Dedicated VRAM: 8541921280
23:24:07.753:     Shared VRAM:    17141098496
23:24:07.753:     PCI ID:         1002:73ef
23:24:07.754:     Driver Version: 31.0.22017.3004
23:24:07.755:     output 0:
23:24:07.755:       name=EV2450
23:24:07.755:       pos={0, 0}
23:24:07.755:       size={1920, 1080}
23:24:07.755:       attached=true
23:24:07.755:       refresh=60
23:24:07.755:       bits_per_color=8
23:24:07.755:       space=RGB_FULL_G22_NONE_P709
23:24:07.755:       sdr_white_nits=80
23:24:07.755:       nit_range=[min=0.500000, max=270.000000, max_full_frame=270.000000]
23:24:07.755:       dpi=96 (100%)
23:24:07.755:       id=\\?\DISPLAY#ENC2530#7&120d150d&1&UID256#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}
23:24:07.755:       alt_id=\\.\DISPLAY1
23:24:07.757:     output 1:
23:24:07.757:       name=EV2450
23:24:07.757:       pos={1920, 0}
23:24:07.757:       size={1920, 1080}
23:24:07.757:       attached=true
23:24:07.757:       refresh=60
23:24:07.757:       bits_per_color=8
23:24:07.757:       space=RGB_FULL_G22_NONE_P709
23:24:07.757:       sdr_white_nits=80
23:24:07.757:       nit_range=[min=0.500000, max=270.000000, max_full_frame=270.000000]
23:24:07.757:       dpi=96 (100%)
23:24:07.757:       id=\\?\DISPLAY#ENC2530#7&120d150d&1&UID260#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}
23:24:07.757:       alt_id=\\.\DISPLAY2
23:24:07.759:     output 2:
23:24:07.759:       name=K3818U
23:24:07.759:       pos={0, 1080}
23:24:07.759:       size={3840, 1100}
23:24:07.759:       attached=true
23:24:07.759:       refresh=60
23:24:07.759:       bits_per_color=10
23:24:07.759:       space=RGB_FULL_G2084_NONE_P2020
23:24:07.759:       sdr_white_nits=240
23:24:07.759:       nit_range=[min=0.000000, max=400.000000, max_full_frame=282.000000]
23:24:07.759:       dpi=96 (100%)
23:24:07.759:       id=\\?\DISPLAY#QJF3750#7&120d150d&1&UID268#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}
23:24:07.759:       alt_id=\\.\DISPLAY3
23:24:07.762: Loading up D3D11 on adapter AMD Radeon RX 6650 XT (0)
23:24:07.823: D3D11 loaded successfully, feature level used: b000
23:24:07.823: DXGI increase maximum frame latency success
23:24:07.823: D3D11 GPU priority setup success
23:24:09.186: ---------------------------------
23:24:09.186: video settings reset:
23:24:09.186:   base resolution:   1920x1080
23:24:09.186:   output resolution: 1920x1080
23:24:09.186:   downscale filter:  Lanczos
23:24:09.186:   fps:               60/1
23:24:09.186:   format:            NV12
23:24:09.186:   YUV mode:          Rec. 709/Partial
23:24:09.186: NV12 texture support enabled
23:24:09.186: P010 texture support not available
23:24:09.187: Audio monitoring device:
23:24:09.187:   name: Speakers (Realtek(R) Audio)
23:24:09.187:   id: {0.0.0.00000000}.{bf2e86d4-01b9-438e-b832-6e8088daaf62}
23:24:09.187: ---------------------------------
23:24:09.189: Failed to load 'en-GB' text for module: 'aja-output-ui.dll'
23:24:09.191: No AJA devices found, skipping loading AJA UI plugin
23:24:09.191: Failed to initialize module 'aja-output-ui.dll'
23:24:09.192: Failed to load 'en-GB' text for module: 'aja.dll'
23:24:09.192: No AJA devices found, skipping loading AJA plugin
23:24:09.192: Failed to initialize module 'aja.dll'
23:24:09.193: Skipping module '../../obs-plugins/64bit/chrome_elf.dll', not an OBS plugin
23:24:09.194: Failed to load 'en-GB' text for module: 'coreaudio-encoder.dll'
23:24:09.203: [CoreAudio encoder]: Adding CoreAudio AAC encoder
23:24:09.204: Failed to load 'en-US' text for module: 'decklink-captions.dll'
23:24:09.205: Failed to load 'en-US' text for module: 'decklink-output-ui.dll'
23:24:09.208: A DeckLink iterator could not be created.  The DeckLink drivers may not be installed
23:24:09.208: Failed to initialize module 'decklink.dll'
23:24:09.402: [AMF] Version 2.8.0 loaded (Compiled: 1.4.14.0, Runtime: 1.4.31.0, Library: 1;4;31;0;23.20.11.01;202309112318;AMD-Radeon-Driver/drivers:5e3e684246a316aa078d698f83c84101f5bce7eb).
23:24:09.455: [AMF] <Id: 1> Unable to set converter transfer characteristic, error AMF_NOT_FOUND (code 11)
23:24:09.510: [AMF] <Id: 2> Unable to set converter transfer characteristic, error AMF_NOT_FOUND (code 11)
23:24:09.511: [AMF] [Capability Manager] Testing Direct3D 11 Adapter 'AMD Radeon RX 6650 XT (VEN_1002/DEV_73ef/SUB_452e1da2/REV_00c1)':
23:24:09.511:   H264/AVC: Supported
23:24:09.511:   H265/HEVC: Supported
23:24:09.511: 
23:24:09.514: Failed to load 'en-GB' text for module: 'frontend-tools.dll'
23:24:09.542: Skipping module '../../obs-plugins/64bit/libcef.dll', not an OBS plugin
23:24:09.542: Skipping module '../../obs-plugins/64bit/libEGL.dll', not an OBS plugin
23:24:09.542: Skipping module '../../obs-plugins/64bit/libGLESv2.dll', not an OBS plugin
23:24:09.558: [obs-browser]: Version 2.21.1
23:24:09.558: [obs-browser]: CEF Version 103.0.5060.134 (runtime), 103.0.0-5060-shared-textures.2591+g4204d54+chromium-103.0.5060.134 (compiled)
23:24:09.664: [noise suppress]: NVIDIA denoiser disabled, redistributable not found or could not be loaded.
23:24:09.664: Failed to get NVVideoEffects.dll version info size
23:24:09.666: [NVIDIA VIDEO FX]: FX disabled, redistributable not found or could not be loaded.
23:24:09.670: Failed to load 'en-GB' text for module: 'obs-qsv11.dll'
23:24:09.710: Failed to load 'en-GB' text for module: 'obs-vst.dll'
23:24:09.712: Failed to load 'en-GB' text for module: 'obs-websocket.dll'
23:24:09.712: [obs-websocket] [obs_module_load] you can haz websockets (Version: 5.2.3 | RPC Version: 1)
23:24:09.712: [obs-websocket] [obs_module_load] Qt version (compile-time): 6.4.3 | Qt version (run-time): 6.4.3
23:24:09.712: [obs-websocket] [obs_module_load] Linked ASIO Version: 101201
23:24:09.719: [obs-websocket] [obs_module_load] Module loaded.
23:24:09.722: Failed to load 'en-GB' text for module: 'rtmp-services.dll'
23:24:09.728: [vlc-video]: VLC 3.0.16 Vetinari found, VLC video source enabled
23:24:09.739: Failed to load 'en-GB' text for module: 'win-wasapi.dll'
23:24:09.739: ---------------------------------
23:24:09.739:   Loaded Modules:
23:24:09.739:     win-wasapi.dll
23:24:09.739:     win-dshow.dll
23:24:09.739:     win-capture.dll
23:24:09.739:     vlc-video.dll
23:24:09.739:     text-freetype2.dll
23:24:09.739:     rtmp-services.dll
23:24:09.739:     obs-x264.dll
23:24:09.739:     obs-websocket.dll
23:24:09.739:     obs-vst.dll
23:24:09.739:     obs-transitions.dll
23:24:09.739:     obs-text.dll
23:24:09.739:     obs-qsv11.dll
23:24:09.739:     obs-outputs.dll
23:24:09.739:     obs-filters.dll
23:24:09.739:     obs-ffmpeg.dll
23:24:09.739:     obs-browser.dll
23:24:09.739:     image-source.dll
23:24:09.739:     frontend-tools.dll
23:24:09.739:     enc-amf.dll
23:24:09.739:     decklink-output-ui.dll
23:24:09.739:     decklink-captions.dll
23:24:09.739:     coreaudio-encoder.dll
23:24:09.739: ---------------------------------
23:24:09.740: ==== Startup complete ===============================================

その他

環境変数PYTHONPATH設定の経緯は,Renesas Extensions for Visual Studio Codeの設定のひとつに存在したから.CMakeやMinGWを疑ったが,この環境変数だった.この設定手順ではPython2.7を具体的にインストールする指示だが,今回はe2studioにバンドルされているものを使用していたため,正しくPython2.7をインストールしてPYTHONPATHを設定した場合は,この問題に陥らないかもしれない.

改訂履歴

# 日付 内容
1 2023/10/30 動作ログを具体的に追記

AE-TYBLE16のFritzingパーツを作る

目的

AE-TYBLE16を使用して工作を始めているが*1,工作レベルで使ってきているFritzingには当然,AE-TYBLE16は存在しない! そのため,今回はFritzingのチュートリアル等に従い,AE-TYBLE16のFritzingパーツを作成する.

名称 規格 製造会社 備考
オペレーティングシステム Windows 10 Pro(64ビット),バージョン20H2 マイクロソフト インターナショナル版
CADソフト fritzing beta Version 0.9.10 Fritzing 2023/02/26時点最新版
ドローソフト Inkscape 1.2.2 Inkscape 2023/02/26時点最新版

結論

Inkscapeを用いてsvgファイルを作成し,以下のブレッドボードビューを作成した.本来はこのモジュールの基板幅は8.0mmだが,ブレッドボードで工作しやすい(?)ように7.62mmとして作成しているため,300milという名称を付加している.

AE-TYBLE16のブレッドボードビュー

以下のGitHubページよりAE-TYBLE16_300mil.fzpzをダウンロードして利用可能とした.このfzpzをダウンロードして実行すると,My Parts内に取り込むことができる.

github.com

苦労の結果のツイートはこちら:

詳細

基本的には,こちらの公式手順New Parts Editor releasedに従う.今回作成したAE-TYBLE16は,Generic ICの部品をベースとして作成した.

必要な画像ファイルは以下の4つ

分類 役割 今回のAE-TYBLE16作成へ当たって
ブレッドボードビュー(Breadboard) ブレッドボード図で使用する 新規作成
回路図ビュー(Schematic 回路図で使用する Generic IC 16ピンより流用して変更
基板図ビュー(PCB) 基板図で使用する Generic IC 16ピンより流用
アイコン(Icon) パーツリスト表示に使用する ブレッドボードビューで代替

の4つである.主として,ブレッドボードビュー,回路図ビューとパーツ情報Metadataの作成である.

事前に公式のテンプレート配布ページからfontsandtemplates.zipをダウンロードして,フォントをインストールしておく必要がある.

Inkscape画像作成編

  1. Inkscape(またはAdobe Illustrator)でファイルメニューからドキュメントのプロパティーを選択
  2. 工作の範囲では2.54mm(0.1in)ピッチのものが多く,今回もそれと同等なのでグリッドを0.1inにしたいので,グリッドから単位をインチinにして0.1ごとになるように設定
  3. 商品画像を実寸で並べてブレッドボードビュー画像を作成していく
  4. ひととおり作成が完了したら,再度,ドキュメントのプロパティーを選択して,作成画像が余白なくフィットするようにリサイズを実行する
  5. リサイズ実行後は,パーツ以外の部分はグレーアウトしてぴったりフィットする(フォントはOCRAを使用している)
  6. 保存時は,Inkscape SVGでも問題なかったが,公式の手順ではPlain SVGとのことである

なお,ブレッドボードビューの画像作成としてはここで完了で,回路図ビューも同等の手順のため割愛する. ただし,ブレッドボードビューに関しては,Fritzingへの取り込み時に以下の問題が発生する(と思われる)ので,これらも対応することを推奨する.

ピン番号が自動的に割り当てられないことへの対処

ブレッドボードビュー画像自体は作成完了したが,この状態ではFritzingに取り込んだ際にピン番号が自動的に割り当てられないために,XMLエディターでオブジェクト名を編集する必要がある.たとえば,1ピンの場合は,該当の図形を選択してid名をconnector0pinにする.2ピンならconnector1pinというようにid名はピン名-1の値となる.

XMLエディターの起動
"ピン"の画像idを`connector#pin`に変更

Fritzingに取り込み後,画像内のフォントが小さくなってしまうことへの対処

以下の画像のように,Inkscape(左)では問題ないが,Fritzing(右)ではフォントが極小になってしまう問題が発生する*2

シルクに対応する文字が極小になる

回避策のひとつとして,該当するテキストのフォントサイズ設定において,数字だけではなくて,単位(ここではpt)も付与して決定すると回避できた.

フォントサイズ指定は単位をつける

Fritzingパーツ取込編

  1. Core PartsからGeneric ICを選択,ブレッドボードビューに配置してから,ピン数をデフォルトの8ピンから16ピンに変更
  2. Generic IC(名称をAE-TYBLE16に変更している)を右クリックして,Edit (new parts editor)を押下
  3. パーツエディターは,起動時にはブレッドボードビューで,ピン名称Nameをpin#(#は自然数)からDIP#に,ピン詳細Descriptionをpin #からP0.#などに変更
  4. ファイルメニューからLoad image for viewを選択して,先に作成したブレッドボードビューの画像(svgファイル)を読み込む
  5. 正しくピン名称も読み込まれると,ピン名称の左隣にチェックマークがつく(読み込まれない場合は前述のオブジェクト名変更connector#pinが必要)
  6. 次に,回路図ビューだが,デフォルトではピン番号のみしか記載がないため,ファイルメニューからShow in Folderから実際のこの回路図画像を探し出して修正し,その修正後の画像を取り込む
  7. 次に,基板図ビューは,今回既存のdip_16_300mil_pcb.svgから変更しないのでこのままでよい*3
  8. 次に,アイコンビューとなるが,これはブレッドボードビュー画像をそのまま利用するため,ファイルメニューからReuse breadboard imageを選択する
  9. 最後に,パーツエディター内で別のシートのメタデータに移動し,好みのデータを入力する

上記操作を実施後,ファイルメニューからSave as new partを選択して,保存したいパーツ名称を入力してOKを押すと,以下の該当するディレクトリーに該当のsvgファイルなどが保存される(部品の重複を防ぐために,おそらくハッシュ値が付与されるつくり).私の環境の場合はAE-TYBLE_300milと入力してブレッドボードビュー画像としてAE-TYBLE_700mil_d01f9ebe032b59cc62e6811b06fe15be_1_breadboard.svgが作成された.

部品名称入力ダイアログ

部品名称 パス(デフォルト)
ブレッドボードビュー %USERPROFILE%\Documents\Fritzing\parts\svg\user\breadboard\
回路図ビュー %USERPROFILE%\Documents\Fritzing\parts\svg\user\schematic\
基板図ビュー %USERPROFILE%\Documents\Fritzing\parts\svg\user\pcb\
アイコン %USERPROFILE%\Documents\Fritzing\parts\svg\user\icon\
fzpファイル %USERPROFILE%\Documents\Fritzing\parts\user\

その他

ほぼ15年ぶりくらいにInkscapeを使ってみて,知らないうちに大きく変わっていた(ような気がしてしまった)と思う.それに加えて,交差の方法だけでなく,中央揃えというような操作まで全然覚えていなくてたいへんだった.

また,Fritzingのパーツ作成で,どうしてもハッシュ値がないパーツ名を作成したかったが,本質的でもないしムダな時間を消費してしまった!

なお,開始当初は以下の画像で行こうと思っていたので,個人的にはだいぶ頑張ったほう.

着手当初の画像

改訂履歴

# 日付 内容
1 2023/02/26 GitHubへのコミットとリンクを記載
節 詳細を記載

参考サイト

  1. Fritzing カスタムパーツの作り方 – jumbleat
  2. New Parts Editor released
  3. InkscapeでDesign- 円/扇型/弧
  4. Inkscape | 切り取りと切り抜き、差分と交差の使い方 | ONE NOTES
  5. Inkscapeで線を引く3つのツールの使い方 | イズクル

リンク先はすべて2023/02/26現在のもの

*1:既に2ヶ月経ってしまった...

*2:実はご覧のとおり,金属枠が真四角になってしまう問題も発生しているが対処方法が全くわからない.

*3:GitHub上のデータはファイル名称だけ変更して使用している.

Device Tree Compilerのエラー2.2-8 syntax errorを解決する

目的

以下のUdemyの教材

www.udemy.com

で,Device Treeの第14章にてDTC(Device Tree Compiler)のコンパイルで以下のエラー2.2-8 syntax errorが出て,全く先に進めなかったのだが,解決策をひとつ見つけたので紹介しておく.

$ cat PCDEV0.dts 
/dts-v1/;
/plugin/;
/ {
    fragment@0 {
        target = <&pcdev1>;
        __OVERLAY__ {
            status = "disabled";
        };
    };
    fragment@1 {
        target = <&pcdev2>;
        __OVERLAY__ {
            status = "disabled";
        };
    };
    fragment@2 {
        target = <&pcdev3>;
        __OVERLAY__ {
            org,size = <1048>;
            org,device-serial-num = "PCDEV4XXXXXX";
        };
    };
};
$ dtc -I dts -O dtb -o PCDEV0.dtbo PCDEV0.dts 
Error: PCDEV0.dts:2.2-8 syntax error
FATAL ERROR: Unable to parse input tree

なお,使用しているLinuxディストリビューションは,Ubuntu 16.04*1で,DTCはバージョン1.4.0である.

$ uname -a
Linux so2akt-VirtualBox 4.15.0-142-generic #146~16.04.1-Ubuntu SMP Tue Apr 13 09:27:15 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
$ dtc -v
Version: DTC 1.4.0

結論

Ubuntu 16.04のaptでインストールされるDTCのバージョン1.4.0が古いのか,バグがあるのかという原因で,ビルドエラーが出る.そのためより新しいバージョンを使う必要があり,ソースコードからビルドして1.4.7を作るシェルがGitHubで提供されていたため,それを使うことで解決できた:

github.com

$ wget https://raw.githubusercontent.com/beagleboard/bb.org-overlays/master/dtc-overlay.sh
$ sudo chmod 777 dtc-overlay.sh 
$ sudo -s
# ./dtc-overlay.sh 
# dtc -v
Version: DTC 1.4.7
# dtc -I dts -O dtb -o PCDEV0.dtbo PCDEV0.dts 
PCDEV0.dtbo: Warning (unit_address_vs_reg): /fragment@0: node has a unit name, but no reg property
PCDEV0.dtbo: Warning (unit_address_vs_reg): /fragment@1: node has a unit name, but no reg property
PCDEV0.dtbo: Warning (unit_address_vs_reg): /fragment@2: node has a unit name, but no reg property
# ls
PCDEV0.dtbo  PCDEV0.dts

なお,そのシェル実行前には,念のため

$ sudo apt-get remove device-tree-compiler

にて既存のDTC 1.4.0を削除してから実行した.

詳細

Googleで検索すると,いくらか同等の現象に直面している人がいたが,なかなか対策がわからなかった.

Ubuntuの新しいものにアップグレード,または新規インストールすれば簡単に済む話でもあるが,仕事上で16.04を使う必要があってその環境をそのままこのUdemyの学習に使用しているので面倒だと考えているときに,ちょうどRaspberry Piのフォーラム

forums.raspberrypi.com

で同じ現象が紹介されており,そのリンク先にソースコードからDTCをビルドするシェルが紹介されていたので,この対策に至った*2

コンソール実行の生データは以下のとおり:

root@so2akt-VirtualBox:~/workspace/ldd/custom_drivers/overlays# uname -a
Linux so2akt-VirtualBox 4.15.0-142-generic #146~16.04.1-Ubuntu SMP Tue Apr 13 09:27:15 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
root@so2akt-VirtualBox:~/workspace/ldd/custom_drivers/overlays# cat PCDEV0.dts 
/dts-v1/;
/plugin/;
/ {
    fragment@0 {
        target = <&pcdev1>;
        __OVERLAY__ {
            status = "disabled";
        };
    };
    fragment@1 {
        target = <&pcdev2>;
        __OVERLAY__ {
            status = "disabled";
        };
    };
    fragment@2 {
        target = <&pcdev3>;
        __OVERLAY__ {
            org,size = <1048>;
            org,device-serial-num = "PCDEV4XXXXXX";
        };
    };
};
root@so2akt-VirtualBox:~/workspace/ldd/custom_drivers/overlays# dtc -I dts -O dtb -o PCDEV0.dtbo PCDEV0.dts 
Error: PCDEV0.dts:2.2-8 syntax error
FATAL ERROR: Unable to parse input tree
root@so2akt-VirtualBox:~/workspace/ldd/custom_drivers/overlays# dtc -v
Version: DTC 1.4.0
so2akt@so2akt-VirtualBox:~$ sudo apt-get remove device-tree-compiler
so2akt@so2akt-VirtualBox:~/Downloads$ wget https://raw.githubusercontent.com/beagleboard/bb.org-overlays/master/dtc-overlay.sh
--2023-02-16 11:28:41--  https://raw.githubusercontent.com/beagleboard/bb.org-overlays/master/dtc-overlay.sh
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.110.133, 185.199.109.133, 185.199.108.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.110.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1245 (1.2K) [text/plain]
Saving to: ‘dtc-overlay.sh’

dtc-overlay.sh                                     100%[================================================================================================================>]   1.22K  --.-KB/s    in 0s      

2023-02-16 11:28:42 (107 MB/s) - ‘dtc-overlay.sh’ saved [1245/1245]

so2akt@so2akt-VirtualBox:~/Downloads$ sudo chmod 777 dtc-overlay.sh 
[sudo] password for so2akt: 
so2akt@so2akt-VirtualBox:~/Downloads$ sudo -s
root@so2akt-VirtualBox:~/Downloads# ./dtc-overlay.sh 
Cloning into '/home/so2akt/git/dtc'...
remote: Enumerating objects: 31, done.
remote: Counting objects: 100% (31/31), done.
remote: Compressing objects: 100% (31/31), done.
remote: Total 5874 (delta 9), reused 0 (delta 0), pack-reused 5843
Receiving objects: 100% (5874/5874), 1.37 MiB | 826.00 KiB/s, done.
Resolving deltas: 100% (4323/4323), done.
Checking connectivity... done.
     CLEAN (libfdt)
     CLEAN (pylibfdt)
     CLEAN (tests)
     CLEAN
Already on 'master'
Your branch is up-to-date with 'origin/master'.
Already up-to-date.
Switched to a new branch 'v1.4.7-build'
     CLEAN (libfdt)
     CLEAN (pylibfdt)
     CLEAN (tests)
     CLEAN
     DEP tests/dumptrees.c
     DEP tests/trees.S
     DEP tests/testutils.c
     DEP tests/value-labels.c
     DEP tests/asm_tree_dump.c
     DEP tests/truncated_memrsv.c
     DEP tests/truncated_string.c
     DEP tests/truncated_property.c
     DEP tests/check_full.c
     DEP tests/check_header.c
     DEP tests/check_path.c
     DEP tests/overlay_bad_fixup.c
     DEP tests/overlay.c
     DEP tests/subnode_iterate.c
     DEP tests/property_iterate.c
     DEP tests/integer-expressions.c
     DEP tests/utilfdt_test.c
     DEP tests/path_offset_aliases.c
     DEP tests/add_subnode_with_nops.c
     DEP tests/dtbs_equal_unordered.c
     DEP tests/dtb_reverse.c
     DEP tests/dtbs_equal_ordered.c
     DEP tests/extra-terminating-null.c
     DEP tests/incbin.c
     DEP tests/boot-cpuid.c
     DEP tests/phandle_format.c
     DEP tests/path-references.c
     DEP tests/references.c
     DEP tests/string_escapes.c
     DEP tests/propname_escapes.c
     DEP tests/appendprop2.c
     DEP tests/appendprop1.c
     DEP tests/del_node.c
     DEP tests/del_property.c
     DEP tests/setprop.c
     DEP tests/set_name.c
     DEP tests/rw_tree1.c
     DEP tests/open_pack.c
     DEP tests/nopulate.c
     DEP tests/mangle-layout.c
     DEP tests/move_and_save.c
     DEP tests/sw_states.c
     DEP tests/sw_tree1.c
     DEP tests/nop_node.c
     DEP tests/nop_property.c
     DEP tests/setprop_inplace.c
     DEP tests/stringlist.c
     DEP tests/addr_size_cells2.c
     DEP tests/addr_size_cells.c
     DEP tests/notfound.c
     DEP tests/sized_cells.c
     DEP tests/char_literal.c
     DEP tests/get_alias.c
     DEP tests/node_offset_by_compatible.c
     DEP tests/node_check_compatible.c
     DEP tests/node_offset_by_phandle.c
     DEP tests/node_offset_by_prop_value.c
     DEP tests/parent_offset.c
     DEP tests/supernode_atdepth_offset.c
     DEP tests/get_path.c
     DEP tests/get_phandle.c
     DEP tests/getprop.c
     DEP tests/get_name.c
     DEP tests/path_offset.c
     DEP tests/subnode_offset.c
     DEP tests/find_property.c
     DEP tests/root_node.c
     DEP tests/get_mem_rsv.c
     DEP libfdt/fdt_overlay.c
     DEP libfdt/fdt_addresses.c
     DEP libfdt/fdt_empty_tree.c
     DEP libfdt/fdt_strerror.c
     DEP libfdt/fdt_rw.c
     DEP libfdt/fdt_sw.c
     DEP libfdt/fdt_wip.c
     DEP libfdt/fdt_ro.c
     DEP libfdt/fdt.c
     DEP util.c
     DEP fdtoverlay.c
     DEP fdtput.c
     DEP fdtget.c
     DEP fdtdump.c
     LEX convert-dtsv0-lexer.lex.c
     DEP convert-dtsv0-lexer.lex.c
     DEP srcpos.c
     BISON dtc-parser.tab.c
     DEP dtc-parser.tab.c
     LEX dtc-lexer.lex.c
     DEP dtc-lexer.lex.c
     DEP treesource.c
     DEP livetree.c
     DEP fstree.c
     DEP flattree.c
     DEP dtc.c
     DEP data.c
     DEP checks.c
    CHK version_gen.h
    UPD version_gen.h
     DEP util.c
    CHK version_gen.h
     CC srcpos.o
     CC util.o
     CC convert-dtsv0-lexer.lex.o
     LD convert-dtsv0
     CC dtc.o
     CC checks.o
     CC data.o
     CC flattree.o
     CC fstree.o
     CC livetree.o
     CC treesource.o
     CC dtc-lexer.lex.o
     CC dtc-parser.tab.o
     LD dtc
     CC fdtdump.o
     LD fdtdump
     CC fdtget.o
     CC libfdt/fdt.o
     CC libfdt/fdt_ro.o
     CC libfdt/fdt_wip.o
     CC libfdt/fdt_sw.o
     CC libfdt/fdt_rw.o
     CC libfdt/fdt_strerror.o
     CC libfdt/fdt_empty_tree.o
     CC libfdt/fdt_addresses.o
     CC libfdt/fdt_overlay.o
     AR libfdt/libfdt.a
     LD fdtget
     CC fdtput.o
     LD fdtput
     CC fdtoverlay.o
     LD fdtoverlay
     LD libfdt/libfdt-1.4.7.so
## Skipping pylibfdt (install python dev and swig to build)
Installing into: /usr/local/bin/
    CHK version_gen.h
## Skipping pylibfdt (install python dev and swig to build)
     INSTALL-BIN
     INSTALL-LIB
     INSTALL-INC
## Skipping pylibfdt (install python dev and swig to build)
dtc: Version: DTC 1.4.7
root@so2akt-VirtualBox:~/Downloads# dtc -v
Version: DTC 1.4.7
root@so2akt-VirtualBox:~/workspace/ldd/custom_drivers/overlays# dtc -I dts -O dtb -o PCDEV0.dtbo PCDEV0.dts 
PCDEV0.dtbo: Warning (unit_address_vs_reg): /fragment@0: node has a unit name, but no reg property
PCDEV0.dtbo: Warning (unit_address_vs_reg): /fragment@1: node has a unit name, but no reg property
PCDEV0.dtbo: Warning (unit_address_vs_reg): /fragment@2: node has a unit name, but no reg property
root@so2akt-VirtualBox:~/workspace/ldd/custom_drivers/overlays# ls
PCDEV0.dtbo  PCDEV0.dts

参考サイト

  1. Dtc compilation fails - Raspberry Pi Forums
  2. RobertCNelson dtc_overlay.sh

リンク先はすべて2023/02/16現在のもの

*1:これが一番の問題!

*2:思わず,上記UdemyのQ&Aに諦めた!というメッセージを投稿してしまい,すぐ1時間後くらいに解決した!というメッセージを投稿してしまった

Excel 2013のハイパーリンクが開けない現象を解消する

目的

直近,電子工作での部品リストを書いている中で,自宅PCで開く場合,以下のエラー組織のポリシーにより、この操作を完了できません。ヘルプデスク担当者に問い合わせてください。が必ず出てハイパーリンクが開けなかった*1

ハイパーリンクが開けないときのメッセージウィンドウ

この記事では,この問題の解消方法を記載する.

名称 規格 製造会社 備考
オペレーティングシステム Windows 10 Pro(64ビット),バージョン20H2 マイクロソフト インターナショナル版
Excel 2013 Office Professional Plus 2013版 マイクロソフト 日本語版

結論

Windows の機能の有効化または無効化から,Internet Explorer 11を有効(チェックを入れる)にして,PCを再起動する.

詳細

どうやら,Excel(少なくとも,現象が発生した2013)では裏でInternet Explorerを呼んでいるようである.そのため,Internet Explorerがシステム上存在しない場合,ハイパーリンクが開けない.詳細な対策手順は以下のとおり:

  1. コントロールパネルを起動する
  2. プログラムのアンインストールをクリックする
  3. Windows の機能の有効化または無効化をクリックする
  4. チェックされていないInternet Explorer 11にチェックを入れてOKを押す
  5. インストール等の操作が自動で進んだあと,今すぐ再起動を押す
    今すぐ再起動

後になって知ったが,OptionalFeatures.exeを実行すれば,GUIの操作を最小限で,Windows の機能の有効化または無効化を呼び出すことができる

OptionalFeatures.exeの呼び出し

参考サイト

  1. Excelでリンクをクリックすると「組織ポリシー…」のエラーで開かない!
  2. Windows 10ミニTips(158) コマンドラインからWindows 10の機能を有効・無効にする | マイナビニュース

リンク先はすべて2023/02/05現在のもの

*1:会社PCのExcelでは問題なかった