Xmas Contest 2017
A - Compressor
問題
- どっちがコンプレッサーかけた音でしょう?(15問)
所感
これを1問目にぶち込んでくるセンスよ。面白いなあ。
耳で聴いたら10/15だった。意外といけるな(自分に対するハードルが低い)
ここまで巫山戯た問題なら、解答側も Brute force で自動Submit する人とかいそうだけど、連投制限あるんだっけ。
解法
wavを読み込んでサンプリングされた数値を得ても、コンプレッサー前後の数値的特徴がどんなところに現れるか、というセンスが無いとどうしようもない。
今回の問題では、「尖度」を計算することでぴたりと答えに当てはまるとのこと。
import wave
from scipy import fromstring, int16
from scipy.stats import variation, kurtosis
src_tpl = 'C:\\path\\to\\data\\input\\{:02d}_{}.wav'
def kurt(wav_path):
with wave.open(wav_path, 'rb') as wr:
data = wr.readframes(wr.getnframes())
nums = fromstring(data, dtype=int16)
return variation(nums), kurtosis(nums)
v_ans, k_ans = [], []
for i in range(1, 16):
va, ka = kurt(src_tpl.format(i, 'A'))
vb, kb = kurt(src_tpl.format(i, 'B'))
v_ans.append('A' if va < vb else 'B')
k_ans.append('A' if ka < kb else 'B')
print(''.join(v_ans)) # 分散
print(''.join(k_ans)) # 尖度
# 分散: BBABBBBABABBAAB
# 尖度: AABAAAABABABBAB
# 答え: AABAAAABABABBAB
サンプリング数値の絶対値の大きさは、大まかには音量を表す。
コンプレッサーは、ざっくり言うと以下の処理を行う。
- 音量の大きい所を小さくする
- 小さくした分、全体的に音量をわずかに上げる
これらが、サンプリング数値に及ぼす影響は、以下になる。
- サンプリング数値が閾値以上のものが、一定の割合で小さくなる
- 全てのサンプリング数値が、一定の割合で大きくなる
(厳密には、自然に聞こえるように、圧縮されるサンプルの前後では割合が緩やかに変化するため、単純では無い)
大きい音から小さい音までとっ散らかった音量がコンプレッサーで圧縮されるので、直感的には分散が減りそう……と思ったが、その後で全体の音量を上げるので、かけた後の方が(平均ー個々のサンプル)が多くのサンプルで僅かずつ大きくなり、結果として分散が増えるようだ。ただしそれも圧縮されたサンプル数と量に依るので、正しかったり正しくなかったりする。
尖度なら、平均より外れたデータが分散よりさらに重大に評価されるので、よく当てはまったということか。

