#include "stm32f4xx.h"                  // Device header
#include "mp3.h"
#include "music.h"
#include "systick_conf.h"
#include "malloc.h"
#include "ff.h"
#include "string.h"
#include "i2s.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "variables.h"
#include "defines.h"
#include "spectrum_dsp.h"
#include "file_unit.h"

#define AUDIO_MIN(x,y)	((x)<(y)? (x):(y))

__mp3ctrl * mp3ctrl;	//mp3控制结构体 

//填充PCM数据到DAC
//buf:PCM数据首地址
//size:pcm数据量(16位为单位)
//nch:声道数(1,单声道,2立体声)
void mp3_fill_buffer(uint16_t* buf,uint16_t size,uint8_t nch)
{
	uint16_t i; 
	uint16_t *p_out;
    int16_t *p_in = (int16_t*)buf; // 视为有符号16位数据处理

	if(I2SdmaBuff == 0) p_out=(uint16_t*)music_ctrl.i2sbuf1;
	else p_out=(uint16_t*)music_ctrl.i2sbuf2;

    if(kv_hdp0_or_spk1) // 开启音量调节
    {
        if(nch==2)
        {
            for(i=0;i<size;i++) 
            {
                int32_t val = ((int32_t)p_in[i] * kv_spk_value) >> 8;
                p_out[i] = (int16_t)val;
            }
        }
        else	//单声道
        {
            for(i=0;i<size;i++)
            {
                int32_t val = ((int32_t)p_in[i] * kv_spk_value) >> 8;
                p_out[2*i] = (int16_t)val;
                p_out[2*i+1] = (int16_t)val;
            }
        }
    }
    else // 原样输出
    {
        if(nch==2)
        {
            memcpy(p_out, buf, size * sizeof(uint16_t));
        }
        else	//单声道
        {
            for(i=0;i<size;i++)
            {
                p_out[2*i]=buf[i];
                p_out[2*i+1]=buf[i];
            }
        }
    }
} 

//解析ID3V1 
//buf:输入数据缓存区(大小固定是128字节)
//pctrl:MP3控制器
//返回值:0,获取正常
//    其他,获取失败
uint8_t mp3_id3v1_decode(uint8_t* buf,__mp3ctrl *pctrl)
{
	ID3V1_Tag *id3v1tag;
	id3v1tag=(ID3V1_Tag*)buf;
	if (strncmp("TAG",(char*)id3v1tag->id,3)==0)//是MP3 ID3V1 TAG
	{
		if(id3v1tag->title[0])strncpy((char*)pctrl->title,(char*)id3v1tag->title,30);
		if(id3v1tag->artist[0])strncpy((char*)pctrl->artist,(char*)id3v1tag->artist,30); 
	}else return 1;
	return 0;
}

//解析ID3V2 
//buf:输入数据缓存区
//size:数据大小
//pctrl:MP3控制器
//返回值:0,获取正常
//    其他,获取失败
uint8_t mp3_id3v2_decode(uint8_t* buf,uint32_t size,__mp3ctrl *pctrl)
{
	ID3V2_TagHead *taghead;
	ID3V23_FrameHead *framehead; 
	uint32_t t;
	uint32_t tagsize;	//tag大小
	uint32_t frame_size;	//帧大小 
	taghead=(ID3V2_TagHead*)buf; 
	if(strncmp("ID3",(const char*)taghead->id,3)==0)//存在ID3?
	{
		tagsize=((uint32_t)taghead->size[0]<<21)|((uint32_t)taghead->size[1]<<14)|((uint16_t)taghead->size[2]<<7)|taghead->size[3];//得到tag 大小
		pctrl->datastart=tagsize;		//得到mp3数据开始的偏移量
		if(tagsize>size)tagsize=size;	//tagsize大于输入bufsize的时候,只处理输入size大小的数据
		if(taghead->mversion<3)
		{
			return 1;
		}
		t=10;
		while(t<tagsize)
		{
			framehead=(ID3V23_FrameHead*)(buf+t);
			frame_size=((uint32_t)framehead->size[0]<<24)|((uint32_t)framehead->size[1]<<16)|((uint32_t)framehead->size[2]<<8)|framehead->size[3];//得到帧大小
 			if (strncmp("TT2",(char*)framehead->id,3)==0||strncmp("TIT2",(char*)framehead->id,4)==0)//找到歌曲标题帧,不支持unicode格式!!
			{
				strncpy((char*)pctrl->title,(char*)(buf+t+sizeof(ID3V23_FrameHead)+1),AUDIO_MIN(frame_size-1,MP3_TITSIZE_MAX-1));
			}
 			if (strncmp("TP1",(char*)framehead->id,3)==0||strncmp("TPE1",(char*)framehead->id,4)==0)//找到歌曲艺术家帧
			{
				strncpy((char*)pctrl->artist,(char*)(buf+t+sizeof(ID3V23_FrameHead)+1),AUDIO_MIN(frame_size-1,MP3_ARTSIZE_MAX-1));
			}
			t+=frame_size+sizeof(ID3V23_FrameHead);
		} 
	}else pctrl->datastart=0;//不存在ID3,mp3数据是从0开始
	return 0;
} 

//获取MP3基本信息
//pname:MP3文件路径
//pctrl:MP3控制信息结构体 
//返回值:0,成功
//    其他,失败
uint8_t mp3_get_info(uint8_t *pname,__mp3ctrl* pctrl)
{
    HMP3Decoder decoder;
    MP3FrameInfo frame_info;
	MP3_FrameXing* fxing;
	MP3_FrameVBRI* fvbri;
	FIL*fmp3;
	uint8_t *buf;
	uint32_t br;
	uint8_t res = 0;
	int offset=0;
	uint32_t p;
	short samples_per_frame;	//一帧的采样个数
	uint32_t totframes;		    //总帧数
	
	fmp3 = malloc_bsc(sizeof(FIL)); 
	buf = malloc_bsc(5*1024);		//申请5K内存
	if(!fmp3 || !buf)
	{
		res = 1;
	}
	if(!res)
	{
		f_open(fmp3,(const char*)pname,FA_READ);//打开文件
		res = f_read(fmp3,(char*)buf,5*1024,&br);
		if(res) res = 2;
	}
	if(!res)//读取文件成功,开始解析ID3V2/ID3V1以及获取MP3信息
	{
		mp3_id3v2_decode(buf,br,pctrl);	//解析ID3V2数据
		f_lseek(fmp3, f_size(fmp3) - 128);//偏移到倒数128的位置
		f_read(fmp3,(char*)buf,128,&br);//读取128字节
		mp3_id3v1_decode(buf,pctrl);	//解析ID3V1数据  
		decoder = MP3InitDecoder(); 	//MP3解码申请内存
		if(!decoder) res = 3;
	}
	if(!res)
	{
		f_lseek(fmp3,pctrl->datastart);	//偏移到数据开始的地方
		f_read(fmp3,(char*)buf,5*1024,&br);	//读取5K字节mp3数据
		offset=MP3FindSyncWord(buf,br);	//查找帧同步信息
		if(offset>=0&&MP3GetNextFrameInfo(decoder,&frame_info,&buf[offset])==0)//找到帧同步信息了,且下一阵信息获取正常	
		{ 
			p=offset+4+32;
			fvbri=(MP3_FrameVBRI*)(buf+p);
			if(strncmp("VBRI",(char*)fvbri->id,4)==0)//存在VBRI帧(VBR格式)
			{
				if (frame_info.version==MPEG1)samples_per_frame=1152;//MPEG1,layer3每帧采样数等于1152
				else samples_per_frame=576;//MPEG2/MPEG2.5,layer3每帧采样数等于576 
				totframes=((uint32_t)fvbri->frames[0]<<24)|((uint32_t)fvbri->frames[1]<<16)|((uint16_t)fvbri->frames[2]<<8)|fvbri->frames[3];//得到总帧数
				pctrl->totsec=totframes*samples_per_frame/frame_info.samprate;//得到文件总长度
			}
			else	//不是VBRI帧,尝试是不是Xing帧(VBR格式)
			{  
				if (frame_info.version==MPEG1)	//MPEG1 
				{
					p=frame_info.nChans==2?32:17;
					samples_per_frame = 1152;	//MPEG1,layer3每帧采样数等于1152
				}
				else
				{
					p=frame_info.nChans==2?17:9;
					samples_per_frame=576;		//MPEG2/MPEG2.5,layer3每帧采样数等于576
				}
				p+=offset+4;
				fxing=(MP3_FrameXing*)(buf+p);
				if(strncmp("Xing",(char*)fxing->id,4)==0||strncmp("Info",(char*)fxing->id,4)==0)//是Xng帧
				{
					if(fxing->flags[3]&0X01)//存在总frame字段
					{
						totframes=((uint32_t)fxing->frames[0]<<24)|((uint32_t)fxing->frames[1]<<16)|((uint16_t)fxing->frames[2]<<8)|fxing->frames[3];//得到总帧数
						pctrl->totsec=totframes*samples_per_frame/frame_info.samprate;//得到文件总长度
					}
					else	//不存在总frames字段
					{
						pctrl->totsec = ((f_size(fmp3) * 8) / frame_info.bitrate); 
					} 
				}
				else 		//CBR格式,直接计算总播放时间
				{
					pctrl->totsec = ((f_size(fmp3) * 8) / frame_info.bitrate);
				}
			} 
			pctrl->bitrate=frame_info.bitrate;			//得到当前帧的码率
			mp3ctrl->samplerate=frame_info.samprate; 	//得到采样率. 
			if(frame_info.nChans==2)mp3ctrl->outsamples=frame_info.outputSamps; //输出PCM数据量大小 
			else mp3ctrl->outsamples=frame_info.outputSamps*2; //输出PCM数据量大小,对于单声道MP3,直接*2,补齐为双声道输出
		}
		else res=3;
		MP3FreeDecoder(decoder);//释放内存		
	}
	f_close(fmp3);
	free_bsc(fmp3);
	free_bsc(buf);	
	return res;	
}

//得到当前播放时间
//fx:文件指针
//mp3x:mp3播放控制器
void mp3_get_curtime(FIL*fx,__mp3ctrl *mp3x)
{
	uint32_t fpos=0;  	 
	if(fx->fptr>mp3x->datastart)
		fpos = (fx->fptr > mp3x->datastart) ? (fx->fptr - mp3x->datastart) : 0;//得到当前文件播放到的地方 
	mp3x->cursec = fpos * mp3x->totsec / (f_size(fx) - mp3x->datastart);	//当前播放到第多少秒了
}

//mp3文件快进快退函数
//pos:需要定位到的文件位置
//返回值:当前文件位置(即定位后的结果)
uint32_t mp3_file_seek(uint32_t pos)
{
    if(pos > f_size(music_ctrl.file))
    {
        pos = f_size(music_ctrl.file);
    }
    f_lseek(music_ctrl.file, pos);
    return f_tell(music_ctrl.file);
}

HMP3Decoder mp3decoder;
MP3FrameInfo mp3frameinfo;
uint8_t* mp3_buffer = NULL;//输入buffer  
uint8_t* mp3_readptr = NULL;//MP3解码读指针
int offset = 0;	//偏移量
int bytesleft = 0;//buffer还剩余的有效数据
uint8_t outofdata = 1;

uint8_t mp3_play_song_prepare(uint8_t* fname)
{ 
	uint8_t res = 0;
 	mp3ctrl=malloc_bsc(sizeof(__mp3ctrl)); 
	mp3_buffer=malloc_bsc(MP3_FILE_BUF_SZ); 	//申请解码buf大小
	music_ctrl.file=(FIL*)malloc_bsc(sizeof(FIL));
	music_ctrl.i2sbuf1=malloc_bsc(2304*2*sizeof(uint16_t));
	music_ctrl.i2sbuf2=malloc_bsc(2304*2*sizeof(uint16_t));
	music_ctrl.tbuf=malloc_bsc(2304*2*sizeof(uint16_t));
	
	if(!mp3ctrl||!mp3_buffer||!music_ctrl.file||!music_ctrl.i2sbuf1||!music_ctrl.i2sbuf2||!music_ctrl.tbuf)
	{
		free_bsc(mp3ctrl);
		free_bsc(mp3_buffer);
		free_bsc(music_ctrl.file);
		free_bsc(music_ctrl.i2sbuf1);
		free_bsc(music_ctrl.i2sbuf2);
		free_bsc(music_ctrl.tbuf); 
		res = 1;
	}
	if(res==0)
	{
		memset(music_ctrl.i2sbuf1,0,2304*2*sizeof(uint16_t));	//数据清零 
		memset(music_ctrl.i2sbuf2,0,2304*2*sizeof(uint16_t));	//数据清零 
		memset(mp3ctrl,0,sizeof(__mp3ctrl));//数据清零 
		res = mp3_get_info(fname,mp3ctrl);  
	}
	if(res==0)
	{ 
		I2S2_Init(I2S_Standard_Phillips,I2S_Mode_MasterTx,I2S_CPOL_Low,I2S_DataFormat_16bextended);
		//飞利浦标准,主机发送,时钟低电平有效,16位扩展帧长度
		I2S2_SampleRate_Set(mp3ctrl->samplerate);		//设置采样率 
		I2S2_TX_DMA_Init(music_ctrl.i2sbuf1,music_ctrl.i2sbuf2,mp3ctrl->outsamples);//配置TX DMA
		mp3decoder=MP3InitDecoder(); 					//MP3解码申请内存
		res = f_open(music_ctrl.file,(char*)fname,FA_READ);	//打开文件

        // [新增] 填充 music_info 结构体
        music_info.total_sec = mp3ctrl->totsec;    // 总秒数
        music_info.bitrate = mp3ctrl->bitrate;     // 比特率
        music_info.samplerate = mp3ctrl->samplerate; // 采样率
        music_info.bit_depth = 16;                 // MP3解码通常输出16位
        music_info.current_sec = 0;                // 当前秒数清零
	}
	if(!res && !mp3decoder)//打开文件成功
	{
		f_lseek(music_ctrl.file,mp3ctrl->datastart);	//跳过文件头中tag信息
	}
	if(res)
	{
		f_close(music_ctrl.file);
		free_bsc(music_ctrl.file); 
		music_ctrl.file = NULL;
	}
	return res;
}

void mp3_play_song_task(uint8_t* fname)
{
	uint8_t res = 0;
	uint32_t br = 0; 
	int err = 0;
	
	if (Music_Status == Song_Prepare) 
	{
		if(mp3_play_song_prepare(fname)) {Music_Status = Song_End;}
		else
		{
            Music_Status = Song_Playing;
			I2S_Play_Start();
        }
    }
	else if(Music_Status == Song_Playing)
	{
		xSemaphoreTake(xI2SSemaphore, portMAX_DELAY);//传输完成
		
		// 确定目标缓冲区
		uint16_t* target_buf;
		if(I2SdmaBuff == 0)
			target_buf = (uint16_t*)music_ctrl.i2sbuf1;
		else
			target_buf = (uint16_t*)music_ctrl.i2sbuf2;
		
		if(Music_Suspend_Flag) // 暂停状态，填充0
		{
			memset(target_buf, 0, 2304 * 2 * sizeof(uint16_t));
		}
		else // 正常播放状态
		{
			if(outofdata)
			{
				mp3_readptr = mp3_buffer;	//MP3读指针指向buffer
				offset = 0;		//偏移量为0
				bytesleft = 0;
				outofdata = 0;
				res=f_read(music_ctrl.file,mp3_buffer,MP3_FILE_BUF_SZ,&br);//一次读取MP3_FILE_BUF_SZ字节
				if(res)//读数据出错了
				{
					Music_Status = Song_End;
				}
				if(br == 0)		//读数为0,说明解码完成了.
				{
					Music_Status = Song_End;
				}
				bytesleft += br;//buffer里面有多少有效MP3数据
				err = 0;
			}
			
			if(Music_Status == Song_Playing) // 检查状态是否改变
			{
				offset = MP3FindSyncWord(mp3_readptr,bytesleft);//在readptr位置,开始查找同步字符
				if(offset<0)	//没有找到同步字符,跳出帧解码循环
				{ 
					outofdata = 1;
				}
				else	        //找到同步字符了
				{
					mp3_readptr += offset;		//MP3读指针偏移到同步字符处.
					bytesleft -= offset;		//buffer里面的有效数据个数,必须减去偏移量
					err = MP3Decode(mp3decoder,&mp3_readptr,&bytesleft,(short*)music_ctrl.tbuf,0);//解码一帧MP3数据
					if(err!=0) outofdata = 1;
					else
					{
						MP3GetLastFrameInfo(mp3decoder,&mp3frameinfo);	//得到刚刚解码的MP3帧信息
						if(mp3ctrl->bitrate!=mp3frameinfo.bitrate)		//更新码率
						{
							mp3ctrl->bitrate = mp3frameinfo.bitrate; 
						}
						mp3_fill_buffer((uint16_t*)music_ctrl.tbuf,mp3frameinfo.outputSamps,mp3frameinfo.nChans);//填充pcm数据
					}
					
					if(bytesleft < MAINBUF_SIZE*2)//当数组内容小于2倍MAINBUF_SIZE的时候,必须补充新的数据进来.
					{
						memmove(mp3_buffer,mp3_readptr,bytesleft);//移动readptr所指向的数据到buffer里面,数据量大小为:bytesleft
						f_read(music_ctrl.file,mp3_buffer+bytesleft,MP3_FILE_BUF_SZ-bytesleft,&br);//补充余下的数据
						if(br<MP3_FILE_BUF_SZ-bytesleft)
						{
							memset(mp3_buffer+bytesleft+br,0,MP3_FILE_BUF_SZ-bytesleft-br); 
						}
						bytesleft = MP3_FILE_BUF_SZ;  
						mp3_readptr=mp3_buffer; 
					}

                    // [新增] 更新全局播放时间
                    mp3_get_curtime(music_ctrl.file, mp3ctrl);
                    music_info.current_sec = mp3ctrl->cursec;
				}
			}
		}
		Extract_FFT((uint8_t*)target_buf);
	}
	else //请求结束播放/播放完成
	{
		I2S_Play_Stop();
        if (mp3decoder) {
            MP3FreeDecoder(mp3decoder);
            mp3decoder = NULL;
        }

		if (music_ctrl.file) {
            f_close(music_ctrl.file);
            free_bsc(music_ctrl.file);
            music_ctrl.file = NULL;
        }

		if (mp3ctrl) { free_bsc(mp3ctrl); mp3ctrl = NULL; }
		if (mp3_buffer) { free_bsc(mp3_buffer); mp3_buffer = NULL; }
		
		if (music_ctrl.i2sbuf1) { free_bsc(music_ctrl.i2sbuf1); music_ctrl.i2sbuf1 = NULL; }
		if (music_ctrl.i2sbuf2) { free_bsc(music_ctrl.i2sbuf2); music_ctrl.i2sbuf2 = NULL; }
		if (music_ctrl.tbuf) { free_bsc(music_ctrl.tbuf); music_ctrl.tbuf = NULL; }
		
		mp3_buffer = NULL;
		mp3_readptr = NULL;
		bytesleft = 0;
		offset = 0;
		outofdata = 1;
		
		if(Music_Status == Song_Error) Music_Status = Music_Exit;
		if(Music_Status == Song_End) 
		{
			if(kv_music_switch_method == Play_In_Order) play_next_song();
			if(kv_music_switch_method == Play_Randomly) play_random_song();
			if(kv_music_switch_method == Play_Repeatly) play_same_song();
			Music_Status = Song_Prepare;
		}
		if(Music_Status == Song_Next)  
		{
			play_next_song();
			Music_Status = Song_Prepare;
		}
		if(Music_Status == Song_Previous)  
		{
			play_previous_song();
			Music_Status = Song_Prepare;
		}
		if(Music_Status == Song_File)
		{
			play_specific_song(chosen_file_path); 
			chosen_file_path_free();
			Music_Status = Song_Prepare;
		}
	}
}
