437行のC++で日本語を喋る -- A tiny Japanese formant speech synthesizer in ~437 lines of C++
Klatt簡易モデルに基づくフォルマント音声合成器。外部ライブラリに一切依存せず、単一のC++ファイル(formant.cpp)だけで日本語の全音素を合成しWAVファイルとして出力します。
A minimal formant speech synthesizer for Japanese, based on a simplified Klatt model. Single-file C++ implementation with zero external dependencies.
- 単一ファイル実装 --
formant.cppのみ(約437行)、外部ライブラリ不要 - 全日本語音素対応 -- 5母音、破裂音、破擦音、摩擦音、鼻音、弾き音、半母音、促音、撥音
- ひらがなテキスト入力 -- コマンドライン引数でひらがなを渡すだけ
- Klatt簡易モデル -- インパルス列 / ノイズ / 混合音源 → 2次IIR共振器 x3段カスケード
- 16bit PCM WAV出力 -- 44100Hz, mono
- C++20 対応コンパイラ
- clang++ 13+ (macOS Xcode 13+)
- g++ 11+
- OS: macOS / Linux
- Make (任意 -- 直接コンパイルも可)
# Makefile を使う場合
make
./formant "こんにちは"
# 直接コンパイル
clang++ -std=c++20 -O2 -Wall -o formant formant.cpp
./formant "さくら"# ひらがなテキストを引数に渡す
./formant "あいうえお"
# => Wrote output.wav (26460 samples, 5 segments)
# デフォルト(引数なし)は "あいうえお"
./formant
# 拗音・促音・撥音にも対応
./formant "きょうはいいてんきです"
./formant "にっぽん"
./formant "しんぶん"
# macOS で再生
afplay output.wav
# Linux で再生(aplay がある場合)
aplay output.wav注意: 入力はひらがな(とカタカナ長音「ー」)のみ対応です。漢字・英数字は無視されます。
テキスト入力(ひらがな UTF-8)
│
▼
textToPhoneme() ── ひらがな→音素列変換(kKanaTable + 拗音/促音/撥音処理)
│
▼
PhonemeEntry列 ── [{FormantParams, duration_samples}, ...]
│
▼
Synthesizer::synthesize()
│
├─ 音源生成 ─── ImpulseTrain(有声音)/ NoiseGen(無声音)/ Mixed(有声摩擦音)
│
├─ フィルタ ─── Resonator x3 直列(F1, F2, F3)── 2次IIR共振器
│ └ 5msフレームごとに係数更新、音素間で線形補間
│
▼
writeWav() ── 16bit PCM WAV (44100Hz, mono) 出力
- 音源: 3種類(インパルス列 / 白色雑音 / 混合)を
SourceTypeで切替 - フィルタ: 2次IIR共振器(
Resonator)をF1/F2/F3の3段カスケード接続 - 遷移: 各音素の末尾30%区間で次の音素へ線形補間(フォルマントロカス)
- フレーム: 5ms(220サンプル)ごとにフィルタ係数を再計算
| 種別 | 音素 |
|---|---|
| 母音 | あ い う え お |
| 無声摩擦音 | /s/、/ɕ/(し)、/ç/(ひ)、/ɸ/(ふ)、/h/ |
| 有声摩擦音 | /z/、/ʑ/(じ) |
| 無声破擦音 | /tɕ/(ち)、/ts/(つ) |
| 有声破擦音 | /dʑ/(ぢ/じ)、/dz/(づ/ず) |
| 鼻音 | /n/(な行)、/m/(ま行) |
| 弾き音 | /ɾ/(ら行) |
| 半母音 | /j/(や行)、/w/(わ) |
| 破裂音 | /p/、/b/、/t/、/d/、/k/、/g/ |
| 促音 | っ(120ms無音) |
| 撥音 | ん(80ms鼻音) |
docs/samples/ にサンプル音声・動画があります。
| ファイル | 内容 |
|---|---|
| all.mp4 | 5文章の結合動画(テキスト表示付き) |
| こんにちは.wav | こんにちは |
| おはようございます.wav | おはようございます |
| ありがとう.wav | ありがとう |
| さようなら.wav | さようなら |
| はじめまして.wav | はじめまして |
make test # 全19スイート / 176テストケースを実行外部依存なしの軽量テストフレームワーク(test_framework.h)を使用。
テストスイート一覧(19スイート)
| スイート | 対象 | ケース数 |
|---|---|---|
| Resonator | 2次IIR共振器 | 5 |
| NoiseGen | LCG乱数生成 | 5 |
| ImpulseTrain | インパルス列 | 5 |
| Lerp | FormantParams線形補間 | 6 |
| Helpers | ms2s / append / makePlosiveCV | 10 |
| PhonemeData | 音素定数値 | 22 |
| SynthBasic | 合成器基本動作 | 6 |
| SynthSource | 音源切替・遷移 | 8 |
| WAVWriter | WAVファイル出力 | 9 |
| Integration | フルパイプライン | 12 |
| MixedSource | 混合音源 | 6 |
| NewFricatives | 新摩擦音定数 | 10 |
| Affricates | 破擦音生成 | 10 |
| HaRow | は行条件異音 | 8 |
| SaRow | さ行 | 8 |
| ZaRow | ざ行 | 10 |
| TextToPhoneme | ひらがな→音素変換 | 14 |
| YouonSpecial | 拗音・促音・撥音・長音 | 12 |
| IntegrationMS6 | テキスト→合成パイプライン | 10 |
- Klatt, D.H. (1980) "Software for a cascade/parallel formant synthesizer" JASA 67(3)
- Stevens, K.N. (1998) Acoustic Phonetics
- eSpeak NG -- klatt.c 参考実装
Issue や Pull Request を歓迎します。
- バグ報告: Issues で日本語/英語どちらでもOK
- 機能提案・改善: PR を送る前に Issue で相談してください
- コードスタイル: 既存のコードに合わせてください(C++20、単一ファイル構成維持)