私自身は、この時機、単純な音声の圧縮を試みていて、音声は逆向きに並んでもパワースペクトル は等しい(*)と誤認識していた。ある長さの区間の音を対称にすれば、それだけで1/2にすることができる と思って対称にするために逆向きの音と平均して聞いてみた。これは、異様な音が混じっていると 気がついて、どうしたらそれがつかめるか考え、その逆向きの音声だけを聞いてみればよいことに 気がつく。そして発見したものである。
特許を取ろうと努力はしたが(**)、ある会社がテープの逆送りの音を正常にする装置として申請されていて、 特許は取れなかった。これを付けては正常なテープの逆送りの音には決してならないし、 もし、その会社がその通り製作したならその効果に仰天しただろう。
すでに20年が経過しようとしている。その会社もその特許が取れたか、取って商品にした形跡はない。 この不思議な技術は、フリーであっていて欲しいものである。
(*)分析区間の長さと逆転区間の長さとが等しいときには、確かに逆転音声は、パワースペクトルを
変えない。しかし、分析区間が逆転区間より大きいときは、まったく違うのである。
(**) 特開昭61-177495, (特願昭60-18989) によって特許庁のデータベースから読むことができる。
1.逆転音声とは
2.効果
3.差分逆転音声
4.スペクトルの反転
5.窓掛け逆転
この処理の入力系列を x(i) とし、出力系列を y(i) とする。 この処理は、N を周期的区間の長さとし、i は、時系列の時刻を表す。
y(i)= x(j) (1)i 時刻の出力の値 y(i) は、j 時刻の入力の値 x(i) を出力する。その j は次式で与える。
j= N x int(i/N) + (N - 1 - (i mod N)) (2)ここで、int(a/b) は割算の商、a mod b は割算の剰余である。
これをリアルタイムに処理するために、i>= j、入力を蓄えて出力するには、i>j の必要がある。 それには少なくとも N 個の値を一時的に蓄えるバッファが必要である。
j= N x int(i/N) + (N - 1 - (i mod N)) + N (3)そのために、(3) は N を引いている。リアルタイム実現には、入力を N 個のデータバッファに 左から右に走査して書き込み、右から左に走査して出力するバッファがあればよい。(Fig 2. 左)
それは、右端と左端が隣接し結合した円環状のバッファを考え、リングバッファへの入力の書込み ヘッドと、出力の読出しヘッドとが逆向きに回転していると考えることができる。(Fig 2 右)
ニュースのアナウンサーの美しい標準語の発声がこれを通すと、とんでもない地方の抑揚アクセント の発声に変わる。歌は、歌手の特徴と歌詞を変えずに旋律の全く違う音楽になる。
男声では 100 Hz 近辺、女性では 200 Hz 近辺であるピッチをうまく逆転させるには、 区間周波数を 200 Hz 〜 400 Hz でピッチの2倍程度にする必要がある。
その後、PC上でこの実験を行なった。44.1 KHz サンプルのCD音楽に変更を掛けるのである。 以前と同様の効果はあるが、サンプリング周波数による違いがある。リアルタイムにリングバッファの 長さ(区間長)を変更する機能がないと調整できないため、当時ほど実験ができていない。
差分逆転音声について、区間内の差分データは、順方向のときの差分であり、逆方向に並べるとき その差分は、符号を逆転すべきではないかと思う。そうすると、区間内の差分の総和が保存される というよい性質がなくなるので、差分の総和を各サンプル時点に分散して2倍にして加算する必要 がある。
この逆転音声、差分逆転は、音の変化にはまず驚くものだが、その聞き取りを妨害する雑音がまだ 問題として残されているが、上記の修正等、今後の改良によって、音声変更、音楽操作の道具になり 得ると思う。 (Mar. 5 2005)
図 4. スペクトルの反転(分析区間 M= 256, 逆転区間 N= 16)
図 5. スペクトルの反転(分析区間 M= 256, 逆転区間 N= 4)
X-Window への表示までのプログラム 図 4, 5 を作成したプログラム。サインカーブ波形を作り逆転させ 周波数分析する。それを X-Window に表示する。Unix, Linux を使う方は、容易に動作させられると思う。 xwd > rev4.xwd で ウインドをダンプし、convert rev4.xwd rev4.png でピングファイルに変換する。png は、gif より格段に圧縮できるため大きい 画像のとき私は png を使う。
この表示 (当時APPLE II で表示した) は、この処理の本質的な事情を理解させる。この処理は、周波数を変化させるが線形処理の範囲 にはいることに注意。線形の定義は、f(X_i + Y_i)= f(X_i) + f(Y_i) である。X_i と Y_i の 2 信号の出力の和 f(X_i) + f(Y_i) は、 和信号 X_i + Y_i を入力したときの出力 f(X_i + Y_i) と等しい。この意味で、DCT も DFT も線形処理である。
しかし、過去のサンプルとの関係から作られる、FIR とか、IIR の時不変 (係数が時間によって変化しない) フィルタ処理ではない。 FIR は、出力は、 Z_i= Σ_k W_k X_(i-k) (k= 0,..,K-1)、 IIR は、Z_i= Σ_k W_k Z_(i-k) (k= 1,..,K-1) によって表され、 過去の入力または出力に係数の積和によって出力が作られ、全く信号の順序を変化させることはできない。この処理をそう表示しても 係数が信号のように刻々に変化するものになる。システム論では信号とシステム(系)が対等の働きをするが、入力信号に系が依存しては、 説明にならない。どのような FIR 又は IIR フィルタも、Gain と位相の周波数特性をもつが、この処理のように入力周波数と異なる 周波数は出さないのである。
この逆転音声の処理は、通常のフィルタ処理が全くそれをなし得ない周波数変換を行う。もちろん、入力振幅の 2 乗や、平方根、絶対値 などを使う非線型処理に、信号とキャリアの和を通すと、信号周波数とキャリア周波数の和差を作成する。周波数差は、周波数の反転である。 また、2 入力信号の積である変調は、信号の周波数の和差を作ることができる。例えば、AM 変調処理(信号+直流とキャリアとの積) または、 Double Side Band 変調 (信号とキャリアとの積) は、入力周波数 f の反転 (キャリア周波数を f_c とするとき、出力周波数が f_c +- f になる) を行える。変調は 2 sinαcosβ = sin(α+β) + sin (α-β) などの 3 角(指数)関数の積が位相(指数)の和差を生むことと理解できる。
変調の処理は、通常、非線型処理とみなされるが、もともと積の演算は双線形であり、入力の一方にとってみれば線形系である。 キャリアは、通常、入力に依存しないから、キャリアをシステムに含めることができ、その場合、変調系は、周波数反転又はシフト機能 をもつ線形系である。その最も単純な例に入力サンプルの符号をサンプル毎に変える処理がある。それは、cos(fs/2 t) との積であり、 出力周波数は、fs/2 - f (f: 入力周波数) となる。 入力周波数は単純に fs/2 から折り返された周波数に変換され、図 4, 5 に同様な図は、左上から右下への壁を生む。類似の処理に cos (fs/m t) (m= 2,3,4..) との積がある。このような処理は、周波数の和差だけを生む。周波数の 2 倍、3 倍...を容易に生じる非線型処理 とは異なる線形処理である。
(Sep. 4 2006)
差分逆転のスペクトル変換
4.3 で、"差分逆転音声について...符号を逆転すべきではないかと思う。"と書いたが、波形全域の符号は、聞こえ方に影響しないから 誤りであった。時系列の差分は、周波数比例のゲインを与え、和分は、周波数に反比例のゲインを与える。差分、逆転、そして和分の3 者の直列は、差分時の入力周波数が逆転によって周波数が変換され、和分のときこの変化した周波数に反比例したゲインをもつため、 逆転によって周波数が上がる領域でゲインが小さく、逆転によって周波数が下がる領域でゲインが大きい。差分逆転と和分は、実際に 有効であるから、その意味を明確にしたいが、その周波数スペクトルの変換図は、何かを読み取ることが難しいほど汚い。差分逆転は 入出力周波数において非対称であり、周波数が下がるときに大きなゲインがあり、かつ直流成分が作られることが分かる。
1/2だけオーバーラップしたフレームにコサイン窓をかけ、逆転して、重複した両側のフレームの結果を加算すれば、不連続性を無くせる。 これの周波数スペクトル変換図は、必要とするスペクトル変換が正しく行われ、雑音は大きく減少している。
差分逆転も窓かけと組み合わせれば、雑音は大きく減少するが、直流成分の発生が残る。(Jul. 20 2010)
窓かけ逆転C言語ソースrevw.tgz:
原理的な効果を確認するだけの目的の単純な短いソースのプログラムです。それらしい結果が得られただけでデバッグを終えていますので、
細かなバグの残る可能性があります。特に、差分の窓掛け逆転の直流雑音は理解できず、単なるバグが原因ではないかという疑いがあります。
決して使いやすいアプリになっていませんが、この処理の効果を考える人の素材になると思い公開します。
revw ディレクトリ内にMakefile, invert.c, inv.c, x.c をいれ、外で tar cvfz revw.tgz revw で作成しました。
%tar xvfz revw.tgz (enter)で、revwディレクトリを復元します。
%cd revw (enter)で revwディレクトリに入り、
%make (enter)で invert.c から invert を作成します。
%invert input_wav_file output_wave_file (enter)で使用して下さい。
invert.c が窓掛け逆転のソースファイル。inv.c は、図7,8 作成用ソース, x.c はinv.c, invert.c で包含(#include)して使用するX関係の部分。 但し、invert.c では包含するがx.cを使っていない。wav file とは CD などのファイル形式の 2ch x 16bit PCM (LSB first)。ヘッダ部分は44 byteを仮定している。 ヘッダの部分は飛ばし、それ以外を処理する。窓長Nはソース invert.c の始めの方で、#define N 110 で指定(例えば音韻変化には22, ピッチ反転には110 を指定)。 WAVファイルのヘッダ部分(44 byte)は、そのままコピーして、その後の8秒分(ソース内に指定)だけ、2ch x Nサンプル毎に窓掛け逆転処理をする。 (2017/6/16)
x.c を使う(X関連のC言語の開発)には、Vine Linux 6.5 では su で apt-get install xorg-x11-devel が必要でした。 x.c を使わず、invert.c から#include "x.c" を除き、stdio.h, stdlib.h, math.h を #include した invert.c に変え、revw.tgz を更新しました。(2017/6/17)