1.1.0版本
This commit is contained in:
0
UniTAP/dev/ports/modules/capturer/audio/__init__.py
Normal file
0
UniTAP/dev/ports/modules/capturer/audio/__init__.py
Normal file
117
UniTAP/dev/ports/modules/capturer/audio/audio_capturer.py
Normal file
117
UniTAP/dev/ports/modules/capturer/audio/audio_capturer.py
Normal file
@@ -0,0 +1,117 @@
|
||||
import time
|
||||
import copy
|
||||
import warnings
|
||||
|
||||
from typing import List
|
||||
|
||||
from UniTAP.common.audio_mode import AudioFrameData
|
||||
from UniTAP.dev.modules.capturer.capture import Capturer, CaptureConfig
|
||||
from UniTAP.dev.modules.capturer.statuses import AudioCaptureStatus
|
||||
from .result_audio import ResultAudioObject
|
||||
|
||||
|
||||
class AudioCapturer:
|
||||
"""
|
||||
Class `AudioCapturer` allows working with capturing audio frames on Sink (RX - receiver) side.
|
||||
You can `start` capturing in several modes, `stop` capturing, getting current `status` and result of capturing
|
||||
`capture_result`.
|
||||
"""
|
||||
def __init__(self, capturer: Capturer):
|
||||
self.__capturer = capturer
|
||||
self.__result = ResultAudioObject()
|
||||
|
||||
@property
|
||||
def status(self) -> AudioCaptureStatus:
|
||||
"""
|
||||
Returns current audio capturer status.
|
||||
|
||||
Returns:
|
||||
object of `AudioCaptureStatus` type
|
||||
"""
|
||||
return self.__capturer.audio_capturer_status
|
||||
|
||||
@property
|
||||
def capture_result(self) -> ResultAudioObject:
|
||||
"""
|
||||
Returns result of audio capturing.
|
||||
|
||||
Returns:
|
||||
object of `ResultAudioObject` type
|
||||
"""
|
||||
return self.__result
|
||||
|
||||
def start(self, frames_count=0, m_sec=0, timeout=None):
|
||||
"""
|
||||
Start capturing. Possible some variants of capturing:
|
||||
- Capture with fixed frames count (will be captured fixed frames count and capturing will be stopped).
|
||||
- Capture with fixed audio duration (captures audio for the specified duration in milliseconds).
|
||||
- Capture without parameters - Live capturing (for getting frames you need to use functions `pop_element`)
|
||||
- Capture with timeout (maximum duration for capturing operations before stopping, in seconds).
|
||||
|
||||
All results can be obtained using the function `capture_result`.
|
||||
|
||||
Args:
|
||||
frames_count (int)
|
||||
m_sec (int)
|
||||
"""
|
||||
config = CaptureConfig()
|
||||
config.audio = True
|
||||
config.type = CaptureConfig.Type.LIVE
|
||||
config.video = True
|
||||
|
||||
self.__capturer.start_capture(config)
|
||||
|
||||
self.__result.clear()
|
||||
self.__result.start_capture_time = time.time()
|
||||
|
||||
if frames_count > 0:
|
||||
self.__result.buffer.extend(self.__capturer.capture_audio_by_n_frames(frames_count, timeout))
|
||||
self.__fill_audio_mode()
|
||||
elif m_sec > 0:
|
||||
self.__result.buffer.extend(self.__capturer.capture_audio_by_m_sec(m_sec))
|
||||
self.__fill_audio_mode()
|
||||
|
||||
def __fill_audio_mode(self):
|
||||
if len(self.__result.buffer) > 0:
|
||||
self.__result.audio_mode.channel_count = self.__result.buffer[0].channel_count
|
||||
self.__result.audio_mode.bits = self.__result.buffer[0].sample_size
|
||||
self.__result.audio_mode.sample_rate = self.__result.buffer[0].sample_rate
|
||||
|
||||
def stop(self):
|
||||
"""
|
||||
Stop capture audio.
|
||||
"""
|
||||
config = CaptureConfig()
|
||||
config.audio = True
|
||||
config.type = CaptureConfig.Type.LIVE
|
||||
config.video = True
|
||||
|
||||
self.__capturer.stop_capture(config)
|
||||
self.__result.end_capture_time = time.time()
|
||||
|
||||
def pop_element(self) -> List[AudioFrameData]:
|
||||
"""
|
||||
Return first object of `AudioFrameData`.
|
||||
|
||||
Returns:
|
||||
object of `AudioFrameData` type
|
||||
"""
|
||||
if self.status == AudioCaptureStatus.Stop:
|
||||
warnings.warn("Audio capture is not working now. Please, turn it on.")
|
||||
captured_audio_frames = self.__capturer.capture_audio_by_n_frames(1)
|
||||
self.__result.buffer.extend(copy.deepcopy(captured_audio_frames))
|
||||
self.__fill_audio_mode()
|
||||
return captured_audio_frames[0]
|
||||
|
||||
def pop_element_as_result_object(self) -> ResultAudioObject:
|
||||
"""
|
||||
Return captured audio frame(objects of `AudioFrameData`) as `ResultAudioObject`.
|
||||
|
||||
Returns:
|
||||
object of `ResultAudioObject` type
|
||||
"""
|
||||
captured_audio_frames = self.__capturer.capture_audio_by_n_frames(1)
|
||||
|
||||
res = ResultAudioObject()
|
||||
res.buffer.extend(captured_audio_frames)
|
||||
return res
|
||||
60
UniTAP/dev/ports/modules/capturer/audio/result_audio.py
Normal file
60
UniTAP/dev/ports/modules/capturer/audio/result_audio.py
Normal file
@@ -0,0 +1,60 @@
|
||||
from UniTAP.dev.modules.capturer.result_object import ResultObject
|
||||
|
||||
from UniTAP.common.audio_mode import AudioMode, AudioFileFormat
|
||||
|
||||
from UniTAP.dev.ports.modules.ag.ag_utils import save_to_bin_file, save_to_wave_file
|
||||
import warnings
|
||||
|
||||
|
||||
class ResultAudioObject(ResultObject):
|
||||
"""
|
||||
Class `ResultAudioObject` inherited from class `ResultObject`.
|
||||
Class `ResultAudioObject` allows saving captured frames to image `save_image_to_file`.
|
||||
Also has all the `ResultObject` functionality.
|
||||
"""
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.__audio_mode = AudioMode()
|
||||
|
||||
@property
|
||||
def audio_mode(self) -> AudioMode:
|
||||
"""
|
||||
Returns current audio mode for captured audio frames.
|
||||
|
||||
Returns:
|
||||
object of `AudioMode` type
|
||||
"""
|
||||
return self.__audio_mode
|
||||
|
||||
def save_to_file(self, file_format: AudioFileFormat, path: str):
|
||||
"""
|
||||
Saving audio frames to file. Supported file formats describe in `AudioFileFormat`.
|
||||
|
||||
Args:
|
||||
file_format (`AudioFileFormat`) - file format
|
||||
path (str) - path to save
|
||||
"""
|
||||
if len(self.buffer) > 0:
|
||||
if file_format == AudioFileFormat.BIN:
|
||||
save_to_bin_file(path=path, data=self.__convert_buffer())
|
||||
elif file_format == AudioFileFormat.WAV:
|
||||
save_to_wave_file(path=path, audio_mode=self.audio_mode, data=self.__convert_buffer())
|
||||
else:
|
||||
raise ValueError(f"Incorrect audio format. Available formats: "
|
||||
f"{AudioFileFormat.BIN.name}, {AudioFileFormat.WAV.name}.\n"
|
||||
f"Transferred audio format: {file_format.name}")
|
||||
else:
|
||||
warnings.warn("Buffer size is equal 0.")
|
||||
|
||||
def __convert_buffer(self):
|
||||
data = []
|
||||
for audio_frame in self.buffer:
|
||||
data.append(audio_frame.data)
|
||||
return bytearray().join(data)
|
||||
|
||||
def __str__(self):
|
||||
return f"Start capture time: {self.start_capture_time}\n" \
|
||||
f"End capture time: {self.end_capture_time}\n" \
|
||||
f"Timestamp: {self.timestamp.__str__()}\n" \
|
||||
f"Audio mode:\n{self.audio_mode.__str__()}\n"
|
||||
|
||||
Reference in New Issue
Block a user