public void TestShow(audio.PitchResult result) { lock (_result) { _result = result; } panel1.Invalidate(); }
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; }
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); }
// 今溜まっている分を解析する 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)); } }
/// <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(); }
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; }
/// <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(); }
public DataUpdatedEventArgs(PitchResult pitchResult, ToneResult toneResult) { Pitch = pitchResult; Tone = toneResult; }
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); }