11 분 소요

활동 기록


팀 활동

  • 4월 30일(화) 10:00~ 14:00 (오프라인 개발 진행)
  • 5월 1일(수) 10:00 ~ 11:30 (오프라인 개발 진행)
  • 5월 1일(수) 13:00 ~ 17:00 (오프라인 개발 진행)

→ 총 9시간 30분 진행

개별 활동

  • 조민수 : 5월 4일 - ui 화면간 상호작용 작업 진행 5시간
  • 유재휘 :
    • VAD 알고리즘 코드 수정 & TTS API 테스트 - 약 6시간
  • 전준표
    • 5월 5일(일) 15:00 ~ 18:30(데이터셋 전처리 알고리즘 수정 및 테스트)

진행 상황


1) Siamese network 정확도 측정 알고리즘 수정

  • 코드 수정
    • 정확도가 비정상적으로 낮았기 때문에 측정 코드를 전체적으로 다시 확인하였다. 확인 결과 각 이미지 간의 유클리드 거리 값을 통해 예측 값을 구하는 부분에서 부등호가 반대로 되어있는 것을 발견하여 이를 수정.
    • 기존의 정확도 측정 방법은 테스트 케이스들을 모두 실행 후 평균을 내는 방법이라 정확도의 편차가 심하였음. 따라서 해당 결과를 100번 반복 실행한 후 평균을 내는 방식으로 변경하여 정확도의 편차가 줄도록 하였음.
  • threshold 파라미터 수정
    • 보다 정확한 측정을 위하여 두 이미지가 동일한 클래스일 경우, 나타날 수 있는 유사도 값의 범위를 측정하여 해당 범위의 최대값을 threshold 값으로 재 설정하였다.
      • 200개의 test case를 통해 산정 ( 값이 낮을수록 유사도가 높음 )
        • 같은 클래스일 때 유사도 값 범위 : 0 ~ 0.74
        • 다른 클래스일 때 유사도 최소값 범위 : 0.27 ~ 1.05
      def compute_accuracy(model, test_loader, threshold=0.74):
          correct = 0
          total = 0
        
          model.eval()
        
          with torch.no_grad():
              for data1, data2, labels in test_loader:
        
                  data1, data2, labels = data1.cuda(), data2.cuda(), labels.cuda()
                  output1, output2 = model(data1, data2)
        
                  euclidean_distance = F.pairwise_distance(output1, output2)
                  predicted = (euclidean_distance > threshold).float()
                  correct += (predicted == labels).sum().item()
                  total += labels.size(0)
        
          accuracy = correct / total
          accuracy *= 100
          return accuracy
        
      result = 0
      for i in range(0,100):
        acc = int(compute_accuracy(net, test_dataloader))
        result += acc 
      print("accuracy : {}%".format(result/100))
    
  • 결과
    • 20% → 76.75%

2) 데이터셋 전처리 알고리즘 테스트 및 수정

3차 학습시작에 앞서, 데이터 셋을 더 늘리고, 일관성 있고 정확한 학습을 위하여 전처리 알고리즘을 전체적으로 체크 및 수정하는 작업을 진행하였다.

  • VAD 적용 여부에 따른 데이터 변조 가능성 테스트
    • 2차까지의 학습에 사용된 데이터에는 VAD 기능을 적용시키지 않았기 때문에 3차부터 VAD 기능을 적용시킨 데이터 셋을 학습에 이용 할 것이다. 바로 적용시키기 전에 원활한 학습을 위하여 VAD가 원본 데이터에 미치는 영향을 조사하였다.
    • 음성 파일
      • VAD적용 시, 음성 데이터 앞, 뒤의 공백 부분이 원활하게 제거되었음.
      • 앞, 뒤의 공백 부분을 제외한 부분 또한 데이터의 변형 없이 원본과 동일.
    • mel-spectrogram. 파일
      • VAD 미 적용

        k10_nonVAD

        k13_nonVAD

        k21_nonVAD

        k30_nonVAD

      • VAD 적용

        k10_VAD

        k13_VAD

        k21_VAD

        k30_VAD

    • 결과
      • 음성 데이터, mel-spectrogram 모두 원본 데이터의 큰 변형 없이 음성의 공백 부분만 제거가 되었다. 따라서 3차 학습부터는 VAD를 적용한 이미지를 학습에 이용 할 예정이다.
  • mel-spectrogram의 dpi 변경
    • 학습결과를 확인하는 과정에서 해상도가 다음과 같이 다소 낮아보이는 이미지가 많이 발견되었다. 원본 자체가 해상도가 낮은 지, 저장 과정에서 해상도의 손실이 발생하는지 확인하기 위하여 mel-spectrogram 저장 시에 dpi를 변경하여 이를 체크하였다.

    → 저장 과정에서 설정을 변경하면서 , 전 후 비교를 해 보았지만 이미지의 해상도에 큰 차이가 없었다.

  • 파일 저장 옵션 변경 & 코드 가독성 향상
    • 전처리 알고리즘 중에서 mel-spectrogram을 4채널 png로 저장한 후, 이를 다시 read 하여 3채널 jpg로 바꾸어주는 번거로운 과정이 포함되어 있었기 때문에 해당 알고리즘의 간략화를 시도하였다.

      → mel-spectrogram 의 저장 옵션을 처음부터 jpg로 선택하였을 경우, 자동으로 3채널로 저장되었기에 저장옵션을 JPG로 변경. 기존에 사용되던 png_to_jpg 부분을 제거하였다.

    • 기존의 코드에는 변수의 이름이나 파라미터의 이름의 직관성이 조금 떨어졌기에 직관적으로 파악 가능한 이름으로 변경하였다.

    → 코드 간략화 및 가독성 향상 작업을 마친 결과는 다음과 같다.

      """
      <각 파일 이름>
      KsponSpeech_[숫자].pcm : .wav로 변환 전 원본 .pcm 파일
      KsponSpeech_[숫자].wav : .pcm -> .wav로 변환된 파일
      VAD_KsponSpeech_[숫자].wav : VAD 알고리즘 적용된 .wav 파일
      Mel_spectrum_KsponSpeech_[숫자].jpg : RGB 3채널 Mel 적용 이미지
      """
        
      # ----------------------------------------------------------------
      import os
      import numpy as np
      import librosa
      import librosa.effects
      import librosa.display
      import soundfile as sf
      import wave
      from PIL import Image
      import matplotlib.pyplot as plt
      from scipy.io.wavfile import read
      # ----------------------------------------------------------------
        
      # ----------------------------------------------------------------
      # .pcm -> .wav 변환함수
      def pcm_to_wav(pcm_data, wav_data, channels, sample_width, frame_rate):
          # PCM 파일 열기
          with open(pcm_data, 'rb') as pcm:
              # WAV 파일 열기
              with wave.open(wav_data, 'wb') as wav:
                  # WAV 파일 헤더 설정
                  wav.setnchannels(channels)
                  wav.setsampwidth(sample_width)
                  wav.setframerate(frame_rate)
                    
                  # 오디오 데이터 쓰기
                  data = pcm.read()
                  wav.writeframes(data)
      # ----------------------------------------------------------------
        
      # ----------------------------------------------------------------
      # VAD 알고리즘
      def wav_to_vad(wav_data, path):
          y, sr = librosa.load(wav_data)
          y_trimmed, index = librosa.effects.trim(y, top_db=30)
          sf.write(path, y_trimmed, sr)
      # ----------------------------------------------------------------
        
      # ----------------------------------------------------------------
      # 현재 위치한 디렉토리 내의 확장자가 .pcm인 모든 파일 불러오기
      data_dir = "/content/drive/MyDrive/kr"
      save_dir = "/content/test"
        
      original_files = [f for f in os.listdir(data_dir) if f.endswith(".pcm")]
        
      # 반복하여 한번에 여러 파일 처리
      for original_file in original_files:
          # original 파일의 이름
          original_path = os.path.join(data_dir, original_file)
          # .wav 파일의 경로
          wav_path = os.path.join(save_dir, os.path.splitext(original_file)[0] + ".wav")
            
          # PCM을 WAV로 변환
          pcm_to_wav(original_path, wav_path, channels=1, sample_width=2, frame_rate=16000)
          print(".pcm을 .wav로 변환 완료")
            
          # VAD 적용하여 새로운 .wav 파일 저장
          vad_wav_path = os.path.join(save_dir, f"VAD_{os.path.splitext(original_file)[0]}.wav")
          wav_to_vad(wav_path, vad_wav_path)
          wav_path = vad_wav_path
          print(".wav 파일에 VAD 알고리즘 적용 완료")
        
          # WAV 파일 읽기
          y, sr = librosa.load(wav_path)
            
          # Mel-spectrogram 계산
          mel_spectrogram = librosa.feature.melspectrogram(y=y, sr=sr)
            
          # Mel-spectrogram을 데시벨로 변환
          mel_spectrogram_db = librosa.power_to_db(mel_spectrogram, ref=np.max)
            
          # Mel-spectrogram 플로팅
          plt.figure(figsize=(10, 4))
          axes = librosa.display.specshow(mel_spectrogram_db, sr=sr, x_axis='time', y_axis='mel')
            
          # plot 그래프 이미지만 나타내기
          plt.yticks(ticks= []) # y축 tick 제거
          plt.xticks(ticks= []) # x축 tick 제거
            
          # # x축, y축 각각 눈금 & 테두리 제거
          plt.gca().axes.get_xaxis().set_visible(False)
          plt.gca().axes.get_yaxis().set_visible(False)
          plt.gca().spines['bottom'].set_visible(False)
          plt.gca().spines['left'].set_visible(False)
          plt.gca().spines['top'].set_visible(False)
          plt.gca().spines['right'].set_visible(False)
        
          # 제목과 컬러바(오른쪽 색상표시바) 제거
          plt.title('')
          plt.colorbar().remove()
        
          # 이미지 저장 (그래프 내용 부분만...흰 배경X)
          output_filename = os.path.join(save_dir, f"Mel_spectrum_{os.path.splitext(os.path.basename(wav_path))[0]}.jpg")
          plt.axis('off')
          plt.savefig(output_filename, bbox_inches='tight', pad_inches=0)
          plt.close()
          print(".wav 파일에 Mel 알고리즘 적용 완료")
      # ----------------------------------------------------------------
    

3) VAD - Mel 알고리즘 코드 보완

기존 코드는 .pcm → .wav 변환 후 바로 Mel spectrogram 알고리즘을 적용하는 방식

  • VAD 기능이 없어 음성 데이터의 앞 뒤에 공백이 많아 학습이 어려움
  • 이를 방지하기 위해 .pcm → .wav 변환 후, VAD를 적용하여 음성 데이터의 목소리 공백 부분을 제거한 후에 Mel 알고리즘 적용하여 데이터셋 정리
  • 기존에 사용한 .png → .jpg 변환하여 4채널(RGBA) 이미지를 3채널(RGB)로 바꾸는 함수 부분은 Mel 이미지 이름을 정하는 부분을 .jpg로 바꾸기만 하면 되어서 삭제

vad_mel.py

"""
<각 파일 이름>
KsponSpeech_[숫자].pcm : .wav로 변환 전 원본 .pcm 파일
KsponSpeech_[숫자].wav : .pcm -> .wav로 변환된 파일
VAD_KsponSpeech_[숫자].wav : VAD 알고리즘 적용된 .wav 파일
Mel_spectrum_KsponSpeech_[숫자].png : RGBA 4채널 Mel 적용 이미지
c_[숫자].jpg : RGB 3채널로 변환된 Mel 적용 이미지
"""

# ----------------------------------------------------------------
import os
import numpy as np
import librosa
import librosa.effects
import librosa.display
import soundfile as sf
import wave
from PIL import Image
import matplotlib.pyplot as plt
from scipy.io.wavfile import read
# ----------------------------------------------------------------

# ----------------------------------------------------------------
# .pcm -> .wav 변환하는 파트
def pcm_to_wav(pcm_file, wav_file, channels, sample_width, frame_rate):
    # PCM 파일 열기
    with open(pcm_file, 'rb') as pcm:
        # WAV 파일 열기
        with wave.open(wav_file, 'wb') as wav:
            # WAV 파일 헤더 설정
            wav.setnchannels(channels)
            wav.setsampwidth(sample_width)
            wav.setframerate(frame_rate)
            
            # 오디오 데이터 쓰기
            data = pcm.read()
            wav.writeframes(data)
# ----------------------------------------------------------------

# ----------------------------------------------------------------
# 현재 실행 중인 파일의 경로
current_directory = os.path.dirname(os.path.abspath(__file__))
# ----------------------------------------------------------------

# ----------------------------------------------------------------
# VAD 알고리즘
def wav_to_vad(no_vad_wav, apply_vad_wav):
    y, sr = librosa.load(no_vad_wav)
    y_trimmed, index = librosa.effects.trim(y, top_db=30)
    sf.write(apply_vad_wav, y_trimmed, sr)
# ----------------------------------------------------------------

# ----------------------------------------------------------------
# 현재 위치한 디렉토리 내의 확장자가 .pcm인 모든 파일 불러오기
pcm_directory = "."

my_pcm_data = [f for f in os.listdir('.') if f.endswith(".pcm")]

# 반복하여 한번에 여러 파일 처리
for pcm_file in my_pcm_data:
    # .pcm 파일의 경로
    pcm_sound = os.path.join(pcm_directory, pcm_file)
    
    # .wav 파일의 경로
    wav_file = os.path.join(pcm_directory, os.path.splitext(pcm_file)[0] + ".wav")
    
    # PCM을 WAV로 변환
    pcm_to_wav(pcm_sound, wav_file, channels=1, sample_width=2, frame_rate=16000)
    print(".pcm을 .wav로 변환 완료")
    
    # VAD 적용하여 새로운 .wav 파일 저장
    vad_wav_file = os.path.join(pcm_directory, f"VAD_{os.path.splitext(pcm_file)[0]}.wav")
    wav_to_vad(wav_file, vad_wav_file)
    print(".wav 파일에 VAD 알고리즘 적용 완료")
    
    # WAV 파일 읽기
    y, sr = librosa.load(wav_file)
    
    # Mel-spectrogram 계산
    mel_spectrogram = librosa.feature.melspectrogram(y=y, sr=sr)
    
    # Mel-spectrogram을 데시벨로 변환
    mel_spectrogram_db = librosa.power_to_db(mel_spectrogram, ref=np.max)
    
    # Mel-spectrogram 플로팅
    plt.figure(figsize=(10, 4))
    axes = librosa.display.specshow(mel_spectrogram_db, sr=sr, x_axis='time', y_axis='mel')
    
    # plot 그래프 이미지만 나타내기
    plt.yticks(ticks= []) # y축 tick 제거
    plt.xticks(ticks= []) # x축 tick 제거
    
    # # x축, y축 각각 눈금 & 테두리 제거
    plt.gca().axes.get_xaxis().set_visible(False)
    plt.gca().axes.get_yaxis().set_visible(False)
    plt.gca().spines['bottom'].set_visible(False)
    plt.gca().spines['left'].set_visible(False)
    plt.gca().spines['top'].set_visible(False)
    plt.gca().spines['right'].set_visible(False)

    # 제목과 컬러바(오른쪽 색상표시바) 제거
    plt.title('')
    plt.colorbar().remove()

    # 이미지 저장 (그래프 내용 부분만...흰 배경X)
    output_filename = os.path.join(pcm_directory, f"Mel_spectrum_{os.path.splitext(os.path.basename(wav_file))[0]}.jpg")
    plt.axis('off')
    plt.savefig(output_filename, bbox_inches='tight', pad_inches=0)
    plt.close()
    print(".wav 파일에 Mel 알고리즘 적용 완료")
    
    print("종료")
# ----------------------------------------------------------------

4) 사운드센서 코드 수정

  • 기존의 사운드센서 코드를 라즈베리에서 동작할 경우 “ValueError: math domain error” 에러 발생
    • 이유: math.log를 사용할 때 괄호안에 값이 0일 경우 나타나는 Error
    • 해결방안: analog_value의 값이 0일 경우 임의로 값을 부여
  • 또한 기존의 코드에서 dB 계산식을 “20 * log10(아날로그 값 / 5)를 사용했지만, 사운드센서에서 print되는 아날로그값 자체가 전압계산을 통해 전처리 된 값이기 때문에 나누기5를 할 필요가 없다
#수정된 코드

import time
import spidev
import math

spi = spidev.SpiDev()
spi.open(0,0)
spi.max_speed_hz = 1350000

def analog_read(channel):
    r = spi.xfer2([1, (8+channel) << 4, 0])
    adc_out = ((r[1]&3) << 8) + r[2]
    return adc_out

while True:
    reading = analog_read(0)
    analog_value = reading
    #math domain error 방지 analog_value 값 임의 부여
    if analog_value <= 0:
       analog_value = 1
    #dB계산법에서 나누기 제외
    db_value = 20 * math.log10(analog_value)
    print("db:", round(db_value, 1))
    time.sleep(0.5)

5) UI에 사운드센서 데이터값 적용

  • 제작된 UI에 다이얼로그를 추가해서 실시간으로 사운드센서 값을 불러올 수 있도록 설정하였다
    • 소음 측정 버튼을 누르면 실시간으로 사운드센서 값을 한번 불러오고 주변의 소음이 어떤지 확인 하는 방향으로 진행 할 예정이다
  • 문제점
    • 원하는 결과값 print: 9.5db 실제 나오는 결과값 print: (9.5, ‘db’)
    • 소음을 한번 측정하고 뒤로가기 버튼을 누른 후에 다시 소음을 측정하면 이전에 값이 사라지지않고 남아있어 글자가 겹치는 현상이 일어난다
  • 사용한 코드
import sys
import spidev
import time
import math

from PyQt5 import uic
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

form_class = uic.loadUiType("./sub.ui")[0]

class WindowClass(QMainWindow, form_class):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.checknoise.setHidden(True)
        self.selectsexual.setHidden(True)
        self.resultnoise.setHidden(True)
        self.result.setHidden(True)
        self.button_selectsexual.clicked.connect(self.uiselectsexual)
        self.button_startchecknoise.clicked.connect(self.uichecknoise)
        self.button_resultnoise.clicked.connect(self.uiresultnoise)
        self.button_result.clicked.connect(self.uiresult)
        self.button_backtoselectsexual.clicked.connect(self.uiselectsexual)
        self.button_backtochecknoise.clicked.connect(self.uichecknoise)
        self.button_backtomain.clicked.connect(self.uimain)
        self.button_rerecord.clicked.connect(self.uiresultnoise)
        self.button_exit.clicked.connect(self.close)
        self.noise = None
        self.dialog = QDialog()
        self.spi = spidev.SpiDev()
        self.spi.open(0,0)
        self.spi.max_speed_hz = 1350000
    def uimain(self):
        self.selectsexual.hide()
        self.checknoise.hide()
        self.resultnoise.hide()
        self.result.hide()
        self.mainwindow.show()
    def uiselectsexual(self):
        self.selectsexual.show()
        self.checknoise.hide()
        self.resultnoise.hide()
        self.result.hide()
        self.mainwindow.hide()

    def uichecknoise(self):
        self.selectsexual.hide()
        self.checknoise.show()
        self.resultnoise.hide()
        self.result.hide()
        self.mainwindow.hide()
        self.dialog.setWindowTitle("Dialog")
        self.dialog.setWindowModality(Qt.ApplicationModal)
        self.dialog.resize(300,200)
        db_value = self.read_sensor_data() #사운드센서 값 불러옴
        self.noise = db_value, "db"
        noiselabel = QLabel(self.dialog)
        noiselabel.move(100,100)
        noiselabel.setText(self.noise)
        self.dialog.show()
        
    def read_sensor_data(self):   #사운드 센서값을 불러오는 함수
	         while True:
	                 r = self.spi.xfer2([1, (8+0) << 4, 0])
	                 adc_out = ((r[1]&3) << 8) + r[2]
	                 analog_value = adc_out
	                 if analog_value <= 0:
	                         analog_value = 1
	                 db_value = round(20 * math.log10(analog_value), 1)
	                 time.sleep(0.5)
	                 return db_value
	                 

    def uiresultnoise(self):
        self.selectsexual.hide()
        self.checknoise.hide()
        self.resultnoise.show()
        self.result.hide()
        self.mainwindow.hide()
    def uiresult(self):
        self.selectsexual.hide()
        self.checknoise.hide()
        self.resultnoise.hide()
        self.result.show()
        self.mainwindow.hide()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ui = WindowClass()
    ui.show()
    exit(app.exec_())
  • 결과 사진

6) TTS API 활용

사용 API

Google Cloud TTS API

API 활용 이유

기존에 완성한 tts 기능은 gtts를 사용하여 남성 목소리만 출력됨 → 사용자의 성별에 따른 더 정확한 분석을 하기 위해 남성/여성 각각 구분하여 TTS를 활용해야 함

활용방법

  1. 가상환경 활용 → API 테스트
  2. 가상환경 없이 활용 → 실제론 이 방법으로 진행

활용순서

0) 시작 전…API 인증키 발급

https://console.cloud.google.com/welcome

해당 링크를 통해 로그인 후, ‘사용자 인증 정보’로 들어가서 ‘사용자 인증 정보 만들기’ 선택

→ 서비스 계정 관리에서 .json 형태의 키 발급 (활용할 코드파일과 같은 디렉토리에 두어야 함)

(역할은 무조건 “소유자(owner)”로 하기)

추가된 서비스계정 목록의 맨 오른쪽에 있는 ‘수정’탭 클릭 → 키 추가로 .json 키 다운로드

1) Google SDK (= CLI 설치)

[빠른 시작: Google Cloud CLI 설치     Google Cloud CLI 문서](https://cloud.google.com/sdk/docs/install-sdk?hl=ko)

하나하나 설치하면 cmd와 같은 명령 프롬프트가 설치됨!

2) 해당 API TTS 기능을 만들 디렉토리 생성

mkdir [파일이름~~]

3) 작동 전, 터미널(cmd 등) 명령어 입력 순서

pip install --upgrade google-cloud-texttospeech
set GOOGLE_APPLICATION_CREDENTIALS=C:\[.json 키파일이 저장된 경로]\[서비스계정키이름].json
gcloud auth activate-service-account --key-file="C:\[.json 키파일이 저장된 경로]\[서비스계정키이름].json"

4) VScode 터미널, 명령 프롬프트 등에서 해당 파일 실행

python [해당코드파일이름].py

발생한 문제1

가상환경에서 테스트한 후, 일반 디렉토리에서 해당 TTS 기능을 만들려고 하였는데 google cloud tts 기능을 다운로드하는 부분에서 아래 ERROR가 뜸

충돌이 일어났던 명령어

pip install --upgrade google-cloud-texttospeech

원인

  • 기존 테스트 때, 가상환경을 설치하고 거기에 했었는데 가상환경을 설치하지 않아도 되는 것을 까먹고 똑같이 하다가 서로 버전이 맞지 않아 에러
  • 설치되는 프로그램 별로 버전이 안맞음 & 일정 버전 이상은 tts 호환X

해결방법

가상환경 없이 할 것이기 때문에, 생성 파트를 스킵하고 바로 아래 명령어를 순서대로 입력 (키 설정)

pip install --upgrade google-cloud-texttospeech
set GOOGLE_APPLICATION_CREDENTIALS=C:\[.json 키파일이 저장된 경로]\[서비스계정키이름].json
gcloud auth activate-service-account --key-file="C:\[.json 키파일이 저장된 경로]\[서비스계정키이름].json"

발생한 문제2

가상환경 활용, 활용 X 둘 다 Google Cloud SDK Shell 프롬프트, 기본 cmd 프롬프트, 아나콘다 프롬프트 전부 사용 가능 → 그러나 할때마다 API 키를 인증해야 함

해당 TTS를 이용할 때마다 Key를 인증해야 하는 문제 → 보안 & 번거로움

원인

코드에 키 인증을 자동으로 해주는 부분 X

해결방법

코드 내부에 자동으로 인증 키인 .json을 인식시켜서 터미널에서 번거롭게 매번 인증하지 않아도, 편리하게 TTS 기능을 이용할 수 있게 함 → 아래 코드 추가하기

from google.oauth2 import service_account

credentials = service_account.Credentials.from_service_account_file([Key이름].json')

client = texttospeech.TextToSpeechClient(credentials=credentials)

startTTS.py

# ----------------------------------------------------------------
from google.cloud import texttospeech
from google.oauth2 import service_account
# ----------------------------------------------------------------

# ----------------------------------------------------------------
# TTS 변환 기능 함수
def run_tts():

    credentials = service_account.Credentials.from_service_account_file('[key이름].json')

    client = texttospeech.TextToSpeechClient(credentials=credentials)
    
    text_block = input("텍스트 입력 : ")
    
    synthesis_input = texttospeech.SynthesisInput(text=text_block)

    voice = texttospeech.VoiceSelectionParams(
        language_code="ko-KR",
        ssml_gender=texttospeech.SsmlVoiceGender.NEUTRAL
    )

    audio_config = texttospeech.AudioConfig(
        audio_encoding=texttospeech.AudioEncoding.MP3
    )

    response = client.synthesize_speech(
        input=synthesis_input, voice=voice, audio_config=audio_config
    )
    
    OUTPUT = input("저장할 파일이름 & 확장자 입력 : ")
    
    with open(OUTPUT, "wb") as out:
        out.write(response.audio_content)
        print(f'Audio content written to file "{OUTPUT}"')
# ----------------------------------------------------------------

# ----------------------------------------------------------------
# main문에서 run_tts 함수 실행
if __name__ == "__main__":
    run_tts()
# ----------------------------------------------------------------

7) UI작업

기존 작업 방법 - 각 화면 UI파일을 각각 생성하고 한 화면의 모습을 지우고 새로운 창을 띄우는 방식으로 진행

문제점

  • 다음 화면으로 넘어갈 때 기존 화면이 꺼지고 새로운 화면이 켜지는 모습이 눈에 띄게 나타남.
  • 연속된 화면 전환을 진행하였을 때 back 버튼을 눌렀을 때 기존 화면이 겹쳐서 나타나는 현상이 나타남

수정된 작업 진행 방향 - 하나의 UI파일을 사용해서 레이아웃을 층층이 겹치는 방향으로 진행

  • 화면 전환이 진행 되었을 때 하나의 UI에서 진행되어 꺼졌다가 켜지는 모습 x
  • 전화면, 다음화면간의 화면전환이 있더라도 여러 화면이 겹쳐서 나타나는 error 해결

수정된 ui파일 화면

각 화면의 레이아웃을 겹쳐서 화면을 제작하였음 또한 크기는 모니터에 띄울 800x480 에 맞추어서 제작함.

  • 화면 전환 함수

ex1) 띄울 화면의 경우 show()함수를 사용해서 레이아웃을 띄움, 보여주지 않을 화면의 경우 hide()함수를 사용해서 보여주지 않음으로써 화면을 제작하였음

    def uimain(self):
        self.selectsexual.hide()
        self.checknoise.hide()
        self.resultnoise.hide()
        self.result.hide()
        self.mainwindow.show()
  • 버튼 클릭 이벤트 함수

ex)clicked.connect 함수를 사용해서 클릭이벤트가 발생하였을 때 이벤트 함수를 작동시킴

위와 같은 방식으로 버튼을 클릭하였을 때 알고리즘 코드가 완성되었을 경우 적용하여 진행 시킬 예정

self.button_backtomain.clicked.connect(self.uimain)

각 버튼 및 화면, 라벨의 경우 이름을 직관적이게 네이밍 하여 구별하는데 어렵지 않도록 진행

비고