예제 #1
0
        /*Documentation
         * Method:  read
         * Author:  Josh Weese
         * Purpose: Reads and processes audio capture memory stream
         * Parameters:
         * Returns:
         * Notes:   #reads audio capture memory stream
         *          #converts stream into usable data
         *          #saves data to txt file if option is checked
         *          #chunks data, converts it to complex numbers, runs FFT, and determines pitch and frequency
         * ChangeLog:   Version 1.0...5/3/2011--Documented
         */
        public void read()
        {
            //make sure data reached the fft lenght thresh hold
            if (audioSink.AudioData.Length >= Constants.fftLength)
            {
                //read the entire memory stream
                audioSink.AudioData.Seek(seekPosition, SeekOrigin.Begin);
                byte[] data = new byte[audioSink.AudioData.Length];
                int chunkSize = 4096;
                int numBytesToRead = (int)audioSink.AudioData.Length;
                int numBytesRead = 0;

                while (numBytesToRead > 0)
                {
                    if (chunkSize + numBytesRead > data.Length)
                    {
                        chunkSize = data.Length - numBytesRead;
                    }
                    int n = audioSink.AudioData.Read(data, numBytesRead, chunkSize);
                    if (n == 0)
                    {
                        break;
                    }
                    numBytesRead += n;
                    numBytesToRead -= n;
                }
                //kill the buffer once read
                audioSink.AudioData.Flush();
                audioSink.AudioData.Dispose();
                //re-initialize
                audioSink.AudioData = new MemoryStream();

                if (saveFile)
                {
                    save(data);
                }
                //length of data
                int length;

                Int16[] int16Data;

                int y = 0;
                int z = 0;

                //convert raw data to useable numbers
                if (audioSink.AudioFormat.BitsPerSample == 16)
                {
                    length = data.Length / 2;
                    int16Data = new Int16[length];
                    if (BitConverter.IsLittleEndian)
                    {
                        Array.Reverse(data);
                    }

                    for (int i = 0; i < length; i += 2)
                    {
                        if (!(i > data.Length))
                        {
                            int16Data[z] = BitConverter.ToInt16(data, i);
                        }
                        else
                        {
                            int16Data[z] = 0;
                        }

                        z++;
                    }
                }
                else
                {
                    length = data.Length;
                    int16Data = new Int16[length];
                    for (int i = 0; i < length; i++)
                    {
                        int16Data[i] = data[i];
                    }
                }

                if (saveFile)
                {
                    save(int16Data);
                }

                z = 0;

                //chunk audio data to feed to FFT and calculate freqency
                while (true)
                {
                    //chunk
                    int max;
                    if (length > Constants.fftLength)
                    {
                        max = Constants.fftLength;
                    }
                    else
                    {
                        if (IsPowerOfTwo((ulong)length))
                        {
                            max = length;
                        }
                        else
                        {
                            break;
                        }
                    }
                    //convert to complex numbers
                    ComplexNumber[] complexData1 = new ComplexNumber[max];
                    y = 0;
                    while (y < max)
                    {
                        complexData1[y] = new ComplexNumber(int16Data[z] / Constants.downsample);
                        y++;
                        z++;
                    }
                    //run fft
                    ComplexNumber[] fft1 = ft.FFT(complexData1, FourierTransform.Direction.Forward);

                    if (saveFile)
                    {
                        save(fft1);
                    }

                    //retrieve pitch
                    pitch = frequency.getPitch(fundFreq.fundamentalFreq, pitchList);
                    //frequency
                    fundFreq.fundamentalFreq = frequency.calcFundamentalFreq(fft1, audioSink.AudioFormat.SamplesPerSecond);
                    //cents
                    fundFreq.cents = frequency.calculateCents(fundFreq.fundamentalFreq, pitch.fundamentalFreq);
                    //actual note
                    fundFreq.note = pitch.note;
                    //accidental
                    fundFreq.accidental = pitch.accidental;

                    if ((length -= max) == 0)
                    {
                        break;
                    }
                }
            }
        }
예제 #2
0
        /*Documentation
         * Method:  manualFrequency
         * Author:  Josh Weese
         * Purpose: Calculates the freqeuncy based on user input
         * Parameters:
         * Returns:
         * Notes:
         *          #This method is ment for accuracy testing
         *          #creates a sine wave based on the input frequency and sample count
         *          #converts to complex numbers
         *          #runs fft and calculates pitch
         * ChangeLog:   Version 1.0...5/3/2011--Documented
         */
        private void manualFrequency(double freq, int sampleCount, int sampleRate)
        {
            //create sine wave
            double increment = (double)(2 * Math.PI) * freq / sampleRate;
            double angle = 0;
            double[] samples = new double[sampleCount];

            for (int i = 0; i < samples.Length; i++)
            {
                samples[i] = ((double)Math.Sin(angle));
                angle += increment;
            }

            if ((bool)saveCheck.IsChecked)
            {
                save(samples);
            }

            //convert to complex numbers
            ComplexNumber[] complexData1 = new ComplexNumber[sampleCount];
            int y = 0;
            while (y < sampleCount)
            {
                complexData1[y] = new ComplexNumber(samples[y]);
                y++;
            }

            //run fft
            ComplexNumber[] fft1 = ft.FFT(complexData1, FourierTransform.Direction.Forward);
            if ((bool)saveCheck.IsChecked)
            {
                save(fft1);
            }

            //frequency
            fundFreq.fundamentalFreq = frequency.calcFundamentalFreq(fft1, sampleRate);
            //get pitch
            pitch = frequency.getPitch(fundFreq.fundamentalFreq, pitchList);

            //cents
            fundFreq.cents = frequency.calculateCents(fundFreq.fundamentalFreq, pitch.fundamentalFreq);
            //actual note
            fundFreq.note = pitch.note;
            //accidental
            fundFreq.accidental = pitch.accidental;
        }
예제 #3
0
 /*Documentation
  * Method:  loadPitches
  * Author:  Josh Weese
  * Purpose: Calculates all pitches (sharps and fundamental) from concert pitch
  * Parameters:  #double concertAfreq...concert pitch to base notes from
  *              #List<Pitch> pitchList...pitch list to store in
  * Returns: List<Pitch> pitchList
  * Notes:  #B and E have no sharp note
  * ChangeLog:   Version 1.0...5/3/2011--Documented
  */
 public List<Pitch> loadPitches(double concertAfreq, List<Pitch> pitchList)
 {
     PitchConstants pConstants = new PitchConstants();
     pitchList = new List<Pitch>();
     int x = 3;
     int z = 0;
     bool y = true;
     for (int i = -33; i < 27; i++)
     {
         Pitch pitch = new Pitch();
         //frequency
         pitch.fundamentalFreq = concertAfreq * (Math.Pow(2.0, (i / 12.0)));
         //accidentals
         if (y)
         {
             switch (z)
             {
                 case 0:
                     pitch.accidental = pConstants.natural;
                     z++;
                     break;
                 case 1:
                     pitch.accidental = pConstants.sharp;
                     z = 0;
                     break;
                 default:
                     break;
             }
         }
         else
         {
             pitch.accidental = pConstants.natural;
         }
         //note
         switch (x)
         {
             case 1:
                 pitch.note = pConstants.A;
                 y = true;
                 break;
             case 2:
                 pitch.note = pConstants.B;
                 y = false;
                 break;
             case 3:
                 pitch.note = pConstants.C;
                 y = true;
                 break;
             case 4:
                 pitch.note = pConstants.D;
                 y = true;
                 break;
             case 5:
                 pitch.note = pConstants.E;
                 y = false;
                 break;
             case 6:
                 pitch.note = pConstants.F;
                 y = true;
                 break;
             case 7:
                 pitch.note = pConstants.G;
                 y = true;
                 break;
             default:
                 x = 1;
                 break;
         }
         if (pitch.accidental == pConstants.sharp || !y)
         {
             x++;
             if (x == 8)
             {
                 x = 1;
             }
         }
         pitchList.Add(pitch);
     }
     return pitchList;
 }