0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

fedoraで音声読み上げサンプル

0
Last updated at Posted at 2025-11-09

目的

WebAPIを使用しないスタンドアロンで
(なるべく)自然な音声読み上げを行う

環境

  • fedora 42
  • orca f9c9267f99f5bf396ffd21bb2056dc5fb9d6777e

orcaは医療とかで使われているやつじゃなくて
picovoiceの音声読み上げライブラリの方です

事前準備

  • picovoiceのサイトで startfree をクリック
  • I am working on a commercial project. のチェックを外すと
    github などのアカウントでサインアップ出来る
  • 下3つのチェックを入れるとアカウントが作成出来て画面が遷移する
  • アクセスキーが表示されているので保存しておく
  • alsaのヘッダが無ければ sudo yum install alsa-lib-devel.x86_64 などでインストールしておく(*1)

(*1)
ファイル出力だけなら不要

ライブラリの作成

git clone --recurse-submodules --depth=1  https://github.com/Picovoice/orca.git
cd orca
# 以下で同梱デモの確認が出来る
cmake -S demo/c/ -B demo/c/build
cmake --build demo/c/build --target orca_demo 
cmake --build demo/c/build --target orca_demo_streaming
./demo/c/build/orca_demo -l lib/linux/x86_64/libpv_orca.so -m lib/common/orca_params_fr_female.pv -a [自分のアクセスキー] -t "je m'appelle yano" -o output.wav
xdg-open output.wav

コード

main.c

自分のアクセスキーを記載すること

main.c
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <alsa/asoundlib.h>
#include "pv_orca.h"

#define ORCA_BASE "../orca/"

#define ALSA_DEVICE "default"

static int setup_alsa(snd_pcm_t **pcm, unsigned int sample_rate)
{
    snd_pcm_t *handle = NULL;
    snd_pcm_hw_params_t *hw;
    int rc;

    rc = snd_pcm_open(&handle, ALSA_DEVICE, SND_PCM_STREAM_PLAYBACK, 0);
    if (rc < 0)
    {
        fprintf(stderr, "snd_pcm_open error: %s\n", snd_strerror(rc));
        return rc;
    }

    snd_pcm_hw_params_malloc(&hw);
    snd_pcm_hw_params_any(handle, hw);
    snd_pcm_hw_params_set_access(handle, hw, SND_PCM_ACCESS_RW_INTERLEAVED);
    snd_pcm_hw_params_set_format(handle, hw, SND_PCM_FORMAT_S16_LE);
    snd_pcm_hw_params_set_channels(handle, hw, 1); // mono
    snd_pcm_hw_params_set_rate_near(handle, hw, &sample_rate, 0);

    // set a reasonable period size (might be adjusted)
    snd_pcm_uframes_t period_size = 1024;
    snd_pcm_hw_params_set_period_size_near(handle, hw, &period_size, 0);

    rc = snd_pcm_hw_params(handle, hw);
    if (rc < 0)
    {
        fprintf(stderr, "snd_pcm_hw_params error: %s\n", snd_strerror(rc));
        snd_pcm_hw_params_free(hw);
        snd_pcm_close(handle);
        return rc;
    }

    snd_pcm_hw_params_free(hw);
    *pcm = handle;
    return 0;
}

static int play_pcm(snd_pcm_t *pcm, int16_t *buf, size_t samples)
{
    size_t offset = 0;
    while (offset < samples)
    {
        snd_pcm_sframes_t frames = snd_pcm_writei(pcm, buf + offset, samples - offset);
        if (frames == -EPIPE)
        {
            // underrun
            fprintf(stderr, "underrun occurred\n");
            snd_pcm_prepare(pcm);
        }
        else if (frames < 0)
        {
            fprintf(stderr, "snd_pcm_writei error: %s\n", snd_strerror(frames));
            return -1;
        }
        else
        {
            offset += frames;
        }
    }
    return 0;
}

int main(int argc, char **argv)
{
    const char *access_key = "ここにアクセスキー";
    const char *model_path = ORCA_BASE "lib/common/orca_params_fr_female.pv";
    const char *text = "Je m'appelle yano.";
    pv_orca_t *orca = NULL;
    pv_status_t status;

    /* init Orca */
    status = pv_orca_init(access_key, model_path, &orca);
    if (status != PV_STATUS_SUCCESS)
    {
        fprintf(stderr, "pv_orca_init failed: %d\n", status);
        return 1;
    }

    /* prepare synth params (defaults) */
    pv_orca_synthesize_params_t *synth_params = NULL;
    pv_orca_synthesize_params_init(&synth_params);

    int32_t num_samples = 0;
    int16_t *synth_pcm = NULL;
    int32_t num_alignments = 0;
    pv_orca_word_alignment_t **alignments = NULL;

    status = pv_orca_synthesize(
        orca,
        text,
        synth_params,
        &num_samples,
        &synth_pcm,
        &num_alignments,
        &alignments);

    if (status != PV_STATUS_SUCCESS)
    {
        fprintf(stderr, "pv_orca_synthesize failed: %d\n", status);
        pv_orca_synthesize_params_delete(synth_params);
        pv_orca_delete(orca);
        return 1;
    }

    /* ALSA 初期化 */
    unsigned int sample_rate = 0;
    status = pv_orca_sample_rate(orca, &sample_rate);
    snd_pcm_t *pcm = NULL;
    if (setup_alsa(&pcm, sample_rate) != 0)
    {
        fprintf(stderr, "ALSA setup failed\n");
        pv_orca_pcm_delete(synth_pcm);
        pv_orca_word_alignments_delete(num_alignments, alignments);
        pv_orca_synthesize_params_delete(synth_params);
        pv_orca_delete(orca);
        return 1;
    }

    /* 再生 */
    if (play_pcm(pcm, synth_pcm, (size_t)num_samples) != 0)
    {
        fprintf(stderr, "Playback error\n");
    }

    /* drain & cleanup */
    snd_pcm_drain(pcm);
    snd_pcm_close(pcm);

    pv_orca_pcm_delete(synth_pcm);
    pv_orca_word_alignments_delete(num_alignments, alignments);
    pv_orca_synthesize_params_delete(synth_params);
    pv_orca_delete(orca);

    return 0;
}

makefile

# こういう構造の場合

[workdir]
├─ [program]
│    ├─ main.c
│    └─ Makefile
└─ orca
makefile
ORCA_BASE := ../orca

CC 		:= gcc
INCLUDE := -I$(ORCA_BASE)/include/
CFLAGS 	:= -g -O2 $(INCLUDE)
LIBS 	:= -L$(ORCA_BASE)/lib/linux/x86_64 \
	-lpv_orca \
	-lasound -ldl -lm \
	-Wl,-rpath=$(CURDIR)/$(ORCA_BASE)/lib/linux/x86_64


SRCS	:= main.c
EXE		:= orca_sample_alsa

all:
	$(CC)  $(CFLAGS) $(LIBS) $(SRCS) -o $(EXE)

実行

こんな感じで実行すると読み上げてくれる

tyano@fedora:sample$ make
gcc  -g -O2 -I../orca/include/ -L../orca/lib/linux/x86_64 -lpv_orca -lasound -ldl -lm -Wl,-rpath=/home/tyano/workspace/français/parle/sample/../orca/lib/linux/x86_64 main.c -o orca_sample_alsa
tyano@fedora:sample$ ./orca_sample_alsa 

その他

商用とかで使うならモデル使用料が要るらしい

対応デバイスはこんな感じ

$ ls ../orca/lib/ | cat
android
common
ios
linux
mac
node
raspberry-pi
wasm
windows

モデルはこんな感じ

$ ls ../orca/lib/common/ | cat
orca_params_de_female.pv
orca_params_de_male.pv
orca_params_en_female.pv
orca_params_en_male.pv
orca_params_es_female.pv
orca_params_es_male.pv
orca_params_fr_female.pv
orca_params_fr_male.pv
orca_params_it_female.pv
orca_params_it_male.pv
orca_params_ja_female.pv
orca_params_ja_male.pv
orca_params_ko_female.pv
orca_params_pt_female.pv
orca_params_pt_male.pv

日本語対応してるのに中国語が無いという攻めた仕様
韓国語はなぜか男性が無い

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?