[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の心臓部」

[LLM] エージェント型

エージェント型 LLM(LLM Agents)は、
「LLM に“考えさせて→行動させる”仕組みを加えたもの」 です。

ChatGPT のような「入力 → 出力」だけの LLM ではなく、
自分で計画を立て、情報を集め、ツールを使い、最終回答を作る“自律的なシステム” に近づきます。

1. LLM エージェントとは?(最も簡単な定義)
LLM エージェント = LLM + Tool + Memory + Reasoning
要素 役割
LLM(大規模言語モデル) 頭脳。計画・判断・生成をする
Tool(外部ツール) 検索、計算、API 呼び出し、データベースなど
Memory(記憶) 会話履歴やユーザ設定の保存(短期・長期)
Reasoning(推論) 目的を分解し、必要なステップを考える

人間と同じように「目的を達成する」仕組みを持つ LLM がエージェントです。

2. “エージェント型 LLM” でできること
① 自律タスク実行
例:メールを読み → 締切を見つけ → カレンダーに入れる

② 外部ツールの利用
Google検索
SQL 実行
Python 計算
API の呼び出し など

③ 情報収集 → 判断 → 行動
RAG(検索)
Web 操作(例:自動ログインして情報取得)
データ分析 → グラフ作成

④ 複雑タスクの分解
“旅行プランを作る”
→ ホテル検索 → 比較 → 予算計算 → プラン生成

🧩 3. 技術構造のイメージ(全体図)
┌───────────┐
│ LLM(頭脳) │
└─────┬─────┘
│ 推論(ReAct / o1 reasoning)
┌─────▼─────┐
│ Agent Policy │ ← どのツールを使うべきか判断
└─────┬─────┘
┌─────▼─────┐
│ Tools │ ← 検索 / 計算 / 実行
└─────┬─────┘

メモリ / DB など

🔧 4. エージェントで使われる代表的な方式
■ ① ReAct(Reasoning + Acting)方式
LLM が「思考」と「行動」を交互に行う。
Thought: 情報が足りないので検索が必要
Action: search(“LLM エージェントとは”)
Observation: 検索結果が返ってきた
Thought: これを要約しよう
Final Answer: …
→ GPT-4 以降のエージェントフレームワークの定番。

■ ② Tool Calling(ツール呼び出し)方式
ChatGPT や OpenAI API の
function calling(tool calling) で、LLM が API を使い分ける。

{
  "tool": "search_google",
  "arguments": {
    "query": "東京駅 ランチ おすすめ"
  }
}

■ ③ Planning(計画生成)方式
大きなタスクを分割し、実行順序を決める。
例:
「YouTube の台本を作る」

テーマ調査
競合動画の分析
構成案
台本作成
推奨サムネ案

🧪 5. Pythonでの“最小エージェント”サンプル
※ OpenAI gpt-4o を使用

from openai import OpenAI
client = OpenAI()

def search_google(query):
    return f"『{query}』を検索した結果(ダミー)"

tools = [
    {
        "type": "function",
        "function": {
            "name": "search_google",
            "description": "Google検索を実行",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {"type": "string"}
                },
                "required": ["query"]
            }
        }
    }
]

prompt = "LLMエージェントとは何か要点を調べて説明して"

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": prompt}],
    tools=tools,
)

# ツール呼び出しか確認
msg = response.choices[0].message
if msg.tool_calls:
    call = msg.tool_calls[0]
    if call.function.name == "search_google":
        result = search_google(call.function.arguments["query"])
        # LLM に戻す
        final = client.chat.completions.create(
            model="gpt-4o",
            messages=[
                {"role": "user", "content": prompt},
                {"role": "assistant", "tool_calls": msg.tool_calls},
                {"role": "tool", "tool_call_id": call.id, "content": result},
            ]
        )
        print(final.choices[0].message["content"])
else:
    print(msg["content"])

🚀 6. LLMエージェントの代表的なフレームワーク
フレームワーク特徴LangChain最も有名。ツール統合・エージェント実装が豊富LlamaIndexRAG 系に強い。データ接続が簡単OpenAI Assistants API超簡単にエージェント構築可能Microsoft AutoGenマルチエージェント(複数AIが協働)

🧠 7. エージェント型 LLM の強み
✔ 自動化
→ 情報収集、検索、分析、報告書生成まで自動でやる
✔ データ統合が得意
→ RAG + ツールで「会社のナレッジ → 即時回答」
✔ 高い拡張性
→ 必要に応じてツール追加が可能

🧩 8. どんなアプリに使われている?
AI カスタマーサポート
社内ナレッジ検索(RAG)+ エージェント
自動メール返信
Web リサーチ bot
自動議事録 → 要約 → タスク化
データ分析 bot(SQL + プロット)
AI 事務アシスタント

🎉 最後に
エージェント型 LLM は 「ただのチャットボット」から “AIアシスタント” に進化させるための重要技術 です。

[デザイン]

レイアウト・余白:グリッド / 視線誘導 / 整列
1. まずレイアウトは“余白”で決まる
初心者が一番つまずくのは「余白」。
プロは 余白を増やす → 可読性UP → 品質UP が鉄則。

🔹基本ルール
内側の余白(padding)は 8px の倍数 にまとめる
(8, 16, 24, 32… → 8ptグリッド)
要素の間隔も 揃える(例:すべて16px に統一)
違う余白をむやみに使わない
近くにあるものをグルーピングする(近接の原則)

2. グリッド(Grid)の基礎
Figmaでのレイアウトを整える最強の機能がグリッド。
✔ グリッドを設定する方法(Frameを選択して)
右パネル → Layout Grid → +

よく使うグリッド
① カラムグリッド(列)

Web・アプリで最重要
例:12カラム、マージン16〜24、ガター16

用途:
レスポンシブデザイン
テキスト幅の統一
コンポーネントの左右位置を揃える

② スクエアグリッド(8px)
要素の配置 / 余白 / アイコンサイズの基準

③ 行グリッド(row)
リストUI、カード群などで役立つが使用頻度は低め

3. 整列(Alignment)の基礎
整列とは、要素を揃えること。
揃っているだけで プロ感が10倍。

✔ よく使う整列
左揃え(Left align)
中央揃え(Center)
右揃え(Right align)
垂直方向の中央揃え(Vertical center)
端揃え(Top/Bottom align)

Figmaショートカット
左揃え:Shift + A → Auto Layout
整列:右上の整列ボタン群

4. 視線誘導(情報の読みやすさ)
人は画面を 左上→右下 にスキャンします。

心地よい視線誘導の作り方
✔ ① 余白のメリハリをつける
見出しの上には大きな余白
見出し下の本文は小さな余白
→ グループ感が出る
✔ ② 文字幅(行幅)を最大化しない
1行60〜80文字が読みやすい

✔ ③ 情報の階層構造を作る
大見出し(24px)
セクションタイトル(18px)
本文(14–16px)

✔ ④ 視線をブロックごとに整理する
カードUI・セクション区切りが有効

5. Figmaでの実践テクニック
✔ Auto Layout(最重要)
整列&余白を全自動にする機能。
使い方:
要素を選択 → Shift+A
効果:
余白を “Padding” で統一
子要素間を “Spacing” で統一
ボタンやカードが自動で伸びる
レスポンシブが簡単になる
✔ Constraints(固定位置)

レイアウトが変わっても要素の位置を維持
例:右上に固定したいボタンなど

✔ Frame と Group の使い分け
Frame:レイアウト管理
Group:単なるまとめ(使う頻度は少なめ)

6. よくあるNG例

❌ 余白がバラバラ(8px, 11px, 13px…)
❌ 文字が左右で揃っていない
❌ 要素が“なんとなく”置かれている
❌ 情報の階層がなく全部同じ大きさ
❌ コンポーネントの幅が統一されていない

👆 このどれかが起きると「素人っぽさ」が出ます。

7. これさえ守れば “UIが安定する” ゴールデンルール
🟦 ① 8pxグリッド

余白・サイズは「8の倍数」

🟥 ② カラムグリッドを必ず使う

Webは12カラムが基本

🟩 ③ 整列を厳格にする

左揃え + 上揃え を基本にする

🟨 ④ Auto Layoutで全ての余白を管理

パディング・ギャップを統一するとプロ級になる

[iOS]アニメーションとトランジション

import SwiftUI

struct ContentView: View {
    @State private var isBig = false

    var body: some View {
        VStack(spacing: 20) {
            Text("アニメーションの基本")
                .font(.title)

            Circle()
                .fill(.blue)
                .frame(width: isBig ? 200 : 100,
                       height: isBig ? 200 : 100)
                .animation(.easeInOut(duration: 0.5), value: isBig)

            Button("サイズ変更") {
                isBig.toggle()
            }
        }
        .padding()
    }
}
import SwiftUI

struct ContentView: View {
    @State private var showBox = false

    var body: some View {
        VStack(spacing: 20) {
            Text("トランジションの基本")
                .font(.title)

            if showBox {
                Rectangle()
                    .fill(.green)
                    .frame(width: 200, height: 150)
                    .transition(.slide)         // ← これがトランジション
                    .animation(.easeInOut, value: showBox)
            }

            Button(showBox ? "消す" : "表示") {
                showBox.toggle()
            }
        }
        .padding()
    }
}
import SwiftUI

struct ContentView: View {
    @State private var showCard = false

    var body: some View {
        VStack(spacing: 20) {
            Text("アニメーション + トランジション")
                .font(.title)

            if showCard {
                RoundedRectangle(cornerRadius: 16)
                    .fill(.orange)
                    .frame(width: 250, height: 160)
                    .shadow(radius: 10)
                    .padding()
                    .transition(.opacity.combined(with: .scale))
                    .animation(.spring(response: 0.4, dampingFraction: 0.6), value: showCard)
            }

            Button(showCard ? "隠す" : "表示") {
                showCard.toggle()
            }
        }
        .padding()
    }
}

3Dアバターの構成要素

3Dアバター制作の基本要素である
メッシュ・テクスチャ・リグ・BlendShape を、
初心者向けだけど専門的に正しくわかりやすくまとめます。

🎨 ① メッシュ(Mesh)= 形・立体の表面のこと
メッシュ=3Dの形そのものです。
点(Vertex)
線(Edge)
面(Face)
これがたくさん集まって、
人間の顔・体・服の立体モデルが作られます。

例:顔の輪郭、鼻、目、唇、髪のボリュームなど。

👀 ポイント
VRMでもBlenderでも「見えている形」は全部メッシュ。

🎨 ② テクスチャ(Texture)= 色・模様の画像のこと
メッシュは“形”だけなので、まだ色がありません。
そこで使うのがテクスチャ。
モデルに貼り付けられた「画像(2D)」のことです。

肌の色
目の模様
服の柄
影の塗り(アニメ調)
シワや質感
すべて テクスチャ画像(PNG/JPEG) で表現されます。

📌 よくある例
VRMの「テクスチャ」というフォルダ内に
face.png
body.png
hair.png
などが入っています。

🦴 ③ リグ(Rig)= 操作するための“骨”の仕組み
メッシュを動かすために内部に入れるのが 骨(ボーン / Armature)。
首を曲げる
口を動かす
手を振る
体を回す

こういった動きは リグ(骨)をメッシュに紐づけることで実現します。

📌 VRM では「Humanoid(人型)の規格」が決まっているため、
UnityやThree.jsが自動で動かしやすいようになっています。

😀 ④ BlendShape(ブレンドシェイプ)= 形の変形(表情・口の動き)
メッシュを「別の形に変形させる仕組み」です。
例えば:
BlendShape名 変形の意味
A 口を「あ」の形に開く
I 「い」の形
O 「お」の形
Smile 口角を上げる
Blink まばたき
Angry 怒り表情

複数のBlendShapeを“混ぜる(Blend)”ことで表情が作れる → これが名前の由来。

📌 リップシンクでは
Viseme(発音記号) → BlendShape(口の形)
へ変換して口の動きを作ります。

⭐ 4つの違いを1行でまとめる
名称 一言で言うと
メッシュ 立体の形
テクスチャ その形に貼る色・模様(画像)
リグ(骨) 動かすための骨組み
BlendShape 表情や口の形の変形

全部セットで、
「しゃべって動く3Dアバター」 が成立します。

[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 を生成できる

[LLM] マルチモーダル

画像 → 理解 → テキスト回答 の最小構成

from openai import OpenAI
import base64

client = OpenAI()

# 画像ファイルを base64 化
with open("image.jpg", "rb") as f:
    img_base64 = base64.b64encode(f.read()).decode("utf-8")

# マルチモーダル(画像 + テキスト)問い合わせ
response = client.chat.completions.create(
    model="gpt-4o",   # または gpt-4o-mini
    messages=[
        {"role": "user", "content": [
            {"type": "text", "text": "この画像を説明してください。"},
            {
                "type": "image_url",
                "image_url": {
                    "url": f"data:image/jpeg;base64,{img_base64}"
                }
            }
        ]}
    ]
)

print(response.choices[0].message["content"])

何が起きているか?
1. 画像を base64 でエンコード
OpenAI API ではファイルアップロードせず、そのまま Base64 で画像を送れる。

2. messages に「画像 + テキスト」を混在させる
{“type”: “image_url”, …} を入れることでマルチモーダルの入力が可能になる。

3. gpt-4o が画像を理解し、テキストで返す
画像認識モデル + 言語モデルが統合されているため、追加設定不要。

[Android] Jetpack Compose Navigation

Jetpack Compose Navigation(複雑版サンプル)

ポイントは次の 4 つ:
NavHost + NavController
複数画面(Home → Detail → Settings)
パラメーター付きルート(Detail/{itemId})
戻る動作(popBackStack

MainActivity.kt
└─ HomeScreen
└─ DetailScreen
└─ SettingsScreen

package com.example.navigationdemo

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.navigation.NavType
import androidx.navigation.compose.*
import androidx.compose.foundation.layout.*
import androidx.compose.material3.Button
import androidx.compose.material3.Text

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            NavigationApp()
        }
    }
}

@Composable
fun NavigationApp() {
    val navController = rememberNavController()

    NavHost(
        navController = navController,
        startDestination = "home"
    ) {
        // ① Home
        composable("home") {
            HomeScreen(
                onSelectItem = { itemId ->
                    navController.navigate("detail/$itemId")
                },
                onOpenSettings = {
                    navController.navigate("settings")
                }
            )
        }

        // ② Detail(パラメータ付き)
        composable(
            route = "detail/{itemId}",
            arguments = listOf(
                navArgument("itemId") { type = NavType.IntType }
            )
        ) { backStackEntry ->
            val id = backStackEntry.arguments?.getInt("itemId")
            DetailScreen(
                itemId = id ?: 0,
                onBack = { navController.popBackStack() }
            )
        }

        // ③ Settings
        composable("settings") {
            SettingsScreen(
                onBack = { navController.popBackStack() }
            )
        }
    }
}

@Composable
fun HomeScreen(onSelectItem: (Int) -> Unit, onOpenSettings: () -> Unit) {
    Column(
        modifier = Modifier.fillMaxSize().padding(20.dp),
        verticalArrangement = Arrangement.spacedBy(16.dp)
    ) {
        Text("Home Screen", style = MaterialTheme.typography.headlineMedium)

        Button(onClick = { onSelectItem(10) }) {
            Text("Go to Detail (itemId = 10)")
        }

        Button(onClick = onOpenSettings) {
            Text("Go to Settings")
        }
    }
}

@Composable
fun DetailScreen(itemId: Int, onBack: () -> Unit) {
    Column(
        modifier = Modifier.fillMaxSize().padding(20.dp),
        verticalArrangement = Arrangement.spacedBy(16.dp)
    ) {
        Text("Detail Screen", style = MaterialTheme.typography.headlineMedium)
        Text("itemId = $itemId")

        Button(onClick = onBack) {
            Text("Back")
        }
    }
}

@Composable
fun SettingsScreen(onBack: () -> Unit) {
    Column(
        modifier = Modifier.fillMaxSize().padding(20.dp),
        verticalArrangement = Arrangement.spacedBy(16.dp)
    ) {
        Text("Settings Screen", style = MaterialTheme.typography.headlineMedium)

        Button(onClick = onBack) {
            Text("Back")
        }
    }
}

[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 の仕事