272 lines
6.7 KiB
Python
272 lines
6.7 KiB
Python
from enum import IntEnum
|
|
from UniTAP.common.timestamp import Timestamp
|
|
|
|
|
|
class AudioFileFormat(IntEnum):
|
|
"""
|
|
Describe all supported audio file formats for saving audio:
|
|
- BIN.
|
|
- WAV.
|
|
"""
|
|
UNKNOWN = -1
|
|
BIN = 0
|
|
WAV = 1
|
|
|
|
|
|
class AudioFormat(IntEnum):
|
|
"""
|
|
Describe all supported audio formats:
|
|
- PCMAudio.
|
|
"""
|
|
Unknown = -1
|
|
L_PCM = 0xFFFF
|
|
|
|
|
|
class AudioMode:
|
|
"""
|
|
Class `AudioMode` contains part information of audio: sample rate, count of bits and channel count.
|
|
"""
|
|
def __init__(self, sample_rate: int = 44100, bits: int = 16, channel_count: int = 2):
|
|
self.sample_rate = sample_rate
|
|
self.bits = bits
|
|
self.channel_count = channel_count
|
|
|
|
def __str__(self):
|
|
return f"Sample rate: {self.sample_rate}\n" \
|
|
f"Bits: {self.bits}\n" \
|
|
f"Channel count: {self.channel_count}\n"
|
|
|
|
def __eq__(self, other):
|
|
return self.sample_rate == other.sample_rate and \
|
|
self.bits == other.bits and \
|
|
self.channel_count == other.channel_count
|
|
|
|
def is_valid(self) -> bool:
|
|
"""
|
|
|
|
Check that information is valid (all values more than 0).
|
|
|
|
Returns:
|
|
object of bool type.
|
|
"""
|
|
return self.sample_rate > 0 and \
|
|
self.bits > 0 and \
|
|
self.channel_count > 0
|
|
|
|
|
|
class AudioFrameData:
|
|
"""
|
|
Class `AudioFrameData` describes captured frame from Sink (RX - receiver) side. Contains information of audio:
|
|
`AudioMode`, samples, `AudioFormat`, frame counter, `Timestamp`, audio data.
|
|
"""
|
|
def __init__(self, audio_mode: AudioMode = AudioMode(), samples: int = 0,
|
|
sample_format: AudioFormat = AudioFormat.Unknown, frame_counter: int = 0,
|
|
timestamp: Timestamp = Timestamp(0), data: bytearray = bytearray()):
|
|
self.__audio_mode = audio_mode
|
|
self.__samples = samples
|
|
self.__sample_format = sample_format
|
|
self.__frame_counter = frame_counter
|
|
self.__timestamp = timestamp
|
|
self.__data = data
|
|
|
|
@property
|
|
def channel_count(self) -> int:
|
|
"""
|
|
|
|
Returns channel count.
|
|
|
|
Returns:
|
|
object of int type.
|
|
"""
|
|
return self.__audio_mode.channel_count
|
|
|
|
@property
|
|
def samples(self) -> int:
|
|
"""
|
|
|
|
Returns samples.
|
|
|
|
Returns:
|
|
object of int type.
|
|
"""
|
|
return self.__samples
|
|
|
|
@property
|
|
def sample_size(self) -> int:
|
|
"""
|
|
|
|
Returns sample size.
|
|
|
|
Returns:
|
|
object of int type.
|
|
"""
|
|
return self.__audio_mode.bits
|
|
|
|
@property
|
|
def sample_rate(self) -> int:
|
|
"""
|
|
|
|
Returns sample rate.
|
|
|
|
Returns:
|
|
object of int type.
|
|
"""
|
|
return self.__audio_mode.sample_rate
|
|
|
|
@property
|
|
def sample_format(self) -> AudioFormat:
|
|
"""
|
|
|
|
Returns sample format.
|
|
|
|
Returns:
|
|
object of AudioFormat type.
|
|
"""
|
|
return self.__sample_format
|
|
|
|
@property
|
|
def frame_counter(self) -> int:
|
|
"""
|
|
|
|
Returns frame counter.
|
|
|
|
Returns:
|
|
object of int type.
|
|
"""
|
|
return self.__frame_counter
|
|
|
|
@property
|
|
def timestamp(self) -> Timestamp:
|
|
"""
|
|
|
|
Returns timestamp.
|
|
|
|
Returns:
|
|
object of Timestamp type.
|
|
"""
|
|
return self.__timestamp
|
|
|
|
@property
|
|
def data(self) -> bytearray:
|
|
"""
|
|
|
|
Returns data.
|
|
|
|
Returns:
|
|
object of bytearray type.
|
|
"""
|
|
return self.__data
|
|
|
|
@channel_count.setter
|
|
def channel_count(self, channel_count: int):
|
|
"""
|
|
|
|
Allows setting new value to channel count.
|
|
|
|
Args:
|
|
channel_count (int) - must be more than 0
|
|
"""
|
|
if channel_count <= 0:
|
|
raise ValueError(f"Channel count must be more than 0.")
|
|
self.__audio_mode.channel_count = channel_count
|
|
|
|
@samples.setter
|
|
def samples(self, samples: int):
|
|
"""
|
|
|
|
Allows setting new value to samples.
|
|
|
|
Args:
|
|
samples (int) - must be more than 0
|
|
"""
|
|
if samples <= 0:
|
|
raise ValueError(f"Samples must be more than 0.")
|
|
self.__samples = samples
|
|
|
|
@sample_size.setter
|
|
def sample_size(self, sample_size: int):
|
|
"""
|
|
|
|
Allows setting new value to sample size.
|
|
|
|
Args:
|
|
sample_size (int) - must be more than 0
|
|
"""
|
|
if sample_size <= 0:
|
|
raise ValueError(f"Sample size must be more than 0.")
|
|
self.__audio_mode.bits = sample_size
|
|
|
|
@sample_rate.setter
|
|
def sample_rate(self, sample_rate: int):
|
|
"""
|
|
|
|
Allows setting new value to sample rate.
|
|
|
|
Args:
|
|
sample_rate (int) - must be more than 0
|
|
"""
|
|
if sample_rate <= 0:
|
|
raise ValueError(f"Sample rate must be more than 0.")
|
|
self.__audio_mode.sample_rate = sample_rate
|
|
|
|
@sample_format.setter
|
|
def sample_format(self, sample_format: int):
|
|
"""
|
|
|
|
Allows setting new value to sample format.
|
|
|
|
Args:
|
|
sample_format (int) - must be more than 0
|
|
"""
|
|
if sample_format <= 0:
|
|
raise ValueError(f"Sample format must be more than 0.")
|
|
self.__sample_format = AudioFormat(sample_format)
|
|
|
|
@timestamp.setter
|
|
def timestamp(self, timestamp: int):
|
|
"""
|
|
|
|
Allows setting new value to timestamp.
|
|
|
|
Args:
|
|
timestamp (int) - must be more than 0
|
|
"""
|
|
if timestamp <= 0:
|
|
raise ValueError(f"Timestamp must be more than 0.")
|
|
self.__timestamp.value = timestamp
|
|
|
|
@frame_counter.setter
|
|
def frame_counter(self, frame_counter: int):
|
|
"""
|
|
|
|
Allows setting new value to frame counter.
|
|
|
|
Args:
|
|
frame_counter (int) - must be more than -1
|
|
"""
|
|
if frame_counter < 0:
|
|
raise ValueError(f"Frame counter must be more than 0.")
|
|
self.__frame_counter = frame_counter
|
|
|
|
@data.setter
|
|
def data(self, value: bytearray):
|
|
"""
|
|
|
|
Allows setting new value to data.
|
|
|
|
Args:
|
|
value (bytearray) - length of value must be more than 0
|
|
"""
|
|
if len(value) <= 0:
|
|
raise ValueError(f"Audio data length must be more than 0.")
|
|
self.__data = value
|
|
|
|
def __str__(self):
|
|
return f"Sample rate: {self.sample_rate}\n" \
|
|
f"Bits (Sample size): {self.sample_size}\n" \
|
|
f"Channel count: {self.channel_count}\n" \
|
|
f"Sample format: {self.sample_format.name}\n" \
|
|
f"Timestamp: {self.timestamp.to_n_sec} n sec\n" \
|
|
f"Frame counter: {self.frame_counter}\n" \
|
|
f"Length of data: {self.data} bytes\n"
|