【Windows】マイク入力のノイズの除去

テレビの音声をPCにマイク入力で渡して、PCとテレビの音を一つのイヤホンで聞く、ということをやっていたのですが、
テレビのノイズがひどかったのでリアルタイムノイズ除去をするようにしました。
その備忘録です。
※実際にはライン入力で試しましたがやり方はUSBでもマイク端子でも同じです。

やり方は下記のブログの方を参考にしました。
【VC、ニコ生向け】マイクに乗ったノイズをリアルタイムで軽減する方法:たすりーのブロマガ - ブロマガ

簡単に書くと下記のような手順です。

  1. Audacityなどを使用してノイズを録音
  2. ノイズのスペクトルデータをCSVファイルとして保存
  3. Equalizer APOをインストール
  4. Equalizer APO にスペクトルデータを読み込ませて反転させる

Equalizer APOはイコライザーですので、不快な周波数領域をカットすることができます。
インストールするだけで特定デバイスの入力信号を調節することができるので、
すべてのソフトに対して使用することができて便利です。

【Unity】3Dと2Dの物体の衝突はできない

UnityではColliderを使って物体間の衝突を検知する。
Colliderは3Dと2DそれぞれのColliderが用意されていて、3Dと3Dの衝突、2Dと2Dの衝突検知はできるんだけど、3Dと2DのColliderの衝突は検知できないらしい。

下記のQ&Aを参照。
Can Rigidbody 2D collide with 3D Colliders? - Unity Answers

なぜならば 3DではPhysXを、2DではBox2Dという別々のライブラリを使っているため。

解決策は以下の通り。
1. 3Dオブジェクトの子オブジェクトとして空のオブジェクトを追加。
2. 空のオブジェクトにBoxCollider2Dを追加する。サイズはオブジェクトに合わせること。
3. 空のオブジェクトにRigidBody2Dを追加する。GravityScaleは0にすること。 サイズはオブジェクトに合わせること。

あるいは上記の逆、2Dオブジェクトに3DのColliderを追加でもよい。

【Python】MIDIをwavファイルに変換

MIDIをwavファイルに変換するためにFluidSynthというライブラリを使った。結構めんどくさかった。
手順はほとんど下記のとおり。
参考:(Windows) pythonでMIDIからWAVを出力 - Qiita
Windowsだからかもしれないけど、参考ページにあるようにライブラリのファイルを修正しないといけなかった。

vcpkgのインストール

  1. ダウンロードする。https://github.com/Microsoft/vcpkg.git
  2. 解凍する。
  3. 解凍したフォルダに移動して下記を実行。
cd vcpkg
.\bootstrap-vcpkg.bat
.\vcpkg integrate install #管理者権限が要求されるので許可する
※下記コマンドの前にVisual Studioに言語パック(英語)をインストール
.\vcpkg install sdl2 curl
# 不要かもしれないけど一応下記コマンド。
.\vcpkg integrate powershell


fluidsynthをインストール

  1. ダウンロードする。https://github.com/FluidSynth/fluidsynth
  2. 解凍する。
  3. 解凍したフォルダに移動して下記を実行。
cd path/to/fluidsynth-2.0.5
path/to/vcpkg install fluidsynth:x64-windows
# 上記コマンドでインストールされるので、下記は不要
# path/to/vcpkg install glib:x64-windows



pyfluidsynthをインストール

  1. pip install pyfluidsynth
  2. path\to\Anaconda3\Lib\site-packages\fluidsynth.pyを修正する。 参考ページの方に従ってファイルを修正。

#変更前
# lib = find_library('fluidsynth') or \
#     find_library('libfluidsynth') or \
#     find_library('libfluidsynth-1')
#変更後
lib = find_library('fluidsynth') or \
find_library('libfluidsynth') or \
find_library('libfluidsynth-2')
以下の変数定義をコメントアウト
fluid_synth_get_channel_info 
fluid_synth_set_reverb_full 
fluid_synth_set_chorus_full 
fluid_synth_get_chorus_speed_Hz 
fluid_synth_get_chorus_depth_ms 
fluid_synth_set_midi_router 

3. ビルドしたfluidsynthのパスを上記ファイルの先頭に追加。

improt sys
sys.path.append("path\\to\\vcpkg\\installed\\x64-windows\\bin") 
#バックスラッシュを使うときは二つずつにしないといけない。エスケープ文字になっちゃうから。

確認

import fluidsynthができればOK

【Python】matplotlibのGIFアニメーションを作成する

オブジェクト指向でのGIFアニメーション作成方法を記載する。

事前準備

matplotlibのオブジェクト指向とはplt.plotではなくax.plot()でプロットする方法のこと。
グラフの軸やプロットラインがアーティストと呼ばれることを知っていると理解が楽。
オブジェクト指向やアーティストの説明は下記のブログなどを参照。
matplotlibをオブジェクト指向スタイルで使う その1 - minus9d's diary
matplotlib - matplotlib の使うために理解するべき基本要素 - Pynote

またgifアニメーションの作成には事前準備が必要。
下記のブログなどを参照。
matplotlibでアニメーションを作成,保存 - 粗大メモ置き場


GIFアニメの保存

import matplotlib.pyplot as plt
import matplotlib.animation as animation
#グラフ作成
fig, ax = plt.subplots(1,1)
a1 = ax.plot([0, 0])
a2 = ax.plot([1, 1])
a3 = ax.plot([2, 2])
#リストのリストとしてartistを保存
arts = [a1, a2, a3]
#アニメの作成
ani = animation.ArtistAnimation(fig, arts)
#gifファイルとして保存
ani.save('axes.gif', writer='imagemagick')

f:id:gushigo:20190505224934g:plain

理解を深めるために

アニメーションの原理とmatplotlibの構造を理解するために下記のコードでGIFを作成する。

import matplotlib.pyplot as plt
import matplotlib.animation as animation
#グラフ作成
fig, ax = plt.subplots(1,1)
ax.plot([0, 0])
ax.plot([1, 1])
ax.plot([2, 2])
#画像の保存
fig.savefig('image.png')
#リストのリストとしてartistを取得
arts = [[art] for art in ax.get_children()]
#アニメの作成
ani = animation.ArtistAnimation(fig, arts)
#gifファイルとして保存
ani.save('alL_arts.gif', writer='imagemagick')

#artsの中身の確認
print(arts)
# Out:
#[[<matplotlib.lines.Line2D at 0xb80dc97a20>],
# [<matplotlib.lines.Line2D at 0xb80c8cc080>],
# [<matplotlib.lines.Line2D at 0xb80c8cc208>],
# [<matplotlib.spines.Spine at 0xb80dc93630>],
# [<matplotlib.spines.Spine at 0xb80dc93748>],
# [<matplotlib.spines.Spine at 0xb80dc93860>],
# [<matplotlib.spines.Spine at 0xb80dc93978>],
# [<matplotlib.axis.XAxis at 0xb80dc93a58>],
# [<matplotlib.axis.YAxis at 0xb80dcaf0f0>],
# [Text(0.5,1,'')],
# [Text(0,1,'')],
# [Text(1,1,'')],
# [<matplotlib.patches.Rectangle at 0xb80c8b5828>]]

image.png
f:id:gushigo:20190505225521p:plain
alL_arts.gif
f:id:gushigo:20190505223319g:plain

ArtistAnimationでは第一引数にfigureを、第二引数にリスト与えている。
リストはfigureが持つアーティストでないといけないはず。
アニメーションはリストに含まれないアーティストがすべて表示された状態で、リストのアーティストが一つずつ表示されるようになっているように思える。

ちなみにSpyderにてウィンドウでグラフ表示しているときにani.save()をすると、ウィンドウにはアニメーションが表示されたが、ファイルとして保存されなかった。ウィンドウを消してから同じコマンドを実行したら無事保存された。謎挙動。

【Windows】ウィンドウを画像化して保存する方法

  1. ウィンドウを選択 した状態にする
    f:id:gushigo:20190425225058p:plain:w320
  2. Alt+PrintScreenキーを押す
  3. Winキー+rで「ファイル名を指定して実行」ウィンドウを立ち上げる
  4. mspaintを入力してEnterを押してペイントを起動する
    f:id:gushigo:20190425223100p:plain
  5. Ctrl+vで貼り付ける
  6. Ctrl+sで保存

多分これが最速です。
Alt+PrintScreenでウィンドウの画像をクリップボードに保存できます。
WindowsのOSバージョンにかかわらず使用できます。

【Excel】読み取り専用で開く方法

エクセルファイルを読み取り専用で開く方法を2つ紹介します。


クイックアクセスツールバーを使う

Excelではクイックアクセスツールバーを使って色々な機能のショートカットを使うことができます。
その一つに「読み取り専用」があります。
オプション>クイックアクセスツールバーですべてのコマンドを選び「読み取り専用の設定/解除」を設定することで、
いつでもファイルを読み取り専用にしたり書き込みできるようにしたりできるようになります。


1. オプションを開く f:id:gushigo:20190421115710p:plain


2. 「読み取り専用の設定/解除」をクイックアクセスツールバーに追加する f:id:gushigo:20190421115700p:plain


3. クイックアクセスツールバーにボタンが現れ、クリックすることで読み取り変更に変更できる f:id:gushigo:20190421120044p:plain


新規ファイルとして開く

右クリックから新規を選ぶことで、元ファイルに影響しないように開くことができます。
そのため読み取り専用で開くとして機能します。
f:id:gushigo:20190421115707p:plain


その他

ネットワークドライブにあるファイルを開こうとすると保護されたファイルとして開かれ読み取り専用と同じ機能を果たしますが、 セルが選択できなかったりフィルター機能が使えなかったり制限が多いです。

【Python】ソースコードを解析して関数名だけ抽出する

作成したソースコード内に存在する関数名を抽出する。 astモジュールを使用。

下記の参考ページのコードから一部変更。
parsing - How to extract functions used in a python code file? - Stack Overflow

import ast

class CallCollector(ast.NodeVisitor):
    def __init__(self):
        self.calls = []
        self.current = None

    def visit_Call(self, node):
        # new call, trace the function expression
        self.current = ''
        self.visit(node.func)
        self.calls.append(self.current)

    def generic_visit(self, node):
        if self.current is not None:
            print("warning: {} node in function expression not supported".format(
                node.__class__.__name__))
        super(CallCollector, self).generic_visit(node)

    # record the func expression 
    def visit_Name(self, node):
        if self.current is None:
            return
        self.current += node.id

    def visit_Attribute(self, node):
        if self.current is None:
            self.generic_visit(node)
        self.visit(node.value)  
        self.current += '.' + node.attr

#ファイルを開く
with open('./mysoure.py', encoding='utf-8') as f:
    tree = ast.parse(f.read())
cc = CallCollector()
cc.visit(tree)
#リスト形式で関数名を出力
print(cc.calls)

astモジュールはデザインパターンのvisitorパターンを使っていることに注意すれば対して難しくない。