OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "base/logging.h" | |
6 #include "services/media/framework/parts/lpcm_reformatter.h" | |
7 | |
8 namespace mojo { | |
9 namespace media { | |
10 | |
11 LpcmReformatter* LpcmReformatter::NewImpl( | |
12 const LpcmStreamType& in_type, | |
13 const LpcmStreamTypeSet& out_type) { | |
14 switch (in_type.sample_format()) { | |
johngro
2016/01/26 23:47:29
up to you, but you can reduce the amount of duplic
dalesat
2016/01/28 18:49:16
Acknowledged.
| |
15 case LpcmStreamType::SampleFormat::kUnsigned8: | |
16 switch (out_type.sample_format()) { | |
17 case LpcmStreamType::SampleFormat::kUnsigned8: | |
18 case LpcmStreamType::SampleFormat::kAny: | |
19 return new LpcmReformatterImpl<uint8_t, uint8_t>( | |
20 in_type, out_type); | |
21 case LpcmStreamType::SampleFormat::kSigned16: | |
22 return new LpcmReformatterImpl<uint8_t, int16_t>( | |
23 in_type, out_type); | |
24 case LpcmStreamType::SampleFormat::kSigned24In32: | |
25 return new LpcmReformatterImpl<uint8_t, int32_t>( | |
26 in_type, out_type); | |
27 case LpcmStreamType::SampleFormat::kFloat: | |
28 return new LpcmReformatterImpl<uint8_t, float>( | |
29 in_type, out_type); | |
30 default: | |
31 NOTREACHED() << "unsupported sample format"; | |
32 return nullptr; | |
33 } | |
34 case LpcmStreamType::SampleFormat::kSigned16: | |
35 switch (out_type.sample_format()) { | |
36 case LpcmStreamType::SampleFormat::kUnsigned8: | |
37 return new LpcmReformatterImpl<int16_t, uint8_t>( | |
38 in_type, out_type); | |
39 case LpcmStreamType::SampleFormat::kSigned16: | |
40 case LpcmStreamType::SampleFormat::kAny: | |
41 return new LpcmReformatterImpl<int16_t, int16_t>( | |
42 in_type, out_type); | |
43 case LpcmStreamType::SampleFormat::kSigned24In32: | |
44 return new LpcmReformatterImpl<int16_t, int32_t>( | |
45 in_type, out_type); | |
46 case LpcmStreamType::SampleFormat::kFloat: | |
47 return new LpcmReformatterImpl<int16_t, float>( | |
48 in_type, out_type); | |
49 default: | |
50 NOTREACHED() << "unsupported sample format"; | |
51 return nullptr; | |
52 } | |
53 case LpcmStreamType::SampleFormat::kSigned24In32: | |
54 switch (out_type.sample_format()) { | |
55 case LpcmStreamType::SampleFormat::kUnsigned8: | |
56 return new LpcmReformatterImpl<int32_t, uint8_t>( | |
57 in_type, out_type); | |
58 case LpcmStreamType::SampleFormat::kSigned16: | |
59 return new LpcmReformatterImpl<int32_t, int16_t>( | |
60 in_type, out_type); | |
61 case LpcmStreamType::SampleFormat::kSigned24In32: | |
62 case LpcmStreamType::SampleFormat::kAny: | |
63 return new LpcmReformatterImpl<int32_t, int32_t>( | |
64 in_type, out_type); | |
65 case LpcmStreamType::SampleFormat::kFloat: | |
66 return new LpcmReformatterImpl<int32_t, float>( | |
67 in_type, out_type); | |
68 default: | |
69 NOTREACHED() << "unsupported sample format"; | |
70 return nullptr; | |
71 } | |
72 case LpcmStreamType::SampleFormat::kFloat: | |
73 switch (out_type.sample_format()) { | |
74 case LpcmStreamType::SampleFormat::kUnsigned8: | |
75 return new LpcmReformatterImpl<float, uint8_t>( | |
76 in_type, out_type); | |
77 case LpcmStreamType::SampleFormat::kSigned16: | |
78 return new LpcmReformatterImpl<float, int16_t>( | |
79 in_type, out_type); | |
80 case LpcmStreamType::SampleFormat::kSigned24In32: | |
81 return new LpcmReformatterImpl<float, int32_t>( | |
82 in_type, out_type); | |
83 case LpcmStreamType::SampleFormat::kFloat: | |
84 case LpcmStreamType::SampleFormat::kAny: | |
85 return new LpcmReformatterImpl<float, float>(in_type, out_type); | |
86 default: | |
87 NOTREACHED() << "unsupported sample format"; | |
88 return nullptr; | |
89 } | |
90 default: | |
91 NOTREACHED() << "unsupported sample format"; | |
92 return nullptr; | |
93 } | |
94 } | |
95 | |
96 template<typename TIn, typename TOut> | |
97 LpcmReformatterImpl<TIn, TOut>::LpcmReformatterImpl( | |
98 const LpcmStreamType& in_type, | |
99 const LpcmStreamTypeSet& out_type) : | |
100 in_type_(in_type), | |
101 out_type_( | |
102 out_type.sample_format() == LpcmStreamType::SampleFormat::kAny ? | |
103 in_type.sample_format() : | |
104 out_type.sample_format(), | |
105 in_type.channels(), | |
106 in_type.frames_per_second()) {} | |
107 | |
108 template<typename TIn, typename TOut> | |
109 LpcmReformatterImpl<TIn, TOut>::~LpcmReformatterImpl() {} | |
110 | |
111 namespace { | |
112 | |
113 // TODO(dalesat): Limit, optimize. | |
114 | |
115 template<typename TIn, typename TOut> | |
116 inline void CopySample(TOut* dest, TIn* source) { | |
117 *dest = static_cast<TOut>(*source); | |
118 } | |
119 | |
120 inline void CopySample(uint8_t* dest, int16_t* source) { | |
121 *dest = static_cast<uint8_t>((*source >> 8) ^ 0x80); | |
122 } | |
123 | |
124 inline void CopySample(uint8_t* dest, int32_t* source) { | |
125 *dest = static_cast<uint8_t>((*source >> 16) ^ 0x80); | |
126 } | |
127 | |
128 inline void CopySample(uint8_t* dest, float* source) { | |
johngro
2016/01/26 23:47:29
Source needs to be clamped to the range [-1.0, 1.0
dalesat
2016/01/28 18:49:15
Done.
| |
129 *dest = static_cast<uint8_t>((*source * 0x7f) + 128); | |
130 } | |
131 | |
132 inline void CopySample(int16_t* dest, uint8_t* source) { | |
133 *dest = static_cast<int16_t>(*source ^ 0x80) << 8; | |
134 } | |
135 | |
136 inline void CopySample(int16_t* dest, int32_t* source) { | |
137 *dest = static_cast<int16_t>(*source >> 8); | |
138 } | |
139 | |
140 inline void CopySample(int16_t* dest, float* source) { | |
141 *dest = static_cast<int16_t>(*source * 0x7fff); | |
142 } | |
143 | |
144 inline void CopySample(int32_t* dest, uint8_t* source) { | |
145 *dest = static_cast<int32_t>(*source ^ 0x80) << 16; | |
146 } | |
147 | |
148 inline void CopySample(int32_t* dest, int16_t* source) { | |
149 *dest = static_cast<int32_t>(*source << 8); | |
150 } | |
151 | |
152 inline void CopySample(int32_t* dest, float* source) { | |
153 *dest = static_cast<int32_t>(*source * 0x7fffff); | |
154 } | |
155 | |
156 inline void CopySample(float* dest, uint8_t* source) { | |
157 *dest = static_cast<float>(*source ^ 0x80) / 0x80; | |
158 } | |
159 | |
160 inline void CopySample(float* dest, int16_t* source) { | |
161 *dest = static_cast<float>(*source) / 0x8000; | |
162 } | |
163 | |
164 inline void CopySample(float* dest, int32_t* source) { | |
165 *dest = static_cast<float>(*source) / 0x800000; | |
166 } | |
167 | |
168 template<typename TIn, typename TOut> | |
169 inline void MixSample(TOut* dest, TIn* source) { | |
170 *dest += static_cast<TOut>(*source); | |
171 } | |
172 | |
173 inline void MixSample(uint8_t* dest, int16_t* source) { | |
174 *dest += static_cast<uint8_t>((*source >> 8) ^ 0x80); | |
175 } | |
176 | |
177 inline void MixSample(uint8_t* dest, int32_t* source) { | |
178 *dest += static_cast<uint8_t>((*source >> 16) ^ 0x80); | |
179 } | |
180 | |
181 inline void MixSample(uint8_t* dest, float* source) { | |
182 *dest += static_cast<uint8_t>((*source * 0x7f) + 128); | |
183 } | |
184 | |
185 inline void MixSample(int16_t* dest, uint8_t* source) { | |
186 *dest += static_cast<int16_t>(*source ^ 0x80) << 8; | |
187 } | |
188 | |
189 inline void MixSample(int16_t* dest, int32_t* source) { | |
190 *dest += static_cast<int16_t>(*source >> 8); | |
191 } | |
192 | |
193 inline void MixSample(int16_t* dest, float* source) { | |
194 *dest += static_cast<int16_t>(*source * 0x7fff); | |
195 } | |
196 | |
197 inline void MixSample(int32_t* dest, uint8_t* source) { | |
198 *dest += static_cast<int32_t>(*source ^ 0x80) << 16; | |
199 } | |
200 | |
201 inline void MixSample(int32_t* dest, int16_t* source) { | |
202 *dest += static_cast<int32_t>(*source << 8); | |
203 } | |
204 | |
205 inline void MixSample(int32_t* dest, float* source) { | |
206 *dest += static_cast<int32_t>(*source * 0x7fffff); | |
207 } | |
208 | |
209 inline void MixSample(float* dest, uint8_t* source) { | |
210 *dest += static_cast<float>(*source ^ 0x80) / 0x80; | |
211 } | |
212 | |
213 inline void MixSample(float* dest, int16_t* source) { | |
214 *dest += static_cast<float>(*source) / 0x8000; | |
215 } | |
216 | |
217 inline void MixSample(float* dest, int32_t* source) { | |
218 *dest += static_cast<float>(*source) / 0x800000; | |
219 } | |
220 | |
221 } // namespace | |
222 | |
223 template<typename TIn, typename TOut> | |
224 const LpcmStreamType& LpcmReformatterImpl<TIn, TOut>::input_stream_type() | |
225 const { | |
226 return in_type_; | |
227 } | |
228 | |
229 template<typename TIn, typename TOut> | |
230 const LpcmStreamType& LpcmReformatterImpl<TIn, TOut>::output_stream_type() | |
231 const { | |
232 return out_type_; | |
233 } | |
234 | |
235 template<typename TIn, typename TOut> | |
236 void LpcmReformatterImpl<TIn, TOut>::TransformFrames( | |
237 LpcmFrames* source, | |
238 LpcmFrames* dest, | |
239 bool mix) { | |
240 DCHECK(source); | |
241 DCHECK(dest); | |
242 DCHECK(source->buffer()); | |
243 DCHECK(source->frame_count()); | |
244 DCHECK(dest->buffer()); | |
245 DCHECK(dest->frame_count()); | |
246 | |
247 uint64_t frame_count = std::min(source->frame_count(), dest->frame_count()); | |
248 | |
249 uint8_t* in_channel = reinterpret_cast<uint8_t*>(source->buffer()); | |
250 uint8_t* out_channel = reinterpret_cast<uint8_t*>(dest->buffer()); | |
johngro
2016/01/26 23:47:29
FWIW - when casing a pointer to a PoD to another p
| |
251 | |
252 for (uint32_t channel = 0; channel < in_type_.channels(); channel++) { | |
253 TIn* in_sample = reinterpret_cast<TIn*>(in_channel); | |
254 TOut* out_sample = reinterpret_cast<TOut*>(out_channel); | |
255 if (mix) { | |
johngro
2016/01/26 23:47:29
if you are going to put the mix decision in here,
dalesat
2016/01/28 18:49:16
The outer loop is per-channel. The test will happe
johngro
2016/02/01 22:38:16
Acknowledged.
| |
256 for (uint64_t sample = 0; sample < frame_count; sample++) { | |
257 MixSample(out_sample, in_sample); | |
258 in_sample += in_type_.channels(); | |
259 out_sample += out_type_.channels(); | |
260 } | |
261 } else { | |
262 for (uint64_t sample = 0; sample < frame_count; sample++) { | |
263 CopySample(out_sample, in_sample); | |
264 in_sample += in_type_.channels(); | |
265 out_sample += out_type_.channels(); | |
266 } | |
267 } | |
268 in_channel += in_type_.sample_size(); | |
269 out_channel += out_type_.sample_size(); | |
270 } | |
271 | |
272 source->advance(frame_count); | |
273 dest->advance(frame_count); | |
274 } | |
275 | |
276 } // namespace media | |
277 } // namespace mojo | |
OLD | NEW |