Wizard Notes

Python, JavaScript を使った音楽信号分析の技術録、作曲活動に関する雑記

MS処理のためのMid/Side変換の実装解説(Pythonスクリプト付き)

MS処理(Mid/Side変換)とは?

f:id:Kurene:20191103061507p:plain
MS処理のイメージ

音響機器やマスタリングプラグインMS処理という表記を見かけたことはありませんか?

MS処理は、通常左右に分かれているステレオの信号を、 中央(ミッド)成分と非中央(サイド)成分に変換し、それぞれにコンプやEQなどのエフェクトをかけて、LR信号に戻す処理を指します。 このMid/Side信号を得る計算は Mid/Side変換(Mid/Side分解)と呼ばれています。

上記の画像のような環境で録音したステレオ信号に対してMid/Side変換を行うと、Mid成分にはボーカルやドラム、Side成分にはベースやギターの音が集中することが期待されます。 また、逆にMid/Side信号からL/R信号を得ることもできます。

例えば、通常、ボーカルは中央に定位しているため、Mid/Side変換を使えばボーカル成分が多く含まれる信号を得ることができます。しかも演算は単純な足し引きだけなので、非常にお得な処理です。

それでは、MS処理でも使われている、Mid/Side変換の実現方法について紹介します

基本

LR => Mid/Sideへの変換

Mid, Sideは単純な足し算・引き算で求まりますので、以下のように演算になります。 f:id:Kurene:20191103052817p:plain

Mid/Side => LRへの変換

逆行列を考えると、以下のようになります。 f:id:Kurene:20191103065241p:plain

実装 (Python)

注意点として、LibROSAの librosa.load でステレオ信号をロードするときはキーワード引数 monomono=Trueにしてください(なお、mono=False だと Mid 信号だけがモノラル信号として返ってきます*1

import numpy as np
audiofilepath = "your stereo audio file"
sr = ...
x_LR, sr =  librosa.load(audiofilename, sr=sr, Mono)
# y.shape == (2, n_samples)

# LR to MS
A = np.array([[1.0, 1.0], [1.0, -1.0]])
y_MS = np.dot(A, x_LR)
# y_MS[0] is mid ch.
# y_MS[1] is side ch.

# MS processing
y_MS[0] = mid_processing(y_MS[0])
y_MS[1] = side_processing(y_MS[1])

# MS to LR
A_inv = np.linalg.inv(A)
# or A_inv = np.array([[0.5, 0.5], [0.5, -0.5]])
x_LR_rec = np.dot(A_inv, y_MS)

応用

MS処理を実装しようとすると、信号のスケールを制御したくなる時があります。

具体的には、LとRの信号を足し引きした時、またはMid/Side領域の信号処理で、値がオーバーフロー/アンダーフローしてしまうときです。

その場合、以下のような演算で係数をうまく調整します。ただし、逆変換するためには a_{Mid}≠0 かつ a_{Side}≠0です。

LR =>Mid/Sideへの変換

f:id:Kurene:20191103053059p:plain

Mid/Side => LRへの変換

f:id:Kurene:20191103053032p:plain

MS処理は良いことばかり?

MS処理をいい感じに使うと、音像がハッキリしたり、ステレオ感が増すこともあるのですが、あまりいじりすぎると逆に音像がスカスカになってしまうこともあります(特にSide成分を持ち上げた時)。

下記のサイトが詳しく書いてくださいっていますので、ご興味ある方は是非読んでみてください。

M/S処理と留意事項:Studio Gyokimae