marubodiary.hateblo.jp
この大昔作ったネタアプリだが、最後に大問題を残したままなのだった。
・起動中に通知領域のマイクが荒ぶる問題
これの解決にようやく取り組む気になってそして解決したので、問題解決版のソースコードを書いておく。
結論
音声入力と画像描画を、スレッドに分けて処理した。
import pygame from pygame.locals import * import sys import pyaudio import numpy as np import threading #pyaudio初期化 chunk = 1024 FORMAT = pyaudio.paInt16 CHANNELS = 1 RATE = 44100 p = pyaudio.PyAudio() stream = p.open(format = FORMAT,channels = CHANNELS, rate = RATE, input = True, frames_per_buffer = chunk) # 閾値 threshold = 0.025 # 音データ格納用配列 x = np.empty(chunk) #pygame初期化 pygame.init() screen = pygame.display.set_mode((500,500)) pygame.display.set_caption("VTuber?") #画像取得 #基本 bg = pygame.image.load("base.png").convert_alpha() image_rect = bg.get_rect() #目 me1 = pygame.image.load("me.png").convert_alpha() me2 = pygame.image.load("me2.png").convert_alpha() me3 = pygame.image.load("me3.png").convert_alpha() #口 kuti1 = pygame.image.load("kuti.png").convert_alpha() kuti2 = pygame.image.load("kuti2.png").convert_alpha() #髪 kami = pygame.image.load("kami.png").convert_alpha() #フォント font = pygame.font.Font(None, 20) #タイマー変数 Timer = 0 #描画周期設定 Clock = pygame.time.Clock() FPS = 30 def draw(): while True: pygame.display.update() #時間経過 Timer = pygame.time.get_ticks() # 画像生成 ImageOut(screen, image_rect, bg, Select_Eye(Timer), Select_mouse(x, threshold), Select_Add()) #デバッグ用 #DebugGraph(screen, Timer) pygame.display.flip() Clock.tick(FPS) #画面更新 def streamread(): global x while True: # 音データの取得 data = stream.read(chunk) # ndarrayに変換 x = np.frombuffer(data, dtype="int16") / 32768.0 def main(): while True: # 終了用のイベント処理 for event in pygame.event.get(): # 閉じるボタンが押されたときの処理 if event.type == QUIT: stream.close() p.terminate() pygame.quit() sys.exit() #---------------- # パーツ選択 #---------------- def Select_Eye(Timer): # 瞬き(力技。。。もうちょい自然な見せ方があるはず if ((Timer % 2100) <= 160): put_me = me2 #目(閉じ)描画 else: put_me = me1 #目描画 #キー押下によって目の描画オブジェクトを変更する pressed_key = pygame.key.get_pressed() if pressed_key[K_q]: put_me = me3 #目(><)描画 return put_me def Select_mouse(x, threshold): #音声認識によって口の描画オブジェクトを変更する if x.max() > threshold: put_kuti = kuti1 #音声入力があるときの口描画 else: put_kuti = kuti2 #何もないときの口描画 return put_kuti def Select_Add(): #一番上に描画する画像(アクセサリーなど) put_add = kami #髪描画 return put_add #---------------- # 描画 #---------------- def ImageOut(screen, image_rect, bg, me, kuti, add): screen.fill((0, 255, 0, 0)) # 画面の背景色(緑) screen.blit(bg, image_rect) # ベース画像の描画 screen.blit(me, image_rect) # 目画像の描画 screen.blit(kuti, image_rect) # 口画像の描画 screen.blit(add, image_rect) # 上部画像の描画 return #---------------- # デバッグ用表示 #---------------- def DebugGraph(screen, Timer): print(Timer) return #スレッド作成 thread1 = threading.Thread(target=draw) thread2 = threading.Thread(target=streamread) thread1.setDaemon(True) thread2.setDaemon(True) thread1.start() thread2.start() if __name__ == "__main__": main()