Skip to content

Instantly share code, notes, and snippets.

@nobonobo
Created March 25, 2013 13:15
Show Gist options
  • Save nobonobo/5237011 to your computer and use it in GitHub Desktop.
Save nobonobo/5237011 to your computer and use it in GitHub Desktop.
リアルタイムスペクトラム・アナライザーを作ってみた。 PortAudioのPython版PyAudioとnumpyに依存。 実行すると横並び64個の0〜9の数値の表示が流れ続けます。 マイク音声を入力すると周波数成分別に数字が大きくなります。 リアルタイム16Kサンプリングの512点FFTがCore-i5レベルCPU2%程度の使用量で動きます。 内部ではちゃんと周波数の値が計算されています(ループの中で計算する必要はなかった・・・) - 口笛で音階をつけると大きな数字が現れる場所がスライドします。 - 打撃音は全部の数値が増えます。
#!/usr/bin/env python
# encoding: utf-8
import sys
import os
import atexit
import time
import numpy as np
import pyaudio
class Spectrum(object):
FORMAT = pyaudio.paFloat32
CHANNELS = 1
RATE = 16000
def __init__(self):
self.pa = pyaudio.PyAudio()
self.last_samples = None
atexit.register(self.pa.terminate)
def fft(self, samples):
win = np.hanning(len(samples))
res = np.fft.fftshift(np.fft.fft(win*samples))
freq = np.fft.fftfreq(len(samples), d=self.RATE**-1)
return zip(freq, 20*np.log10(np.abs(res)))
def callback(self, in_data, frame_count, time_info, status):
data = np.fromstring(in_data, np.float32)
pr = []
for f,v in self.fft(data)[256-64:256]:
pr.append(str(min(9, max(0, int((v+50)/10)))))
print ''.join(pr)
return (in_data, self.recording)
def record(self):
self.recording = pyaudio.paContinue
stream = self.pa.open(format = self.FORMAT,
channels = self.CHANNELS,
rate = self.RATE,
input = True,
output = False,
#frames_per_buffer = self.FRAME_LEN,
frames_per_buffer = 512,
stream_callback = self.callback)
stream.start_stream()
while stream.is_active():
try:
time.sleep(1)
except KeyboardInterrupt:
self.recording = pyaudio.paAbort
stream.start_stream()
stream.close()
if __name__ == '__main__':
spe = Spectrum()
spe.record()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment