海苔音源をプログラミングでなんとかしてみる

#概要
　近年の[音圧戦争](http://tmt481.blogspot.jp/2014/05/cd.html)により、「マスタリング段階で波形の高い部分がダイナミックレンジに収まりきらずクロップされてしまう」という憂き目に遭う**海苔音源**が多く発生しています。[大雑把に原因を示した画像](https://twitter.com/YSRKEN/status/662991961675071489)もありますが、こうなると[無駄な高周波成分が発生](http://www.orixrentec.jp/helpful_info/detail.html?id=17)して音が劣化するのは**火を見るより明らか**ですね。
　そこで、適切に補間することで、その状態をどの程度解消できるかを実験してみることにしました。

#まずはライブラリを揃えよう
　wavファイルを読み込むためのライブラリは、適当にググッて見つけた「[WAV ファイルを読み込むよ！](http://d.hatena.ne.jp/colorcle/20100203/1265209117)」にしました。8 or 16bitで1 or 2chのwavファイルを読み込めるC++用のライブラリですが、微修正(少しincludeの記述を追加)程度でVS2013でも使えたので凄く助かりました。
　このライブラリでは、1データにつき8bitでは0～255、16bitでは-32768～32767の範囲のshort型として読み込みます。また、各チャンネルごとのデータはstd::vector\<short\>型に代入されるので、C++側から扱うのが楽というメリットも……[良いですね、良いと思います！](http://wikiwiki.jp/kancolle/?Littorio)
　また、「クロップされた部分」の定義についてですが、とりあえず「生の値が一定以上・以下であるもの」とします。例えば16bitオーディオなら、「-32760以下か32760以上のデータ＝クロップ箇所」とする感じですね。1データ[だけなら誤差かもしれない](http://dic.nicovideo.jp/a/%E8%AA%A4%E5%B0%84)ので、そういった**極端に大きな値が2データ以上続いている場合**を対象とします。

#補間方法を考える
　数学上での補間は様々存在しますが、ここでは**線形補間**および**ラグランジュ補間**を使用することにします。
　線形補間の場合、$(x_0, y_0)$と$(x_1, y_1)$とを通る直線が$y=y_0+\frac{(y_1-y_0)(x-x_0)}{(x_1-x_0)}$で表されることを利用して、図1のような三角形に補間します。
　ラグランジュ補間の場合、$(x_0, y_0),(x_1, y_1),...,(x_N, y_N)$を通る曲線が$y=\sum_{k=0}^N L_k(x)y_k　L_k(x)=\prod_{j=0}^N \frac{x-x_j}{x_k-x_j}　j\neq k$で表わされることを利用して、クロップ箇所の前後から2点づつ取って3次関数として図2のように補間します。
![cap.png](https://qiita-image-store.s3.amazonaws.com/0/29802/cf0ab877-e936-d32b-91d5-d75d164d1e2b.png)
　……なお、ここでお気づきの方もいらっしゃると思いますが、補間する際は**全体の音量を下げた後、補間部分でクロップ箇所を埋める**といった作業になります。

#実験および結果
　上記の考えからC++で実装しました(試行錯誤中なのでソースは貼れませんが)。補間するサンプルとして、[Sound Engine Free](http://soundengine.jp/software/soundengine/)で適当に生成した正弦波(10Hz,最大音量は0dB)を6dBだけ持ち上げて無理矢理音割れさせたものを用意します。それを線形補間およびラグランジュ補間したものについて、[Wave Spectra](http://efu.jp.net/soft/ws/ws.html)でピーク値を取得することにより比較しました。なお、FFTのサンプリング数は4096・Hanning窓とします。
![cap2.png](https://qiita-image-store.s3.amazonaws.com/0/29802/bfb303d4-4f73-c268-0a2b-ed2c6f8d6d4d.png)
　こうして見る限りでは、線形補間よりもラグランジュ補間の方が明らかに質が良いと分かりますね。若干山の高さが低く見えますが、元波形を伏せられた場合を考えるとまあまあ妥当と言えるでしょう。
　もちろん実際の曲でも検証しています。以前レンタルで借りてきてリッピングしておいた[「only my railgun」のCD音源](http://www.amazon.co.jp/dp/B002KKMM3G)を引っ張ってきましたが、補間前におけるクロップ箇所が、補間後では解消されていることが分かるでしょう。
![only my railgun.png](https://qiita-image-store.s3.amazonaws.com/0/29802/50cd7e44-84e1-a73f-4617-b4e97330826e.png)
　あいにく**とても耳が良いわけではない**ので、聴感としてどれほど違うかははっきりとは分かりません。一応試せるサンプルを配布しますので、是非あなたの耳で確かめてみてください(そしてこの記事にコメントいただけると幸いです)。

ソフトの配布URL：
https://drive.google.com/file/d/0B22mWPiNr-6-M1k3aTcwSi05QXc/view?usp=sharing

# 追加実験(2016/01/01)
　更に今回、補間方法として[スプライン補間](http://www.akita-nct.ac.jp/yamamoto/lecture/2004/5E/interpolation/text/html/node3.html)を用いたものを作成しました。これの場合、周辺4点どころか**いくらでも増やせる**ので、精度向上が期待できます。更に改良として、スケールを動的に決定させることで、前回のように「何dB減らせばちょうどいいんだ？」と悩む必要を無くしました。テストデータとしては、[Sound Engine Free](http://soundengine.jp/software/soundengine/)で適当に生成した正弦波(10Hz,最大音量は0dB)を6dBだけ持ち上げて無理矢理音割れさせたものに対して、前回の補間および今回の補間を実施し、[Audacity](http://www.forest.impress.co.jp/library/software/audacity/)でFFT幅4096・Hanning窓で表示させて比較しました。結果がこちらになります。
![合体.png](https://qiita-image-store.s3.amazonaws.com/0/29802/fd9e1c43-dc21-8ad3-8bb2-50606ac3cae6.png)
　……なんと言うか、前回とあまり変わってませんねorz
　とは言えソフト的には大幅に使いやすくなったはずですので、ここにうｐしておきます。

ソフトの配布URL2：
https://github.com/YSRKEN/Decropper/releases