bt_common/generic_audio/
codec_configuration.rs1use std::collections::HashSet;
6use std::ops::RangeBounds;
7
8use crate::core::ltv::LtValue;
9use crate::decodable_enum;
10
11use super::AudioLocation;
12
13#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
14pub enum CodecConfigurationType {
15 SamplingFrequency,
16 FrameDuration,
17 AudioChannelAllocation,
18 OctetsPerCodecFrame,
19 CodecFramesPerSdu,
20}
21
22impl From<CodecConfigurationType> for u8 {
23 fn from(value: CodecConfigurationType) -> Self {
24 match value {
25 CodecConfigurationType::SamplingFrequency => 1,
26 CodecConfigurationType::FrameDuration => 2,
27 CodecConfigurationType::AudioChannelAllocation => 3,
28 CodecConfigurationType::OctetsPerCodecFrame => 4,
29 CodecConfigurationType::CodecFramesPerSdu => 5,
30 }
31 }
32}
33
34decodable_enum! {
35 pub enum FrameDuration<u8, crate::packet_encoding::Error, OutOfRange> {
36 SevenFiveMs = 0x00,
37 TenMs = 0x01,
38 }
39}
40
41decodable_enum! {
42 pub enum SamplingFrequency<u8, crate::packet_encoding::Error, OutOfRange> {
43 F8000Hz = 0x01,
44 F11025Hz = 0x02,
45 F16000Hz = 0x03,
46 F22050Hz = 0x04,
47 F24000Hz = 0x05,
48 F32000Hz = 0x06,
49 F44100Hz = 0x07,
50 F48000Hz = 0x08,
51 F88200Hz = 0x09,
52 F96000Hz = 0x0A,
53 F176400Hz = 0x0B,
54 F192000Hz = 0x0C,
55 F384000Hz = 0x0D,
56 }
57}
58
59#[derive(Clone, PartialEq, Eq, Debug)]
63pub enum CodecConfiguration {
64 SamplingFrequency(SamplingFrequency),
65 FrameDuration(FrameDuration),
66 AudioChannelAllocation(std::collections::HashSet<AudioLocation>),
67 OctetsPerCodecFrame(u16),
68 CodecFramesPerSdu(u8),
69}
70
71impl LtValue for CodecConfiguration {
72 type Type = CodecConfigurationType;
73
74 const NAME: &'static str = "Codec Compatability";
75
76 fn type_from_octet(x: u8) -> Option<Self::Type> {
77 match x {
78 1 => Some(CodecConfigurationType::SamplingFrequency),
79 2 => Some(CodecConfigurationType::FrameDuration),
80 3 => Some(CodecConfigurationType::AudioChannelAllocation),
81 4 => Some(CodecConfigurationType::OctetsPerCodecFrame),
82 5 => Some(CodecConfigurationType::CodecFramesPerSdu),
83 _ => None,
84 }
85 }
86
87 fn length_range_from_type(ty: Self::Type) -> std::ops::RangeInclusive<u8> {
88 match ty {
89 CodecConfigurationType::SamplingFrequency => 2..=2,
90 CodecConfigurationType::FrameDuration => 2..=2,
91 CodecConfigurationType::AudioChannelAllocation => 5..=5,
92 CodecConfigurationType::OctetsPerCodecFrame => 3..=3,
93 CodecConfigurationType::CodecFramesPerSdu => 2..=2,
94 }
95 }
96
97 fn into_type(&self) -> Self::Type {
98 match self {
99 CodecConfiguration::SamplingFrequency(_) => CodecConfigurationType::SamplingFrequency,
100 CodecConfiguration::FrameDuration(_) => CodecConfigurationType::FrameDuration,
101 CodecConfiguration::AudioChannelAllocation(_) => {
102 CodecConfigurationType::AudioChannelAllocation
103 }
104 CodecConfiguration::OctetsPerCodecFrame(_) => {
105 CodecConfigurationType::OctetsPerCodecFrame
106 }
107 CodecConfiguration::CodecFramesPerSdu(_) => CodecConfigurationType::CodecFramesPerSdu,
108 }
109 }
110
111 fn value_encoded_len(&self) -> u8 {
112 let range = Self::length_range_from_type(self.into_type());
114 let std::ops::Bound::Included(len) = range.start_bound() else {
115 unreachable!();
116 };
117 (len - 1).into()
118 }
119
120 fn encode_value(&self, buf: &mut [u8]) -> Result<(), crate::packet_encoding::Error> {
121 match self {
122 CodecConfiguration::SamplingFrequency(freq) => buf[0] = u8::from(*freq),
123 CodecConfiguration::FrameDuration(fd) => buf[0] = u8::from(*fd),
124 CodecConfiguration::AudioChannelAllocation(audio_locations) => {
125 let locations: Vec<&AudioLocation> = audio_locations.into_iter().collect();
126 buf[0..4]
127 .copy_from_slice(&AudioLocation::to_bits(locations.into_iter()).to_le_bytes());
128 }
129 CodecConfiguration::OctetsPerCodecFrame(octets) => {
130 buf[0..2].copy_from_slice(&octets.to_le_bytes())
131 }
132 CodecConfiguration::CodecFramesPerSdu(frames) => buf[0] = *frames,
133 };
134 Ok(())
135 }
136
137 fn decode_value(
138 ty: &CodecConfigurationType,
139 buf: &[u8],
140 ) -> Result<Self, crate::packet_encoding::Error> {
141 match ty {
142 CodecConfigurationType::SamplingFrequency => {
143 let freq = SamplingFrequency::try_from(buf[0])?;
144 Ok(Self::SamplingFrequency(freq))
145 }
146 CodecConfigurationType::FrameDuration => {
147 let fd = FrameDuration::try_from(buf[0])?;
148 Ok(Self::FrameDuration(fd))
149 }
150 CodecConfigurationType::AudioChannelAllocation => {
151 let raw_value = u32::from_le_bytes(buf[0..4].try_into().unwrap());
152 let locations = AudioLocation::from_bits(raw_value).collect::<HashSet<_>>();
153 Ok(Self::AudioChannelAllocation(locations))
154 }
155 CodecConfigurationType::OctetsPerCodecFrame => {
156 let value = u16::from_le_bytes(buf[0..2].try_into().unwrap());
157 Ok(Self::OctetsPerCodecFrame(value))
158 }
159 CodecConfigurationType::CodecFramesPerSdu => Ok(Self::CodecFramesPerSdu(buf[0])),
160 }
161 }
162}
163
164#[cfg(test)]
165mod tests {}