[TTS] Mel-spectrogram出力 → vocoder変換

$ pip3 install librosa soundfile numpy

import numpy as np
import librosa
import soundfile as sf

# ---- 1. ダミーのMelスペクトログラムを作る ----
mel = np.random.rand(80, 100).astype(np.float32)

# ---- 2. Mel → 線形スペクトログラムに逆変換 ----
sr = 22050
n_fft = 1024
hop_length = 256
win_length = 1024

mel_basis = librosa.filters.mel(
    sr=sr,
    n_fft=n_fft,
    n_mels=80
)

inv_mel_basis = np.linalg.pinv(mel_basis)
S = np.dot(inv_mel_basis, mel)

# ---- 3. Griffin-Limで波形へ ----
audio = librosa.griffinlim(
    S,
    n_iter=60,
    hop_length=hop_length,
    win_length=win_length
)

# ---- 4. WAVとして保存 ----
sf.write("output.wav", audio, sr)

print("output.wav を生成しました!")

Melスペクトログラムこそが、TTS(Text-to-Speech)の “声の元” です。

以下で「なぜ Mel が TTS の中心なのか」をわかりやすく説明します。

🔊 結論:TTS の音声生成は『Melスペクトログラム → Vocoder → 音声』です

TTS(特に Tacotron2 / FastSpeech2 / VITS などの Neural TTS)は、
次の2段階で音声を作っています:

① Acoustic Model(Tacotron2 / FastSpeech)
→ メルスペクトログラムを生成

② Vocoder(WaveGlow / HiFi-GAN / WaveRNN)
→ メルスペクトログラムを音声波形に変換

つまり…

🎤 TTS が作るのは “直接の音声” ではなく Melスペクトログラム
✔️ TTS の本体(Acoustic Model)が出力するもの

“音声波形(wav)” ではない

Melスペクトログラム(80次元 × フレーム数)

理由:

人間の声の特徴をコンパクトに持てる

音声波形に比べて扱いやすい(次元が小さく学習が安定)

周波数分解能が人間の聴覚特性に近い

👂 Melスペクトログラムは “声の写真”

イメージとしては:

横:時間

縦:周波数(低音 → 高音)

色:音の強さ

写真のように「音の特徴が平面にまとまっている」。

だから AI が学習しやすい。

📘 なぜ Mel を使うのか?(技術理由)
① 音声波形(時系列)は扱いにくい

1秒で 22,050 サンプル → 学習には巨大すぎる
⇒ 変動が激しく、局所性が弱い

② Melスペクトログラムは圧縮され学習しやすい

22,050サンプル → 約80次元に圧縮
しかも

音の高さ(フォルマント)

強さ

リズム

声質の特徴
が明瞭になるため 学習のターゲットとして最高。

③ 聴覚特性に合う(メルスケール)

人間の耳は

低音に敏感

高音に鈍い
→ Mel スケールはこの特性に合わせている
→ 音質向上につながる

🎛 Vocoder が Melスペクトログラムを“音声”に変換する

代表的なvocoder:

Vocoder 特徴
WaveGlow 高音質、高速
HiFi-GAN いま最も使われる、軽量&高品質
WaveRNN 高品質、軽量だがやや遅い
DiffWave 拡散モデルで高品質

Vocoder があるからこそ、
「絵(mel)」→「声(wav)」が成立する。

TTS の7〜8割は「いかに自然な Mel を作るか」にかかっています。

[TTS] Encoder–Attention–Decoder構造

🎤 結論(まずはざっくり)
Encoder–Attention–Decoder 構造とは、
テキストを音声(またはメルスペクトログラム)に変換するための
“情報を読む → 関連付ける → 出力を作る” という3段階モデルのことです。

特に Tacotron / Tacotron2 などの TTS で使われており、
自然な発話の基礎となります。

🧩 ① Encoder(テキストを数値ベクトルに変換)
テキストはそのままではAIに扱えません。
そこで Encoder が次の処理を行います:
✔️ Encoderがすること
テキストを文字や音素に分割
Embedding で数値ベクトル化
Conv + LSTM で文の特徴を学習


“hello”
→ [‘h’,’e’,’l’,’l’,’o’]
→ [ベクトル, ベクトル, …]
→ 文全体の意味・発音特徴を持つ系列データ

Encoder の出力は、
文章を「読みやすい形」に整理した特徴データだと思えばOK。
🔎 ② Attention(どの文字を読んでいるか対応付ける)
Attention は TTS の心臓部で、最も重要です。
TTS では「テキストのどの部分を、話し声のどのタイミングで使うか」
という対応(Alignment)が必要ですが、
これを自動で解決してくれるのが Attention です。

✔️ なぜ必要?
音声は 1秒=数百フレーム
テキストは10文字程度
→ 「ある文字を何フレーム分話すか」が決まらない

✔️ Attention が行うこと
Decoder が「次にどの文字の情報を見るべきか」を計算する
視線を動かすように
今は “he” の部分を読む
次は “ll” を読む
最後は “o” を読む

といった 読み位置(焦点) を動かします。

TTS 特有の Attention
Location-sensitive Attention
逆戻りしにくい
読み飛ばしが起きにくい

🎛 ③ Decoder(メルスペクトログラムを生成)
✔️ Decoder が行うこと

Attention で選ばれた文字情報を使い、
少しずつメルスペクトログラムを生成する。

仕組み:
現在のメルフレーム (1フレーム) を入力
LSTM(またはGRU)に通す
次のメルフレームを生成
Attention で次に参照する文字位置を更新
これを繰り返す(autoregressive)

図で描くとこう:

(text) → Encoder → Attention → Decoder → mel
→ mel
→ mel

※ Tacotron2 は1ステップで5フレームまとめて生成する(Teacher Forcingあり)

📘 全体の流れ(図)
┌────────┐ ┌──────────┐ ┌──────────┐
│ Encoder │ → │ Attention │ → │ Decoder │ → Melスペクトログラム
└────────┘ └──────────┘ └──────────┘
↑ テキスト入力 ↑ 文字のどこを使う?

これが TTS の “中核構造” です。
🗣 なぜこの構造がTTSに向いているの?
✔️ 1. 文字数と音声フレーム数が一致しない

文字数:数十
音声フレーム:数千
Attention が自動で対応付けてくれる。
✔️ 2. 抑揚(プロソディ)が自然に出る
Decoder が自動で長さや強弱を学習するため
人間に近い発話が実現。

✔️ 3. End-to-Endで学習が簡単
従来のような細かい手設計(ルール)が不要。

🔧 技術者向け(もう少しだけ深く)
Encoder
512次元 embedding
3層の 1D Conv(ReLU)
Bi-LSTM(256ユニット×2方向)
Attention
Location-Sensitive
Additive(Bahdanau)Attention の拡張
Decoder
Prenet(Dropout付き全結合)
2層 LSTM(1024次元)
Postnet(Conv)

🎯 まとめ(超簡単理解バージョン)
構造 役割 たとえ
Encoder テキストを理解する 本を読む
Attention 次にどこを読めばいいか決める 文章の特定の場所に視線を置く
Decoder 声の元(mel)を作る 読んだ文章を声に変換

[TTS] Tacotron2とは

🎤 Tacotron2とは?
Tacotron2 は Google が開発した「自然な音声を生成するTTSモデル」 で、
Neural TTS(ニューラルTTS)を大きく前進させた代表的な音声生成モデルです。

✔️ Tacotron2 の特徴(ざっくり)
テキスト → メルスペクトログラムを生成するモデル
WaveGlow / WaveRNN などの vocoder と組み合わせて音声に復元
人間の声に近い自然な抑揚(プロソディ)が得られる
End-to-End(前処理が少ない)

🎛 Tacotron2 の構造(これが最重要)
Tacotron2 は大きく 2つの部分 に分かれています。
① Acoustic Model(文章 → Melスペクトログラム)
② Vocoder(Melスペクトログラム → 音声波形)

① Acoustic Model(Tacotron2本体)
内部構造:
Encoder(文章を特徴ベクトルに変換)
テキストを文字単位でEmbedding
Convolution + LSTM
Attention(位置を揃える)
テキストとメルスペクトログラムの対応を学習
Location-Sensitive Attention で「読み飛ばし」を防止
Decoder(Melスペクトログラム生成)
RNNベース

1フレームずつメルスペクトログラムを生成
→ Tacotron2はテキストを“メル画像”に変換する装置

② Vocoder(WaveGlow / WaveRNN など)
Tacotron2はメルスペクトログラムまでしか作らないので、
これを波形に変えるのが Vocoder の役割。
有名な組み合わせ:
Acoustic Vocoder
Tacotron2 WaveGlow
Tacotron2 WaveRNN
Tacotron2 HiFi-GAN
🎧 Tacotron2 が使うメルスペクトログラムの特徴

80次元 Mel
22,050Hz サンプリング
対数変換(log-mel)
hop=256, win=1024
これらは ほぼすべての NeuraI TTS の標準仕様 になりました。

🔍 Tacotron2 がすごかった理由
✔️ 1. 文章のリズム(韻律)が自然
Attentionにより、
「どこを読んでいるか」を内部で推定することで
自然な抑揚を作れるようになった。

✔️ 2. End-to-Endなので音質が高い
従来:
形態素解析
音素列変換
音響モデル
デュレーションモデル
vocoder
→ Tacotron2は中間を自動学習

✔️ 3. WaveGlowと組み合わせて高品質な音声
従来のvocoder(Griffin-Lim等)は粗い音質だったが
WaveGlowで劇的に改善。

📘 Tacotron2 の処理フロー(図)
Text → Encoder → Attention → Decoder → Mel-spec
Mel-spec → Vocoder → Audio(WAV)

🧪 Pythonでの実行例(PyTorch)
※ NVIDIA の公式実装を利用した例
import torch
from tacotron2.model import Tacotron2
from denoiser import Denoiser

# モデル読み込み
checkpoint_path = “tacotron2_statedict.pt”
model = torch.load(checkpoint_path)[‘state_dict’]

# 入力テキスト
text = “こんにちは、これはTacotron2のテストです。”

# 1) テキスト → メルスペクトログラム
mel = tacotron2(text)

# 2) vocoder (WaveGlow)
audio = waveglow.infer(mel)

# 保存
torchaudio.save(“output.wav”, audio, 22050)

実際にはモデルファイルが必要ですが、
構造としてはこのように Mel → Audio の2段階です。

✔️ 要点まとめ
項目 内容
モデル名 Tacotron2
種類 Acoustic Model(テキスト→メル)
Vocoderが必要か 必要(WaveGlow等)
長所 抑揚が自然、高品質
短所 生成速度が遅い・Attentionの不安定性

[TTS] モデルのパラーメタファイルと設定ファイル

1. パラメータファイル (Model Checkpoint)
パラメータファイル(例:my_voice_model.pth)はバイナリデータなので中身をテキストで見ることはできませんが、概念的には以下のようなモデルの学習結果が数値の配列として格納されています。

項目概念的な内容役割
ジェネレーターの重み$W_G: [[0.12, -0.05, …], [0.99, 0.01, …], …]$音響特徴量から生の音声波形を生成するための数百万の数値。
エンコーダーの重み$W_E: [[-0.45, 0.22, …], [0.10, -0.87, …], …]$テキスト情報から音響特徴量を作り出すための数百万の数値。
話者埋め込みベクトル$V_{\text{speaker}}: [0.75, -0.11, 0.40, …]$このモデルが学習した**話者(声質)**を特徴づける固有の数値(声のDNAのようなもの)。

ポイント: このファイルは、提供された音声データとテキストの関係を学習したニューラルネットワークの脳そのものです。

2. 設定ファイル

"train": {
    "log_interval": 200,
    "eval_interval": 1000,
    "seed": 1234,
    "epochs": 1000
  },
  "data": {
    "training_files": "filelists/train.txt",
    "validation_files": "filelists/val.txt",
    "max_wav_value": 32768.0,
    "sampling_rate": 24000  // 💡重要:音声の品質(サンプリングレート)
  },
  "model": {
    "inter_channels": 192,
    "hidden_channels": 192,
    "filter_channels": 768,
    "n_heads": 2,
    "n_layers": 6,
    "kernel_size": 3,
    "p_dropout": 0.1,
    "gin_channels": 256, // 💡話者埋め込みベクトルの次元
    "style_channels": 128 // 💡Style-Bert-VITS2のスタイル特徴量の次元
  },
  "speakers": {
    "speaker01": 0,
    "speaker02": 1
  } // 💡話者IDとモデル内でのインデックスの対応
}

https://github.com/litagin02/Style-Bert-VITS2
config.jsonと.pthのセット
https://huggingface.co/RinneAi/Rinne_Style-Bert-VITS2

設定ファイル config.json モデルの構造、サンプリングレートなどの設計情報を定義するテキストファイル。
パラメータファイル Rinne.safetensors 学習によって得られた**モデルの重み(パラメータ)**を格納したファイル。従来の.pthに代わり、安全性の高い.safetensors形式が使われることが増えています。
スタイル情報 style_vectors.npy Style-Bert-VITS2特有の、声の**スタイル(話し方、感情など)**の特徴を格納したファイル。

これらのファイル3点セットをダウンロードし、Style-Bert-VITS2の実行環境に配置することで、テキストから指定した声(この場合は「Rinne」)で音声を合成できるようになります。

なるほど〜、

[TTS] TTS のサンプリング周波数・ビット深度

1. サンプリング周波数(Sampling Rate)
1秒間に「音を何回測るか」
を表す数字。
例:
サンプリング周波数 何を意味する? 用途
16,000 Hz (16kHz) 1秒に16,000回測る 音声AI・電話
22,050 Hz 1秒に22,050回測る 一般的なTTS
44,100 Hz (44.1kHz) CD音質 音楽・高音質TTS

2. ビット深度(Bit Depth)
1回の測定で、音の強さを何段階で記録するか
例:
ビット深度 段階数 特徴
16bit 65,536段階 CD音質・一般的
24bit 16,777,216段階 スタジオ品質
32bit 約40億段階 研究・高音質合成

TTSではどう使われる?
用途 サンプリング周波数 ビット深度
音声AI(STT/TTS) 16kHz 16bit
高音質TTS(商用) 22kHz〜48kHz 16bit or 24bit
音楽/歌声合成 44.1kHz or 48kHz 24bit

[TTS] Mel-Spectrogram

🎧 Mel-Spectrogram(メル・スペクトログラム)とは?
音声を 時間 × 周波数 の画像のようにしたものが スペクトログラムです。
その中でも 人間の聴覚に近い周波数感度で変換したものが
Mel-Spectrogram(メルスペクトログラム) です。

🧠 ポイント(簡単)
1. STFT(短時間フーリエ変換)で時間を細かく分ける
音声を短い区間に分けて FFT → 周波数別のエネルギーを得る。

2. 周波数軸を Mel scale(メル尺度)に変換
人間の聴感に近い形(低音域は細かく、高音域は粗く)。

3. 結果は 2D の行列 → 画像のように扱える
音声AI(TTS、音声認識、歌声合成)では
メルスペクトログラムを中間表現として使うのが主流。

📊 Melスペクトログラムのイメージ(構成)
← 時間軸 →
│□□□□□□□□□□□□□□
│■■□□□□□□■■■■□□
│■■■□□□□■■■■■□
│■■■■□□■■■■■■■

Mel周波数

🧪 Pythonで Mel-Spectrogram を生成するサンプル
以下は librosa を使った最小サンプルです。

import librosa
import librosa.display
import matplotlib.pyplot as plt

# 音声ファイル読み込み(例:sample.wav)
audio_path = "sample.wav"
y, sr = librosa.load(audio_path, sr=22050)

# Melスペクトログラム計算
mel_spec = librosa.feature.melspectrogram(
    y=y,
    sr=sr,
    n_fft=1024,
    hop_length=256,
    n_mels=80
)

# 対数Melスペクトログラム(TTSでよく使う)
mel_db = librosa.power_to_db(mel_spec, ref=np.max)

# 表示
plt.figure(figsize=(10, 4))
librosa.display.specshow(mel_db, sr=sr, hop_length=256, x_axis='time', y_axis='mel')
plt.colorbar(format='%+2.0f dB')
plt.title('Mel-Spectrogram')
plt.tight_layout()
plt.show()

✔️ コード解説(最重要点)
n_fft=1024
FFTの窓長
→ 高周波の精度が上がるが時間精度は悪くなる

hop_length=256

時間方向のステップ
→ 小さいほど細かい

n_mels=80

TTSでは 80次元 Mel が最も一般的
(Tacotron2, FastSpeech2, VITS 全て同じ)
power_to_db

TTS モデルに入れるときは 対数(dB) が使われることが多い。
🔊 TTS と Melスペクトログラムの関係
ほぼ全ての Neural TTS の特徴:
1. テキスト → Melスペクトログラム(Acoustic Model)
例:Tacotron2, FastSpeech2, VITS

2. Melスペクトログラム → 波形(Vocoder)
例:HiFi-GAN, WaveGlow, WaveRNN

つまり Melスペクトログラムは「TTSの心臓部」

[TTS] WAV

TTS が出力する音声ファイルとして最も一般的な形式のひとつです。
特徴:
音質が劣化しない
サイズは MP3 より大きい
音声処理(AI、機械学習、編集)に使われやすい
多くの TTS エンジンのデフォルト出力

from openai import OpenAI

client = OpenAI(api_key="YOUR_API_KEY")

# TTSで音声(WAV)を生成
response = client.audio.speech.create(
    model="gpt-4o-mini-tts",
    voice="alloy",
    input="こんにちは、これはWAV形式のサンプルです。",
    format="wav"
)

# バイナリを保存
with open("sample.wav", "wb") as f:
    f.write(response.read())

print("sample.wav を作成しました")

Google cloud

from google.cloud import texttospeech

client = texttospeech.TextToSpeechClient()

input_text = texttospeech.SynthesisInput(text="こんにちは、WAVのサンプルです。")

voice = texttospeech.VoiceSelectionParams(
    language_code="ja-JP",
    name="ja-JP-Wavenet-B"
)

audio_config = texttospeech.AudioConfig(
    audio_encoding=texttospeech.AudioEncoding.LINEAR16  # WAV
)

response = client.synthesize_speech(
    input=input_text,
    voice=voice,
    audio_config=audio_config
)

with open("sample.wav", "wb") as out:
    out.write(response.audio_content)

WAV = 高音質の音声ファイル形式
TTS の標準出力としてよく使われる
Python の TTS では簡単に WAV を生成できる

[TTS] pmcとは

「TTS の PMC」という言葉は、文脈によって指しているものが異なりますが、
主に以下の2つの意味で使われることが多い。

結論からいうと、TTS(Text-to-Speech)分野でよく出てくる PMC = Prosody Model / Prosody Modification / Prosody Modeling Component の略として使われることがある。

1. Prosody Modeling Component(韻律モデル・韻律制御モジュール)
TTS が自然に聞こえるためには、
イントネーション(抑揚)
音の強弱
音の高さ(F0)
話速(テンポ)
間の取り方(ポーズ)
といった 韻律(Prosody) が非常に重要

これらを制御する仕組みを Prosody Modeling Component (PMC) と呼ぶ

特に以下のような論文や TTS アーキテクチャで登場する用語です:
Tacotron 系
FastSpeech 系
Prosody Embedding
Duration / Pitch / Energy Predictor

2. Prosody Modification Control(韻律変更コントロール)
TTS に emotion や表現力を持たせるときに必要な操作で、
PMC = Prosody Modification Control(韻律変換コントロール)
という意味で使われることもあります。

例:
ピッチカーブを直接操作する
話速/音素長を変える
感情(怒り、喜び、悲しみ)を調整
商用TTSエンジンや研究用TTSで PMC という言葉を使うケースがあります。

TTS の PMC = Prosody(韻律)に関係するモジュールの総称
Prosody Modeling Component
Prosody Modification Control
などの略として使われることが多い

PMC の役割
抑揚
強弱
音の高さ
話速
ポーズ
感情表現

これらを予測したり制御するのが PMC の仕事

[TTS] Flaskチャットに音声応答機能を統合

以下では OpenAI の TTS API(新しい audio API)を Flask チャットアプリで使う方法 を、
できるだけシンプルで実用的な構成で紹介します。

✅ 基本構成
Flaskでチャットアプリを作る場合、
Web画面でユーザーがテキスト入力
Flaskサーバーが OpenAI API に TTS リクエスト
得た音声バイナリ(mp3/wav)を返す
ブラウザ側で audio タグ / JS で再生
という流れになります。

📌 必要ライブラリ
pip install flask openai

🚀 サンプル:Flask + OpenAI TTS API
📁 app.py

from flask import Flask, request, send_file, jsonify
from openai import OpenAI
import os
import io

app = Flask(__name__)

# OpenAI API キー
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

@app.route("/")
def index():
    return """
    <form action="/tts" method="post">
        <input name="text" placeholder="Enter text">
        <button type="submit">Generate</button>
    </form>
    """

@app.route("/tts", methods=["POST"])
def tts():
    text = request.form.get("text", "")

    # OpenAI TTS API 呼び出し
    response = client.audio.speech.create(
        model="gpt-4o-mini-tts",     # OpenAI TTSモデル
        voice="alloy",               # 声(例:alloy / verse / shimmer など)
        input=text,
        format="mp3"
    )

    # バイナリ取得
    audio_bytes = response.read()

    # メモリ内に保存して返す
    return send_file(
        io.BytesIO(audio_bytes),
        mimetype="audio/mpeg",
        download_name="speech.mp3"
    )

if __name__ == "__main__":
    app.run(debug=True)

📌 ブラウザで音声を自動再生するフロント(例)

index.html を返すなら:

<!DOCTYPE html>
<html>
<body>
    <h2>OpenAI TTS Demo</h2>
    <input id="txt" placeholder="Enter text">
    <button onclick="speak()">Speak</button>
    <audio id="audio" controls></audio>

    <script>
        async function speak() {
            const text = document.getElementById("txt").value;

            const formData = new FormData();
            formData.append("text", text);

            const res = await fetch("/tts", { method: "POST", body: formData });
            const blob = await res.blob();

            const url = URL.createObjectURL(blob);
            document.getElementById("audio").src = url;
        }
    </script>
</body>
</html>

🔊 レスポンス形式の選択

OpenAI公式では以下が使えます:

形式 MIMEタイプ 特徴
mp3 audio/mpeg 一般的・最小サイズ
aac audio/aac 高音質
wav audio/wav ロスレス(重い)
flac audio/flac 高品質

[TTS] AzureでTTS APIを使う手順

1. サブスクリプションをupgrade

画面左上の「リソースの作成」または上部の検索バーで「Speech」と入力して検索します。
検索結果から「Speech」または「Azure AI サービス」を選択し、「作成」をクリックします。

サブスクリプション 課金が行われるアカウントです。 従量課金制にアップグレード済みのサブスクリプションを選択します。
リソース グループ 先ほど作成したグループです。 作成済みのリソースグループを選択します。
リージョン サービスがデプロイされる場所です。 アプリケーションのユーザーに近いリージョン、または性能・遅延が適切なリージョンを選択します。(例: East US、Japan Eastなど)
名前 このSpeechリソースの名称です。 任意の名前(例: MyTtsResource2025)を入力します。
価格レベル 料金プランです。 Standard (S0) を選択します。(無料枠を使い切っているため)

import azure.cognitiveservices.speech as speechsdk

# Azure Speech Service のキーとリージョン
speech_key = "YOUR_SPEECH_KEY"
service_region = "eastasia"   # East Asia リージョン

# SpeechConfig を作成
speech_config = speechsdk.SpeechConfig(subscription=speech_key, region=service_region)

# 出力音声を設定(標準はwav)
audio_config = speechsdk.audio.AudioOutputConfig(filename="output.wav")

# 音声の種類(例: 日本語の女性)
speech_config.speech_synthesis_voice_name = "ja-JP-NanamiNeural"

# Speech Synthesizer を作成
synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=audio_config)

# 読み上げるテキスト
text = "こんにちは、これは Azure Text to Speech のテストです。"

# TTS 実行
result = synthesizer.speak_text_async(text).get()

# 結果チェック
if result.reason == speechsdk.ResultReason.SynthesizingAudioCompleted:
    print("✅ 音声ファイル 'output.wav' を生成しました")
else:
    print("❌ エラー:", result.reason)

Azureだと音声が全然違いますね!