記憶:WORLDで遊んだ

これは何?

pyworldというライブラリで遊んだ時の記憶です。
未来の271108へ。
このライブラリに対するメモ書きではないのでいつか理解する日が来たらメモ書きをしてください。

WORLDって何?

多分、「PyWorldVocoder」のこと。少なくとも遊んだ時の参考サイトにはそう書いてあった。

インストール

pip install pyworld

なお、参考サイトにはこう書いてあった。

先にscipyを入れておかないとpyworldのインストールでコケることがある

今回はもともとscipy入ってたのでそのままインストールしても問題なかった。

試した

特徴量を抽出し、音声を合成

なんかすごく面白そうな記事だったのでとりあえずまねっこをしましょう。
※参考元サイトのコードをそのままやっても動かなかったので一応私が実行した形で掲載。詳しい話は参考元のサイトを見てくれ。

from scipy.io import wavfile
import pyworld as pw
import numpy as np

WAV_FILE = ファイル名

fs, data = wavfile.read(WAV_FILE)
data = data.astype(np.float)

↑見ての通り、ファイルの読み込みを行っている。

_f0, t = pw.dio(data, fs)  # 基本周波数の抽出
f0 = pw.stonemask(data, _f0, t, fs)  # 基本周波数の修正
sp = pw.cheaptrick(data, f0, t, fs)  # スペクトル包絡の抽出
ap = pw.d4c(data, f0, t, fs)  # 非周期性指標の抽出

↑見て分かんない通り、特徴量の抽出を行っている。

synthesized = pw.synthesize(f0, sp, ap, fs)

↑得られた特徴量からを音声を合成するにはsynthesize メソッドを使うそうです。

import IPython.display as display

print('original')
display.display(
    display.Audio(data, rate=fs)
)

print('synthesized')
display.display(
    display.Audio(synthesized, rate=fs)
)

↑再生。


↑オリジナル
↑synthesized

簡単ですね。

うん、私にゃぁ何にも分からなかったよ。動いたけど。
ついでに言うとdata(オリジナル音源)とsynthesizedの違いがわからなかったよ。



でも違うってよ。PC君が言うんだから間違いない。私の聴覚機能よりよっぽどか信頼できる。

音声の変換

参考サイトではとりあえず1オクターブ高い声に変換してました。オクターブ、なんとなくしか分かりませんが、まあ真似てみましょう。

high_freq = pw.synthesize(f0*2.0, sp, ap, fs)  # 周波数を2倍にすると1オクターブ上がる

print('high_freq')
display.display(
    display.Audio(high_freq, rate=fs)
)


……甲高くてやかましいですね。まあもともとが女声なので当然といえば当然です。
じゃ、逆に半分にすればええか!

high_freq = pw.synthesize(f0*0.5, sp, ap, fs)  # 周波数を2倍にすると1オクターブ上がる

print('low_freq')
display.display(
    display.Audio(high_freq, rate=fs)
)


低く……なったかな?まあどっちかっていうと容疑者を知る人へのインタビュー感がぬぐえませんが。

本命

なんでこんなのやりだしたかって、「ロボットっぽく音声を変換できる」ってのにヒットしたからです。だからわざわざCCD-0500に話させて声質変換なんてかけているんです。
まあいいや。

参考サイト通り
robot_like_f0 = np.ones_like(f0)*100  # 100は適当な数字
robot_like = pw.synthesize(robot_like_f0, sp, ap, fs)

print('robot_like')
display.display(
    display.Audio(robot_like, rate=fs)
)


声低いなぁ。

ちょっと改善?

「f0とおんなじ形の1しか入っていない配列に100を掛けたもの」だから低いんですよね。
じゃあ高くしてみましょう。

f0ってのはこんな中身をしています。3秒で考えた案は3つ。

  1. とりあえず平均値でどうよ?
  2. いや、中央値のほうがいいのでは?
  3. 0に引っ張られて中央値も小さくならない?非0の中央値はどう?

じゃ、やってみましょ。

robot_like_f0_1 = np.ones_like(f0)*f0.mean()
robot_like_1 = pw.synthesize(robot_like_f0_1, sp, ap, fs)
print('f0.mean()')
display.display(display.Audio(robot_like_1, rate=fs))
write('f0.mean.wav', fs, robot_like_1)

robot_like_f0_2 = np.ones_like(f0)*np.median(f0)
robot_like_2 = pw.synthesize(robot_like_f0_2, sp, ap, fs)
print('median(f0)')
display.display(display.Audio(robot_like_2, rate=fs))
write('median(f0).wav', fs, robot_like_2)

robot_like_f0_3 = np.ones_like(f0)*np.median(np.nonzero(f0))
robot_like_3 = pw.synthesize(robot_like_f0_3, sp, ap, fs)
print('非零中央値')
display.display(display.Audio(robot_like_3, rate=fs))
write('非零中央値.wav', fs, robot_like_3)

あ、この基本周波数、f0ってもしかして抑揚の根幹なの?
あー……

とは思ったものの

いざ抑揚を0にさせると、それでもロボットっぽさは出ない。

この違いってなんなんすかね?


でも、

what_is_the_elements_of_robots = (np.ones_like(f0)*np.median(np.nonzero(f0)) + f0)/3.5
what_is_the_elements_of_robots_test = pw.synthesize(what_is_the_elements_of_robots, sp, ap, fs)
display.display(display.Audio(what_is_the_elements_of_robots_test, rate=fs))


こうするとロボットっぽさあるでしょ?

……ない?

次回予定

もう少し、様々な声を作れるのかもしれないようなのでさらに触ってみる。

参考元

qiita.com

余談

朝に突然謎の動画の連騰をしましたが全部この記憶貯蔵のためです。別に私がおかしくなったとかそんなことはございません。

メモ書き:Windowsのcmd使うやつ(subprocessとか)

subprocess.run()

なんかこれを使うことが推奨されてるらしい。*1

subprocess.Popen()

実行の処理の完了を待たずに次の処理に移る。

powershellを使う場合

import os
os.system("powershell -Command python test2.py")

python test2.pyを実行する場合。
この時、pythonの仮想環境で実行するとその仮想環境で普通に実行してた。この辺ちゃんと確認したほうがいいかも。

*1:※271108はpython3.6、3.7、3.9を使っています。python3.5以降から使用を推奨されているらしい。

思い付きのメモのまとめ直し

文字通りのメモの記事はこちら↓
271108.hatenablog.com

前提

沢山の文(と言うかツイート)をなんやかんやして集める、と言うか集めてる。別にAmesiorineさんのお仕事は1時間に1回トンチキなことをツイートするためだけじゃあないんですよ。

271108の知識関係なく考えること

対話システム、乃至発言システムというのはどうにも常識外れのことを発言してしまうものです。そのため、Amesiorineにはある程度賢そうに見えない設定が必要になるでしょう。天才そうに見えているのにすっとぼけたことを言うとがっかりしますからね。アホの子がアホなことを言っても「かわいいね」で済みますが、スーツ着た偉そうな人があほなことを言うと叩かれるようなものです。(本当?)
そのため、幼めの設定が必要になるはず。
あとは271108の趣味でいいでしょう。設定資料作ったら誰かに絵とか頼むか?

文章生成システム

気軽にできそうなものを上に、できなさそうなものを下に並び替えてメモにする。

バグ修正

多分今エミィなんも食べてない。
・DailySwallow()
・CanAmyEatThisTextList(d)
・swallow(c)
多分この辺にミスがあるっぽいので確認。
↑対応済

アップデート:BeTSCAE*1

  1. 作った文章を全部記録したほうがいいかも。
  2. テキスト生成の評価指標があったはず。これで作った文章の評価していいかも。
  3. 生成した文章の単語を置き換え*2てもいいんじゃないかな。単語スワップLSIとかで複数パターンできたりしない?

特定の単語から文章生成を開始することってできない?

案1
  1. 特定単語から開始
  2. 後ろへ展開していってEOSで終わり。
  3. 今度は特定単語から前へ展開していってBOSで終わり。
  4. できたものを出力

↑これだと、つなぎ目の部分が崩壊するかもしれない

案2
  1. 特定単語を真ん中に持つMDを持ってくる
  2. そのMDから案1と同じように展開して出力

単語スワップ:BeTSCAE内

単語スワップ構想案
  1. 該当単語達がw2vにあるか確認する
  2. 単語の稀少度(IDFとか?)を算出?
  3. 1番稀少な単語を入れ替える
  4. 2番目に稀少な単語*3をw2vとかの足し算引き算してそれっぽく置き換える。

2の補足:IDFを使ってその文章の中で希少単語がどれかを調べる。(順位付をする?)

単語スワップ:BeTSCAE大幅改築

  1. マスク単語推定(正しくは何て言うんだっけ?BERTとかRoBERTとかT5みたいなのでできるやつ)をして文を書き換えるのができるかも。
  2. これと単語スワップでデータのカサ増しができるかも?
  3. カサ増ししたものも、目視だけじゃなくて、テキスト生成の評価指標あったはず、それかなんかである程度判定できないかな

未検討

  1. 格フレームってものがあったはず。用言とそれに関係する名詞とか助詞とかなんかだったような。
  2. MAUVE?

対話システム

まだそもそもデータを集めていない。

  1. 271108とエミィのリプライだけでもいいしそれ以外も集めてもいいかも。もっとも、遠くの人のデータまで集めに行くのはめんどい。

同じようなデータを集めないといろいろ面倒かもしれない。

データ整備

  1. DBDC対話破綻検出。対話が破綻しているかどうかのモデルを作るならこの辺?

*1:BeTSCAEとは現在Amesiorineに使っている文章生成システムの名前です。命名センスは271108依存です。

*2:以降、「単語スワップ」と呼ぶ

*3:ただし、1番稀少な単語とは別単語

思いつきのメモ

沢山の文(と言うかツイート)をなんやかんやして集める、と言うか集めてる

 

IDFを使ってその文章の中で希少単語がどれかを調べる。(順位付をする?)

該当単語達がw2vにあるか確認

あればマスク単語推定(正しくは何て言うんだっけ?BERTとかRoBERTとかT5みたいなのでできるやつ)とw2vを使った単語スワップでデータのカサ増しができるかも?

 

その単語スワップLSIとかで複数パターンできたりしない?

 

カサ増ししたものも、目視だけじゃなくて、テキスト生成の評価指標あったはず、それかなんかである程度判定できないかな

 

格フレームってものがあったはず。用言とそれに関係する名詞とか助詞とかなんかだったような。

pyopenjtalkのインストールに四苦八苦した記憶

pipによるインストール

どうやらpipでインストールできるらしいと知り、試す。

Getting requirements to build wheel: finished with status 'error'

が、ダメ。
「wheelファイル」と「Python実行環境」の不一致によるものらしい?が調べても最適解は出なかった。

note: This error originates from a subprocess, and is likely not a problem with pip.

って言われてるし、subprocessのほうになんかあるらしい。ほえ~。

調べてたら別の記事を見つけた。

teitoku-window.hatenablog.com
この記事の本、まだ積んでるんだよなぁ…という感想も得た。早く読もうね。

CMakeツールとかが要るらしい

そういえば新しいPC*1にはVisual Studio入ってなかったかもしれない。
VisualStudio経由で「MSVC なんちゃらかんちゃら」と「WindowsC++ CMakeツール」をインストールする。

んでもって、CMakeで通すパスはこんな感じだった。見つけるのに時間がかかって苦しんだ。

C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin

これでようやくインストール……!

pip install pyopenjtalk

でインストールできた。

NKT……

*1:QuartaviaVonNeumann

Amesiorine ver2

バージョン2にしました。

「何をもってバージョンを更新したか」という明確な定義なんてありません。私が2と言えば2になるんです。
Amesiorine
twitter.com

アプデ内容

1.12からのアップデート内容です。

  • 271108が「save」の指示を出したリプライをすると、Amesiorine自身がツイートしたリプライ元のツイートを保存するようにした……つもりです
  • SFBとSFRは他の子と中身一緒にしたい。

「SFBとSFRが何か」については、多分どこでもブログ記事にしていないので271108以外には分からないものなので気にしなくていいです。

以上。

271108.hatenablog.com

「save」の指示の動機の記憶

これ多分忘れそうなのでここに残しておきます。
さてこのAmesiorine、私好みのことを言い出します。(もっとも、エミィに食べさせたデータが私のツイートデータですからね。)

ですが、Amesiorineに食べさせたデータ、どうやら整備ができていなかったみたいで。文章として崩壊しかねないような形になっていたのでそこの補正をする必要があることに気付いたのです。
でも、そのデータ全部再確認するの面倒でしょ?そういうわけである程度もう保存して置けるように確保しておこうと思いまして。
そのための機能です。

メモ書き:python.exe() (pyinstaller)

0:無駄話

毎回毎回python呼び出すの面倒なのでexe化しようかなぁって思い立ったので軽く調べたり調べなかったりしました。

世のプログラミングをやっている人がどうかなんて私には分かりませんが、私にプログラミングの世界を勧めてくれた人は「プログラミングなんてめんどくさがりがめんどいことをやらせるためにやってんよ」と言っていました。面倒なことだったりやりたくないことは勝手に機械どもにやらせておくに限るんです。
ね?そうだよね?PLB-279-T?

まあいいや。

1:インストール(本題ここから)

この記事はpyinstallerを使った時の記憶です。

pip install pyinstaller

2:実行

pyinstaller <変換pythonファイル> --name <出力exeファイル名> --onefile --icon <アイコンファイル>

どうやらアイコンファイルを指定できるみたい。

3:各種エラー

3-1:そもそもインストールできないエラーがあるらしい。

qiita.com
記事を読んだ感じ、Anaconda環境でconda installとpip installの両方を使ったりしてるとインストールできないみたい。今回の船井には影響なかったし伝聞に過ぎないけど一応記憶。

3-2:The 'typing' package is an obsolete backport of a standard library package and is incompatible with PyInstaller. Please `pip uninstall typing` then try again.

要するに「その'typing'っていうパッケージあるじゃん?それって、PyInstallerとの互換性ねぇンだわ。消せ。」って言われたわけです。じゃあ消すか。

なお、消す以外になんか方法あったりしない?と思って調べたらこんなの出てきた。
stackoverflow.com
草。

4:その他記憶

  • 出力されるexeファイルはdist下に生成される
  • カレントディレクトリ関連のコードを含んでいる場合、当然そのdistがカレントディレクトリになるっぽい
  • 別にdistからexeファイルを移動させても動く。この場合、カレントディレクトリはその移動させた先になるっぽい。
  • 今回はtqdmとか使ってたものをexeにした。コマンドプロンプトの画面でtqdmが表示されてるのでexe化するならこの辺も弄りたいよね……?って気持ちになった。
  • distやbuildフォルダを削除しても普通に動くっぽい