/**
* @brief Безопасное дублирование моно-канала в стерео in-place
* @param buf Указатель на буфер. Должен иметь физический размер не менее (mono_frames * 4) байт!
* @param mono_frames Количество моно-фреймов (сэмплов), например 320.
*/
static void audio_mono_to_stereo(void *buf, int mono_frames) {
/* Явно приводим к знаковому типу сэмплов */
int16_t *b16 = (int16_t *)buf;
// Идем с конца буфера (с 639-го сэмпла стерео для 320 фреймов),
// чтобы не затирать еще не обработанные моно-сэмплы в начале
for (int i = mono_frames - 1; i >= 0; i--) {
b16[i * 2 + 1] = b16[i]; // Правый канал I2S
b16[i * 2] = b16[i]; // Левый канал I2S
}
}
/**
* @brief Безопасное сжатие стерео-буфера в моно in-place
* @param buf Указатель на буфер с данными от I2S.
* @param target_mono_frames Количество моно-фреймов, которые нужно получить на выходе (например, 320).
*/
static void audio_stereo_to_mono(void *buf, int target_mono_frames) {
int16_t *b16 = (int16_t *)buf;
// Идем с начала к концу, перезаписывая стерео-пары моно-сэмплами
for (int i = 0; i < target_mono_frames; i++) {
b16[i] = b16[i * 2]; // Оставляем левый канал кодека, правый отбрасываем
}
}
/**
* @brief Диспетчер конверсии каналов
* @param pjsip_frames Количество фреймов, заданное кодеком (framesPerBuffer от PJSIP)
*/
void audio_convert_channels(int cur_chan, int out_chan, uint8_t *buf, size_t pjsip_frames) {
if (cur_chan == out_chan) {
return;
}
// Передаем pjsip_frames (320), которые теперь интерпретируются исключительно как фреймы (отсчеты)
if (cur_chan == 1 && out_chan == 2) {
audio_mono_to_stereo(buf, (int)pjsip_frames);
} else if (cur_chan == 2 && out_chan == 1) {
audio_stereo_to_mono(buf, (int)pjsip_frames);
}
}