11try :
22 from pyaudio import PyAudio , paInt16
3+ from scipy .signal import resample
34except ImportError :
45 raise ImportError (f"Pyaudio is required, please install pyaudio or ghostos[audio] first" )
56
7+ import numpy as np
68from typing import Callable , Optional
79from ghostos .abcd .realtime import Listener , Listening
810from threading import Thread , Event
@@ -18,25 +20,28 @@ class PyAudioPCM16Listener(Listener):
1820
1921 def __init__ (
2022 self ,
21- rate : int = 24000 ,
23+ sample_rate : int = 24000 ,
24+ output_rate : int = 24000 ,
2225 chunk_size : int = CHUNK ,
2326 interval : float = 0.5 ,
2427 channels : int = CHANNELS ,
2528 input_device_index : Optional [int ] = None ,
2629 ):
27- self .rate = rate
30+ self .sample_rate = sample_rate
31+ self .output_rate = output_rate
2832 self .chunk_size = chunk_size
2933 self .stream = PyAudio ().open (
3034 format = paInt16 ,
3135 channels = channels ,
32- rate = self .rate ,
36+ rate = self .sample_rate ,
3337 input = True ,
3438 input_device_index = input_device_index ,
3539 )
3640 self .interval = interval
3741
3842 def listen (self , sender : Callable [[bytes ], None ]) -> Listening :
39- return PyAudioPCM16Listening (self .stream , sender , self .rate , self .chunk_size , self .interval )
43+ return PyAudioPCM16Listening (self .stream , sender , self .sample_rate , self .output_rate , self .chunk_size ,
44+ self .interval )
4045
4146 def __del__ (self ):
4247 self .stream .close ()
@@ -48,14 +53,16 @@ def __init__(
4853 self ,
4954 stream ,
5055 sender : Callable [[bytes ], None ],
51- rate : int = 24000 ,
56+ sample_rate : int = 24000 ,
57+ output_rate : int = 24000 ,
5258 chunk : int = CHUNK ,
5359 interval : float = 0.5 ,
5460 ):
5561 self .sender = sender
5662 self .stream = stream
5763 self .interval = interval
58- self .rate = rate
64+ self .sample_rate = sample_rate
65+ self .output_rate = output_rate
5966 self .chunk = chunk
6067 self .stopped = Event ()
6168 self .thread = Thread (target = self ._listening )
@@ -64,12 +71,25 @@ def _listening(self):
6471 self .stream .start_stream ()
6572 while not self .stopped .is_set ():
6673 buffer = BytesIO ()
67- for i in range (int ((self .rate / self .chunk ) * self .interval )):
74+ for i in range (int ((self .sample_rate / self .chunk ) * self .interval )):
6875 data = self .stream .read (self .chunk , exception_on_overflow = False )
6976 buffer .write (data )
70- self .sender (buffer .getvalue ())
77+ parsed = self ._parse_output_data (buffer .getvalue ())
78+ self .sender (parsed )
7179 self .stream .stop_stream ()
7280
81+ def _parse_output_data (self , data : bytes ) -> bytes :
82+ if self .sample_rate == self .output_rate :
83+ return data
84+ audio_data = np .frombuffer (data , dtype = np .int16 )
85+ num_samples = int (len (audio_data ) * self .output_rate / self .sample_rate )
86+
87+ # 使用 resample 进行重新采样
88+ resampled_audio = resample (audio_data , num_samples )
89+
90+ # 导出为二进制数据
91+ return resampled_audio .astype (np .int16 )
92+
7393 def __enter__ (self ):
7494 self .thread .start ()
7595
0 commit comments