예제 #1
0
 public void TestShow(audio.PitchResult result)
 {
     lock (_result)
     {
         _result = result;
     }
     panel1.Invalidate();
 }
예제 #2
0
        public PitchResult Copy()
        {
            PitchResult result = new PitchResult(Length, SampleFrequency);
            result.Pitch = Pitch;
            result.Clarity = Clarity;

            Array.Copy(Signal, result.Signal, Signal.Length);
            Array.Copy(Frequency, result.Frequency, Frequency.Length);
            Array.Copy(Amplitude, result.Amplitude, Amplitude.Length);
            Array.Copy(Power, result.Power, Power.Length);
            Array.Copy(Time, result.Time, Time.Length);
            Array.Copy(Correlation, result.Correlation, Correlation.Length);
            Array.Copy(NSDF, result.NSDF, NSDF.Length);
            return result;
        }
예제 #3
0
        public PitchResult Copy()
        {
            PitchResult result = new PitchResult(Length, SampleFrequency);

            result.Pitch   = Pitch;
            result.Clarity = Clarity;

            Array.Copy(Signal, result.Signal, Signal.Length);
            Array.Copy(Frequency, result.Frequency, Frequency.Length);
            Array.Copy(Amplitude, result.Amplitude, Amplitude.Length);
            Array.Copy(Power, result.Power, Power.Length);
            Array.Copy(Time, result.Time, Time.Length);
            Array.Copy(Correlation, result.Correlation, Correlation.Length);
            Array.Copy(NSDF, result.NSDF, NSDF.Length);
            return(result);
        }
예제 #4
0
        // 今溜まっている分を解析する
        private void analyzeBuffer()
        {
            _prevAnalyzeTime = Environment.TickCount;
            _pitchAnalyzer.SampleFrequency = _capFormat.nSamplesPerSec;

            double[] buf = _buffer.ToArray();
            for (int i = 0; i < buf.Length; i++)
            {
                buf[i] /= _capFormat.nChannels;
            }
            PitchResult result = _pitchAnalyzer.Analyze(buf);
            ToneResult  tone   = ToneAnalyzer.Analyze(result.Pitch, result.Clarity);

            // イベント発火
            DataUpdatedEventHandler del = DataUpdated;

            if (del != null)
            {
                del.Invoke(this, new DataUpdatedEventArgs(result, tone));
            }
        }
예제 #5
0
 /// <summary>
 /// AudioInput初期化
 /// </summary>
 private void initAudio()
 {
     _audioInput = new audio.AudioInput();
     _audioInput.DeviceInfoUpdated += (s, e) =>
     {
         if (e.DeviceInfo.FindIndex((audio.DeviceInfo di) => { return(di.DeviceId == Config.Instance.DeviceId); }) >= 0)
         {
             if (!string.IsNullOrEmpty(Config.Instance.DeviceId))
             {
                 _audioInput.SelectDevice(Config.Instance.DeviceId);
             }
         }
         else
         {
             // 繋ぎたいデバイスが消えた
             _deviceRemoved = true;
         }
     };
     _audioInput.DeviceSelected += (s, e) =>
     {
         Config.Instance.DeviceId = e.Device.Id;
         _selectedDeviceIndex     = e.Index;
         _audioInput.StartCapture();
     };
     _audioInput.CaptureStarted += (s, e) => { };
     _audioInput.CaptureStopped += (s, e) => { };
     _audioInput.Disposed       += (s, e) => { };
     _audioInput.DataUpdated    += (s, e) =>
     {
         lock (_audioLockObj)
         {
             _pitchResult = e.Pitch;
             _toneResult  = e.Tone;
         }
     };
     _audioInput.UpdateDeviceInfo();
 }
예제 #6
0
        public PitchResult Analyze(double[] sig)
        {
            // 必要数
            int n = (int)Math.Floor(Math.Log(sig.Length, 2));
            int size = (int)Math.Pow(2, n > 13 ? 13 : n); // limit of AForge.NET

            // 返り値用意
            PitchResult result = new PitchResult(size, SampleFrequency);

            // 時間幅・周波数分解能算出
            double curFreq = 0;
            double diffFreq = _sampleFrequency / (double)size;

            // zero pad
            double[] windowed = new double[size * 2];
            for (int i = 0; i < windowed.Length; i++)
            {
                windowed[i] = i < size ? sig[sig.Length - size + i] : 0;

                if (i < result.Signal.Length)
                {
                    result.Signal[i] = windowed[i]; // ついでに入力を保存
                    result.Time[i] = i * 1000 / result.SampleFrequency; // ms
                }
            }

            // FFT -> frequency domein
            Complex[] input = Array.ConvertAll<double, Complex>(windowed, (d) => { return new Complex(d, 0); });
            FourierTransform.FFT(input, FourierTransform.Direction.Forward);

            // 自己相関関数
            //  (パワースペクトル -> 逆フーリエ変換
            Complex[] powerSpec = Array.ConvertAll<Complex, Complex>(input, (c) => { return new Complex(c.SquaredMagnitude * 4 * size * size, 0); });
            FourierTransform.FFT(powerSpec, FourierTransform.Direction.Backward);
            double[] correlation = Array.ConvertAll<Complex, double>(powerSpec, (c) => { return c.Re / (size * 2); });

            int idx = 0;
            int highestNsdfIdx = 0; bool positiveCross = false;
            List<KeyValuePair<double, double>> keyMaxes = new List<KeyValuePair<double, double>>();
            double squared = 0; double max = double.MinValue;

            foreach (Complex c in input)
            {
                result.Correlation[idx] = correlation[idx];
                if (idx == 0)
                {
                    // ndsf divider
                    squared = result.Correlation[idx] * 2.0;
                }
                else
                {
                    // フーリエ変換の結果を入力
                    curFreq += diffFreq;
                    result.Frequency[idx - 1] = curFreq;
                    result.Amplitude[idx - 1] = c.Magnitude * 2.0;
                    result.Power[idx - 1] = c.SquaredMagnitude * 4.0;

                    // ndsf divider
                    squared = squared
                        - Math.Pow(result.Signal[idx - 1], 2)
                        - Math.Pow(result.Signal[result.Length - idx], 2);
                }

                // Normalized Square Difference Function
                if (squared == 0)
                    result.NSDF[idx] = 0;
                else
                    result.NSDF[idx] = 2 * result.Correlation[idx] / squared;

                // pick key max
                if (idx > 0)
                {
                    if (result.NSDF[idx - 1] < 0 && result.NSDF[idx] >= 0)
                    {
                        positiveCross = true;
                        highestNsdfIdx = idx;
                    }
                    else if (result.NSDF[idx - 1] > 0 && result.NSDF[idx] <= 0 || idx == result.Length - 2)
                    {
                        positiveCross = false;
                        if (highestNsdfIdx > 0 && result.NSDF[highestNsdfIdx] > 0)
                        {
                            double peakIdx; double clarity;
                            parabolicInterpolation(
                                highestNsdfIdx - 1, result.NSDF[highestNsdfIdx - 1],
                                highestNsdfIdx, result.NSDF[highestNsdfIdx],
                                highestNsdfIdx + 1, result.NSDF[highestNsdfIdx + 1],
                                out peakIdx, out clarity);
                            if(keyMaxes.Count > 0 || peakIdx < result.Length / 2.0)
                                keyMaxes.Add(new KeyValuePair<double, double>(peakIdx, clarity));
                            if (max < clarity) max = clarity;
                        }
                    }

                    if (positiveCross && result.NSDF[highestNsdfIdx] < result.NSDF[idx])
                    {
                        highestNsdfIdx = idx;
                    }
                }

                idx++;
                if (idx >= result.Length) break;
            }

            // pick max
            KeyValuePair<double, double> keyMax = keyMaxes.Find((KeyValuePair<double, double> kv) => { return (kv.Value > max * 0.8); });
            if (keyMaxes.Count <= 1)
            {
                result.Pitch = 440;
                result.Clarity = 0;
            }
            else
            {
                result.Pitch = result.SampleFrequency / keyMax.Key;
                result.Clarity = keyMax.Value;
            }

            return result;
        }
예제 #7
0
 /// <summary>
 /// AudioInput初期化
 /// </summary>
 private void initAudio()
 {
     _audioInput = new audio.AudioInput();
     _audioInput.DeviceInfoUpdated += (s, e) =>
     {
         if (e.DeviceInfo.FindIndex((audio.DeviceInfo di) => { return di.DeviceId == Config.Instance.DeviceId; }) >= 0)
         {
             if (!string.IsNullOrEmpty(Config.Instance.DeviceId))
             {
                 _audioInput.SelectDevice(Config.Instance.DeviceId);
             }
         }
         else
         {
             // 繋ぎたいデバイスが消えた
             _deviceRemoved = true;
         }
     };
     _audioInput.DeviceSelected += (s, e) =>
     {
         Config.Instance.DeviceId = e.Device.Id;
         _selectedDeviceIndex = e.Index;
         _audioInput.StartCapture();
     };
     _audioInput.CaptureStarted += (s, e) => { };
     _audioInput.CaptureStopped += (s, e) => { };
     _audioInput.Disposed += (s, e) => { };
     _audioInput.DataUpdated += (s, e) =>
     {
         lock (_audioLockObj)
         {
             _pitchResult = e.Pitch;
             _toneResult = e.Tone;
         }
     };
     _audioInput.UpdateDeviceInfo();
 }
예제 #8
0
 public DataUpdatedEventArgs(PitchResult pitchResult, ToneResult toneResult)
 {
     Pitch = pitchResult;
     Tone  = toneResult;
 }
예제 #9
0
 public DataUpdatedEventArgs(PitchResult pitchResult, ToneResult toneResult)
 {
     Pitch = pitchResult;
     Tone = toneResult;
 }
예제 #10
0
        public PitchResult Analyze(double[] sig)
        {
            // 必要数
            int n    = (int)Math.Floor(Math.Log(sig.Length, 2));
            int size = (int)Math.Pow(2, n > 13 ? 13 : n); // limit of AForge.NET

            // 返り値用意
            PitchResult result = new PitchResult(size, SampleFrequency);

            // 時間幅・周波数分解能算出
            double curFreq  = 0;
            double diffFreq = _sampleFrequency / (double)size;

            // zero pad
            double[] windowed = new double[size * 2];
            for (int i = 0; i < windowed.Length; i++)
            {
                windowed[i] = i < size ? sig[sig.Length - size + i] : 0;

                if (i < result.Signal.Length)
                {
                    result.Signal[i] = windowed[i];                       // ついでに入力を保存
                    result.Time[i]   = i * 1000 / result.SampleFrequency; // ms
                }
            }

            // FFT -> frequency domein
            Complex[] input = Array.ConvertAll <double, Complex>(windowed, (d) => { return(new Complex(d, 0)); });
            FourierTransform.FFT(input, FourierTransform.Direction.Forward);

            // 自己相関関数
            //  (パワースペクトル -> 逆フーリエ変換
            Complex[] powerSpec = Array.ConvertAll <Complex, Complex>(input, (c) => { return(new Complex(c.SquaredMagnitude * 4 * size * size, 0)); });
            FourierTransform.FFT(powerSpec, FourierTransform.Direction.Backward);
            double[] correlation = Array.ConvertAll <Complex, double>(powerSpec, (c) => { return(c.Re / (size * 2)); });

            int idx = 0;
            int highestNsdfIdx = 0; bool positiveCross = false;
            List <KeyValuePair <double, double> > keyMaxes = new List <KeyValuePair <double, double> >();
            double squared = 0; double max = double.MinValue;

            foreach (Complex c in input)
            {
                result.Correlation[idx] = correlation[idx];
                if (idx == 0)
                {
                    // ndsf divider
                    squared = result.Correlation[idx] * 2.0;
                }
                else
                {
                    // フーリエ変換の結果を入力
                    curFreq += diffFreq;
                    result.Frequency[idx - 1] = curFreq;
                    result.Amplitude[idx - 1] = c.Magnitude * 2.0;
                    result.Power[idx - 1]     = c.SquaredMagnitude * 4.0;

                    // ndsf divider
                    squared = squared
                              - Math.Pow(result.Signal[idx - 1], 2)
                              - Math.Pow(result.Signal[result.Length - idx], 2);
                }

                // Normalized Square Difference Function
                if (squared == 0)
                {
                    result.NSDF[idx] = 0;
                }
                else
                {
                    result.NSDF[idx] = 2 * result.Correlation[idx] / squared;
                }

                // pick key max
                if (idx > 0)
                {
                    if (result.NSDF[idx - 1] < 0 && result.NSDF[idx] >= 0)
                    {
                        positiveCross  = true;
                        highestNsdfIdx = idx;
                    }
                    else if (result.NSDF[idx - 1] > 0 && result.NSDF[idx] <= 0 || idx == result.Length - 2)
                    {
                        positiveCross = false;
                        if (highestNsdfIdx > 0 && result.NSDF[highestNsdfIdx] > 0)
                        {
                            double peakIdx; double clarity;
                            parabolicInterpolation(
                                highestNsdfIdx - 1, result.NSDF[highestNsdfIdx - 1],
                                highestNsdfIdx, result.NSDF[highestNsdfIdx],
                                highestNsdfIdx + 1, result.NSDF[highestNsdfIdx + 1],
                                out peakIdx, out clarity);
                            if (keyMaxes.Count > 0 || peakIdx < result.Length / 2.0)
                            {
                                keyMaxes.Add(new KeyValuePair <double, double>(peakIdx, clarity));
                            }
                            if (max < clarity)
                            {
                                max = clarity;
                            }
                        }
                    }

                    if (positiveCross && result.NSDF[highestNsdfIdx] < result.NSDF[idx])
                    {
                        highestNsdfIdx = idx;
                    }
                }

                idx++;
                if (idx >= result.Length)
                {
                    break;
                }
            }

            // pick max
            KeyValuePair <double, double> keyMax = keyMaxes.Find((KeyValuePair <double, double> kv) => { return(kv.Value > max * 0.8); });

            if (keyMaxes.Count <= 1)
            {
                result.Pitch   = 440;
                result.Clarity = 0;
            }
            else
            {
                result.Pitch   = result.SampleFrequency / keyMax.Key;
                result.Clarity = keyMax.Value;
            }

            return(result);
        }