.wavってめんどいよね？

[Wanoグループ Advent Calendar 2020](https://qiita.com/advent-calendar/2020/wano-group) の16日目は、TuneCore Japan（略TCJ）でサービスを展開する上で発生する音源、.wav ファイルの問題を振り返ってみます。TCJでは、アーティストの曲を世界185カ国以上の配信ストアで販売・配信のサービスをおこなっています。

### ググレカスでは解決しない
標準PCMに対するWAVEフォーマット定義をググると色々と異なる情報がでてきます。ナゼなんでしょうか？音系定義全般を明らかにしたいのかな？理由は色々あると考えますが、正直混乱するだけですよね。
1991年にIBMとMicrosoftからマルチメディア向けファイルフォーマットRIFFに含まれる仕様の１つとして初版が公表されています。
[**Multimedia Programming Interface and Data Specifications 1.0**](http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/Docs/riffmci.pdf)
[**update (Revision: 3.0)**](http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/Docs/RIFFNEW.pdf)
仕様書の中には大変重要なことが書かれています。
>The WAVE form is defined as follows. Programs must expect (and ignore) any unknown chunks encountered, as with all RIFF forms. However, fmt-ck must always occur before wave-data, and both of these chunks are mandatory in a WAVE file.

**both mandatory！** **both mandatory！** 大事なことなので２回言いました。つまり必須のチャンクはfmtチャンクとdataチャンクのみと定義しているわけです。更に不明なチャンクを予期および無視する必要があると定義しています。30年前の資料に大事なことが書いてあるって、普通気づかないよ。

### MP3はなにを夢みたのか？
最近は見かけませんが、RIFFフォーマットMP3というものがあります。
**RIFF WAVE**
dataチャンクにMP3データストリームを収容することが可能で、fmtチャンクの内容も音声カテゴリWAVE_FORMAT_MPEGLAYER3である点以外は同じです。拡張子も.wavです。
**RIFF MP3**
dataチャンクにMP3データストリームを収容する点は同じですが、fmtチャンクは省略、フォームタイプ'RMP3'を用います。拡張子は.rmpです。

**ID3 Tag Ver.1**は、128バイトの情報部に曲名（30バイト）、アーティスト（30バイト）、アルバム名（30バイト）、日付（4バイト）、コメント（30バイト）、ジャンル（1バイト）と定義されています。日本語環境下では制限がキツく、独自拡張が行われました。当時の状況では**神キター、神降臨！**の出来事ですが、現在のLISTチャンクの仕様把握に悪影響を与えてる点では、もはや**黒歴史**です。
先のドキュメントにあるようにLISTチャンク（**INFO List Chunk**）はRIFFに含まれる仕様の１つとして定義されています。LISTチャンクに以下の様なチャンク（代表的なもの）が追加されました。

**追加チャンク**

| チャンク | 内容 |
| --- | --- | 
| ILYC | 歌詞 |
| IMP3 | MP3情報 |
| IID3 | ID3タグ |

## 放送業界が仕込んだワナ？
放送業界には業界向けの.wavファイルが規格として存在しています。制作側のDTM界隈でもサポートしているので、頻繁に目にできます。
[**Specification of the Broadcast Wave Format (BWF)**](https://tech.ebu.ch/docs/tech/tech3285.pdf)
[**BWF-J オーディオファイルフォーマット**](http://www.jppanet.or.jp/bwf-j/jppa-1-2009_bwf-j_audio_file_format.pdf)

先のLISTチャンクの他にWaveform Audio File FormatにもLISTチャンク（**Associated Data Chunk**）は存在していて、BWFJの.wavファイルでは結構現れます。

## DTMツールって主張が多い？
DAWは独自チャンクを追加しているので、要注意です。例えばループシーケンサDAW ACIDではacidチャンクを用意しています。ループ情報が含まれていてACIDized WAVと呼ばれています。また、CubaseではiXMLチャンクを用意してプロジェクト関連のメタ情報を追加できます。DTM界隈は独自チャンクの採用が多いです。

## 結論と解決策は？
一般に広まっている.wavファイルのツール（各言語ライブラリ含め）は、LISTチャンクや独自チャンクを必要以上にチェックする傾向があります。また、BWFも考慮してるとはいえません。仕様で必須のチャンクはfmtチャンクとdataチャンクのみと定義しているので、素直に従えばトラブルに合うことはありません。

[libsndfile](http://www.mega-nerd.com/libsndfile/)が信用できるので、愛用しています。ソースからコンパイルすると[便利なツール](http://lfsbookja.osdn.jp/BLFS/svn-ja/multimedia/libsndfile.html)が手に入ります。サウンドファイルの情報を表示する**sndfile-info**と同一メッセージが吐き出せる点などlibsndfileに正しく追従しているので、Pythonの[PySoundFile](https://pysoundfile.readthedocs.io/en/latest/)で以下コードをVSCodeで修正、Jupyter ExtensionのマジックコマンドでRunさせて.wavファイルをfmtチャンクとdataチャンクのみに修正しています。
24bit.wavファイルに変換できないということもなく、FLACやOggなどにも普通に変換できるのでストレスがなくて良いです。ただし、MP3は作者がライセンスの問題でサポートしないらしいです、残念。

```
# %%
import glob
import soundfile as sf

# %%
src = glob.glob("./src/*")
for file in src:
    i = sf.info(file, verbose=True)
    print(i)

# %%
data, samplerate = sf.read('/wav2wav/src/src.wav')
i = sf.info('/wav2wav/src/src.wav', verbose=True)
print(i)
sf.write('/wav2wav/dst/dst.wav', data, samplerate, subtype=i.subtype)
i = sf.info('/wav2wav/dst/dst.wav', verbose=True)
print(i)
```

## 告知
[**シングル配信無料キャンペーン #IndependentAF**](https://www.tunecore.co.jp/news/258)
内容：シングル配信利用料が無料 (配信1年分・1アカウント1回のみ)
期間：2020年12月21日 (月) まで
対象：全アカウント
利用方法（キャンペーンに参加する）：
1. アカウントへログイン後、シングルリリースを作成します（アカウント作成は[こちら](https://www.tunecore.co.jp/register)）
2. STEP4 決済画面にて 1年間配信 を選択、「"IndependentAF" シングル配信無料キャンペーンクーポン」を選択します 
3. 決済金額が0円になったことを確認し、手続きを完了させてください
* シングルリリース登録はPCより行なってください
* 再配信にはクーポンコードを使用できません

**Wanoは積極的にエンジニア採用を行なっています！**
まずはオンラインでVPoEとのカジュアル面談から。お好きな入り口からお気軽にお声がけください！
Wano Recruitページ　https://group.wano.co.jp/recruit/
QiitaJobs　https://jobs.qiita.com/employers/wano-inc/postings/1297
Wantedly　https://www.wantedly.com/companies/wano/projects
Findy　https://findy-code.io/companies/522