Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

setParamプラグイン向けの機能を追加 (otoini.py, utils) #13

Merged
merged 3 commits into from
Oct 10, 2024

Conversation

8uta
Copy link
Contributor

@8uta 8uta commented Oct 3, 2024

変更内容の概要

  • otoini.pyに、setParamプラグイン向けの関数とメソッドを追加しました。
  • utilsに、トライ木を扱う_trie.pyを追加しました。
  • それに伴い、utils__init__.pyを更新しました。

変更の理由

setParamプラグインの制作を容易にするためです。

影響範囲

この変更により、otoini.pyまたはutilsを使用しているコードが影響を受ける可能性があります。

テスト結果

  • 関数およびメソッド単位で、VS Code上でスクリプトをテストし、正常に動作することを確認しました。
  • Nuitkaを用いてexe化し、setParam上での動作を確認しました。

レビュワーへの注意点

  • 可能な限り確認を行いましたが、入門から日が浅く、初めてのプルリクエストですので、初歩的なミスが含まれている可能性があります。
  • 他のコードに悪影響を及ぼさないか、書き方が適切かどうか、特にご確認をお願いします。

変更の詳細

関数

otoini.pyに、次の関数を追加しました。

  • read_in_param: この関数は、次の情報を受け取ります。
    • cur_dir: setParamプラグイン本体が入っているフォルダの絶対パス。
    • vb_dir: setParamで開いている音源フォルダ、または処理対象の音源フォルダの絶対パス。
    • oto_ini_path: 原音設定の絶対パス。
    • oto_sp_path: 更新用原音設定の絶対パス。
    • f0_interval: F0の抽出間隔(単位=秒)。
    • power_interval: パワーの抽出間隔(単位=秒)。
    • view_rows: setParamの波形窓で現在表示しているデータの行番号。
    • select_rows: setParamのパラメータ一覧表で現在選択しているセルの行番号。
    • comment_txt_path: setParam用コメントテキストの絶対パス。
    • comment_sp_path: setParam用の更新用コメントテキストの絶対パス。
  • load_sp: この関数は、setParamプラグインの汎用的な初期設定を行います。
  • create_cv_dict: この関数は、単独音パラメータの辞書を作成します。

メソッド

otoini.pyOtoIniクラスに、次のメソッドを追加しました。

  • _apply_regex: このメソッドは、対象行 (エイリアスが正規表現に一致した行、または全行) に、引数で渡された関数を適用します。
  • replace_regexp_alias: このメソッドは、エイリアスを置換します。(正規表現対応)
  • add_alias: このメソッドは、エイリアスに接頭辞または接尾辞を追加します。
  • trim_alias: このメソッドは、エイリアスの前後から文字数を指定して削除します。
  • remove_duplicate: このメソッドは、エイリアスが重複している行を削除します。
  • copy_rename: このメソッドは、行の複製とリネームを行います。
  • copy_rename_csv: このメソッドは、「before,after」というcsv形式で書かれたファイルを元に、copy_renameを実行します。
  • round_param: このメソッドは、指定した小数点以下の桁数で四捨五入を行います。
  • overlap_1_3: このメソッドは、オーバーラップを先行発声の1/3にし、先行発声、固定範囲、右ブランクの位置は動かしません。
  • convert_vcv: このメソッドは、収録BPMから求めた連続音パラメータに変換します。
  • convert_cv: このメソッドは、収録BPMと辞書から求めた単独音パラメータに変換します。
  • set_cv_vcv: このメソッドは、単独音パラメータと連続音パラメータを適用します。

プライベートスクリプト

utils_trie.pyを追加しました。これはトライ木を作成および検索するためのモジュールです。現在は単独音の辞書を作成するcreate_cv_dictとその検索にのみ使用していますが、新しい内容も辞書化できるようにしています。

utaupy/otoini.py Outdated
continue
return self

def round_param(self, digits=None, pattern=None):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

数値をroundするのは明白なのでメソッド名 round() でやってしまいましょう!

Copy link
Contributor Author

@8uta 8uta Oct 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます。その件でひとつ心配していて、私の環境では関数を定義すると、関数名が青くなるんですが、round()にすると、関数名が緑になります。これはn = round(n, 3)のように四捨五入するときと同じ色です。これは大丈夫でしょうか?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

関数定義だと組み込み関数の round をオーバーライドしてしまうのでNGですが、OtoIni 内のメソッドであれば許容されます。色はおそらく、組み込み関数を使う際に分かりやすいようにテーマが気を利かせてくれているのだと思います。

Copy link
Owner

@oatsu-gh oatsu-gh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • otoini.OtoIni の汎用的なメソッドについては取り込みたいと思います。関数名等の調整をお願いします。
  • 具体的な数値固定の処理を伴うものはできるだけ避けたいので、その関連は見送りとしたいです。
    setParam プラグインの入出力はぜひとも使用したいです。その関連関数については otoini.py ではなくsetparam.py として新ファイルでお願いします。

utaupy/otoini.py Outdated
Comment on lines 288 to 319
def overlap_1_3(self, value=None, fixed=None, pattern=None):
"""
オーバーラップを先行発声の1/3にする。

Parameters:
value(float): 先行発声。または収録BPM。
fixed(bool): Trueではvalue=先行発声、それ以外ではvalue=収録BPMとして受け取る。
pattern(str): 対象行の正規表現のパターン。完全一致。省略時は全行に実行。
"""
if fixed is True:
# 先行発声を入力したとき
new_preutterance = float(value or 250)
new_overlap = new_preutterance / 3
else:
# 収録BPMを入力したとき
bpm = float(value or 120)
new_preutterance = (60000 / bpm) / 2
new_overlap = new_preutterance / 3

# 一致した行 or 全行で計算
def overlap_1_3_func(oto):
moving_value = oto.preutterance - new_preutterance
oto.offset = oto.offset + moving_value
oto.preutterance = new_preutterance
oto.overlap = new_overlap
oto.consonant -= moving_value
if oto.cutoff < 0:
oto.cutoff += moving_value
else:
oto.cutoff = oto.cutoff

return self._apply_regex(overlap_1_3_func, pattern=pattern)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

value と fixed の組み合わせで分岐するのは使い方を覚えづらいため、
value -> bpm=120
fixed -> preutterance=None
のようなオプション引数にするのが良いと考えます。
preutterance が None でなければ先行発声に基づいて処理、そうでなければbpmで計算するという流れがいいかなと思いました。

先行発声に対するオーバーラップの比率については、オプション引数 ratio (デフォルト値 1/3) を追加して、1/2 等任意の比率で実行にできるようにしたら汎用性上がりそうです。1/3 固定ではなくなるので関数名はかえた方がいいかもしれないです。init_overlap_ratio とかでしょうか、、、。

上記をまとめると、def overlap_1_3(self, bpm=120, preutterance=None, ratio=1/3, pattern=None) のような形式がいいかと思います。実装意図と異なる部分あったらコメントください。

utaupy/otoini.py Outdated
continue
return self

def round_param(self, digits=None, pattern=None):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

関数定義だと組み込み関数の round をオーバーライドしてしまうのでNGですが、OtoIni 内のメソッドであれば許容されます。色はおそらく、組み込み関数を使う際に分かりやすいようにテーマが気を利かせてくれているのだと思います。

utaupy/otoini.py Outdated

return self._apply_regex(overlap_1_3_func, pattern=pattern)

def convert_vcv(self, bpm=None, pattern=None):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

def convert_vcv(self, bpm=120, pattern=None):

とすれば 後続の bpm = float(bpm or 120) を省略可能です。

utaupy/otoini.py Outdated
oto.overlap = new_overlap
return self._apply_regex(convert_vcv_func, pattern=pattern)

def convert_cv(self, bpm=None, pattern=None):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

def convert_cv(self, bpm=120, pattern=None):

とすれば 後続の bpm = float(bpm or 120) を省略可能です。

utaupy/otoini.py Outdated
Comment on lines 206 to 216
def remove_duplicate(self):
"""
エイリアスが重複している行を削除する。対象は全行。
"""
seen_aliases = set()
unique_otoini = []
for oto in self:
if oto.alias not in seen_aliases:
unique_otoini.append(oto)
seen_aliases.add(oto.alias)
self.data = unique_otoini
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • 必須機能だと思うので大変助かります。
  • メソッド名は pandas に倣って、drop_duplicates にしたいと思います。
  • 残すのを最初の行にするか最後の行にするかを選べるといいなと思います。
    • オプション引数 keep='first' を追加し、'first' の時は最初の行を残して、'last' の時は最後の行を残し、それ以外が入力されたときはエラー
    • last の場合の実装は、listを反転させて処理したのちに再度反転させれば簡単だと思います。(別の方法でもかまいません)

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

convert_cv, convert_vcv, set_cv_vcv 見送りに伴って見送りとします。

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

otoini.Oto.convert_cv, convert_vcv, set_cv_vcv 見送りに伴って見送りとします。

utaupy/otoini.py Outdated
Comment on lines 44 to 116
def read_in_param(key=None):
"""
inParam.txtを読み込む。

Reference:
setParam.exeのあるフォルダ > plugins > README.txt

Example of Use:
from utaupy.otoini import load, read_in_param, OtoIni # インポート
path = read_in_param("oto_sp_path") # パス取得
otoini = load(path) # 原音設定を読み込む
otoing = OtoIni(otoini) # インスタンス化
otoing.round_param(1) # 原音設定を編集(例: 小数点以下1桁で四捨五入)
otoing.write(path) # 原音設定を保存
"""
# inParam.txtを探す
cur_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
par_dir = os.path.dirname(cur_dir)
in_param_path = os.path.join(par_dir, 'inParam.txt')

# inParam.txtを読み込む
with open(in_param_path, 'r', encoding='cp932') as f:
lines = [line.strip() for line in f.readlines()]
vb_dir = lines[0]
oto_sp_path = lines[1]
f0_interval = float(lines[2])
power_interval = float(lines[3])
view_rows = int(lines[4])
select_rows_str = lines[5]
select_rows = (
list(map(int, select_rows_str.split(',')))
if ',' in select_rows_str
else int(select_rows_str))

# inParam.txtのパスを元に、残りのパスを取得
oto_ini_path = os.path.join(vb_dir, 'oto.ini')
comment_txt_path = os.path.join(vb_dir, 'oto-comment.txt')
comment_sp_path = os.path.join(vb_dir, 'oto-autoEstimation-comment.txt')

settings = {}
settings = {
'cur_dir': cur_dir, # プラグイン本体の保存フォルダのパス
'vb_dir': vb_dir, # 処理対象の音源フォルダの絶対パス
'oto_sp_path': oto_sp_path, # 更新用の原音設定の絶対パス(ここから読み、ここに保存すること)
'oto_ini_path': oto_ini_path, # 原音設定の絶対パス
'f0_interval': f0_interval, # F0の抽出間隔(単位=秒)
'power_interval': power_interval, # パワーの抽出間隔(単位=秒)
'view_rows': view_rows, # setParamの波形窓で現在表示しているデータの行番号
'select_rows': select_rows, # setParamのパラメータ一覧表で現在選択しているセルの行番号
'comment_sp_path': comment_sp_path, # 更新用のsetParam用コメントテキストのパス
'comment_txt_path': comment_txt_path, # setParam用コメントテキストのパス
}
if key:
return settings.get(key, None)
return settings


def load_sp():
"""
setParamプラグインの汎用的な初期設定を行う。

Example of Use:
from utaupy.otoini import load_sp # インポート
path, otoing = load_sp() # 原音設定を読み込む、OtoIniのインスタンス化
otoing.round_param(1): # 原音設定を編集(例: 小数点以下1桁で四捨五入)
otoing.write(path) # 原音設定を保存
"""
path = read_in_param("oto_sp_path")
otoini = load(path)
otoing = OtoIni(otoini)
return path, otoing


Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これすごく助かります!
setParam プラグインに特化した setparam.py として別ファイルで作成お願いします。

Copy link
Contributor Author

@8uta 8uta Oct 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます! 関数名は変更しますか?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

read_in_param → read_inparam
load_sp → load
でお願いします。

utaupy/otoini.py Outdated
comment_txt_path = os.path.join(vb_dir, 'oto-comment.txt')
comment_sp_path = os.path.join(vb_dir, 'oto-autoEstimation-comment.txt')

settings = {}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この行は不要

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

すみません、こちらだと4行くらい表示されているので…何行目のことを指していますか? settings=のことのみでしょうか。それとも、コメントを編集するパスも取得しなくて良いという意味でしょうか?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

失礼しました。settingの行だけです。
つぎの行以降で定義し直しているので、この行はなくていいと思いました。

utaupy/otoini.py Outdated
Comment on lines 152 to 204
def replace_regexp_alias(self, before, after=None, pattern=None):
"""
エイリアスを置換する。(正規表現対応)

Parameters:
before(str): 置換する文字列。
after(str): 置換後の文字列。省略時は空文字。
pattern(str): 対象行の正規表現のパターン。完全一致。省略時は全行に実行。
"""
# 入力を取得 or デフォルト値を設定
before = str(before or "")
after = str(after or "")

# 一致した行 or 全行で置換
def replace_func(oto, before, after):
oto.alias = oto.alias.replace(before, after)
return self._apply_regex(replace_func, before, after, pattern=pattern)

def add_alias(self, prefix=None, suffix=None, pattern=None):
"""
エイリアスに接頭辞と接尾辞を追加する。

Parameters:
prefix(str): 追加する接頭辞。省略時は追加しない。
suffix(str): 追加する接尾辞。省略時は追加しない。
pattern(str): 対象行の正規表現のパターン。完全一致。省略時は全行に実行。
"""
# 入力を取得 or デフォルト値を設定
prefix = str(prefix or "")
suffix = str(suffix or "")

# 一致した行 or 全行に追加
def add_alias_func(oto):
oto.alias = (prefix or "") + oto.alias + (suffix or "")
return self._apply_regex(add_alias_func, pattern=pattern)

def trim_alias(self, prefix_len=None, suffix_len=None, pattern=None):
"""
エイリアスの前後から指定した文字数を削除する。

Parameters:
prefix(int): 語頭から削除する桁数。省略時は削除しない。
suffix(int): 語尾から削除する桁数。省略時は削除しない。
pattern(str): 対象行の正規表現のパターン。完全一致。省略時は全行に実行。
"""
# 入力を整数として取得 or デフォルト値を設定
prefix_len = int(prefix_len or 0)
suffix_len = int(suffix_len or 0)

# 一致した行 or 全行から削除
def trim_func(oto):
oto.alias = oto.alias[prefix_len:len(oto.alias)-suffix_len]
return self._apply_regex(trim_func, pattern=pattern)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

取り扱い検討中です。ライブラリとしては無くてもいい気もする一方であってもいい気もします。
いったん見送りとしますが今後継続検討としたく、切り分けてプルリク出していただけると幸いです。

@8uta
Copy link
Contributor Author

8uta commented Oct 5, 2024

たくさんのご指摘ありがとうございます…!一旦こちらで整理してみて、疑問点をまとめて改めてお伺いします。

@8uta
Copy link
Contributor Author

8uta commented Oct 10, 2024

修正内容

レビューありがとうございました。コードを修正しましたのでご確認ください。

変更点

  • 次の機能を削除しました。

    • _trie.py
    • copy_rename
    • copy_rename_csv
    • convert_cv
    • convert_vcv
    • set_cv_vcv
    • create_cv_dict
    • replace_regexp_alias
    • add_alias
    • trim_alias
  • 次の変更を行いました。

    • utaupy\utils\__init__.py: 初期化
    • utaupy\setparam.py: 新規作成
    • utaupy\__init__.py: setParamを追加
    • utaupy\otoini.py:
      • read_in_param: read_inparamに改名、setparam.pyに移動、setting={}の行を削除
      • load_sp: loadに改名、setparam.pyに移動
      • _apply_regex: apply_regexに改名、mapなどを追加
      • remove_duplicate: drop_duplicatesに改名、最後の行を残せるように変更
      • overlap_1_3:
        • 定義を init_overlap_ratio(self, bpm=120, preutterance=None, ratio=1/3, pattern=None) に変更
        • 計算式を new_overlap = new_preutterance * ratio に変更

@8uta
Copy link
Contributor Author

8uta commented Oct 10, 2024

エイリアス関連の機能を、別プルリクエスト #14 に分割しました。

@oatsu-gh
Copy link
Owner

ありがとうございます。内容確認しました。

@oatsu-gh oatsu-gh marked this pull request as ready for review October 10, 2024 11:20
@oatsu-gh oatsu-gh merged commit 7bfa9c4 into oatsu-gh:master Oct 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants