private static int GetNumSamples(WaveProps wave)
 {
     try
     {
         int totalSamples = wave.Subchunk2Size / wave.NumChannels / (wave.BitsPerSample / 8);
         return(totalSamples);
     }
     catch (DivideByZeroException e)
     {
         Console.WriteLine("Can't divide by zero! Re-encoded file?");
         return(0);
     }
     catch (Exception e)
     {
         Console.WriteLine("Problem calculating samples!");
         Console.WriteLine(e);
         return(0);
     }
 }
    //--------------------------------------------------------------------------

    private void ApplyNextWave()
    {
        bonusBombsSpawned = 0;
        waveStartTime     = Time.time;
        isRushing         = false;
        currentWaveIndex++;

        currentWave = waveProps[0];

        foreach (WaveProps wave in waveProps)
        {
            if (wave.waveIndex <= currentWaveIndex && wave.waveIndex > currentWave.waveIndex)
            {
                currentWave = wave;
            }
        }

        blockController.fallInterval = GetFallInterval();

        BroadcastMessage(TetrisController.HANDLE_RUSH_ENDED);
    }
    //**************************************************************************
    // Init

    private void InitWaveProps()
    {
        waveProps = new List <WaveProps>();
        WaveProps prop;

        prop = new WaveProps(20, 10, 0.11f, 0, 0);
        waveProps.Add(prop);

        prop = new WaveProps(20, 15, 0.09f, 0, 1);         // Points
        waveProps.Add(prop);

        prop = new WaveProps(20, 15, 0.12f, 0, 2);
        waveProps.Add(prop);

        prop = new WaveProps(20, 10, 0.08f, 0, 3);         // Shooter
        waveProps.Add(prop);

        prop = new WaveProps(5, 15, 0.08f, 0, 4);
        waveProps.Add(prop);

        prop = new WaveProps(10, 8, 0.10f, 0, 5);         // Bombs
        waveProps.Add(prop);

        prop = new WaveProps(30, 10, 0.07f, 0, 6);
        waveProps.Add(prop);

        prop = new WaveProps(20, 15, 0.12f, 1, 7);         // Quad Figure
        waveProps.Add(prop);

        prop = new WaveProps(20, 15, 0.10f, 1, 8);         // Bombs
        waveProps.Add(prop);

        prop = new WaveProps(20, 15, 0.1f, 0, 9);         // L figure
        waveProps.Add(prop);

        prop = new WaveProps(25, 4, 0.045f, 0, 10);         // FAST
        waveProps.Add(prop);

        prop = new WaveProps(35, 15, 0.09f, 0, 11);         // Z figure
        waveProps.Add(prop);

        prop = new WaveProps(30, 13, 0.07f, 0, 12);         // BOMBS
        waveProps.Add(prop);

        prop = new WaveProps(20, 35, 0.09f, 0, 13);         // Long
        waveProps.Add(prop);

        prop = new WaveProps(20, 15, 0.07f, 0, 14);
        waveProps.Add(prop);

        prop = new WaveProps(20, 20, 0.1f, 0, 16);         // Points
        waveProps.Add(prop);

        prop = new WaveProps(20, 15, 0.07f, 2, 17);
        waveProps.Add(prop);

        prop = new WaveProps(20, 20, 0.07f, 0, 20);         // Bombs
        waveProps.Add(prop);

        prop = new WaveProps(20, 10, 0.06f, 1, 21);
        waveProps.Add(prop);

        prop = new WaveProps(5, 5, 0.06f, 0, 23);         // Z figure
        waveProps.Add(prop);

        prop = new WaveProps(5, 5, 0.06f, 0, 24);         // L figure
        waveProps.Add(prop);

        prop = new WaveProps(5, 5, 0.06f, 0, 25);         // Quad figure
        waveProps.Add(prop);

        prop = new WaveProps(5, 17, 0.09f, 0, 26);         // Bombs
        waveProps.Add(prop);

        prop = new WaveProps(50, 20, 0.08f, 0, 27);
        waveProps.Add(prop);

        prop = new WaveProps(50, 15, 0.08f, 3, 28);
        waveProps.Add(prop);
    }
        private static WaveProps GetWaveProps(string filePath)
        {
            WaveProps props = new WaveProps();

            try
            {
                // read in wave file header info to props
                using (BinaryReader reader = new BinaryReader(File.OpenRead(filePath)))
                {
                    props.ChunkID       = Encoding.ASCII.GetString(reader.ReadBytes(4));
                    props.ChunkSize     = reader.ReadInt32();
                    props.Format        = Encoding.ASCII.GetString(reader.ReadBytes(4));
                    props.Subchunk1ID   = Encoding.ASCII.GetString(reader.ReadBytes(4));
                    props.Subchunk1Size = reader.ReadInt32();
                    props.AudioFormat   = reader.ReadInt16();
                    props.NumChannels   = reader.ReadInt16();
                    props.SampleRate    = reader.ReadInt32();
                    props.ByteRate      = reader.ReadInt32();
                    props.BlockAlign    = reader.ReadInt16();
                    props.BitsPerSample = reader.ReadInt16();

                    // handle if there are extra params
                    if (props.Subchunk1Size != 16)
                    {
                        props.ExtraParamsSize = reader.ReadInt16();
                        props.ExtraParams     = reader.ReadBytes(props.ExtraParamsSize);
                    }
                    else
                    {
                        props.ExtraParamsSize = 0;
                        props.ExtraParams     = null;
                    }

                    props.Subchunk2ID   = Encoding.ASCII.GetString(reader.ReadBytes(4));
                    props.Subchunk2Size = reader.ReadInt32();
                    props.DataOffset    = reader.BaseStream.Position;
                }

                if (displayInfo)
                {
                    Console.ForegroundColor = ConsoleColor.Cyan;
                    Console.WriteLine($"File: {filePath}");
                    Console.ResetColor();
                    Console.WriteLine($"RIFF: {props.ChunkID}");
                    Console.WriteLine($"ChunkSize: {props.ChunkSize}");
                    Console.WriteLine($"Format: {props.Format}");
                    Console.WriteLine($"Subchunk1ID: {props.Subchunk1ID}");
                    Console.WriteLine($"Subchunk1Size: {props.Subchunk1Size}");
                    Console.WriteLine($"AudioFormat: {props.AudioFormat}");
                    Console.WriteLine($"Channels: {props.NumChannels}");
                    Console.WriteLine($"Sample Rate: {props.SampleRate}");
                    Console.WriteLine($"Byte Rate: {props.ByteRate}");
                    Console.WriteLine($"Block Align: {props.BlockAlign}");
                    if (props.ExtraParamsSize > 0)
                    {
                        Console.WriteLine($"ExtraParamsSize: {props.ExtraParamsSize}");
                        Console.WriteLine($"ExtraParams: {string.Join(",", props.ExtraParams)}");
                        Console.WriteLine($"Samples per Block: {props.ExtraParams[0]}");
                    }
                    Console.WriteLine($"Bits Per Sample: {props.BitsPerSample}");
                    Console.WriteLine($"Subchunk2ID: {props.Subchunk2ID}");
                    Console.WriteLine($"Subchunk2Size: {props.Subchunk2Size}");
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Problem reading wave file!");
                Console.WriteLine(e);
            }

            return(props);
        }
        // encode wav to raw + txth
        private static bool EncodeWave(string inputFilePath, string outputFilePath, long startSample, long endSample)
        {
            // check if input file should be re-encoded
            bool waveRequiresEncoding = RequiresEncoding(inputFilePath, outputFilePath);

            // only update txth file if wave doesn't need to be encoded
            if (!waveRequiresEncoding)
            {
                Console.WriteLine("Updating txth file!");
                // store result of txth updated
                bool txthUpdated = txthHandler.UpdateTxthFile($"{outputFilePath}.txth", startSample, endSample);
                return(txthUpdated);
            }

            // file path to store temp encoded file (still has header)
            string tempFilePath = $@"{outputFilePath}.temp";

            ProcessStartInfo encodeInfo = new ProcessStartInfo
            {
                FileName  = encoderPath,
                Arguments = $@"""{inputFilePath}"" ""{tempFilePath}""",
            };

            // encode file given
            try
            {
                Process process = Process.Start(encodeInfo);
                process.WaitForExit();

                if (process.ExitCode != 0)
                {
                    Console.WriteLine($"Problem with AdpcmEncode! Exit code: {process.ExitCode}");
                    return(false);
                }
            }
            catch (Exception e)
            {
                // problem starting process, exit early
                Console.WriteLine("Problem running AdpcmEncode!");
                Console.WriteLine(e);
                return(false);
            }

            // get wave props of input file
            WaveProps inputWaveProps = GetWaveProps(inputFilePath);
            // get num samples from input wave
            int numSamples = GetNumSamples(inputWaveProps);

            if (numSamples <= 0)
            {
                Console.WriteLine("Could not determine number of samples from input wave!");
                return(false);
            }

            // get wave props of temp file
            WaveProps outputWaveProps = GetWaveProps(tempFilePath);

            // array to store data chunk bytes
            byte[] outDataChunk = new byte[outputWaveProps.Subchunk2Size];

            try
            {
                // read data chunk into array
                using (FileStream tempfile = File.OpenRead(tempFilePath))
                {
                    tempfile.Seek(outputWaveProps.DataOffset, SeekOrigin.Begin);
                    tempfile.Read(outDataChunk, 0, outDataChunk.Length);
                }
            }
            catch (Exception e)
            {
                // exit early if error reading data chunk
                Console.WriteLine($"Problem reading in data chunk of output!");
                Console.WriteLine(e);
                return(false);
            }

            // write txth file
            bool txthSuccess = txthHandler.WriteTxthFile($"{outputFilePath}.txth", outputWaveProps, numSamples, startSample, endSample);

            if (!txthSuccess)
            {
                return(false);
            }

            // write raw to file
            try
            {
                // write raw file
                File.WriteAllBytes($"{outputFilePath}", outDataChunk);
                // delete temp file
                File.Delete(tempFilePath);
            }
            catch (Exception e)
            {
                Console.WriteLine("Problem writing raw to file!");
                Console.WriteLine(e);
                return(false);
            }

            return(true);
        }