음향 통신 송수신 구현 - 소음 처리 및 동기화
시연 동영상 링크
https://youtu.be/u44eXyy3Eic
주제
Send morse code over sound on air
주요 목표
송수신 기능 완성
#1 송신
send_data(): 사용자가 입력한 영어 문자나 숫자를 모스부호로 변환한 후 이를 사인파로 재생, 모스부호를 송신한다.
1) 텍스트 입력 처리

- input()을 통해 문자열을 입력받고, strip()으로 양쪽 공백을 제거한 뒤 upper()로 모두 대문자로 변환함. 모스부호는 모두 알파벳 대문자를 다루기 때문.
- 정규 표현식(re.match)을 사용해 영어 알파벳(A-Z), 숫자(0-9), 공백으로만 구성되었는지 확인 후 유효하지 않은 입력(특수 문자 등)이 포함되면 경고 메시지를 출력하고 함수를 종료하도록 함.
2) 모스 부호 생성


- english와 number 딕셔너리를 참조하여 각 문자를 해당 모스부호로 변환함.
- 문자 간 구분을 위해 각 모스부호 뒤에 공백(‘ ‘)을 추가하고, 입력 텍스트에 공백(‘ ‘)이 포함되면 단어 간 구분을 나타내는 슬래시(/)로 변환함.
3) 오디오 신호 생성

- 코드 상단에 INTMAX를 2**(32 - 1) - 1로 정의했다. 과제 조건에 맞게 timing unit, sample rate, frequency를 설정하고 국제 표준에 맞도록 audio list에 샘플 단위 오디오 데이터가 저장되도록 했다. (지난 과제 작성 코드 참고)
4) 소리 출력

- PyAudio를 초기화하고 paInt32, mono channel, 48000Hz sample rate로 출력 스트림을 엶.
- 오디오 데이터를 1024 chunk_size로 나누어 처리함.
- struct.pack()을 사용하여 소리를 출력할 수 있도록, 샘플을 바이너리 형식으로 변환하여 스피커에 전달할 수 있게 함. 이후 stream.write()로 소리가 나오게 하고, 재생이 끝나면 스트림을 닫고 PyAudio를 종료.
#2) 수신
- calculate_rms(): audio sample의 RMS(Root Mean Square)값을 계산하여 소리의 세기를 수치화하고, 소리와 무음을 구분하는 데 사용함.
- receive_data(): 마이크를 통해 입력된 소리를 실시간으로 분석하여 모스 부호로 변환하고, 이를 다시 영어 문자나 숫자 텍스트로 변환함. 소리의 세기와 타이밍을 기반으로 모스 부호를 인식하며, 5초간 무음이 지속되면 종료하도록 함.
1) 초기 설정


- 위와 같이, 과제 요구사항에 맞게 설정. silence_limit의 경우 SILENCE_TIMEOUT(5초)을 sample chunk 단위로 변환함.
2) 오디오 스트림 열기

- 데이터 송신과 비슷하게 마이크 입력 스트림을 열어 실시간으로 음성을 수집할 준비를 함.
- 스트림 오픈 성공 여부에 따라 디버깅용으로 다른 메시지가 출력되도록 함.
3) 모스 부호 수신 및 실시간 변환

- 오디오 데이터를 분석해 모스 부호를 생성하는 코드임.
- 변수 초기화
-
동작
- 정확한 타이밍에 소리가 들어온다고 보장할 수 없으므로, 소리 판단에 있어 오차 범위를 유하게 반영했다.
4) 스트림 종료

- 스트림을 닫는다.
5) 모스 부호 → 텍스트 변환

-
단어(‘ / ‘)와 문자(‘ ‘) 단위로 분리 후, english와 number 딕셔너리로 매핑한다. 이렇게 모스 부호를 텍스트로 변환하여 출력한다.
-
나머지 부분(main)은 강의 자료에서 제공된 코드를 사용했다.
세부 목표
목표1) 소음에 대한 처리
- calculate_rms 함수를 통해 입력된 audio sample(chunk)의 RMS값을 계산하여 소리 세기를 측정하도록 했다.
- 이때 MORSE_THRESHOLD값을 설정하여 잡음과 모스 부호 신호를 구분하는 기준값이 되도록 했다. 소음 환경에서 신호의 세기가 소음보다 강할 것이니, RMS 값이 이 임계값을 초과하면 소리로 판단된다.
목표2) 데이터가 언제 시작하는지 알아내기 (동기화) - 데이터 시작
- recieve_data()함수에서 초기 변수 설정 시 data_started를 False로 설정한 바 있다. RMS(코드에서는 level)값이 앞서 언급한 MORSE_THRESHOLD를 초과하면 신호가 시작된 것으로 판단하고 자동으로 부호 변환을 시작한다. data_started를 True로 변경하며, “Data started.”를 터미널에 출력하여 사용자에게 수신 시작을 알리도록 했다.
- 또한 다음 코드는 무음/잡음 → 소리로 변환하는 상황을 처리한다.
목표3) 데이터가 언제 끝나는지 알아내기 (동기화) - 데이터 끝
- 코드에서
SILENCE_TIMEOUT값과silence_limit값을 설정했다. - 즉, RMS 값이
MORSE_THRESHOLD이하일 때silence_chunks가 증가하는데, 이silence_chunks가silence_limit(약 469)에 도달하면 5초간 무음이 지속된 것으로 간주하고 자동으로 종료되는 것이다. - 종료 시 “5s silence detected. Stopping.”을 터미널에 출력해 사용자에게 알리도록 했다.
- 모스부호 국제표준에 따르면 단어 간 공백이 0.7초이고 이 코드에서의 종료 판단 기준이 5초이므로, 데이터 끝을 명확히 판단할 수 있다.
Leave a comment