노현욱

함수및 기능 대부분 구현

1 +import pyaudio
2 +import numpy as np
3 +import scipy.signal as signal
4 +import pydub
5 +import time
6 +import librosa
7 +import tkinter as tk
8 +
9 +ORIGIN_SOUND = np.frombuffer(pydub.AudioSegment.from_mp3("./sounds/ping.mp3").raw_data, dtype=np.int16)
10 +
11 +# 파라미터 설정
12 +RATE = 44100 # 샘플링 주파수
13 +CHUNK = 1024 # 읽을 샘플의 수
14 +THRESHOLD = 256 # 피크를 검출하기 위한 threshold 값
15 +WIN_SIZE = 1024 # STFT를 적용할 윈도우 사이즈
16 +HOP_SIZE = 512 # STFT에서 윈도우 사이의 거리 (오버랩 사이즈)
17 +DELAY = 0.1 # Delay time in seconds
18 +MAX_FREQ = 3000 # max freq for pitch shifting
19 +MAX_HEIGHT = 2000 # max height for pitch shifting
20 +
21 +sound_idx = 0
22 +
23 +window = tk.Tk()
24 +window.title("Sound Effect")
25 +window.geometry("640x400+100+100")
26 +window.resizable(False, False)
27 +
28 +info_text = tk.StringVar()
29 +info_text.set("welcome! please press record button.")
30 +
31 +info_label = tk.Button(window, textvariable=info_text, foreground="black", background="white")
32 +info_label.pack()
33 +
34 +def set_source_mode(mode):
35 + global SOURCE_MODE
36 + SOURCE_MODE = mode
37 +
38 +# 사용자의 목소리를 duration 초간 녹음.
39 +def get_user_audio(duration):
40 + global info_text, info_label
41 + frames = []
42 + p = pyaudio.PyAudio()
43 +
44 + # 카운터 시작
45 +
46 + info_text.set("ready for recording...")
47 + for _ in range(3, 0, -1):
48 + info_text.set(str(_))
49 + time.sleep(1)
50 + info_text.set("start...")
51 +
52 + # 실제 녹음 콜백 함수
53 + def add_to_frame(in_data, frame_count, time_info, status):
54 + frames.append(np.frombuffer(in_data, dtype=np.int16))
55 + if(len(frames) < RATE/CHUNK * duration):
56 + return (in_data, pyaudio.paContinue)
57 + return (in_data, pyaudio.paComplete)
58 +
59 + # 녹음 진행
60 + stream = p.open(format=pyaudio.paInt16, channels=1, rate=RATE, input=True, frames_per_buffer=CHUNK, input_device_index=1, stream_callback=add_to_frame)
61 +
62 + time.sleep(1)
63 + stream.start_stream()
64 +
65 + sound = np.frombuffer(b''.join(frames), dtype=np.int16)
66 +
67 + # stream및 객체들 정리
68 + stream.stop_stream()
69 + stream.close()
70 + p.terminate()
71 +
72 + return sound
73 +
74 +def record():
75 + global ORIGIN_SOUND
76 + global SOURCE_MODE
77 + ORIGIN_SOUND = get_user_audio(0.5)
78 + SOURCE_MODE = "decibel" # decibel or frequency
79 +
80 +def start():
81 + global MODE, SOUND_SIZE, sound_idx, sound
82 + MODE = "high_filter" # echo or pitch_shift
83 + SOUND_SIZE = len(ORIGIN_SOUND) # 음원 길이
84 +
85 + sound = ORIGIN_SOUND.copy()
86 +
87 + print(type(sound), len(sound))
88 +
89 + p = pyaudio.PyAudio()
90 +
91 + last_frame = 0
92 +
93 + # 콜백 함수 정의
94 + def process_audio(in_data, frame_count, time_info, status):
95 +
96 +
97 + def get_distortion(height, frequency):
98 + height = min(height, MAX_HEIGHT) / MAX_HEIGHT
99 + frequency = min(frequency, MAX_FREQ) / MAX_FREQ
100 +
101 + if SOURCE_MODE == "decibel":
102 + param = height
103 + elif SOURCE_MODE == "frequency":
104 + param = frequency
105 + else:
106 + return ORIGIN_SOUND
107 +
108 + if MODE == "pitch_shift":
109 + return shift_pitch(param)
110 + elif MODE == "echo":
111 + return add_echo(param)
112 + elif MODE == "low_filter":
113 + return low_filter(param)
114 + else:
115 + return ORIGIN_SOUND
116 +
117 + def add_echo(decay):
118 + # Create an empty array to store the echoed audio samples
119 + echoed_samples = np.zeros_like(ORIGIN_SOUND, dtype=np.int16)
120 +
121 + # Calculate the delay in samples
122 + delay_samples = int(DELAY * 44100) # Assuming a sample rate of 44100 Hz
123 +
124 + # Apply the echo effect
125 + for i in range(delay_samples, len(ORIGIN_SOUND)):
126 + echoed_samples[i] = ORIGIN_SOUND[i] + int(decay * echoed_samples[i - delay_samples])
127 +
128 + return echoed_samples
129 +
130 + def shift_pitch(frequency):
131 + pitch_shift_factor = frequency
132 + audio_array = ORIGIN_SOUND.copy()
133 + # Resample the audio array to change the pitch
134 + resampled_array = librosa.effects.pitch_shift(np.array(audio_array, dtype=np.float32), sr=RATE, n_steps=pitch_shift_factor, bins_per_octave=1)
135 + return np.array(resampled_array, dtype=np.int16)
136 +
137 + def low_filter(param):
138 + audio_data = data
139 + # Define the filter parameters
140 + cutoff_freq = param * MAX_FREQ # Frequency cutoff for the low-pass filter (in Hz)
141 + nyquist_freq = 0.5 * RATE # Nyquist frequency (half of the sampling rate)
142 + normalized_cutoff = cutoff_freq / nyquist_freq # Normalized cutoff frequency
143 +
144 + # Design the low-pass filter
145 + b, a = signal.butter(4, normalized_cutoff, btype='low', analog=False, output='ba')
146 +
147 + # Apply the low-pass filter to the audio data
148 + filtered_audio = signal.lfilter(b, a, audio_data)
149 +
150 + return filtered_audio
151 +
152 + # 오디오 데이터 변환
153 + data = np.frombuffer(in_data, dtype=np.int16)
154 +
155 + # STFT 수행
156 + f, t, Zxx = signal.stft(data, RATE, nperseg=WIN_SIZE, noverlap=HOP_SIZE)
157 +
158 + # 피크 검출
159 + peaks, _ = signal.find_peaks(np.abs(np.mean(Zxx, axis=1)), height=THRESHOLD, distance=WIN_SIZE)
160 + # 파라미터 추정
161 + if len(peaks) > 0 and last_frame+1 != frame_count:
162 + last_frame = frame_count
163 + peak_idx = peaks[0] # 첫 번째 피크 선택
164 + height = np.abs(Zxx[peak_idx, 0]) # 피크의 높이 추정
165 + freq = f[peak_idx] # 피크의 주파수 추정
166 + amp = np.max(np.abs(data)) # 신호의 진폭 추정
167 + decibel = np.mean(librosa.amplitude_to_db(np.abs(Zxx))) # 진폭을 데시벨로 변환
168 +
169 + if(decibel > 20):
170 + print("Height: {:.2f}, 주파수: {:.2f}, Amplitude: {:.2f}, Decibel: {:.2f}".format(height, freq, amp, decibel))
171 + new_sound = get_distortion(height, freq)
172 + if(sound_idx > len(sound)):
173 + sound_idx = 0
174 + else:
175 + mixed_end = min(len(sound), sound_idx + len(new_sound))
176 + print(mixed_end, sound_idx)
177 + sound[sound_idx:mixed_end] = new_sound[:mixed_end-sound_idx] + sound[sound_idx:mixed_end]
178 + if(mixed_end-sound_idx < len(new_sound)):
179 + result = np.concatenate((sound, new_sound[mixed_end-sound_idx:]),axis=0)
180 + sound = result
181 + elif len(peaks) > 0:
182 + last_frame = frame_count
183 +
184 + sound_idx += 1024
185 + if sound_idx > len(sound):
186 + sound = ORIGIN_SOUND.copy()
187 + return (np.zeros(data.shape), pyaudio.paContinue)
188 + return (sound[sound_idx-1024:sound_idx], pyaudio.paContinue)
189 +
190 +
191 + # 입력 스트림 열기
192 + stream = p.open(format=p.get_format_from_width(2),
193 + channels=1,
194 + rate=RATE,
195 + input_device_index=1,
196 + output_device_index=2,
197 + input=True,
198 + output=True,
199 + frames_per_buffer=CHUNK,
200 + stream_callback=process_audio
201 + )
202 +
203 + # 스트림 시작
204 + stream.start_stream()
205 +
206 +
207 +
208 + # 프로그램 실행 중지 전까지 무한 대기
209 + while stream.is_active():
210 + pass
211 +
212 +
213 + # 스트림과 PyAudio 객체 종료
214 + stream.stop_stream()
215 + stream.close()
216 + p.terminate()
217 +
218 +
219 +record_button = tk.Button(window, text="Record", width=10, height=2, command=lambda: record())
220 +record_button.pack()
221 +
222 +decibel_button = tk.Button(window, text="Decibel", width=10, height=2, command=lambda: set_source_mode("decibel"))
223 +decibel_button.pack()
224 +
225 +frequency_button = tk.Button(window, text="Frequency", width=10, height=2, command = lambda: set_source_mode("frequency"))
226 +frequency_button.pack()
227 +
228 +start_button = tk.Button(window, text="Start", width=10, height=2, command=lambda: start())
229 +start_button.pack()
230 +
231 +
232 +window.mainloop()
1 import pyaudio 1 import pyaudio
2 import numpy as np 2 import numpy as np
3 import scipy.signal as signal 3 import scipy.signal as signal
4 -import matplotlib.pyplot as plt 4 +import pydub
5 +import time
6 +import librosa
7 +import tkinter as tk
8 +
9 +ORIGIN_SOUND = np.frombuffer(pydub.AudioSegment.from_mp3("./sounds/ping.mp3").raw_data, dtype=np.int16)
10 +
5 # 파라미터 설정 11 # 파라미터 설정
6 RATE = 44100 # 샘플링 주파수 12 RATE = 44100 # 샘플링 주파수
7 CHUNK = 1024 # 읽을 샘플의 수 13 CHUNK = 1024 # 읽을 샘플의 수
8 THRESHOLD = 256 # 피크를 검출하기 위한 threshold 값 14 THRESHOLD = 256 # 피크를 검출하기 위한 threshold 값
9 WIN_SIZE = 1024 # STFT를 적용할 윈도우 사이즈 15 WIN_SIZE = 1024 # STFT를 적용할 윈도우 사이즈
10 HOP_SIZE = 512 # STFT에서 윈도우 사이의 거리 (오버랩 사이즈) 16 HOP_SIZE = 512 # STFT에서 윈도우 사이의 거리 (오버랩 사이즈)
17 +DELAY = 0.1 # Delay time in seconds
18 +MAX_FREQ = 3000 # max freq for pitch shifting
19 +MAX_HEIGHT = 2000 # max height for pitch shifting
20 +
21 +sound_idx = 0
22 +
23 +
24 +# 사용자의 목소리를 duration 초간 녹음.
25 +def get_user_audio(duration):
26 +
27 + frames = []
28 + p = pyaudio.PyAudio()
29 +
30 + # 카운터 시작
31 + print("ready for recording...")
32 + for _ in range(3, 0, -1):
33 + print(_)
34 + time.sleep(1)
35 + print("start...")
36 +
37 + # 실제 녹음 콜백 함수
38 + def add_to_frame(in_data, frame_count, time_info, status):
39 + frames.append(np.frombuffer(in_data, dtype=np.int16))
40 + if(len(frames) < RATE/CHUNK * duration):
41 + return (in_data, pyaudio.paContinue)
42 + return (in_data, pyaudio.paComplete)
43 +
44 + # 녹음 진행
45 + stream = p.open(format=pyaudio.paInt16, channels=1, rate=RATE, input=True, frames_per_buffer=CHUNK, input_device_index=1, stream_callback=add_to_frame)
46 +
47 + time.sleep(1)
48 + stream.start_stream()
49 +
50 + sound = np.frombuffer(b''.join(frames), dtype=np.int16)
51 +
52 + # stream및 객체들 정리
53 + stream.stop_stream()
54 + stream.close()
55 + p.terminate()
56 +
57 + return sound
58 +
59 +ORIGIN_SOUND = get_user_audio(0.5)
60 +SOURCE_MODE = "decibel" # decibel or frequency
61 +MODE = "high_filter" # echo or pitch_shift
62 +SOUND_SIZE = len(ORIGIN_SOUND) # 음원 길이
63 +
64 +sound = ORIGIN_SOUND.copy()
65 +
66 +print(type(sound), len(sound))
11 67
12 -# PyAudio 객체 생성
13 p = pyaudio.PyAudio() 68 p = pyaudio.PyAudio()
14 69
70 +last_frame = 0
71 +
15 # 콜백 함수 정의 72 # 콜백 함수 정의
16 def process_audio(in_data, frame_count, time_info, status): 73 def process_audio(in_data, frame_count, time_info, status):
74 + global buffer
75 + global sound
76 + global sound_idx
77 + global last_frame
78 +
79 +
80 + def get_distortion(height, frequency):
81 + height = min(height, MAX_HEIGHT) / MAX_HEIGHT
82 + frequency = min(frequency, MAX_FREQ) / MAX_FREQ
83 +
84 + if SOURCE_MODE == "decibel":
85 + param = height
86 + elif SOURCE_MODE == "frequency":
87 + param = frequency
88 + else:
89 + return ORIGIN_SOUND
90 +
91 + if MODE == "pitch_shift":
92 + return shift_pitch(param)
93 + elif MODE == "echo":
94 + return add_echo(param)
95 + elif MODE == "low_filter":
96 + return low_filter(param)
97 + return ORIGIN_SOUND
98 +
99 + def add_echo(decay):
100 + # Create an empty array to store the echoed audio samples
101 + echoed_samples = np.zeros_like(ORIGIN_SOUND, dtype=np.int16)
102 +
103 + # Calculate the delay in samples
104 + delay_samples = int(DELAY * 44100) # Assuming a sample rate of 44100 Hz
105 +
106 + # Apply the echo effect
107 + for i in range(delay_samples, len(ORIGIN_SOUND)):
108 + echoed_samples[i] = ORIGIN_SOUND[i] + int(decay * echoed_samples[i - delay_samples])
109 +
110 + return echoed_samples
111 +
112 + def shift_pitch(frequency):
113 + pitch_shift_factor = frequency
114 + audio_array = ORIGIN_SOUND.copy()
115 + # Resample the audio array to change the pitch
116 + resampled_array = librosa.effects.pitch_shift(np.array(audio_array, dtype=np.float32), sr=RATE, n_steps=pitch_shift_factor, bins_per_octave=1)
117 + return np.array(resampled_array, dtype=np.int16)
118 +
119 + def low_filter(param):
120 + audio_data = data
121 + # Define the filter parameters
122 + cutoff_freq = param * MAX_FREQ # Frequency cutoff for the low-pass filter (in Hz)
123 + nyquist_freq = 0.5 * RATE # Nyquist frequency (half of the sampling rate)
124 + normalized_cutoff = cutoff_freq / nyquist_freq # Normalized cutoff frequency
125 +
126 + # Design the low-pass filter
127 + b, a = signal.butter(4, normalized_cutoff, btype='low', analog=False, output='ba')
128 +
129 + # Apply the low-pass filter to the audio data
130 + filtered_audio = signal.lfilter(b, a, audio_data)
131 +
132 + return filtered_audio
133 +
17 # 오디오 데이터 변환 134 # 오디오 데이터 변환
18 data = np.frombuffer(in_data, dtype=np.int16) 135 data = np.frombuffer(in_data, dtype=np.int16)
19 136
...@@ -23,23 +140,42 @@ def process_audio(in_data, frame_count, time_info, status): ...@@ -23,23 +140,42 @@ def process_audio(in_data, frame_count, time_info, status):
23 # 피크 검출 140 # 피크 검출
24 peaks, _ = signal.find_peaks(np.abs(np.mean(Zxx, axis=1)), height=THRESHOLD, distance=WIN_SIZE) 141 peaks, _ = signal.find_peaks(np.abs(np.mean(Zxx, axis=1)), height=THRESHOLD, distance=WIN_SIZE)
25 # 파라미터 추정 142 # 파라미터 추정
26 - if len(peaks) > 0: 143 + if len(peaks) > 0 and last_frame+1 != frame_count:
144 + last_frame = frame_count
27 peak_idx = peaks[0] # 첫 번째 피크 선택 145 peak_idx = peaks[0] # 첫 번째 피크 선택
28 height = np.abs(Zxx[peak_idx, 0]) # 피크의 높이 추정 146 height = np.abs(Zxx[peak_idx, 0]) # 피크의 높이 추정
29 freq = f[peak_idx] # 피크의 주파수 추정 147 freq = f[peak_idx] # 피크의 주파수 추정
30 amp = np.max(np.abs(data)) # 신호의 진폭 추정 148 amp = np.max(np.abs(data)) # 신호의 진폭 추정
31 - progress = (peak_idx + HOP_SIZE) / RATE # 충돌음의 진행 길이 추정 149 + decibel = np.mean(librosa.amplitude_to_db(np.abs(Zxx))) # 진폭을 데시벨로 변환
32 150
33 - # 결과 출력 151 + if(decibel > 20):
34 - print("Height: {:.2f}, Frequency: {:.2f}, Amplitude: {:.2f}, Progress: {:.2f}".format(height, freq, amp, progress)) 152 + print("Height: {:.2f}, 주파수: {:.2f}, Amplitude: {:.2f}, Decibel: {:.2f}".format(height, freq, amp, decibel))
153 + new_sound = get_distortion(height, freq)
154 + if(sound_idx > len(sound)):
155 + sound_idx = 0
156 + else:
157 + mixed_end = min(len(sound), sound_idx + len(new_sound))
158 + print(mixed_end, sound_idx)
159 + sound[sound_idx:mixed_end] = new_sound[:mixed_end-sound_idx] + sound[sound_idx:mixed_end]
160 + if(mixed_end-sound_idx < len(new_sound)):
161 + result = np.concatenate((sound, new_sound[mixed_end-sound_idx:]),axis=0)
162 + sound = result
163 + elif len(peaks) > 0:
164 + last_frame = frame_count
165 +
166 + sound_idx += 1024
167 + if sound_idx > len(sound):
168 + sound = ORIGIN_SOUND.copy()
169 + return (np.zeros(data.shape), pyaudio.paContinue)
170 + return (sound[sound_idx-1024:sound_idx], pyaudio.paContinue)
35 171
36 - # 반환할 데이터 없음
37 - return (in_data, pyaudio.paContinue)
38 172
39 # 입력 스트림 열기 173 # 입력 스트림 열기
40 stream = p.open(format=p.get_format_from_width(2), 174 stream = p.open(format=p.get_format_from_width(2),
41 channels=1, 175 channels=1,
42 rate=RATE, 176 rate=RATE,
177 + input_device_index=1,
178 + output_device_index=2,
43 input=True, 179 input=True,
44 output=True, 180 output=True,
45 frames_per_buffer=CHUNK, 181 frames_per_buffer=CHUNK,
...@@ -49,6 +185,8 @@ stream = p.open(format=p.get_format_from_width(2), ...@@ -49,6 +185,8 @@ stream = p.open(format=p.get_format_from_width(2),
49 # 스트림 시작 185 # 스트림 시작
50 stream.start_stream() 186 stream.start_stream()
51 187
188 +
189 +
52 # 프로그램 실행 중지 전까지 무한 대기 190 # 프로그램 실행 중지 전까지 무한 대기
53 while stream.is_active(): 191 while stream.is_active():
54 pass 192 pass
......
1 +import tkinter as tk
2 +
3 +
4 +def clear_row(button, buttons):
5 + button_row = buttons[:3] if button in buttons[:3] else buttons[3:]
6 +
7 + for button in button_row:
8 + button.config(text='OFF')
9 +
10 +def toggle_button(button):
11 + global buttons
12 + if button['text'] == 'ON':
13 + button.config(text='OFF')
14 + else:
15 + clear_row(button, buttons)
16 + button.config(text='ON')
17 +
18 +def get_states():
19 + global buttons
20 + for i in range(3):
21 + if buttons[i].cget('text') == 'ON':
22 + mode = i
23 + mode = 0
24 +
25 + for i in range(3, 6):
26 + if buttons[i].cget('text') == 'ON':
27 + distortion = i - 3
28 + distortion = 0
29 +
30 + return mode, distortion
31 +
32 +
33 +
34 +# Create the Tkinter window
35 +window = tk.Tk()
36 +window.title("Toggle Buttons")
37 +
38 +# Create two frames for two rows
39 +frame1 = tk.Frame(window)
40 +frame1.pack(side=tk.TOP)
41 +
42 +frame2 = tk.Frame(window)
43 +frame2.pack(side=tk.TOP)
44 +
45 +# Create six toggle buttons in two rows
46 +buttons = []
47 +for i in range(6):
48 + if i < 3:
49 + frame = frame1
50 + else:
51 + frame = frame2
52 +
53 + button = tk.Button(frame, text='OFF', width=10)
54 + button.config(command=lambda button=button: toggle_button(button))
55 + button.pack(side=tk.LEFT)
56 + buttons.append(button)
57 +
58 +# Start the Tkinter event loop
59 +window.mainloop()
1 +import pyaudio
2 +import numpy as np
3 +
4 +# Create an instance of the PyAudio class
5 +audio = pyaudio.PyAudio()
6 +
7 +# Define the desired pitch shift factor
8 +pitch_shift_factor = 1.5 # Increase by 50%
9 +
10 +# Choose the desired input and output devices
11 +input_device_index = 1
12 +output_device_index = 1
13 +
14 +# Open input stream
15 +input_stream = audio.open(input_device_index=input_device_index, format=pyaudio.paFloat32,
16 + channels=1, rate=44100, input=True, frames_per_buffer=1024)
17 +
18 +# Open output stream
19 +output_stream = audio.open(output_device_index=output_device_index, format=pyaudio.paFloat32,
20 + channels=2, rate=int(44100 * pitch_shift_factor), output=True)
21 +
22 +# Read input audio and apply pitch shift
23 +frames = []
24 +while True:
25 + data = input_stream.read(1024)
26 + frames.append(data)
27 +
28 + # Adjust pitch by changing sample rate
29 + if len(frames) >= 1024:
30 + audio_data = b''.join(frames)
31 + audio_array = np.frombuffer(audio_data, dtype=np.float32)
32 +
33 + # Resample the audio array to change the pitch
34 + resampled_array = np.resize(audio_array, int(len(audio_array) / pitch_shift_factor))
35 +
36 + # Convert the resampled array back to bytes
37 + resampled_data = resampled_array.astype(np.float32).tobytes()
38 +
39 + # Play the resampled audio
40 + output_stream.write(resampled_data)
41 +
42 + frames = []
43 +
44 +# Stop and close the streams
45 +input_stream.stop_stream()
46 +input_stream.close()
47 +output_stream.stop_stream()
48 +output_stream.close()
49 +
50 +# Terminate PyAudio
51 +audio.terminate()
1 -import base64
2 -
3 -task_list = []
4 -
5 -
6 -def display_menu():
7 - print("일정 관리자")
8 - print("1. 일정 추가")
9 - print("2. 일정 보기")
10 - print("3. 일정 완료 표시")
11 - print("4. 종료")
12 -
13 -
14 -def add_task():
15 - title = input("일정 제목 입력: ")
16 - description = input("일정 설명 입력: ")
17 - status = "하는 중"
18 - task = { "title": title, "description": description, "status": status}
19 - task_list.append(task)
20 - print("일정이 추가되었습니다.")
21 -
22 -
23 -def view_tasks():
24 - if not task_list:
25 - print("일정 목록이 비어 있습니다.")
26 - else:
27 - print()
28 - print("일정 목록:")
29 - print("----------------")
30 - for task in task_list:
31 - print(f"제목: {task['title']}")
32 - print(f"설명: {task['description']}")
33 - print(f"상태: {task['status']}")
34 - print("----------------")
35 -
36 -
37 -def mark_task_complete():
38 - if not task_list:
39 - print("일정 목록이 비어 있습니다.")
40 - return
41 -
42 - title = input("완료로 표시할 일정의 제목 입력: ")
43 - for task in task_list:
44 - if task['title'] == title:
45 - task['status'] = "완료"
46 - print("일정이 완료로 표시되었습니다.")
47 - return
48 -
49 - print("식별자와 일치하는 일정을 찾을 수 없습니다.")
50 -
51 -
52 -while True:
53 - display_menu()
54 - choice = input("선택: ")
55 -
56 - if choice == "1":
57 - add_task()
58 - elif choice == "2":
59 - view_tasks()
60 - elif choice == "3":
61 - mark_task_complete()
62 - elif choice == "4":
63 - print("프로그램을 종료합니다.")
64 - break
65 - else:
66 - print("올바른 선택지를 입력하세요.")
67 - print()
68 -
No preview for this file type
No preview for this file type
...@@ -2,6 +2,7 @@ import sys ...@@ -2,6 +2,7 @@ import sys
2 import numpy as np 2 import numpy as np
3 import pyaudio 3 import pyaudio
4 import librosa 4 import librosa
5 +import scipy.signal as signal
5 6
6 RECORD_SECONDS = 5 7 RECORD_SECONDS = 5
7 CHUNK = 1024 8 CHUNK = 1024
...@@ -10,11 +11,14 @@ DELAY = 0.1 # Delay time in seconds ...@@ -10,11 +11,14 @@ DELAY = 0.1 # Delay time in seconds
10 GAIN = 1 # Echo gain (0 to 1) 11 GAIN = 1 # Echo gain (0 to 1)
11 MAX_FREQ = 3000 12 MAX_FREQ = 3000
12 13
14 +input_device_index = 1
15 +output_device_index = 4
16 +
13 # Create buffer for delayed audio data 17 # Create buffer for delayed audio data
14 buffer_size = int(RATE * DELAY) 18 buffer_size = int(RATE * DELAY)
15 buffer = np.zeros(buffer_size, dtype=np.int16) 19 buffer = np.zeros(buffer_size, dtype=np.int16)
16 20
17 -def add_echo(in_data, frame_count, time_info, status_flags): 21 +def do_process(in_data, frame_count, time_info, status_flags):
18 global buffer 22 global buffer
19 data = np.frombuffer(in_data, dtype=np.int16) 23 data = np.frombuffer(in_data, dtype=np.int16)
20 24
...@@ -22,7 +26,7 @@ def add_echo(in_data, frame_count, time_info, status_flags): ...@@ -22,7 +26,7 @@ def add_echo(in_data, frame_count, time_info, status_flags):
22 data_float = data.astype(np.float32) 26 data_float = data.astype(np.float32)
23 27
24 # Compute the power spectrogram of the data 28 # Compute the power spectrogram of the data
25 - S = librosa.stft(data_float, n_fft=2048, hop_length=512) 29 + S = librosa.stft(data_float, n_fft=256, hop_length=512)
26 S_power = np.abs(S)**2 30 S_power = np.abs(S)**2
27 31
28 # Convert power spectrogram to dB scale 32 # Convert power spectrogram to dB scale
...@@ -47,7 +51,7 @@ def add_echo(in_data, frame_count, time_info, status_flags): ...@@ -47,7 +51,7 @@ def add_echo(in_data, frame_count, time_info, status_flags):
47 freqs = np.fft.fftfreq(len(psd_data), d=1/RATE) 51 freqs = np.fft.fftfreq(len(psd_data), d=1/RATE)
48 52
49 # Compute the power spectrogram on the mel scale 53 # Compute the power spectrogram on the mel scale
50 - S = librosa.feature.melspectrogram(y=data, sr=RATE, n_fft=2048, hop_length=1024) 54 + S = librosa.feature.melspectrogram(y=data, sr=RATE, n_fft=256, hop_length=1024, n_mels=64)
51 55
52 # Find the frequency bin with the maximum energy in each frame 56 # Find the frequency bin with the maximum energy in each frame
53 max_bin = np.argmax(S, axis=0) 57 max_bin = np.argmax(S, axis=0)
...@@ -60,14 +64,47 @@ def add_echo(in_data, frame_count, time_info, status_flags): ...@@ -60,14 +64,47 @@ def add_echo(in_data, frame_count, time_info, status_flags):
60 64
61 return dominant_freq 65 return dominant_freq
62 66
63 - freq = get_dominant_freq(data) 67 + def add_echo(gain):
64 - avg_db, max_db = get_max_average_db(data) 68 + global buffer
65 - print(int(freq), int(avg_db), int(max_db))
66 - temp_gain = freq/MAX_FREQ
67 - output = data + freq/2500 * buffer[:len(data)]
68 buffer = np.roll(buffer, len(data)) 69 buffer = np.roll(buffer, len(data))
69 buffer[-len(data):] = data 70 buffer[-len(data):] = data
70 - return (output.astype(np.int16).tostring(), pyaudio.paContinue) 71 + return data + gain * buffer[:len(data)]
72 +
73 + def shift_pitch(pitch_shift_factor):
74 + audio_array = data
75 + # Resample the audio array to change the pitch
76 + resampled_array = np.resize(audio_array, int(len(audio_array) / pitch_shift_factor))
77 +
78 + return resampled_array
79 +
80 + def high_filter(param):
81 + audio_data = data
82 + # Define the filter parameters
83 + cutoff_freq = param * MAX_FREQ # Frequency cutoff for the low-pass filter (in Hz)
84 + nyquist_freq = 0.5 * RATE # Nyquist frequency (half of the sampling rate)
85 + normalized_cutoff = cutoff_freq / nyquist_freq # Normalized cutoff frequency
86 +
87 + # Design the low-pass filter
88 + b, a = signal.butter(4, normalized_cutoff, btype='low', analog=False, output='ba')
89 +
90 + # Apply the low-pass filter to the audio data
91 + filtered_audio = signal.lfilter(b, a, audio_data)
92 +
93 + return filtered_audio
94 +
95 + try:
96 + freq = get_dominant_freq(data)
97 + # avg_db, max_db = get_max_average_db(data)
98 +
99 + # temp_gain = freq/MAX_FREQ
100 + # output = add_echo(temp_gain)
101 + output = shift_pitch(0.5 + freq/MAX_FREQ)
102 + # output = high_filter(0.5)
103 + # print(int(freq), int(avg_db), int(max_db))
104 + return (output.astype(np.int16).tobytes(), pyaudio.paContinue)
105 + except:
106 + print("exception occured")
107 + return data
71 108
72 109
73 p = pyaudio.PyAudio() 110 p = pyaudio.PyAudio()
...@@ -75,9 +112,11 @@ stream = p.open(format=p.get_format_from_width(2), ...@@ -75,9 +112,11 @@ stream = p.open(format=p.get_format_from_width(2),
75 channels=1 if sys.platform == 'darwin' else 2, 112 channels=1 if sys.platform == 'darwin' else 2,
76 rate=RATE, 113 rate=RATE,
77 input=True, 114 input=True,
115 + input_device_index=input_device_index,
116 + output_device_index=output_device_index,
78 output=True, 117 output=True,
79 frames_per_buffer=CHUNK, 118 frames_per_buffer=CHUNK,
80 - stream_callback=add_echo 119 + stream_callback=do_process
81 ) 120 )
82 121
83 print('* recording') 122 print('* recording')
......
...@@ -7,3 +7,5 @@ ...@@ -7,3 +7,5 @@
7 1. 실제 소리변형으로 뭔가 만들기 7 1. 실제 소리변형으로 뭔가 만들기
8 - 실제 소리가 들릴거냐 말거냐 8 - 실제 소리가 들릴거냐 말거냐
9 2. identification만 하고, 다른 소리 재생도 할 수 있음. 9 2. identification만 하고, 다른 소리 재생도 할 수 있음.
10 +
11 +- 소리 identification을 진행?
......