예제 #1
0
        private WavDataCharacteristics wd = null; // Class that encapsulates properties of wav data

        #endregion Fields

        #region Constructors

        private WavFile(BinaryReader br)
        {
            rf = new RIFFChunk(br);

            if (rf.validate() == false)
                throw new Exception("RIFF chunk invalid");

            ft = new FMTChunk(br);

            if (ft.validate() == false)
            {
             //   ft.printInfo();
                throw new Exception("FMT chunk invalid. WAVE file is not 8KHz 16bit Mono PCM WAVE file.");
            }

            dt = new DataChunk(br, ft);

            if (dt.validate() == false)
            {
                throw new Exception("Data Chunk invalid");
            }

            wd = dt.analyzePCMData();
        }
예제 #2
0
 public WavDataCharacteristics analyzeData()
 {
     if (wd == null)
     {
         wd = dt.analyzePCMData();
     }
     return wd;
 }
예제 #3
0
        /// <summary>
        /// Method to obtain WAV file characteristics
        /// </summary>
        public void display()
        {
            Console.WriteLine("WAVE File Characteristics");
            Console.WriteLine(ft.ToString());

            if (wd == null)
            {
                wd = dt.analyzePCMData();
            }
            wd.display();
        }
예제 #4
0
        /// <summary>
        /// Method to analyze the PCM data and provide information about max power, min power etc
        /// </summary>
        public WavDataCharacteristics analyzePCMData()
        {
            bool firstFrameFound = false;       // If first audio frame's index is already determined
            bool isFrameSilence = false;
            bool isFrameEmpty = false;

            long tempNumConsecutiveEmptyFrames = 0; // Temp variable for finding largest series of consecutive empty frames
            long numConsecutiveEmptyFrames = 0;

            long tempNumConsecutiveSilenceFrames = 0; // Temp variable for finding largest series of consecutive silence frames
            long numConsecutiveSilenceFrames = 0;

            uint nSamplesPerFrame;
            uint nNumFrames;
            uint nFrameCount;
            short currentSample;                // Current WAVE data sample

            uint nSamplesPerSec = ftChunk.SampleRate;
            uint nRawSampleCount = chunkSize / (ftChunk.BitsPerSample / 8);

            // compute number of samples per frame and number of frames
            nSamplesPerFrame = nFrameLengthMS * nSamplesPerSec / 1000;
            nNumFrames = (nRawSampleCount - 1) / nSamplesPerFrame;

            //Console.WriteLine("Num Samples Per Sec = " + nSamplesPerSec);
            //Console.WriteLine("Bits per Sample = " + ftChunk.BitsPerSample);
            //Console.WriteLine("Num Samples Per Frame = " + nSamplesPerFrame);
            //Console.WriteLine("Num Frames = " + nNumFrames);
            //Console.WriteLine("Their Product = " + nSamplesPerFrame * nNumFrames);

            // Now we compute the number of bytes per frame
            numBytesPerFrame = ftChunk.BitsPerSample * nSamplesPerFrame / 8;
            //Console.WriteLine("Number of Bytes per Frame = " + numBytesPerFrame);

            // Now we will analyze the raw audio checking for saturation, determining the minsample
            // and maxsample, and compute the DC offset.
            int nNormalizeSampleCount = (int)(dblNormalizeContributionFactor * nRawSampleCount);
            for (int i = 0; i < nNormalizeSampleCount; i++)
            {
                currentSample = wavData[i];

                if ((currentSample == 32767) || (currentSample == -32768))
                {
                    nNumSaturatedFrames++;
                }
                if (currentSample > sMaxSample)
                {
                    sMaxSample = currentSample;
                }
                if (currentSample < sMinSample)
                {
                    sMinSample = currentSample;
                }
                dblDCOffset += currentSample;
            }

            if (nNormalizeSampleCount > 0)
            {
                dblDCOffset = dblDCOffset / nNormalizeSampleCount;
            }

            uint dataIdx;  // Index into WAVE data
            double dblMaxPower = -1000.0;
            double dblMinPower = 1000.0;
            uint nNumEmptyFrames = 0;
            uint nNumSilenceFrames = 0;
            double dblPower;
            short sSample = 0;

            for (uint nFrameIndex = 0; nFrameIndex < nNumFrames; nFrameIndex++)
            {
                dataIdx = nFrameIndex * nSamplesPerFrame;
                dblPower = 0.0;

                isFrameEmpty = false;
                isFrameSilence = false;

                for (int nSampleIndex = 0; nSampleIndex < nSamplesPerFrame; nSampleIndex++)
                {
                    //try
                    //{
                    //    sSample = Convert.ToInt16(wavData[dataIdx + nSampleIndex + 1] - wavData[dataIdx + nSampleIndex]);
                    //}
                    //catch (Exception e)
                    //{
                    //    Console.WriteLine(e.Message + " " + e.StackTrace);
                    //    Console.WriteLine(wavData[dataIdx + nSampleIndex + 1]);
                    //    Console.WriteLine(wavData[dataIdx + nSampleIndex]);
                    //}

                    //dblPower += sSample * sSample;

                    // If the transition between frames is very much abrupt, the difference could be more than 32767, the limit
                    // of Int16. Thus, we don't compute actual difference, instead we just use 32767.
                    if (wavData[dataIdx + nSampleIndex + 1] - wavData[dataIdx + nSampleIndex] <= 32767 && (wavData[dataIdx + nSampleIndex + 1] - wavData[dataIdx + nSampleIndex] >= -32768))
                    {
                        dblPower += Math.Pow(wavData[dataIdx + nSampleIndex + 1] - wavData[dataIdx + nSampleIndex], 2.0);
                    }
                    else
                    {
                        dblPower += Math.Pow(32767, 2.0);
                    }
                }

                if (dblPower == 0.0)
                {
                    ++nNumEmptyFrames;
                    isFrameEmpty = true;
                }
                else
                {
                    if ((dblPower / nSamplesPerFrame) <= dblNoiseFloor)
                    {
                        ++nNumSilenceFrames;
                        isFrameSilence = true;
                    }
                    dblPower = 10.0 * Math.Log10(dblPower / nSamplesPerFrame);
                    if (dblPower > dblMaxPower)
                    {
                        dblMaxPower = dblPower;
                    }
                    if (dblPower < dblMinPower)
                    {
                        dblMinPower = dblPower;
                    }
                }

                if (isFrameSilence == false && isFrameEmpty == false)
                {
                    avgPower += dblPower;
                    numFramesAvg++;

                    // Keep modifying the index of the last audio frame until we detect it at the end of the audio
                    lastAudioFrameIdx = nFrameIndex;

                    // If this was the first audio-frame, we want to keep track of it
                    if (firstFrameFound == false)
                    {
                        firstAudioFrameIdx = nFrameIndex;
                        firstFrameFound = true;
                    }
                }

                #region Code to detect the longest sequence of continuous empty frames
                // If an empty frame has been found after the audio frame, increment numConsecutiveEmptyFrames
                if (isFrameEmpty == true && firstFrameFound == true)
                {
                    tempNumConsecutiveEmptyFrames++;
                }
                else
                if (isFrameEmpty == false)
                {
                    if (tempNumConsecutiveEmptyFrames > numConsecutiveEmptyFrames)
                    {
                        numConsecutiveEmptyFrames = tempNumConsecutiveEmptyFrames;
                    }
                    tempNumConsecutiveEmptyFrames = 0;
                }
                #endregion

                #region Code to detect the longest sequence of continous silence frames
                if (isFrameSilence == true && firstFrameFound == true)
                {
                    tempNumConsecutiveSilenceFrames++;
                }
                else
                if(isFrameSilence == false)
                {
                    if (tempNumConsecutiveSilenceFrames > numConsecutiveSilenceFrames)
                    {
                        numConsecutiveSilenceFrames = tempNumConsecutiveSilenceFrames;
                    }
                    tempNumConsecutiveSilenceFrames = 0;
                }
                #endregion
            }

            if (tempNumConsecutiveSilenceFrames > numConsecutiveSilenceFrames)
                numConsecutiveSilenceFrames = tempNumConsecutiveSilenceFrames;

            if (tempNumConsecutiveEmptyFrames > numConsecutiveEmptyFrames)
                numConsecutiveEmptyFrames = tempNumConsecutiveEmptyFrames;

               cntTotalFrames = nNumFrames;

               // Calculate the average power for the audio file
               avgPower = avgPower / numFramesAvg * 1.0;

               WavDataCharacteristics wd = new WavDataCharacteristics(nNumFrames, nNumSaturatedFrames, nNumEmptyFrames, nNumSilenceFrames, dblMaxPower, dblMinPower, sMaxSample, sMinSample, dblDCOffset);
               wd.AveragePower = avgPower;
               wd.NumFramesForAvgPower = numFramesAvg;
               wd.NumConsecutiveEmptyFrames = numConsecutiveEmptyFrames;
               wd.NumConsecutiveSilenceFrames = numConsecutiveSilenceFrames;

               wd.EmptyAudioDuration = numConsecutiveEmptyFrames * frameDuration;

               //Console.WriteLine("Average Power = {0} over {1} frames ",avgPower, numFramesAvg);
               //Console.WriteLine("First Audio frame index = " + firstAudioFrameIdx);
               //Console.WriteLine("Last Audio frame index = " + lastAudioFrameIdx);
               //Console.WriteLine("Largest Number of consecutive empty frames inside Audio = " + numConsecutiveEmptyFrames);
               //Console.WriteLine("Duration for empty audio = " + numConsecutiveEmptyFrames * nFrameLengthMS / 1000.0 + " sec");
               return wd;
        }