Загрузка данных


/**
 * @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);
	}
}