Pythonによる周波数分析器の利用方法 ― 2026年10月26日 17:30
余りにも英語の発音が下手なので、基本の母音と子音の区別から始めてみた。
だが、その前に母音とか、子音とかいうがその差はいったい何なのか、テキストには母音は声帯からの声をそのまま出した声、子音は歯や、唇や舌で押さえることで発声する声といった解説があるが、いまいちピンとこない。
そこで、各音の周波数分析ができないかとChatGPTに頼んだら、簡単にPythonプログラムによる周波数分析プログラムを作ってくれた。
下記のプログラムがそれである。これをPythonをインストールしたPC(マイク、スピーカー付き)で実行すると、画面に周波数分析窓が表示され、リアルタイムで話している声の周波数分析ができる。
その結果、分かったことは(誰でもやれば分かることだが)
(1)母音はいずれも低周波数にピークがあり、その倍音、3倍音などから構成されている。
(2)子音はいずれも低周波数のピークはなく、ノイズと同じように複雑な周波数構成になっている。
(3)二重子音(trとかblとか日本人が特に発音に苦労する音)は日本的な発音では二重子音の間に母音のu音が入り、低周波にピークが一瞬現れる。
従って、二重子音の発音時に低周波ピークが出ないような発声であれば、ネイティブな発音に近づくに違いない。
また、ネイティブ発音をパソコンに聞かせて、その周波数分析結果を見て、それに近い波長分布にすれば、ネイティブ発音の練習が客観的できるはずである。まだそこまではやれていないが可能性はあると思う。
以下はそのためのPythonプログラムである。PCさえあればすべて無料ですぐに可能なので時間と費用は大幅に節約できる英語発音上達法である。
import queue
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import sounddevice as sd
FS = 44100
BLOCK = 2048
N = 8192
MAX_HZ = 2000
q = queue.Queue(maxsize=12)
audio = np.zeros(N, dtype=np.float64)
def callback(indata, frames, time, status):
if status:
print(status)
try:
q.put_nowait(indata[:, 0].copy())
except queue.Full:
pass
def estimate_f0(x):
x = x - np.mean(x)
if np.sqrt(np.mean(x*x)) < 0.002:
return None
x = x * np.hanning(len(x))
# FFT autocorrelation, normalized by lag-dependent overlap
nfft = 1 << (2*len(x)-1).bit_length()
spectrum = np.fft.rfft(x, nfft)
ac = np.fft.irfft(abs(spectrum)**2, nfft)[:len(x)]
lo, hi = int(FS/400), int(FS/65)
lags = np.arange(lo, hi+1)
normalized = ac[lo:hi+1] / np.maximum(ac[0], 1e-12)
peaks = np.where((normalized[1:-1] > normalized[:-2]) &
(normalized[1:-1] >= normalized[2:]))[0] + 1
if not len(peaks):
return None
strong = peaks[normalized[peaks] >= max(0.25, normalized[peaks].max()*0.8)]
if not len(strong):
return None
lag = lags[strong[-1]] # favor longer period to reduce octave doubling
return FS / lag
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(11, 7))
fig.subplots_adjust(hspace=0.4, top=0.88)
fig.suptitle('Live microphone: waveform and spectrum', fontsize=14)
t = np.arange(N)/FS
wave, = ax1.plot(t, audio, lw=0.8)
ax1.set(xlabel='Time (s)', ylabel='Amplitude', xlim=(0, N/FS), ylim=(-1, 1))
ax1.grid(True)
freq = np.fft.rfftfreq(N, 1/FS)
mask = freq <= MAX_HZ
line, = ax2.plot(freq[mask], np.full(mask.sum(), -50.0), lw=1)
ax2.set(xlabel='Frequency (Hz)', ylabel='Level (dB, relative)', xlim=(0, MAX_HZ), ylim=(-50, 0))
ax2.grid(True)
f0_text = fig.text(0.5, 0.92, 'F0: -- Hz', ha='center', fontsize=16)
harmonics = []
def update(_):
global audio, harmonics
changed = False
while not q.empty():
chunk = q.get_nowait()
k = len(chunk)
audio = np.roll(audio, -k)
audio[-k:] = chunk
changed = True
if not changed:
return (wave, line, f0_text)
wave.set_ydata(audio)
spec = np.abs(np.fft.rfft(audio*np.hanning(N)))
db = 20*np.log10(np.maximum(spec, 1e-12))
db -= max(db.max(), 1e-12)
line.set_ydata(np.maximum(db[mask], -90))
for artist in harmonics:
artist.remove()
harmonics = []
f0 = estimate_f0(audio)
if f0 is None:
f0_text.set_text('F0: -- Hz (no stable voice)')
else:
f0_text.set_text(f'F0: {f0:.1f} Hz (estimated)')
for i in range(1, min(9, int(MAX_HZ/f0)+1)):
harmonics.append(ax2.axvline(i*f0, color='tab:red', ls=':', lw=0.9))
return (wave, line, f0_text)
try:
with sd.InputStream(samplerate=FS, channels=1, blocksize=BLOCK, callback=callback):
animation = FuncAnimation(fig, update, interval=80, cache_frame_data=False)
plt.show()
except sd.PortAudioError as e:
print('Microphone could not be opened:', e)
print('Check Windows microphone permission and the default input device.')
以下はこのpython プログラム(voice_spectrumr1-50db.pyと名付けました)の実行方法です。(下記3.10の部分は3.13などインストールしたバージョンに変更してみてください。
1. ライブラリをインストールする
Windows 11の「コマンドプロンプト」を開き、次のコマンドを実行してください。
py -3.10 -m pip install numpy matplotlib sounddevice
py -3.10 と指定することで、Python 3.10にインストールできます。
2. プログラムを実行する
1. 上記プログラムをテキストデータとして、voice_spectrumr1-50db.py という名前のファイルに保存します。
2. Python IDLE 3.10.3を起動します。
3. 「File」→「Open」で voice_spectrumr1-50db.py を開きます。
4. **F5キー(Run Module)**を押します。
5. 小窓が開き、音声の振幅、周波数分析結果がリアルタイムで表示されます。
6. マイクに向かって発声します。
3. 反応がない場合、マイクの確認
Windows 11の「設定」→「プライバシーとセキュリティ」→「マイク」で、デスクトップアプリにマイクへのアクセスを許可するがオンになっていることを確認してください。
だが、その前に母音とか、子音とかいうがその差はいったい何なのか、テキストには母音は声帯からの声をそのまま出した声、子音は歯や、唇や舌で押さえることで発声する声といった解説があるが、いまいちピンとこない。
そこで、各音の周波数分析ができないかとChatGPTに頼んだら、簡単にPythonプログラムによる周波数分析プログラムを作ってくれた。
下記のプログラムがそれである。これをPythonをインストールしたPC(マイク、スピーカー付き)で実行すると、画面に周波数分析窓が表示され、リアルタイムで話している声の周波数分析ができる。
その結果、分かったことは(誰でもやれば分かることだが)
(1)母音はいずれも低周波数にピークがあり、その倍音、3倍音などから構成されている。
(2)子音はいずれも低周波数のピークはなく、ノイズと同じように複雑な周波数構成になっている。
(3)二重子音(trとかblとか日本人が特に発音に苦労する音)は日本的な発音では二重子音の間に母音のu音が入り、低周波にピークが一瞬現れる。
従って、二重子音の発音時に低周波ピークが出ないような発声であれば、ネイティブな発音に近づくに違いない。
また、ネイティブ発音をパソコンに聞かせて、その周波数分析結果を見て、それに近い波長分布にすれば、ネイティブ発音の練習が客観的できるはずである。まだそこまではやれていないが可能性はあると思う。
以下はそのためのPythonプログラムである。PCさえあればすべて無料ですぐに可能なので時間と費用は大幅に節約できる英語発音上達法である。
import queue
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import sounddevice as sd
FS = 44100
BLOCK = 2048
N = 8192
MAX_HZ = 2000
q = queue.Queue(maxsize=12)
audio = np.zeros(N, dtype=np.float64)
def callback(indata, frames, time, status):
if status:
print(status)
try:
q.put_nowait(indata[:, 0].copy())
except queue.Full:
pass
def estimate_f0(x):
x = x - np.mean(x)
if np.sqrt(np.mean(x*x)) < 0.002:
return None
x = x * np.hanning(len(x))
# FFT autocorrelation, normalized by lag-dependent overlap
nfft = 1 << (2*len(x)-1).bit_length()
spectrum = np.fft.rfft(x, nfft)
ac = np.fft.irfft(abs(spectrum)**2, nfft)[:len(x)]
lo, hi = int(FS/400), int(FS/65)
lags = np.arange(lo, hi+1)
normalized = ac[lo:hi+1] / np.maximum(ac[0], 1e-12)
peaks = np.where((normalized[1:-1] > normalized[:-2]) &
(normalized[1:-1] >= normalized[2:]))[0] + 1
if not len(peaks):
return None
strong = peaks[normalized[peaks] >= max(0.25, normalized[peaks].max()*0.8)]
if not len(strong):
return None
lag = lags[strong[-1]] # favor longer period to reduce octave doubling
return FS / lag
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(11, 7))
fig.subplots_adjust(hspace=0.4, top=0.88)
fig.suptitle('Live microphone: waveform and spectrum', fontsize=14)
t = np.arange(N)/FS
wave, = ax1.plot(t, audio, lw=0.8)
ax1.set(xlabel='Time (s)', ylabel='Amplitude', xlim=(0, N/FS), ylim=(-1, 1))
ax1.grid(True)
freq = np.fft.rfftfreq(N, 1/FS)
mask = freq <= MAX_HZ
line, = ax2.plot(freq[mask], np.full(mask.sum(), -50.0), lw=1)
ax2.set(xlabel='Frequency (Hz)', ylabel='Level (dB, relative)', xlim=(0, MAX_HZ), ylim=(-50, 0))
ax2.grid(True)
f0_text = fig.text(0.5, 0.92, 'F0: -- Hz', ha='center', fontsize=16)
harmonics = []
def update(_):
global audio, harmonics
changed = False
while not q.empty():
chunk = q.get_nowait()
k = len(chunk)
audio = np.roll(audio, -k)
audio[-k:] = chunk
changed = True
if not changed:
return (wave, line, f0_text)
wave.set_ydata(audio)
spec = np.abs(np.fft.rfft(audio*np.hanning(N)))
db = 20*np.log10(np.maximum(spec, 1e-12))
db -= max(db.max(), 1e-12)
line.set_ydata(np.maximum(db[mask], -90))
for artist in harmonics:
artist.remove()
harmonics = []
f0 = estimate_f0(audio)
if f0 is None:
f0_text.set_text('F0: -- Hz (no stable voice)')
else:
f0_text.set_text(f'F0: {f0:.1f} Hz (estimated)')
for i in range(1, min(9, int(MAX_HZ/f0)+1)):
harmonics.append(ax2.axvline(i*f0, color='tab:red', ls=':', lw=0.9))
return (wave, line, f0_text)
try:
with sd.InputStream(samplerate=FS, channels=1, blocksize=BLOCK, callback=callback):
animation = FuncAnimation(fig, update, interval=80, cache_frame_data=False)
plt.show()
except sd.PortAudioError as e:
print('Microphone could not be opened:', e)
print('Check Windows microphone permission and the default input device.')
以下はこのpython プログラム(voice_spectrumr1-50db.pyと名付けました)の実行方法です。(下記3.10の部分は3.13などインストールしたバージョンに変更してみてください。
1. ライブラリをインストールする
Windows 11の「コマンドプロンプト」を開き、次のコマンドを実行してください。
py -3.10 -m pip install numpy matplotlib sounddevice
py -3.10 と指定することで、Python 3.10にインストールできます。
2. プログラムを実行する
1. 上記プログラムをテキストデータとして、voice_spectrumr1-50db.py という名前のファイルに保存します。
2. Python IDLE 3.10.3を起動します。
3. 「File」→「Open」で voice_spectrumr1-50db.py を開きます。
4. **F5キー(Run Module)**を押します。
5. 小窓が開き、音声の振幅、周波数分析結果がリアルタイムで表示されます。
6. マイクに向かって発声します。
3. 反応がない場合、マイクの確認
Windows 11の「設定」→「プライバシーとセキュリティ」→「マイク」で、デスクトップアプリにマイクへのアクセスを許可するがオンになっていることを確認してください。
コメント
トラックバック
このエントリのトラックバックURL: http://yokoyamashindo.asablo.jp/blog/2026/10/26/9883129/tb
※なお、送られたトラックバックはブログの管理者が確認するまで公開されません。
コメントをどうぞ
※メールアドレスとURLの入力は必須ではありません。 入力されたメールアドレスは記事に反映されず、ブログの管理者のみが参照できます。
※なお、送られたコメントはブログの管理者が確認するまで公開されません。