#include "effect_linein.h"
#include "stream_entry.h"
#include "application/audio_dig_vol.h"
#include "system/includes.h"
#include "audio_config.h"
#include "audio_enc.h"
#include "audio_dec.h"
#include "audio_adc.h"
#include "audio_config.h"
#include "media/includes.h"


struct __effect_linein {
    struct audio_adc_ch  		ch;
    struct audio_adc_output_hdl output;
    s16 						*adc_buf;
    u16 						adc_buf_len;
    void 						*dvol;
    struct __stream_entry 		*stream;
};

//adc出数顺序 lineinL lineinR  mic
//mic通路数据源是单声道，用reverb会变双声道，用echo声道数不变
int effect_linein_mix_callback(void *priv, struct audio_data_frame *in)
{
    struct __effect_linein *linein = (struct __effect_linein *)priv;
    s16 *data = in->data;
    u32 len = in->data_len;
    if (linein && linein->adc_buf) {
#if SYS_DIGVOL_GROUP_EN
        if (linein->dvol) {
            audio_dig_vol_run(linein->dvol, linein->adc_buf, len);
        }
#endif/*SYS_DIGVOL_GROUP_EN*/
        int i, j;
        int points = len >> 1;
        if (in->channel == 2) {
            for (i = 0; i < points; i++) {
                data[i] = data_sat_s16(data[i] + linein->adc_buf[i]);//声道数一致时，lineinLR与过了reverb后混响通路数据点数一致
            }
        } else {
            //混响通路是单声道时，lineinLR声道点数是mic通路数据的两倍
            s16 *tmp = linein->adc_buf;
            for (i = 0, j = 0; i < points * 2; i += 2, j++) {
                tmp[j] = data_sat_s16(tmp[i] + tmp[i + 1]); //将linein LR合成 单声道
            }

            for (i = 0; i < points; i++) {
                data[i] = data_sat_s16(data[i] + linein->adc_buf[i]);//将合成单声道后的linein数据，叠加到混响通路
            }
        }
    }
    return len;
}


static void linein_adc_irq_output(void *priv, s16 *data, int len)
{
    struct __effect_linein  *linein = (struct __effect_linein *)priv;
    if (linein) {
        linein->adc_buf = data;
        linein->adc_buf_len = len;
    }
}

struct __effect_linein *effect_linein_open(void)
{
    struct __effect_linein *linein = zalloc(sizeof(struct __effect_linein));
    if (linein) {
        linein->stream = stream_entry_open(linein, effect_linein_mix_callback, 0);
        if (linein->stream) {
            /* [修改] 混响用默认TCFG_LINEIN_LR_CH，传0即可，老接口无第4参数 */
            /* if (audio_linein_open(&linein->ch, MIC_EFFECT_SAMPLERATE, 3) == 0) {  // 老: 3参数 */
            if (audio_linein_open(&linein->ch, MIC_EFFECT_SAMPLERATE, 3, 0) == 0) {
#if SYS_DIGVOL_GROUP_EN
                audio_dig_vol_param linein_digvol_param = {
                    .vol_start = 0,
                    .vol_max = 100,
                    .ch_total = 2,
                    .fade_en = 1,
                    .fade_points_step = 5,
                    .fade_gain_step = 10,
                    .vol_list = NULL,
                };
                linein->dvol = audio_dig_vol_open(&linein_digvol_param);

                if (linein->dvol) {
                    audio_dig_vol_group_add(sys_digvol_group, linein->dvol, "music_linein");
                }
#endif/*SYS_DIGVOL_GROUP_EN*/
                linein->output.handler = linein_adc_irq_output;
                linein->output.priv = linein;
                audio_linein_add_output(&linein->output);
                audio_linein_start(&linein->ch);
                printf("audio_linein_open ok!!!\n ");
                return linein;
            }
        } else {
            effect_linein_close(&linein);
            return NULL;
        }
    }
    return NULL;
}

void effect_linein_close(struct __effect_linein **hdl)
{
    if (hdl && (*hdl))		{
        struct __effect_linein *linein = *hdl;
#if SYS_DIGVOL_GROUP_EN
        sys_digvol_group_ch_close("music_linein");
#endif/*SYS_DIGVOL_GROUP_EN*/
        audio_linein_close(&linein->ch, &linein->output);
        stream_entry_close(&linein->stream);
        local_irq_disable();
        free(linein);
        *hdl = NULL;
        local_irq_enable();
    }
}

struct audio_stream_entry *effect_linein_get_stream_entry(struct __effect_linein *hdl)
{
    if (hdl && hdl->stream) {
        return &(hdl->stream->entry);
    }
    return NULL;
}



