PCの内臓マイクから音声を取得して音程を判定してみた。[Python, pyaudio, FFT]

概要

  • pythonでPC内臓マイクからの音声を取得して遊んでみた
  • リアルタイムに音声波形を描画してみた
  • フーリエ変換して音程の判定をやってみた


環境

  • OS: mac OS Big Sur バージョン 11.6.1
  • conda 4.11.0
  • Python 3.6.13


準備

anacondaで環境を準備。今回はPython 3.6.13でやっていきます。



canda install で以下を用意


  • matplotlib
  • pyaudio
  • numpy
  • opencv


実践

1.音声取得して波形をリアルタイム描画

pcの内臓マイクから音声をとって波形をプロットしました。


bufferとかrateは適当に設定。


ctrl+cで終了します。


import matplotlib.pyplot as plt
import pyaudio as pa
import numpy as np

RATE=44100
BUFFER_SIZE=16384

## ストリーム準備
audio = pa.PyAudio()
stream = audio.open( rate=RATE,
		channels=1,
		format=pa.paInt16,
		input=True,
		frames_per_buffer=BUFFER_SIZE)

## 波形プロット用のバッファ
data_buffer = np.zeros(BUFFER_SIZE*16, int)
while True:
	try:
		## ストリームからデータを取得
		audio_data=stream.read(BUFFER_SIZE)
		data=np.frombuffer(audio_data,dtype='int16')
		
		## リアルタイム音声波形プロット
		data_buffer = np.append(data_buffer[BUFFER_SIZE:],data)
		plt.plot(data_buffer)
		plt.ylim(-10000,10000)
		plt.draw()
		plt.pause(0.0001)
		plt.cla()
		
	except KeyboardInterrupt: ## ctrl+c で終了
		break

## 後始末
stream.stop_stream()
stream.close()
audio.terminate()


波形プロット結果





良い感じで波形が取れました。



2.フーリエ変換してみた

音声データが取れたのでとりあえずフーリエ変換して周波数成分を見てみました。


FFTをするわけですがnumpy使えばFFT自体は1行で終わります。


簡単で良いです。


fft_data = np.fft.fft(data)


これでフーリエ変換したデータは得られるのであとは良い感じにプロットを整えます。


import matplotlib.pyplot as plt
import pyaudio as pa
import numpy as np

RATE=44100
BUFFER_SIZE=16384

## ストリーム準備
audio = pa.PyAudio()
stream = audio.open( rate=RATE,
		channels=1,
		format=pa.paInt16,
		input=True,
		frames_per_buffer=BUFFER_SIZE)

## 波形プロット用のバッファ
data_buffer = np.zeros(BUFFER_SIZE*16, int)

## 二つのプロットを並べて描画
fig  = plt.figure()
fft_fig = fig.add_subplot(2,1,1)
wave_fig = fig.add_subplot(2,1,2)

while True:
	try:
		## ストリームからデータを取得
		audio_data=stream.read(BUFFER_SIZE)
		data=np.frombuffer(audio_data,dtype='int16')
		fft_data = np.fft.fft(data)
		freq=np.fft.fftfreq(BUFFER_SIZE, d=1/RATE)
		
		## プロット
		data_buffer = np.append(data_buffer[BUFFER_SIZE:],data)
		wave_fig.plot(data_buffer)
		fft_fig.plot(freq[:BUFFER_SIZE//20],np.abs(fft_data[:BUFFER_SIZE//20]))
		wave_fig.set_ylim(-10000,10000)
		plt.pause(0.0001)
		fft_fig.cla()
		wave_fig.cla()

		
	except KeyboardInterrupt: ## ctrl+c で終了
		break

## 後始末
stream.stop_stream()
stream.close()
audio.terminate()


波形プロット結果(上:FFT,下:音声波形)





1kHzのsin派を鳴らしてみました。


ちゃんとフーリエ変換できていそうです。



3.音程判定

フーリエ変換したデータからスペクトルで最大成分を取ってきて12音階に変換しました。


音階への変換はこんな感んじで。


(多分これで大丈夫だと思いますがテキトーです。)


SCALE=[
	'ラ', 'ラ#', 'シ', 'ド', 'ド#', 'レ',
	'レ#', 'ミ', 'ファ', 'ファ#','ソ', 'ソ#'
]


val=freq[np.argmax(fft_data)]
offset = 0.5 if val >= 440 else -0.5
scale_num=int(np.log2((val/440.0)**12)+offset)%len(SCALE)


ついでにopencvで現在の音程を文字で表示させました。


日本語描画するのに地味に手間取り。


コード


import matplotlib.pyplot as plt
import pyaudio as pa
import numpy as np
import cv2
from PIL import Image, ImageFont, ImageDraw

RATE=44100
BUFFER_SIZE=16384

HEIGHT=300
WIDTH=400
SCALE=[
	'ラ', 'ラ#', 'シ', 'ド', 'ド#', 'レ',
	'レ#', 'ミ', 'ファ', 'ファ#','ソ', 'ソ#'
]

## ストリーム準備
audio = pa.PyAudio()
stream = audio.open( rate=RATE,
		channels=1,
		format=pa.paInt16,
		input=True,
		frames_per_buffer=BUFFER_SIZE)

## 波形プロット用のバッファ				
data_buffer = np.zeros(BUFFER_SIZE*16, int)		

## 二つのプロットを並べて描画
fig  = plt.figure()
fft_fig = fig.add_subplot(2,1,1)		
wave_fig = fig.add_subplot(2,1,2)

while True:
	try:
		## ストリームからデータを取得
		audio_data=stream.read(BUFFER_SIZE)
		data=np.frombuffer(audio_data,dtype='int16')
		fd = np.fft.fft(data)
		fft_data = np.abs(fd[:BUFFER_SIZE//2])
		freq=np.fft.fftfreq(BUFFER_SIZE, d=1/RATE)

		## スペクトルで最大の成分を取得
		val=freq[np.argmax(fft_data)]
		offset = 0.5 if val >= 440 else -0.5
		scale_num=int(np.log2((val/440.0)**12)+offset)%len(SCALE)
		
		## 描画準備
		canvas = np.full((HEIGHT,WIDTH,3),255,np.uint8)
		
		## 日本語を描画するのは少し手間がかかる
		### 自身の環境に合わせてフォントへのpathを指定する
		font = ImageFont.truetype(
			'/System/Library/Fonts/ヒラギノ角ゴシック W5.ttc',
			120)
		canvas = Image.fromarray(canvas)
		draw = ImageDraw.Draw(canvas)
		draw.text((20, 100),
			SCALE[scale_num],
			font=font,
			fill=(0, 0, 0, 0))
		canvas = np.array(canvas)

		## 判定結果を描画
		cv2.imshow('sample',canvas)

		## プロット
		data_buffer = np.append(data_buffer[BUFFER_SIZE:],data)
		wave_fig.plot(data_buffer)
		fft_fig.plot(freq[:BUFFER_SIZE//20],fft_data[:BUFFER_SIZE//20])
		wave_fig.set_ylim(-10000,10000)
		plt.pause(0.0001)
		fft_fig.cla()
		wave_fig.cla()

		
	except KeyboardInterrupt: ## ctrl+c で終了
		break

## 後始末
stream.stop_stream()
stream.close()
audio.terminate()


実行結果





sin派(ラ:880Hz)を入れてみましたが良い感じに判定できていそうです。


人間の声でも大丈夫かは不安なところがありますが、、


とりあえずは今回はここまで。



所感

  • pythonは思いついたことがすぐに試せるので良い
  • 音にエフェクトをかけたり、他にも色々試せそう
  • 思いのほかフーリエ変換が簡単にできて驚いた
  • 自分の声で試したが音痴なので全然狙った音程が出せませんでした。
5

Game Up Your Life.

Skimieアプリをダウンロードして、タスク管理をゲーム化しよう

Skimieは、仕事や勉強にゲーミフィケーションを取り入れ、モチベーションアップをサポートする情報管理サービスです。

新着記事

誰もいない…?

一番上の投稿が3ヶ月前…

『ワードカスケード』って知ってますか?

ブックマークの整理をしていた際に、以下のサイトが目に留まりました。だいぶ前になるのですが、気になってブックマークしたのを思い出しました。https://river.tango-gacha.com/Cascade(カスケード)とは小滝・階段状に連続する滝のことを意味するようです。アイディア出しや頭の中を整理する時に、しばらく眺めるのは効果ありそうですね。クリックすると背景色が変わったり、しばらくすると左下にXへ遷移できるアイコンが出てきたりとする楽しい動きも良いですね!

Stable Diffusion オススメアプリと使い方

初心者から上級者まで、無料でもアニメ系のイラストを描きやすい、個人的にオススメなStable Diffusionベースアプリです。 【DaysAI】 レベルアップ報酬が手に入るようになったことで、無料〜ゴールド課金で充分使えるアプリです。 (プレミアム課金は費用対効果的によほど使い倒さない限り他のアプリの年額と同時に使った方が良いです) 「うちの子」と付くアプリだけあり、作成したキャラをベースに描いてくれるので、髪型、表情、服装の一部を修正もできます。 日本語、ポジティブプロンプトやしきい値対応。有料会員になればネガティブプロンプトにも対応します。 「(全身)、上から、ビューアを見る」とかでいけます。

Skimie のバトルのお気に入りパーティ

みなさんのお気に入りのキャラクターはなんですか? 自分は ・タダシ ・ヴァール ・羽柴シバ です。 ![](https://skimie.com/uploads/u/IEozBO1uEfWNYUwdTgAeADBUU4F3/img/090938062c2ca448d931523f898d4b4a229dc0f3833b087fe.png)

Days AI 7/27 挑戦分

使用アプリ:Days AI テーマ:「夏の温泉」 テーマに組み込まれているはずの浴衣が吹っ飛びました。多分、表情や髪型描き込み過ぎました…。 このアプリの仕様上、キャラの雛形はあるしので、髪の纏め方も「花の髪飾り」と「まとめ上げたポニーテール」くらいで良かったんだろうと反省…。 夏の温泉で足湯&冷酒呑んで酔っ払ってる、オッサン寄りな亜人種イケオジを描きたかっただけなんです…。

使い方がわからない!助けて!

使う練習であげてみました。 このアプリまだ使い方が わからないので ヒントをもらえると嬉しいです。

本日も毎日1筆です♪

![](https://skimie.com/uploads/u/8N0K1D3KdpeWs9IUaBbNTtqmjmv2/img/072628348c2ca448d931523f898d4b4a229dc0f3833b087fe.png) ゲーム、OMORIのファンアートです。

生成AI検索『Perplexity』とは?

『Perplexity』というサービスを耳にして、とても気になったので調べてみました。検索に利用できるサービスで、Google検索よりも便利とか、、、実際に利用してみた感じ、とても便利そうです!『Perplexity』とは?AI チャットボットを活用した調査および会話型検索エンジンのこと。「Perplexity AI」は、元Google AI研究者らによって提供されるAIアシスタントです。参考ページhttps://www.sbbit.jp/article/cont1/134482https://meet.acesinc.co.jp/blog/perplexityai/運営元:Perplexity AI, Inc.設立:2022年8月所在地: アメリカ合衆国に拠点事業内容:会話型人工知能(AI)を専門とするソフトウェア会社会話型AIを用いた回答エンジンを提供。Perplexity AIの特徴情報源がわかる自動で情報源が表示される。検索範囲を絞ることができる「YouTubeから」「学術論文から」など、検索範囲をプラットフォームやカテゴリに絞ってリサーチができる。目的により最適な情報源を選ぶことが可能です。自動で要約してくれる返答の文章を箇条書き形式で端的にまとめて生成がされる。最新データを基にした回答が可能インターネット上の情報から回答を生成するブラウジング機能が搭載されている。日本語にも対応しているスマホアプリで利用ができる『Perplexity』のURLhttps://www.perplexity.ai/

色覚検定3級クイズについて

何問かは伏せますが、「敵を警戒させる色」で、誤入力かと思いますが、同じ回答が2つあります。 正解は上の方です。これは問題側にミスがあるのでネタバレしていいかと思い描きました。 普段私は、短編小説(SS)、小説、AI生成イラストで自分のキャラクターの可視化などしています。

お気に入りの謎解きイベント

西武線沿線の駅周辺を散策しながら謎を解き明かしていく周遊型の謎解き宝探しイベントがやっていて、ここ3年くらい参加しています。Webページを確認すると、2019年より毎年開催しているとのことです。こちらイベントですが参加は無料!※ただし、西武線沿線でたくさん駅を乗り降りするため、西武線全線を自由に乗り降りできる切符を購入する必要があります。【2024年】WEST CODE 第六弾 見知らぬ絵日記と約束の列車期間:2024.4.26~9.16https://www.seiburailway.jp/newsroom/news/20240417_WESTCODE/西武線の色々な駅を知れる良い機会で、子供を含めて家族で参加しています。駅で冊子が配られているので、シーズンの休日は多くの参加者を目にするイベントです。謎のレベルは高めで、去年はゴールできなかったので、今年こそはクリアしたいです!

LINE新機能「スタンプアレンジ機能」とは?

5/8より、複数のLINEスタンプを組み合わせて送信できる機能がスタートしました!簡単に利用が出来て楽しいです。参考ページhttps://news.yahoo.co.jp/articles/695c6ea72b6a7a6746a0af4fd8376c8f34dfdd43やり方はとても簡単で、スタンプを長押しすると複数を選択できるモードになります。組み合わせたいスタンプを選択し、後は自由にレイアウトして送るだけです。以下、注意点です。スタンプアレンジできる物とできない物があるパソコンは、送信も表示もできない

私なりの Skimie の使い方。ゲーミフィケーションで楽しく日々のタスク管理や備忘録。

Skimie というこのサービス。まだ、色々な機能が成熟してないようだがゲーミフィケーションとタスク管理の組み合わせは面白いなと思って使ってみています。主な使い方は・タスク管理機能日々のタスクを管理するのはもちろん。買い物リストなどとしても活用しています。iPhone でいうリマンイダーみたいな使い方。・ナレッジ機能思いついたことなど備忘録をつらつらとメモするのに活用しています。基本的には非公開にして、自分用のメモです。今回はみなさんが活用するヒントになればと思い、ナレッジを一般公開してみます。タスクをこなしたり、ナレッジを書き溜めるとコインがもらえるので、それを使ってとりあえずキャラクターを育てるために日々コツコツと続けてます。Skimie を使うヒントになれば幸いです。

複数の写真を1つにする方法が知りたい

Xで投稿する際に、やりたいと思ったので調べてみました。意外と簡単な方法が見つからなかったので、もう少し調べたり、周りに聞こうと思います。とりあえずは、Androidユーザーの私が一番簡単にできそうな方法をご紹介します。参考サイトhttps://support.google.com/photos/answer/12637115?hl=ja&co=GENIE.Platform%3DAndroidツール「Googleフォト」アプリ機能「コラージュ」という機能を利用します。手順は参考サイトに記載ありますが、とても簡単です。テンプレートは無料なのは4つほどです。私のスマホにあるラーメン画像だとこんな感じ。

イオンクレジットカードの付帯保険「ショッピングセーフティ保険」が気になる

最近、イオンクレジットカードの広告を見て、気になる内容があったのでピックアップします。それは、イオンクレジットカードの付帯保険で「ショッピングセーフティ保険」のサービスです。とてもお得なサービスなので、他のクレジットカードなどにも同様のサービスがないか調べたいです。また、スマホやパソコンなどWeb購入する機会もあるので、ぜひ利用したいと思います。▶公式サイトhttps://www.aeon.co.jp/service/safety/イオンクレジットカードの「ショッピングセーフティ保険」はどんなサービスこちらの記事の最後に公式サイトのスクショも添付します。約半年間になりますが、偶然による事故の補償するサービスです。【対象】イオン銀行が発行したクレジットカードでクレジット決済する5,000円以上の商品【対象範囲】偶然による事故破損事故火災事故盗難事故【保証期間】購入日から180日以内

複数のPDFファイルを結合したい

最近、複数のPDFの資料を確認する作業があり、PDFを結合するサービスを探していました。検索すると、Webサービスを利用してオンラインでやる方法とツールをインストールする方法の2つがあるようです。今回は、ツールをインストールしてみました。見つけたツールCubePDF Pagehttps://www.cube-soft.jp/cubepdfpage/評判以下のサイトを参考にしました。ざっと読んでみると評価は良さそうな感じでした。https://www.itreview.jp/products/cubepdf-page/reviews感想利用方法がとてもシンプルで、特にマニュアルことなく利用ができました。注意点こちらのソフトをインストールすると、一緒に「CubeWidet」というソフトもインストールされるようです。こちらは、最小化してニュースが表示するようになり気になったのでアンインストールしました。補足こちら、pdfファイルの他にpngファイルでも同様の事ができないか試してみたところ対応できました!

ウェブサイトのパスワードをスマートに管理したい

色々なWebサービスを利用していると、パスワードの管理は困りませんか?最近、Googleで「Google パスワード マネージャー」というサービスがあることを知りました。パスワードを考えたり、メモしたり、管理したり、思い出したりするストレスから解放されるので、とても便利なサービスなので、ぜひ活用しましょう。公式サイトhttps://support.google.com/chrome/answer/95606?hl=JA&ref_topic=7438325サービス概要Chromeを利用して様々なサイトのパスワードを保存することができますパスワードの保存方法Chromeにて、ウェブサイトで新しいパスワードを入力すると、Chromeでパスワードを保存するかダイアログが表示されますので、こちらで [保存] をクリックするだけです。保存したパスワードの利用方法パスワード保存したウェブサイトのログインフォームを表示すると、自動的に入力されます。便利な点パスワードを覚える必要がないGoogleアカウントに連携しているため、スマホ・パソコンのどちらでもパスワード管理ができる操作がとても簡単