def play(s: pyaudio.Stream, freq: float, duration: float): # 指定周波数のサイン波を指定秒数分生成 samples = np.sin( np.arange(int(duration * SAMPLE_RATE)) * freq * np.pi * 2 / SAMPLE_RATE) # ストリームに渡して再生 s.write(samples.astype(np.float32).tobytes())
def _write_to_stream(self, stream: pyaudio.Stream, stream_queue: Queue): while True: data = stream_queue.get() if data is None: break stream.write(data) stream_queue.task_done()
def play(s: pyaudio.Stream, freq: float, duration: float): # Generate sin Wave samples = np.sin( np.arange(int(duration * SAMPLE_RATE)) * freq * np.pi * 2 / SAMPLE_RATE) # Play that s.write(samples.astype(np.float32).tostring())
def __init__(self, codecBitrate): self.isActive = False self.audioOut = pyaudio.PyAudio() self.info = self.audioOut.get_host_api_info_by_index(0) self.numdevices = self.info.get('deviceCount') self.idxDevOut = 0 self.frames_per_buffer = 1920 self.dataLst = [] self.labelAverageDataCount = QLabel self.streamOut = Stream(self, rate=48000, channels=1, format=pyaudio.paInt16, input=False, output=True) self.streamOut.stop_stream() self.codec = OpusCodec(channels=1, rate=48000, frame_size=self.frames_per_buffer, bitrate=codecBitrate)
def play(s: pyaudio.Stream, freq1: float, freq2: float, freq3: float, duration: float): # 指定周波数のサイン波を指定秒数分生成 samples = np.sin( np.arange(int(duration * SAMPLE_RATE)) * freq1 * np.pi * 2 / SAMPLE_RATE) samples += np.sin( np.arange(int(duration * SAMPLE_RATE)) * freq2 * np.pi * 2 / SAMPLE_RATE) samples += np.sin( np.arange(int(duration * SAMPLE_RATE)) * freq3 * np.pi * 2 / SAMPLE_RATE) # ストリームに渡して再生 s.write(samples.astype(np.float32).tostring())
def __init__(self, stream): Stream.__init__(self, stream._parent, stream._rate, stream._channels, stream._format, input=stream._is_input, output=stream._is_output, input_device_index=None, output_device_index=None, frames_per_buffer=1024, start=stream._is_running, input_host_api_specific_stream_info=None, output_host_api_specific_stream_info=None, stream_callback=None) stream.close()
def get_data(stream: pyaudio.Stream) -> np.ndarray: """ reads from the audio stream for a constant length of time, converts it to data inputs: stream, PyAudio object outputs: int16 data array """ input_data = stream.read(CHUNK_SIZE, exception_on_overflow = False) data = np.frombuffer(input_data, np.int16) return data
def __init__(self, codecBitrate): self.audioIn = pyaudio.PyAudio() self.audioOut = pyaudio.PyAudio() self.info = self.audioIn.get_host_api_info_by_index(0) self.numdevices = self.info.get('deviceCount') self.codecBitrate = codecBitrate self.isRecordingActive = False self.rawBytesCount = 0 self.opusBytesCount = 0 self.volume = 100 self.dataLst = [] self.UDPclients = {} # Initialize streams self.streamIn = Stream(self, rate=rate, channels=channels, format=pyaudio.paInt16, input=True, output=False) self.streamIn.stop_stream() self.streamOut = Stream(self, rate=rate, channels=channels, format=pyaudio.paInt16, input=False, output=True) self.streamOut.stop_stream() self.opusencoded_data = b'\00'
class StreamAudioPlayer(): def __init__(self, codecBitrate): self.isActive = False self.audioOut = pyaudio.PyAudio() self.info = self.audioOut.get_host_api_info_by_index(0) self.numdevices = self.info.get('deviceCount') self.idxDevOut = 0 self.frames_per_buffer = 1920 self.dataLst = [] self.labelAverageDataCount = QLabel self.streamOut = Stream(self, rate=48000, channels=1, format=pyaudio.paInt16, input=False, output=True) self.streamOut.stop_stream() self.codec = OpusCodec(channels=1, rate=48000, frame_size=self.frames_per_buffer, bitrate=codecBitrate) def setCodecBitrate(self, codecBitrate): self.codec.setBitrate(codecBitrate) def startRecv(self, devOut, intfAddr, udpPort): chunk = self.frames_per_buffer self.isActive = True self.streamOut = self.audioOut.open(format=pyaudio.paInt16, channels=1, rate=48000, input=False, output=True, output_device_index=devOut, frames_per_buffer=self.frames_per_buffer) Thread(target=self.udpStream, args=(chunk, intfAddr, udpPort)).start() Timer(1.0, function=self.calculateAverage).start() def stopRecvAndAudio(self): self.isActive = False self.streamOut.stop_stream() def calculateAverage(self): # print(round(sum(self.dataLst) / 1024, 2)) self.labelAverageDataCount.setText(str(round(sum(self.dataLst) / 1024, 2))) self.dataLst = [] if self.isActive: Timer(1.0, function=self.calculateAverage).start() else: self.labelAverageDataCount.setText('0') def udpStream(self, chunk, intfAddr, udpPort): udpReceiveSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) udpReceiveSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) udpReceiveSocket.bind((intfAddr, udpPort)) print("UDP socket binded to local address: " + str(intfAddr)) while self.isActive: soundData, addr = udpReceiveSocket.recvfrom(chunk) if len(soundData) > 35: self.dataLst.append(len(soundData)) opusdecoded_data = self.codec.decode(soundData) if len(opusdecoded_data) > 100: self.streamOut.write(opusdecoded_data) udpReceiveSocket.close() print("socket closed") def getDefaultAudioOutDeviceIndex(self): return self.audioOut.get_default_output_device_info()["index"] def getAudioOutputDevices(self): devices = {} for i in range(0, self.numdevices): devOut = self.audioOut.get_device_info_by_host_api_device_index(0, i) if (devOut.get('maxOutputChannels')) > 0: d = {devOut.get('index'): devOut.get('name')} devices.update(d) return devices def setAverageDataLabel(self, label): self.labelAverageDataCount = label
class AudioTranscoder: def __init__(self, codecBitrate): self.audioIn = pyaudio.PyAudio() self.audioOut = pyaudio.PyAudio() self.info = self.audioIn.get_host_api_info_by_index(0) self.numdevices = self.info.get('deviceCount') self.codecBitrate = codecBitrate self.isRecordingActive = False self.rawBytesCount = 0 self.opusBytesCount = 0 self.volume = 100 self.dataLst = [] self.UDPclients = {} # Initialize streams self.streamIn = Stream(self, rate=rate, channels=channels, format=pyaudio.paInt16, input=True, output=False) self.streamIn.stop_stream() self.streamOut = Stream(self, rate=rate, channels=channels, format=pyaudio.paInt16, input=False, output=True) self.streamOut.stop_stream() self.opusencoded_data = b'\00' def setBitrate(self, bitrate): self.codecBitrate = bitrate def getBitrate(self): return self.codecBitrate def getAudioOutputDevices(self): devices = {} for i in range(0, self.numdevices): devOut = self.audioOut.get_device_info_by_host_api_device_index(0, i) if (devOut.get('maxOutputChannels')) > 0: d = {devOut.get('index'): devOut.get('name')} devices.update(d) return devices def getAudioInputDevices(self): devices = {} for i in range(0, self.numdevices): devIn = self.audioIn.get_device_info_by_host_api_device_index(0, i) if (devIn.get('maxInputChannels')) > 0: d = {devIn.get('index'): devIn.get('name')} devices.update(d) return devices def getDefaultAudioInDeviceIndex(self): return self.audioIn.get_default_input_device_info()["index"] def getDefaultAudioOutDeviceIndex(self): return self.audioOut.get_default_output_device_info()["index"] def startRec(self, idxDevIn, idxDevOut): self.isRecordingActive = True threading.Thread(target=self.transcodingThread, args=(idxDevIn, idxDevOut)).start() def stopRec(self): self.isRecordingActive = False self.rawBytesCount = 0 self.opusBytesCount = 0 self.removeAllUDPClients() def getDataLst(self): return self.dataLst def clearDataLst(self): self.dataLst = [] def set_audio_volume(self, datalist, volume): sound_level = (volume / 100.) chunk = numpy.frombuffer(datalist, numpy.int16) chunk = chunk * sound_level return chunk.astype(numpy.int16).tostring() def transcodingThread(self, idxDevIn, idxDevOut): self.streamIn = self.audioIn.open(format=pyaudio.paInt16, channels=channels, rate=rate, input_device_index=idxDevIn, input=True, output=False, frames_per_buffer=frames_per_buffer) if idxDevOut > -1: self.streamOut = self.audioOut.open(format=pyaudio.paInt16, channels=channels, rate=rate, input=False, output=True, output_device_index=idxDevOut, frames_per_buffer=frames_per_buffer) codec = OpusCodec(channels=channels, rate=rate, frame_size=opus_frame_size, bitrate=self.codecBitrate) while self.isRecordingActive: data = self.streamIn.read(frames_per_buffer, exception_on_overflow=False) #increase volume if needed, may cause some echo effect on high level volume data = self.set_audio_volume(data, self.volume) self.opusencoded_data = codec.encode(data) if len(self.UDPclients) > 0: threading.Thread(target=self.udpStreamToClients, args=(self.opusencoded_data,)).start() if idxDevOut > -1: opusdecoded_data = codec.decode(self.opusencoded_data) self.streamOut.write(opusdecoded_data) if not self.isRecordingActive: self.streamIn.stop_stream() self.streamIn.close() if self.streamOut is not None: self.streamOut.stop_stream() if self.streamOut.is_active(): self.streamOut.close() print("Transcoding thread finished.") def addUDPClient(self, clientAddressPort, client_udp_socket): self.UDPclients[clientAddressPort] = client_udp_socket def removeUDPClient(self, address): if len(self.UDPclients) > 0: for clientAddressPort, socket in self.UDPclients.items(): if clientAddressPort.find(address) > -1: del(self.UDPclients[clientAddressPort]) socket.close() print("UDP client removed: ", address) break def removeAllUDPClients(self): if len(self.UDPclients) > 0: for clientAddressPort, clientSocket in self.UDPclients.items(): clientSocket.close() print("UDP client removed: ", clientAddressPort) self.UDPclients = {} def getUDPStreamsCount(self): return len(self.UDPclients) def udpStreamToClients(self, soundData): if len(self.UDPclients) > 0: try: for clientAddressPort, clientSocket in self.UDPclients.items(): address = clientAddressPort.partition(":")[0] port = int(clientAddressPort.partition(":")[2]) clientSocket.sendto(soundData, (address, port)) self.dataLst.append(len(soundData)) except: pass def setVolume(self, volume): self.volume = volume
def _play(self, stream: pyaudio.Stream, stream_queue: Queue, exec_queue: mp.Queue, data_stream: streaming.AudioStream = None): self.playing.set(True) self.old.set(True) print('playing %s' % self) if data_stream is not None: data_stream.seek_chunk(data_stream.chunk_number(self.temp_start)) data_stream.set_eof_at_chunk( data_stream.chunk_number(self.temp_end)) chunks = streaming.audio_stream_blocker(data_stream, self.CHUNK) print(chunks) else: chunks = make_chunks(self.track[self.temp_start:self.temp_end], self.CHUNK) for chunk in chunks: #print('chunked') if self.paused: print('pause_lock acquired') stream.stop_stream( ) # Sometimes audio gets stuck in the pipes and pops when pausing/resuming self.pause_lock.acquire( ) # yay Locks; blocks until released in resume() #print('pause checked') if not self.playing: print('stopping track') break # Kills thread #print('play checked') #print('round') if stream.is_stopped(): stream.start_stream() #print('stop checked') try: if data_stream is not None: data = audioop.mul( chunk, self.sample_width, 10**(float(self.channel.gain + self.gain) / 10)) else: data = ( chunk + self.channel.gain + self.gain )._data # Live gain editing is possible because it's applied to each chunk in real time #print('new segment created') stream_queue.join( ) # this should block until _write_to_stream() is done processing stream_queue.put( data ) # this will also block if there's more than 1 item in the queue, but that's impossible? #stream.write(data) except OSError: # Couldn't write to host device; maybe it unplugged? raise DeviceDisconnected #print('wrote!') self.play_time += self.CHUNK if self.queue_index != len(self.at_time_queue) and abs( self.at_time_queue[self.queue_index.get()][0] - self.play_time) < self.CHUNK: # If within a CHUNK of the execution time for s in self.at_time_queue[self.queue_index.get()][1]: exec_queue.put(s) self.queue_index += 1 # print(self.play_time) stream.stop_stream()