#include "soundfielddescription.h"

//template <typename Enumeration> auto as_integer(Enumeration const value)->typename std::underlying_type<SamplingRate>::type
//{
//	return static_cast<typename std::underlying_type<Enumeration>::type(value);
//}


soundfielddescription::soundfielddescription()
{

    char text[] = R"(
		{
			"$schema": "http://json-schema.org/draft-07/schema#",
			"title": "Microphone Array Geometry",
			"MicrophoneArrayType": 0,
			"MicrophoneArrayScat": 0,
			"MicrophoneArrayFilterURI": "filter.file",
			"SamplingRate": 4,
			"SampleType": 2,
			"BlockSize": 5,
			"NumberofMicrophones": 32,
			"MicrophoneList" : [
					{"xCoord" :  0.93358,"yCoord" : 0.0,"zCoord" : 0.35836,"directivity" : 0.0,"micxLookCoord" : 0.93358,"micyLookCoord" : 0.0,"miczLookCoord" : 0.35836},
					{"xCoord" :  0.84804,"yCoord" : 0.52991,"zCoord" : 0.0,"directivity" : 0.0,"micxLookCoord" : 0.84804,"micyLookCoord" : 0.52991,"miczLookCoord" : 0.0},
					{"xCoord" :  0.93358,"yCoord" : 0.0,"zCoord" : -0.35836,"directivity" : 0.0,"micxLookCoord" : 0.93358,"micyLookCoord" : 0.0,"miczLookCoord" : -0.35836},
					{"xCoord" :  0.84804,"yCoord" : -0.52991,"zCoord" : 0.0,"directivity" : 0.0,"micxLookCoord" : 0.84804,"micyLookCoord" : -0.52991,"miczLookCoord" : 0.0},
					{"xCoord" :  0.52991,"yCoord" : 0.0,"zCoord" : 0.84804,"directivity" : 0.0,"micxLookCoord" : 0.52991,"micyLookCoord" : 0.0,"miczLookCoord" : 0.84804},
					{"xCoord" :  0.57922,"yCoord" : 0.57922,"zCoord" : 0.57357,"directivity" : 0.0,"micxLookCoord" : 0.57922,"micyLookCoord" : 0.57922,"miczLookCoord" : 0.57357},
					{"xCoord" :  0.35836,"yCoord" : 0.93358,"zCoord" : 0.0,"directivity" : 0.0,"micxLookCoord" : 0.35836,"micyLookCoord" : 0.93358,"miczLookCoord" : 0.0},
					{"xCoord" :  0.57922,"yCoord" : 0.57922,"zCoord" : -0.57357,"directivity" : 0.0,"micxLookCoord" : 0.57922,"micyLookCoord" : 0.57922,"miczLookCoord" : -0.57357},
					{"xCoord" :  0.52991,"yCoord" : 0.0,"zCoord" : -0.84804,"directivity" : 0.0,"micxLookCoord" : 0.52991,"micyLookCoord" : 0.0,"miczLookCoord" : -0.84804},
					{"xCoord" :  0.57922,"yCoord" : -0.57922,"zCoord" : -0.57357,"directivity" : 0.0,"micxLookCoord" : 0.57922,"micyLookCoord" : -0.57922,"miczLookCoord" : -0.57357},
					{"xCoord" :  0.35836,"yCoord" : -0.93358,"zCoord" : 0.0,"directivity" : 0.0,"micxLookCoord" : 0.35836,"micyLookCoord" : -0.93358,"miczLookCoord" : 0.0},
					{"xCoord" :  0.57922,"yCoord" : -0.57922,"zCoord" : 0.57357,"directivity" : 0.0,"micxLookCoord" : 0.57922,"micyLookCoord" : -0.57922,"miczLookCoord" : 0.57357},
					{"xCoord" :  -0.00625,"yCoord" : 0.35831,"zCoord" : 0.93358,"directivity" : 0.0,"micxLookCoord" : -0.00625,"micyLookCoord" : 0.35831,"miczLookCoord" : 0.93358},
					{"xCoord" :  0.0,"yCoord" : 0.84804,"zCoord" : 0.52991,"directivity" : 0.0,"micxLookCoord" : 0.0,"micyLookCoord" : 0.84804,"miczLookCoord" : 0.52991},
					{"xCoord" :  0.0,"yCoord" : 0.85716,"zCoord" : -0.51503,"directivity" : 0.0,"micxLookCoord" : 0.0,"micyLookCoord" :  0.85716,"miczLookCoord" : -0.51503},
					{"xCoord" :  0.006254,"yCoord" : 0.35831,"zCoord" : -0.93358,"directivity" : 0.0,"micxLookCoord" : 0.006254,"micyLookCoord" : 0.35831,"miczLookCoord" : -0.93358},
					{"xCoord" :  -0.93358,"yCoord" : 0.0,"zCoord" : 0.35836,"directivity" : 0.0,"micxLookCoord" : -0.93358,"micyLookCoord" : 0.0,"miczLookCoord" : 0.35836},
					{"xCoord" :  -0.84804,"yCoord" : -0.52991,"zCoord" : 0.0,"directivity" : 0.0,"micxLookCoord" : -0.84804,"micyLookCoord" : -0.52991,"miczLookCoord" : 0.0},
					{"xCoord" :  -0.93358,"yCoord" : 0.0,"zCoord" : -0.35836,"directivity" : 0.0,"micxLookCoord" : -0.93358,"micyLookCoord" : 0.0,"miczLookCoord" : -0.35836},
					{"xCoord" :  -0.84804,"yCoord" : 0.52991,"zCoord" : 0.0,"directivity" : 0.0,"micxLookCoord" : -0.84804,"micyLookCoord" : 0.52991,"miczLookCoord" : 0.0},
					{"xCoord" :  -0.52991,"yCoord" : 0.0,"zCoord" : 0.84804,"directivity" : 0.0,"micxLookCoord" : -0.52991,"micyLookCoord" : 0.0,"miczLookCoord" : 0.84804},
					{"xCoord" :  -0.57922,"yCoord" : -0.57922,"zCoord" : 0.57357,"directivity" : 0.0,"micxLookCoord" : -0.57922,"micyLookCoord" : -0.57922,"miczLookCoord" : 0.57357},
					{"xCoord" :  -0.35836,"yCoord" : -0.93358,"zCoord" : 0.0,"directivity" : 0.0,"micxLookCoord" : -0.35836,"micyLookCoord" : -0.93358,"miczLookCoord" : 0.0},
					{"xCoord" :  -0.57922,"yCoord" : -0.57922,"zCoord" : -0.57357,"directivity" : 0.0,"micxLookCoord" : -0.57922,"micyLookCoord" : -0.57922,"miczLookCoord" : -0.57357},
					{"xCoord" :  -0.52991,"yCoord" : 0.0,"zCoord" : -0.84804,"directivity" : 0.0,"micxLookCoord" : -0.52991,"micyLookCoord" : 0.0,"miczLookCoord" : -0.84804},
					{"xCoord" :  -0.57922,"yCoord" : 0.57922,"zCoord" : -0.57357,"directivity" : 0.0,"micxLookCoord" : -0.57922,"micyLookCoord" : 0.57922,"miczLookCoord" : -0.57357},
					{"xCoord" :  -0.35836,"yCoord" : 0.93358,"zCoord" : 0.0,"directivity" : 0.0,"micxLookCoord" : -0.35836,"micyLookCoord" : 0.93358,"miczLookCoord" : 0.0},
					{"xCoord" :  -0.57922,"yCoord" : 0.57922,"zCoord" : 0.57357,"directivity" : 0.0,"micxLookCoord" : -0.57922,"micyLookCoord" : 0.57922,"miczLookCoord" : 0.57357},
					{"xCoord" :  -0.00625,"yCoord" : -0.35831,"zCoord" : 0.93358,"directivity" : 0.0,"micxLookCoord" : -0.00625,"micyLookCoord" : -0.35831,"miczLookCoord" : 0.93358},
					{"xCoord" :  0.0,"yCoord" : -0.84804,"zCoord" : 0.52991,"directivity" : 0.0,"micxLookCoord" : 0.0,"micyLookCoord" : -0.84804,"miczLookCoord" : 0.52991},
					{"xCoord" :  0.0,"yCoord" : -0.84804,"zCoord" : -0.52991,"directivity" : 0.0,"micxLookCoord" : 0.0,"micyLookCoord" : -0.84804,"miczLookCoord" : -0.52991},
					{"xCoord" :  0.00625,"yCoord" : -0.35831,"zCoord" : -0.93358,"directivity" : 0.0,"micxLookCoord" : 0.00625,"micyLookCoord" : -0.35831,"miczLookCoord" : -0.93358}
				],
			 "MicrophoneArrayLookCoord" : {"xLookCoord" : 0.0, "yLookCoord" : 0.0, "zLookCoord" : 0.0}
		}
     )";

    // parsing and serializing JSON
    json j_complete = json::parse(text);

	nofmicrophones = j_complete["NumberofMicrophones"];
	array_type = (ArrayType)j_complete["MicrophoneArrayType"];
	array_scattering_type = (ArrayScattering)j_complete["MicrophoneArrayScat"];
	sampling_rate = samplingrates[static_cast<int>(j_complete["SamplingRate"])];
	sample_type = sampletypes[static_cast<int>(j_complete["SampleType"])];
	block_size = blocksizes[static_cast<int>(j_complete["BlockSize"])];

	microphone_array_params = micarray();

	for (int klm = 0; klm < nofmicrophones; klm++)
	{
		microphone_array_params.addnewmicrophone(j_complete["MicrophoneList"][klm]["xCoord"], j_complete["MicrophoneList"][klm]["yCoord"], j_complete["MicrophoneList"][klm]["zCoord"], j_complete["MicrophoneList"][klm]["micxLookCoord"], j_complete["MicrophoneList"][klm]["micyLookCoord"], j_complete["MicrophoneList"][klm]["miczLookCoord"], j_complete["MicrophoneArrayLookCoord"]["xLookCoord"], j_complete["MicrophoneArrayLookCoord"]["yLookCoord"], j_complete["MicrophoneArrayLookCoord"]["zLookCoord"]);
	}
	micanglestheta = microphone_array_params.getmicthetas();
	micanglesphi = microphone_array_params.getmicphis();

}
void* soundfielddescription::calcsphericalharmonics(double* pressure_real_in, double* pressure_imag_in, double* shd_realpart_out, double* shd_imagpart_out)
{
    int nof_sph = (int)(pow(SHDorder + 1, 2));
    for (int sn = 0; sn < nofsamples; sn++)
    {

        //malloc with zero valued spherical harmonics
        complex<double>* sph_harmonics = (complex<double>*)calloc(nof_sph, sizeof(complex<double>));

        //SHD computation according to the recording microphones
        for (int ml = 0; ml < nofmicrophones; ml++)
        {
            // get the microphone coordinates in theta/phi
            model::point<double, 2, cs::spherical<radian> > p1((micanglestheta.at(ml) * PI / 180), (micanglesphi.at(ml) * PI / 180));
            int counter = 0;
            // SHD calculations according to the spherical harmonics
            for (int sph_n = 0; sph_n <= SHDorder; sph_n++)
            {
                for (int sph_m = ((-1) * sph_n); sph_m <= sph_n; sph_m++)
                {
                    complex<double> calcharmonic_conj = conj((complex<double>)boost::math::spherical_harmonic(sph_n, sph_m, get<0>(p1), get<1>(p1)));
                    *(sph_harmonics + counter) += complex<double>(pressure_real_in[sn* nofmicrophones + ml], pressure_imag_in[sn * nofmicrophones + ml]) * calcharmonic_conj;
                    shd_realpart_out[sn * nof_sph + counter] = sph_harmonics[counter].real();
                    shd_imagpart_out[sn * nof_sph + counter] = sph_harmonics[counter].imag();
                    counter++;
                }
            }
        }
    }
    return 0;
}