20 #include "audio_converter.h"
22 const unsigned int TEMPORARY_BUFFER_SIZE = 100 * 1024;
28 process_conversion_params();
32 int audio_converter::process_conversion_params()
35 bool format_ok =
false;
36 bool sample_rate_ok =
false;
38 bool downsample =
false;
40 m_op = UNSUPPORTED_CONVERSION;
46 INFO(
"Convert 16-bit stereo to mono.\n");
52 if(m_out_props.format == m_in_props.format)
54 INFO(
"No format conversion.\n");
63 INFO(
"Convert Mono/mono-left/mono-right to mono.\n");
67 ERROR(
"Unsupported format conversion: 0x%x to 0x%x.\n", m_in_props.format, m_out_props.format);
73 unsigned int in_sampling_rate, in_bits_per_sample, in_num_channels;
74 unsigned int out_sampling_rate, out_bits_per_sample, out_num_channels;
75 audiocapturemgr::get_individual_audio_parameters(m_in_props, in_sampling_rate, in_bits_per_sample, in_num_channels);
76 audiocapturemgr::get_individual_audio_parameters(m_out_props, out_sampling_rate, out_bits_per_sample, out_num_channels);
78 if(out_sampling_rate > in_sampling_rate)
80 ERROR(
"Cannot up-sample. %d to %d.\n", in_sampling_rate, out_sampling_rate);
82 else if(0 != (in_sampling_rate % out_sampling_rate))
84 ERROR(
"Incompatible sampling rates: %d to %d.\n", in_sampling_rate, out_sampling_rate);
88 sample_rate_ok =
true;
89 if(out_sampling_rate < in_sampling_rate)
92 INFO(
"Downsample from %d to %d\n", in_sampling_rate, out_sampling_rate);
97 if(format_ok && sample_rate_ok)
99 if (downmix && downsample)
101 m_op = DOWNMIX_AND_DOWNSAMPLE;
103 else if(downmix && !downsample)
107 else if (!downmix && downsample)
113 m_op = NO_CONVERSION;
120 int audio_converter::downsample_and_downmix(
const std::list<audio_buffer *> &queue,
int size)
124 unsigned int in_sampling_rate, in_bits_per_sample, in_num_channels;
125 audiocapturemgr::get_individual_audio_parameters(m_in_props, in_sampling_rate, in_bits_per_sample, in_num_channels);
127 unsigned int out_sampling_rate, out_bits_per_sample, out_num_channels;
128 audiocapturemgr::get_individual_audio_parameters(m_out_props, out_sampling_rate, out_bits_per_sample, out_num_channels);
130 unsigned int sample_size = in_bits_per_sample / 8;
131 unsigned int frame_size = in_num_channels * sample_size;
132 unsigned int leap_value = frame_size * in_sampling_rate / out_sampling_rate;
133 unsigned int write_length = (DOWNMIX_AND_DOWNSAMPLE == m_op ? sample_size : frame_size );
137 unsigned int temp_buffer_write_offset = 0;
139 for(
auto &entry: queue)
141 char * ptr = (
char *)entry->m_start_ptr + read_offset;
142 if(0 != (entry->m_size % frame_size))
144 WARN(
"Audio buffer not aligned with frame boundary!\n");
147 int buffer_size = entry->m_size;
148 while (buffer_size > 0)
150 m_sink.write_data(ptr, write_length);
151 buffer_size -= leap_value;
163 read_offset = -1 * buffer_size;
165 size -= entry->m_size;
175 int audio_converter::downmix(
const std::list<audio_buffer *> &queue,
int size)
179 unsigned int in_sampling_rate, in_bits_per_sample, in_num_channels;
180 audiocapturemgr::get_individual_audio_parameters(m_in_props, in_sampling_rate, in_bits_per_sample, in_num_channels);
182 unsigned int sample_size = in_bits_per_sample / 8;
183 unsigned int frame_size = in_num_channels * sample_size;
188 if(memsink && (16 == in_bits_per_sample) && (2 == in_num_channels))
190 INFO(
"Running special optimizations for 16-bit stereo to mono conversion.\n");
191 int16_t * dptr = (int16_t *)memsink->get_buffer();
192 unsigned int write_offset = memsink->get_size();
193 for(
auto &entry: queue)
195 int16_t * sptr = (int16_t *)entry->m_start_ptr;
196 unsigned int data_remaining = entry->m_size;
197 while(32 <= data_remaining)
209 data_remaining -= 16 * 2;
210 write_offset += 8 * 2;
214 while(0 != data_remaining)
219 data_remaining -= 2 * 2;
220 write_offset += 1 * 2;
224 memsink->m_write_offset = write_offset;
225 INFO(
"Final write offset is %d. Final value of dptr: %p\n", write_offset, dptr);
229 for(
auto &entry: queue)
231 char * ptr = (
char *)entry->m_start_ptr;
232 if(0 != (entry->m_size % frame_size))
234 WARN(
"Audio buffer not aligned with frame boundary!\n");
237 unsigned int buffer_size = entry->m_size;
238 while (buffer_size > 0)
240 m_sink.write_data(ptr, sample_size);
241 buffer_size -= frame_size;
245 size -= entry->m_size;
255 int audio_converter::downsample(std::list<audio_buffer *> &queue,
int size)
259 unsigned int in_sampling_rate, in_bits_per_sample, in_num_channels;
260 audiocapturemgr::get_individual_audio_parameters(m_in_props, in_sampling_rate, in_bits_per_sample, in_num_channels);
262 unsigned int out_sampling_rate, out_bits_per_sample, out_num_channels;
263 audiocapturemgr::get_individual_audio_parameters(m_out_props, out_sampling_rate, out_bits_per_sample, out_num_channels);
265 unsigned int frame_size = in_num_channels * in_bits_per_sample * 8;
266 unsigned int leap_value = frame_size * in_sampling_rate / out_sampling_rate;
269 for(
auto &entry: queue)
271 char * ptr = (
char *)entry->m_start_ptr + read_offset;
272 if(0 != (entry->m_size % frame_size))
274 WARN(
"Audio buffer not aligned with frame boundary!\n");
277 int buffer_size = entry->m_size;
278 while (buffer_size > 0)
280 m_sink.write_data(ptr, frame_size);
281 buffer_size -= leap_value;
284 read_offset = -1 * buffer_size;
286 size -= entry->m_size;
295 int audio_converter::passthrough(
const std::list<audio_buffer *> &queue,
int size)
298 for(
auto &entry: queue)
300 ret = m_sink.write_data((
char *)entry->m_start_ptr, entry->m_size);
303 ERROR(
"Write error!\n");
306 size -= entry->m_size;
315 int audio_converter::convert(
const std::list<audio_buffer *> &queue,
unsigned int size)
318 INFO(
"Operation: 0x%x\n", m_op);
321 case DOWNMIX_AND_DOWNSAMPLE:
322 ret = downsample_and_downmix(queue, size);
326 ret = downmix(queue, size);
330 ret = downsample_and_downmix(queue, size);
334 ret = passthrough(queue, size);
338 ERROR(
"Unsupported conversion.\n");
345 int audio_converter_file_sink::write_data(
const char * ptr,
unsigned int size)
348 m_file.write(ptr, size);
353 audio_converter_memory_sink::audio_converter_memory_sink(
unsigned int max_size) : m_write_offset(0)
355 m_buffer =
new char[max_size];
356 INFO(
"Created with size %d. ptr: %p, this: %p\n", max_size, m_buffer,
this);
359 audio_converter_memory_sink::~audio_converter_memory_sink()
361 INFO(
"Destroying %p\n",
this);
365 int audio_converter_memory_sink::write_data(
const char * ptr,
unsigned int size)
368 memcpy(&m_buffer[m_write_offset], ptr, size);
369 m_write_offset += size;