#include <stdio.h>
#include <vector>
#include "htra_api.h"
#include <iostream>
#include <fstream>
#include <string>
#include <msgpack.h>
#include <filesystem>
#include <iomanip> 
#define _CRT_SECURE_NO_WARNINGS
using namespace std;

/* Byte order reversal (endianness conversion) */
// 64-bit unsigned integer byte order reversal
uint64_t swap_641(uint64_t value) {
    uint64_t result = 0;
    result |= (value & 0xff00000000000000) >> 56;
    result |= (value & 0x00ff000000000000) >> 40;
    result |= (value & 0x0000ff0000000000) >> 24;
    result |= (value & 0x000000ff00000000) >> 8;
    result |= (value & 0x00000000ff000000) << 8;
    result |= (value & 0x0000000000ff0000) << 24;
    result |= (value & 0x000000000000ff00) << 40;
    result |= (value & 0x00000000000000ff) << 56;
    return result;
}

// 32-bit unsigned integer byte order reversal
uint32_t swap_321(uint32_t val)
{

    return ((0xff000000 & val << 24) \
        | (0x00ff0000 & val << 8) \
        | (0x0000ff00 & val >> 8) \
        | (0x000000ff & val >> 24));
}

// 16-bit unsigned integer byte order reversal
uint16_t swap_161(uint16_t val)
{
    return ((val & 0x00ff) << 8) | ((val & 0xff00) >> 8);
}

// Byte order reversal for float type data
float convertEndianFloat1(float value) {
    union {
        float f;
        uint32_t i;
    } u;
    u.f = value;
    u.i = swap_321(u.i);
    return u.f;
}

// Byte order reversal for double type data
double convertEndianDouble1(double value) {
    union {
        double d;
        uint64_t l;
    } u;
    u.d = value;
    u.l = swap_641(u.l);
    return u.d;
}


// Read IQS mode configuration info and device information
int GetIQSWavFileInfo1(const char* FilePath, IQS_Profile_TypeDef* IQS_Profile, IQS_StreamInfo_TypeDef* IQS_StreamInfo, DeviceInfo_TypeDef* DeviceInfo, uint32_t* IQSize)
{
    int Status = 0;

    // Open the record file
    fstream File;
    string FilePath_s = FilePath;
    File.open(FilePath_s, ios::in | ios::binary);

    if (!File.is_open())
    {
        Status = -1009;
        return Status;
    }

    uint16_t StructSize = 0;
    uint32_t IQ_Size = 0;
    char InfoSize_2[2];
    char InfoSize_4[4];
    char InfoSize_8[8];

    /* Get IQS_Profile and IQS_StreamInfo */

    // Read the total byte length of IQS_Profile and IQS_StreamInfo structures
    File.seekp(108, ios::beg);
    File.read(InfoSize_2, sizeof(InfoSize_2));
    memcpy(&StructSize, InfoSize_2, sizeof(InfoSize_2));
    StructSize = swap_161(StructSize); // Convert the read byte length from big-endian to little-endian (host byte order)

    // Read the data of IQS_Profile and IQS_StreamInfo
    char* IQSProAndStream = new char[StructSize];
    File.read(IQSProAndStream, StructSize);

    // Use msgpack to unpack the read data according to the record file format description, parsing each parameter one by one. (The data in IQS_Profile and IQS_StreamInfo is recorded in little-endian format)
    msgpack_unpacked unpacked;
    msgpack_unpacked_init(&unpacked);
    size_t off = 0;

    msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off); // Parse the center frequency (unit: Hz) and assign the unpacked 64-bit double to IQS_Profile->CenterFreq_Hz
    IQS_Profile->CenterFreq_Hz = unpacked.data.via.f64;

    msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off); // Parse the reference level value (unit: dBm) and assign the unpacked 64-bit double to IQS_Profile->RefLevel_dBm
    IQS_Profile->RefLevel_dBm = unpacked.data.via.f64;

    msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off); // Parse the decimation factor, convert the unpacked 64-bit unsigned integer to 32-bit unsigned integer, and assign to IQS_Profile->DecimateFactor
    IQS_Profile->DecimateFactor = static_cast<uint32_t>(unpacked.data.via.u64);

    msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off); // Same parsing method as above, refer to the "Record File Format Description" for detailed data type information
    IQS_Profile->RxPort = static_cast<RxPort_TypeDef>(unpacked.data.via.i64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->BusTimeout_ms = static_cast<uint32_t>(unpacked.data.via.u64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->TriggerSource = static_cast<IQS_TriggerSource_TypeDef>(unpacked.data.via.i64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->TriggerEdge = static_cast<TriggerEdge_TypeDef>(unpacked.data.via.i64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->TriggerMode = static_cast<TriggerMode_TypeDef>(unpacked.data.via.i64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->TriggerLength = unpacked.data.via.u64;

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->TriggerOutMode = static_cast<TriggerOutMode_TypeDef>(unpacked.data.via.i64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->TriggerOutPulsePolarity = static_cast<TriggerOutPulsePolarity_TypeDef>(unpacked.data.via.i64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->TriggerLevel_dBm = unpacked.data.via.f64;

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->TriggerLevel_SafeTime = unpacked.data.via.f64;

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->TriggerDelay = (TriggerOutMode_TypeDef)unpacked.data.via.f64;

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->PreTriggerTime = (TriggerOutPulsePolarity_TypeDef)unpacked.data.via.f64;

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->TriggerTimerSync = static_cast<TriggerTimerSync_TypeDef>(unpacked.data.via.i64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->TriggerTimer_Period = unpacked.data.via.f64;

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->EnableReTrigger = static_cast<uint8_t>(unpacked.data.via.u64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->ReTrigger_Period = unpacked.data.via.f64;

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->ReTrigger_Count = static_cast<uint16_t>(unpacked.data.via.u64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->DataFormat = static_cast<DataFormat_TypeDef>(unpacked.data.via.i64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->GainStrategy = static_cast<GainStrategy_TypeDef>(unpacked.data.via.i64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->Preamplifier = static_cast<PreamplifierState_TypeDef>(unpacked.data.via.i64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->AnalogIFBWGrade = static_cast<uint8_t>(unpacked.data.via.u64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->IFGainGrade = static_cast<uint8_t>(unpacked.data.via.u64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->EnableDebugMode = static_cast<uint8_t>(unpacked.data.via.u64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->ReferenceClockSource = static_cast<ReferenceClockSource_TypeDef>(unpacked.data.via.i64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->ReferenceClockFrequency = unpacked.data.via.f64;

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->EnableReferenceClockOut = static_cast<uint8_t>(unpacked.data.via.u64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->SystemClockSource = static_cast<SystemClockSource_TypeDef>(unpacked.data.via.i64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->ExternalSystemClockFrequency = unpacked.data.via.f64;

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->NativeIQSampleRate_SPS = unpacked.data.via.f64;

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->EnableIFAGC = static_cast<uint8_t>(unpacked.data.via.u64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->Atten = static_cast<int8_t>(unpacked.data.via.i64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->DCCancelerMode = static_cast<DCCancelerMode_TypeDef>(unpacked.data.via.i64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->QDCMode = static_cast<QDCMode_TypeDef>(unpacked.data.via.i64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->QDCIGain = static_cast<float>(unpacked.data.via.f64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->QDCQGain = static_cast<float>(unpacked.data.via.f64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->QDCPhaseComp = static_cast<float>(unpacked.data.via.f64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->DCCIOffset = static_cast<int8_t>(unpacked.data.via.i64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->DCCQOffset = static_cast<int8_t>(unpacked.data.via.i64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_Profile->LOOptimization = static_cast<LOOptimization_TypeDef>(unpacked.data.via.i64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_StreamInfo->Bandwidth = unpacked.data.via.f64;

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_StreamInfo->IQSampleRate = unpacked.data.via.f64;

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_StreamInfo->PacketCount = unpacked.data.via.u64;

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_StreamInfo->StreamSamples = unpacked.data.via.u64;

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_StreamInfo->StreamDataSize = unpacked.data.via.u64;

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_StreamInfo->PacketSamples = static_cast<uint32_t>(unpacked.data.via.u64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_StreamInfo->PacketDataSize = static_cast<uint32_t>(unpacked.data.via.u64);

	msgpack_unpack_next(&unpacked, IQSProAndStream, (size_t)StructSize, &off);
	IQS_StreamInfo->GainParameter = static_cast<uint32_t>(unpacked.data.via.u64);

	/*Get DeviceInfo*/
	File.read(InfoSize_2, sizeof(InfoSize_2)); //DeviceInfo structure byte length

	File.read(InfoSize_8, sizeof(InfoSize_8)); //Read device UID
	memcpy(&DeviceInfo->DeviceUID, InfoSize_8, sizeof(InfoSize_8));
	DeviceInfo->DeviceUID = swap_641(DeviceInfo->DeviceUID); //Big-endian to little-endian

	File.read(InfoSize_2, sizeof(InfoSize_2));       //Read device model
	memcpy(&DeviceInfo->Model, InfoSize_2, sizeof(InfoSize_2));
	DeviceInfo->Model = swap_161(DeviceInfo->Model); //Big-endian to little-endian

	File.read(InfoSize_2, sizeof(InfoSize_2));                           //Read device hardware version
	memcpy(&DeviceInfo->HardwareVersion, InfoSize_2, sizeof(InfoSize_2));
	DeviceInfo->HardwareVersion = swap_161(DeviceInfo->HardwareVersion); //Big-endian to little-endian

	File.read(InfoSize_4, sizeof(InfoSize_4));                 //Read device MCU firmware version
	memcpy(&DeviceInfo->MFWVersion, InfoSize_4, sizeof(InfoSize_4));
	DeviceInfo->MFWVersion = swap_321(DeviceInfo->MFWVersion); //Big-endian to little-endian

	File.read(InfoSize_4, sizeof(InfoSize_4));                 //Read device FPGA firmware version
	memcpy(&DeviceInfo->FFWVersion, InfoSize_4, sizeof(InfoSize_4));
	DeviceInfo->FFWVersion = swap_321(DeviceInfo->FFWVersion); //Big-endian to little-endian

	//Get the total length of IQ data
	File.seekp(25 * 1024 * 1024 + 404, ios::beg); //Move file pointer to the "data" format block length position
	File.read(InfoSize_4, sizeof(InfoSize_4));    //Read the format block length
	memcpy(&IQ_Size, InfoSize_4, sizeof(InfoSize_4));

	*IQSize = IQ_Size / 64968; //Get the total number of recorded packets (each packet has 64968 bytes)

	File.close();
	return Status;
}

//Read the interleaved IQ data stream in IQS mode, the scale factor from integer to absolute amplitude (in volts), and trigger-related information
int GetIQSWavFileData1(IQS_Profile_TypeDef* IQS_Profile, const char* FilePath, const uint32_t PacketNum, IQStream_TypeDef* IQStream, int16_t IQData[])
{
	int Status = 0;
	fstream File;
	string FilePath_s = FilePath;                 //Convert the file path to string type
	File.open(FilePath_s, ios::in | ios::binary); //Open the .wav file for reading in binary mode.

	if (!File.is_open())
	{
		Status = -1009;
		return Status;
	}

	// Define buffer for reading file data
	char InfoSize_1[1];
	char InfoSize_2[2];
	char InfoSize_4[4];
	char InfoSize_8[8];

	/*Get IQS_TriggerInfo*/
	//Jump to the IQS_TriggerInfo structure byte length position for each packet, locate the current structure position based on PacketNum and structure size
	File.seekp(408 + PacketNum * (405), ios::beg); // (Each packet is 405 bytes)
	File.read(InfoSize_2, sizeof(InfoSize_2));     //IQS_TriggerInfo Struct Size

	File.read(InfoSize_8, sizeof(InfoSize_8));
	memcpy(&IQStream->IQS_TriggerInfo.SysTimerCountOfFirstDataPoint, InfoSize_8, sizeof(InfoSize_8));                                         //Read the system timestamp of the first data point in the current packet
	IQStream->IQS_TriggerInfo.SysTimerCountOfFirstDataPoint = convertEndianDouble1(IQStream->IQS_TriggerInfo.SysTimerCountOfFirstDataPoint); //Big-endian to little-endian (the .wav file stores it in big-endian, if the host is little-endian, byte order conversion is needed)

	File.read(InfoSize_2, sizeof(InfoSize_2));
	memcpy(&IQStream->IQS_TriggerInfo.InPacketTriggeredDataSize, InfoSize_2, sizeof(InfoSize_2));                        //Read the number of valid triggered data bytes in the current packet
	IQStream->IQS_TriggerInfo.InPacketTriggeredDataSize = swap_161(IQStream->IQS_TriggerInfo.InPacketTriggeredDataSize); //Big-endian to little-endian

	File.read(InfoSize_2, sizeof(InfoSize_2));
	memcpy(&IQStream->IQS_TriggerInfo.InPacketTriggerEdges, InfoSize_2, sizeof(InfoSize_2));                   //Read the number of trigger edges contained in the current packet
	IQStream->IQS_TriggerInfo.InPacketTriggerEdges = swap_161(IQStream->IQS_TriggerInfo.InPacketTriggerEdges); //Big-endian to little-endian

	//The following parsing is similar. Refer to the "Record File Format Specification" for detailed byte order and data type information.
	for (int i = 0; i < 25; i++)
	{
		File.read(InfoSize_4, sizeof(InfoSize_4));
		memcpy(&IQStream->IQS_TriggerInfo.StartDataIndexOfTriggerEdges[i], InfoSize_4, sizeof(InfoSize_4));
	}
	for (int i = 0; i < 25; i++)
	{
		File.read(InfoSize_8, sizeof(InfoSize_8));
		memcpy(&IQStream->IQS_TriggerInfo.SysTimerCountOfEdges[i], InfoSize_8, sizeof(InfoSize_8));
	}
	for (int i = 0; i < 25; i++)
	{
		File.read(InfoSize_1, sizeof(InfoSize_1));
		memcpy(&IQStream->IQS_TriggerInfo.EdgeType[i], InfoSize_1, sizeof(InfoSize_1));
	}

	/*Get DeviceState*/
	File.read(InfoSize_2, sizeof(InfoSize_2)); //DeviceState struct size

	File.read(InfoSize_2, sizeof(InfoSize_2));
	memcpy(&IQStream->DeviceState.Temperature, InfoSize_2, sizeof(InfoSize_2));      //Read temperature information
	IQStream->DeviceState.Temperature = swap_161(IQStream->DeviceState.Temperature); //Big-endian to little-endian

	File.read(InfoSize_2, sizeof(InfoSize_2));
	memcpy(&IQStream->DeviceState.RFState, InfoSize_2, sizeof(InfoSize_2));  //Read RF state
	IQStream->DeviceState.RFState = swap_161(IQStream->DeviceState.RFState); //Big-endian to little-endian

	File.read(InfoSize_2, sizeof(InfoSize_2));
	memcpy(&IQStream->DeviceState.BBState, InfoSize_2, sizeof(InfoSize_2));  //Read BB (Baseband) state
	IQStream->DeviceState.BBState = swap_161(IQStream->DeviceState.BBState); //Big-endian to little-endian

	File.read(InfoSize_8, sizeof(InfoSize_8)); //The following parsing is similar to above
	memcpy(&IQStream->DeviceState.AbsoluteTimeStamp, InfoSize_8, sizeof(InfoSize_8));
	IQStream->DeviceState.AbsoluteTimeStamp = convertEndianDouble1(IQStream->DeviceState.AbsoluteTimeStamp);

	File.read(InfoSize_4, sizeof(InfoSize_4));
	memcpy(&IQStream->DeviceState.Latitude, InfoSize_4, sizeof(InfoSize_4));
	IQStream->DeviceState.Latitude = convertEndianFloat1(IQStream->DeviceState.Latitude);

	File.read(InfoSize_4, sizeof(InfoSize_4));
	memcpy(&IQStream->DeviceState.Longitude, InfoSize_4, sizeof(InfoSize_4));
	IQStream->DeviceState.Longitude = convertEndianFloat1(IQStream->DeviceState.Longitude);

	File.read(InfoSize_2, sizeof(InfoSize_2));
	memcpy(&IQStream->DeviceState.GainPattern, InfoSize_2, sizeof(InfoSize_2));
	IQStream->DeviceState.GainPattern = swap_161(IQStream->DeviceState.GainPattern);

	File.read(InfoSize_8, sizeof(InfoSize_8));
	memcpy(&IQStream->DeviceState.RFCFreq, InfoSize_8, sizeof(InfoSize_8));
	IQStream->DeviceState.RFCFreq = swap_641(IQStream->DeviceState.RFCFreq);

	File.read(InfoSize_4, sizeof(InfoSize_4));
	memcpy(&IQStream->DeviceState.ConvertPattern, InfoSize_4, sizeof(InfoSize_4));
	IQStream->DeviceState.ConvertPattern = swap_321(IQStream->DeviceState.ConvertPattern);

	File.read(InfoSize_4, sizeof(InfoSize_4));
	memcpy(&IQStream->DeviceState.NCOFTW, InfoSize_4, sizeof(InfoSize_4));
	IQStream->DeviceState.NCOFTW = swap_321(IQStream->DeviceState.NCOFTW);

	File.read(InfoSize_4, sizeof(InfoSize_4));
	memcpy(&IQStream->DeviceState.SampleRate, InfoSize_4, sizeof(InfoSize_4));
	IQStream->DeviceState.SampleRate = swap_321(IQStream->DeviceState.SampleRate);

	File.read(InfoSize_2, sizeof(InfoSize_2));
	memcpy(&IQStream->DeviceState.CPU_BCFlag, InfoSize_2, sizeof(InfoSize_2));
	IQStream->DeviceState.CPU_BCFlag = swap_161(IQStream->DeviceState.CPU_BCFlag);

	File.read(InfoSize_2, sizeof(InfoSize_2));
	memcpy(&IQStream->DeviceState.IFOverflow, InfoSize_2, sizeof(InfoSize_2));
	IQStream->DeviceState.IFOverflow = swap_161(IQStream->DeviceState.IFOverflow);

	File.read(InfoSize_2, sizeof(InfoSize_2));
	memcpy(&IQStream->DeviceState.DecimateFactor, InfoSize_2, sizeof(InfoSize_2));
	IQStream->DeviceState.DecimateFactor = swap_161(IQStream->DeviceState.DecimateFactor);

	File.read(InfoSize_2, sizeof(InfoSize_2));
	memcpy(&IQStream->DeviceState.OptionState, InfoSize_2, sizeof(InfoSize_2));
	IQStream->DeviceState.OptionState = swap_161(IQStream->DeviceState.OptionState);

	/*Get IQS_ScaleToV, MaxPower_dBm, MaxIndex*/
	File.read(InfoSize_4, sizeof(InfoSize_4));
	memcpy(&IQStream->IQS_ScaleToV, InfoSize_4, sizeof(InfoSize_4));
	IQStream->IQS_ScaleToV = convertEndianFloat1(IQStream->IQS_ScaleToV);

	File.read(InfoSize_4, sizeof(InfoSize_4));
	memcpy(&IQStream->MaxPower_dBm, InfoSize_4, sizeof(InfoSize_4));
	IQStream->MaxPower_dBm = convertEndianFloat1(IQStream->MaxPower_dBm);

	File.read(InfoSize_4, sizeof(InfoSize_4));
	memcpy(&IQStream->MaxIndex, InfoSize_4, sizeof(InfoSize_4));
	IQStream->MaxIndex = swap_321(IQStream->MaxIndex);

	//Get total length of IQ data
	File.seekp(25 * 1024 * 1024 + 404, ios::beg); //Move file pointer to the length field of the data block
	File.read(InfoSize_4, sizeof(InfoSize_4));    //Read total IQ data length

	int format = 0;

	//Determine IQ data format
	switch (IQS_Profile->DataFormat)
	{
	case  Complex32bit:
		format = 4;
		break;
	case Complex16bit:
		format = 2;
		break;
	case Complex8bit:
		format = 1;
		break;
	default:
		break;
	}

	//Get IQ data
	File.seekp(25 * 1024 * 1024 + 408 + PacketNum * 64968, ios::beg); //Move file pointer to the start of the specified PacketNum

	for (uint32_t i = 0; i < (64968 / format); i++)
	{
		File.read(InfoSize_2, sizeof(InfoSize_2));
		memcpy(&IQData[i], InfoSize_2, sizeof(InfoSize_2));
	}

	File.close();
	return Status;
}

//Get relevant information from wav file
int IQSMode_WavToCsv()
{
	int Status = 0;
	
	char path[] = "./data/0029_20250107_165029.part1.iq.wav"; //Please modify the record file name as needed, e.g., 0022_20241225_164858.part1.iq.wav

	IQStream_TypeDef IQStream;
	DeviceInfo_TypeDef DeviceInfo;
	IQS_Profile_TypeDef IQS_Profile;
	IQS_StreamInfo_TypeDef StreamInfo;
	uint32_t PacketCount = 0;

	string FilePath_last = "./data/"; // File saving path is ./data/

	//Check if the directory exists, if not, create it
	if (!(filesystem::exists(FilePath_last))) {
		//Attempt to create the directory and its parent directories
		filesystem::create_directories(FilePath_last);
		cout << "Data folder path: Htra_RecordingandPlayBack\\data" << endl;
		if (filesystem::create_directories(FilePath_last)) {
			cout << "Failed to create directory \"" << FilePath_last << "\"." << endl;
			return 0;
		}
	}

	Status = GetIQSWavFileInfo1(path, &IQS_Profile, &StreamInfo, &DeviceInfo, &PacketCount); //Get IQS structure information and DeviceInfo
	
	IQStream.IQS_Profile = IQS_Profile;
	IQStream.IQS_StreamInfo = StreamInfo;
	IQStream.DeviceInfo = DeviceInfo;

	vector<int16_t> IQ_Data(StreamInfo.PacketSamples * 2);          //Allocate memory to store one packet of data
	vector<int16_t> I_Data(StreamInfo.PacketSamples * PacketCount); //Allocate memory to store I channel data
	vector<int16_t> Q_Data(StreamInfo.PacketSamples * PacketCount); //Allocate memory to store Q channel data
	
	char FileName[255]; //Define a character array for the filename

	sprintf_s(FileName, "./data/IQSMode_Data.csv"); //Format filename as "IQSMode_Data.csv"

	ofstream File1; //Create an ofstream object to store parsed IQ data
	
	File1.open(FileName, ios::out); //Open the file in write mode

	File1 << "Device UID:," << std::hex << DeviceInfo.DeviceUID << "\n"; //First row of CSV file, device UID
	File1 << std::dec;                                                   //Restore default decimal output format
	File1 << "CenterFreq_Hz:," <<IQS_Profile.CenterFreq_Hz << "\n";      //Second row, center frequency
	File1 << "IQSampleRate:," << StreamInfo.IQSampleRate << "\n";        //Third row, sampling rate
	File1 << "DecimateFactor:," << IQS_Profile.DecimateFactor << "\n";   //Fourth row, decimation factor
	File1 << "I_Data,Q_Data\n";                                          //Fifth row, I and Q channel data

	for (uint32_t PacketNum = 0; PacketNum < PacketCount; PacketNum++) 
	{
		Status = GetIQSWavFileData1(&IQS_Profile, path, PacketNum, &IQStream, IQ_Data.data());  //Get data

		//if (PacketNum == 0)
		//{
		//	// Get the current position of the file write pointer
		//	streampos pos = File1.tellp();

		//	File1 << "IQS_ScaleToV:," << IQStream.IQS_ScaleToV << "\n";
		//}

		uint32_t Points = StreamInfo.PacketSamples;

		if (PacketNum == PacketCount - 1 && StreamInfo.StreamSamples % StreamInfo.PacketSamples != 0) {
			//The last packet may not be full (16242 points), only loop through the actual number of points
			Points = StreamInfo.StreamSamples % (uint64_t)StreamInfo.PacketSamples;
		}

		for (uint32_t i = 0; i < Points; i++) {
			Q_Data[i + StreamInfo.PacketSamples * PacketNum] = IQ_Data[i * 2];
			I_Data[i + StreamInfo.PacketSamples * PacketNum] = IQ_Data[i * 2 + 1];
			//Write CSV data separated by commas
			File1 << IQ_Data[i * 2 + 1] << "," << IQ_Data[i * 2] << "\n";
		}
	}

	//Close file stream, save and release resources
	File1.close();
	return 0;
}

