diff --git a/Vocaluxe/Base/CSound.cs b/Vocaluxe/Base/CSound.cs index 440d405d..0ccf4d07 100644 --- a/Vocaluxe/Base/CSound.cs +++ b/Vocaluxe/Base/CSound.cs @@ -237,6 +237,16 @@ namespace Vocaluxe.Base return _Record.GetMaxVolume(Player); } + public static int NumHalfTones(int Player) + { + return _Record.NumHalfTones(Player); + } + + public static float[] ToneWeigth(int Player) + { + return _Record.ToneWeigth(Player); + } + public static SRecordDevice[] RecordGetDevices() { SRecordDevice[] devices = _Record.RecordDevices(); @@ -281,9 +291,10 @@ namespace Vocaluxe.Base class CBuffer { - private const double BaseToneFreq = 65.4064; - private const int NumHalfTones = 47; + private const double _BaseToneFreq = 65.4064; + private const int _NumHalfTones = 47; + private float[] _ToneWeigth; private Int16[] _AnalysisBuffer = new Int16[4096]; private Object _AnalysisBufferLock = new Object(); @@ -295,6 +306,17 @@ namespace Vocaluxe.Base private MemoryStream _Stream; // full buffer + public CBuffer() + { + _ToneWeigth = new float[_NumHalfTones]; + _Stream = new MemoryStream(); + } + + public int NumHalfTones + { + get { return _NumHalfTones; } + } + public int ToneAbs { get @@ -346,11 +368,6 @@ namespace Vocaluxe.Base } } - public CBuffer() - { - _Stream = new MemoryStream(); - } - public long Length { get { return _Stream.Length; } @@ -361,6 +378,17 @@ namespace Vocaluxe.Base get { return _Stream.ToArray(); } } + public float[] ToneWeigth + { + get + { + lock (_AnalysisBufferLock) + { + return _ToneWeigth; + } + } + } + public void Reset() { _Stream.SetLength(0L); @@ -443,13 +471,9 @@ namespace Vocaluxe.Base } if (_MaxVolume >= 0.05f) - { - // analyse the current voice pitch - AnalyzeByAutocorrelation(); - _ToneValid = true; - } + AnalyzeByAutocorrelation(true); else - _ToneValid = false; + AnalyzeByAutocorrelation(false); _NewSamples = false; } @@ -460,7 +484,7 @@ namespace Vocaluxe.Base } } - private void AnalyzeByAutocorrelation() + private void AnalyzeByAutocorrelation(bool valid) { const double HalftoneBase = 1.05946309436; // 2^(1/12) -> HalftoneBase^12 = 2 (one octave) @@ -473,9 +497,9 @@ namespace Vocaluxe.Base // at 44.1 (or 48kHz) only 6 (or 5) samples are compared, this might be // too few samples -> use a bigger buffer-size - for (int ToneIndex = 0; ToneIndex < NumHalfTones; ToneIndex++) + for (int ToneIndex = 0; ToneIndex < _NumHalfTones; ToneIndex++) { - double CurFreq = BaseToneFreq * Math.Pow(HalftoneBase, ToneIndex); + double CurFreq = _BaseToneFreq * Math.Pow(HalftoneBase, ToneIndex); double CurWeight = AnalyzeAutocorrelationFreq(CurFreq); // TODO: prefer higher frequencies (use >= or use downto) @@ -485,10 +509,17 @@ namespace Vocaluxe.Base MaxWeight = CurWeight; MaxTone = ToneIndex; } + _ToneWeigth[ToneIndex] = (float)CurWeight; } - _ToneAbs = MaxTone; - _Tone = MaxTone % 12; + if (valid) + { + _ToneAbs = MaxTone; + _Tone = MaxTone % 12; + _ToneValid = true; + } + else + _ToneValid = false; } private double AnalyzeAutocorrelationFreq(double Freq) diff --git a/Vocaluxe/Lib/Sound/CPortAudioRecord.cs b/Vocaluxe/Lib/Sound/CPortAudioRecord.cs index 87bff1ab..b0ca8503 100644 --- a/Vocaluxe/Lib/Sound/CPortAudioRecord.cs +++ b/Vocaluxe/Lib/Sound/CPortAudioRecord.cs @@ -240,6 +240,22 @@ namespace Vocaluxe.Lib.Sound return _Buffer[Player].ToneValid; } + public int NumHalfTones(int Player) + { + if (!_initialized) + return 0; + + return _Buffer[Player].NumHalfTones; + } + + public float[] ToneWeigth(int Player) + { + if (!_initialized) + return null; + + return _Buffer[Player].ToneWeigth; + } + public SRecordDevice[] RecordDevices() { if (!_initialized) diff --git a/Vocaluxe/Lib/Sound/IRecord.cs b/Vocaluxe/Lib/Sound/IRecord.cs index e4b9cc2b..3b664a71 100644 --- a/Vocaluxe/Lib/Sound/IRecord.cs +++ b/Vocaluxe/Lib/Sound/IRecord.cs @@ -51,6 +51,8 @@ namespace Vocaluxe.Lib.Sound void SetTone(int Player, int Tone); float GetMaxVolume(int Player); bool ToneValid(int Player); + int NumHalfTones(int Player); + float[] ToneWeigth(int Player); SRecordDevice[] RecordDevices(); } diff --git a/Vocaluxe/Screens/CScreenOptionsRecord.cs b/Vocaluxe/Screens/CScreenOptionsRecord.cs index 4426b7af..89cb5291 100644 --- a/Vocaluxe/Screens/CScreenOptionsRecord.cs +++ b/Vocaluxe/Screens/CScreenOptionsRecord.cs @@ -51,6 +51,8 @@ namespace Vocaluxe.Screens private bool _DelayTestRunning; private int _DelaySound; + private Equalizer[] _Equalizer; + public CScreenOptionsRecord() { Init(); @@ -274,6 +276,7 @@ namespace Vocaluxe.Screens if (player > 0) { ChannelEnergy[0] = CSound.RecordGetMaxVolume(player - 1); + _Equalizer[0].Update(CSound.ToneWeigth(player - 1)); } ChannelEnergy[1] = 0f; @@ -281,6 +284,7 @@ namespace Vocaluxe.Screens if (player > 0) { ChannelEnergy[1] = CSound.RecordGetMaxVolume(player - 1); + _Equalizer[1].Update(CSound.ToneWeigth(player - 1)); } } else @@ -288,6 +292,7 @@ namespace Vocaluxe.Screens for (int i = 0; i < ChannelEnergy.Length; i++) { ChannelEnergy[i] = 0f; + _Equalizer[i].Reset(); } } @@ -351,6 +356,13 @@ namespace Vocaluxe.Screens _DelayTestRunning = false; _DelaySound = -1; + + _Equalizer = new Equalizer[2]; + + for (int i = 0; i < _Equalizer.Length; i++) + { + _Equalizer[i] = new Equalizer(new SRectF(50 + 300 * i, 400, 250, 150, -1), CSound.NumHalfTones(0), 1); + } } public override void OnShowFinish() @@ -389,6 +401,11 @@ namespace Vocaluxe.Screens } } + for (int i = 0; i < _Equalizer.Length; i++) + { + _Equalizer[i].Draw(); + } + DrawFG(); return true; @@ -571,4 +588,69 @@ namespace Vocaluxe.Screens } } } + + class Equalizer + { + + private SRectF _Bounds; + private float _Space; + + private float[] _Bars; + + public Equalizer(SRectF bounds, int numBars, float space) + { + _Bounds = bounds; + + if (numBars > 0) + _Bars = new float[numBars]; + } + + public void Update(float[] weights) + { + if (weights == null || weights.Length == 0 || _Bars == null) + return; + + if (_Bars.Length < weights.Length) + { + } + else if (_Bars.Length > weights.Length) + { + } + else + { + for (int i = 0; i < _Bars.Length; i++) + { + //if (weights[i] > 0) + _Bars[i] = weights[i]; + //else + // _Bars[i] = 0f; + } + } + } + + public void Reset() + { + if (_Bars == null || _Bars.Length == 0) + return; + + for (int i = 0; i < _Bars.Length; i++) + { + _Bars[i] = 0f; + } + } + + public void Draw() + { + if (_Bars == null) + return; + + float dx = _Bounds.W / _Bars.Length; + + for (int i = 0; i < _Bars.Length; i++) + { + SRectF bar = new SRectF(_Bounds.X + dx * i, _Bounds.Y + _Bounds.H - _Bars[i] * _Bounds.H, dx, _Bars[i] * _Bounds.H, _Bounds.Z); + CDraw.DrawColor(new SColorF(1f, 1f, 1f, 1f), bar); + } + } + } }