Use window function
Update reference notes Improve comparison
This commit is contained in:
1 parent
7c380f62f1
commit
be6a40aa1d
4 files changed
+108
-73
No files matched your search
Binary file not shown.
+82
-58
@@ -108,24 +108,26 @@ int PtAKF::_GetNote(float* restrict samples, double* restrict maxVolume, float*
|
|||||||
//maxVolumeL /= 32767.;
|
//maxVolumeL /= 32767.;
|
||||||
*maxVolume = maxVolumeL;
|
*maxVolume = maxVolumeL;
|
||||||
|
|
||||||
|
float samplesWindowed[_SampleCt];
|
||||||
|
|
||||||
for(int i = 0; i < _SampleCt; i++){
|
for(int i = 0; i < _SampleCt; i++){
|
||||||
samples[i] *= _Window[i];
|
samplesWindowed[i] = samples[i] * _Window[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now analyze the samples and get peaks at the most appropriate tones
|
// Now analyze the samples and get peaks at the most appropriate tones
|
||||||
|
|
||||||
SPeak peaks[_MaxPeaks];
|
|
||||||
InitPeaks(peaks);
|
|
||||||
|
|
||||||
//Attention: We have a peak at lag 0 that might stretch that far, that we detect a wrong "peak" at _MaxHalfTone
|
//Attention: We have a peak at lag 0 that might stretch that far, that we detect a wrong "peak" at _MaxHalfTone
|
||||||
//Because of that we filter out all tones that are past the last zero crossing from below but keep tones with decreasing weights (going towards zero crossing from above)
|
//Because of that we filter out all tones that are past the last zero crossing from below but keep tones with decreasing weights (going towards zero crossing from above)
|
||||||
int lastValidTone = 0;
|
int lastValidTone = 0;
|
||||||
float lastWeight = 1.f;
|
float lastWeight = 1.f;
|
||||||
|
float maxWeight = 0.f;
|
||||||
for (int toneIndex = _MinHalfTone; toneIndex <= _MaxHalfTone; toneIndex++)
|
for (int toneIndex = _MinHalfTone; toneIndex <= _MaxHalfTone; toneIndex++)
|
||||||
{
|
{
|
||||||
float curWeight = _AnalyzeByTone(samples, toneIndex);
|
float curWeight = _AnalyzeByTone(samples, samplesWindowed, toneIndex);
|
||||||
|
|
||||||
AddPeak(peaks, curWeight, toneIndex);
|
if(curWeight > maxWeight){
|
||||||
|
maxWeight = curWeight;
|
||||||
|
}
|
||||||
|
|
||||||
weights[toneIndex - _MinHalfTone] = curWeight;
|
weights[toneIndex - _MinHalfTone] = curWeight;
|
||||||
|
|
||||||
@@ -137,7 +139,7 @@ int PtAKF::_GetNote(float* restrict samples, double* restrict maxVolume, float*
|
|||||||
|
|
||||||
// Now clear off the lag 0 peak if required
|
// Now clear off the lag 0 peak if required
|
||||||
|
|
||||||
if(peaks[_MaxPeaks - 1].toneIndex ==_MaxHalfTone){
|
if(maxWeight >= weights[_MaxHalfTone]){
|
||||||
//We might have caught the lag 0 peak so go a bit further to check for other zero crossings (or we won't be able to detect _MaxHalfTone)
|
//We might have caught the lag 0 peak so go a bit further to check for other zero crossings (or we won't be able to detect _MaxHalfTone)
|
||||||
float lastWeight = _AKFByTone(samples, _MaxHalfTone);
|
float lastWeight = _AKFByTone(samples, _MaxHalfTone);
|
||||||
for(int toneIndex = _MaxHalfTone+1; toneIndex <= _MaxHalfTone + _HalfTonesAdd; toneIndex++){
|
for(int toneIndex = _MaxHalfTone+1; toneIndex <= _MaxHalfTone + _HalfTonesAdd; toneIndex++){
|
||||||
@@ -148,40 +150,57 @@ int PtAKF::_GetNote(float* restrict samples, double* restrict maxVolume, float*
|
|||||||
}
|
}
|
||||||
lastWeight = curWeight;
|
lastWeight = curWeight;
|
||||||
}
|
}
|
||||||
if(lastValidTone < peaks[_MaxPeaks - 1].toneIndex){
|
//Set all invalid weights to 0
|
||||||
InitPeaks(peaks);
|
for(int toneIndex = lastValidTone + 1;toneIndex < _MaxHalfTone; toneIndex++){
|
||||||
for(int toneIndex = _MinHalfTone; toneIndex <= lastValidTone; toneIndex++){
|
weights[toneIndex - _MinHalfTone] = 0.f;
|
||||||
AddPeak(peaks, weights[toneIndex - _MinHalfTone], toneIndex);
|
|
||||||
}
|
|
||||||
//Set all invalid weights to 0
|
|
||||||
for(int toneIndex = lastValidTone + 1;toneIndex < _MaxHalfTone; toneIndex++){
|
|
||||||
weights[toneIndex - _MinHalfTone] = 0.f;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SPeak peaks[_MaxPeaks];
|
||||||
|
InitPeaks(peaks);
|
||||||
|
int numPeaks = 0;
|
||||||
|
bool up = true;
|
||||||
|
for(int i = _MinHalfTone + 1; i <= _MaxHalfTone; i++){
|
||||||
|
if(weights[i-1] > weights[i]){
|
||||||
|
if(up){
|
||||||
|
AddPeak(peaks, weights[i - 1 - _MinHalfTone], i - 1);
|
||||||
|
numPeaks++;
|
||||||
|
up = false;
|
||||||
|
}
|
||||||
|
}else if(!up){
|
||||||
|
up = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(up){
|
||||||
|
AddPeak(peaks, weights[_MaxHalfTone - _MinHalfTone], _MaxHalfTone);
|
||||||
|
numPeaks++;
|
||||||
|
}
|
||||||
|
if(numPeaks > _MaxPeaks)
|
||||||
|
numPeaks = _MaxPeaks;
|
||||||
|
|
||||||
// Further analyze the found peaks and find the real maximum
|
// Further analyze the found peaks and find the real maximum
|
||||||
// This is necessary because we may have our real peak a bit off the exact tone frequency
|
// This is necessary because we may have our real peak a bit off the exact tone frequency
|
||||||
// and a 'wrong' peak that is exactly at another tone which might become higher than the one at the 'right' tone
|
// and a 'wrong' peak that is exactly at another tone which might become higher than the one at the 'right' tone
|
||||||
|
|
||||||
int maxTone = peaks[_MaxPeaks - 1].toneIndex;
|
int maxTone = peaks[_MaxPeaks-1].toneIndex;
|
||||||
int maxToneFine = -1;
|
int maxToneFine = -1;
|
||||||
float maxWeight = peaks[_MaxPeaks - 1].weight;
|
maxWeight = peaks[_MaxPeaks-1].weight;
|
||||||
for(int i = 0; i < _MaxPeaks; i++){
|
for(int i = _MaxPeaks - numPeaks; i < _MaxPeaks; i++){
|
||||||
|
float curWeight = peaks[i].weight;
|
||||||
|
if(curWeight * 3.f < maxWeight)
|
||||||
|
continue;
|
||||||
int toneIndex = peaks[i].toneIndex;
|
int toneIndex = peaks[i].toneIndex;
|
||||||
float curWeightCenter = peaks[i].weight;
|
float curWeightDown = _AnalyzeBySampleCt(samples, samplesWindowed, _SamplesPerPeriodPerToneFine[toneIndex * 2]);
|
||||||
float curWeightDown = _AnalyzeBySampleCt(samples, _SamplesPerPeriodPerToneFine[toneIndex * 2]);
|
|
||||||
float curWeight;
|
|
||||||
int otherToneIndex;
|
int otherToneIndex;
|
||||||
int otherToneFineIndex;
|
int otherToneFineIndex;
|
||||||
if(curWeightDown > curWeightCenter){
|
if(curWeightDown > curWeight){
|
||||||
otherToneIndex = toneIndex - 1;
|
otherToneIndex = toneIndex - 1;
|
||||||
otherToneFineIndex = 1;
|
otherToneFineIndex = 1;
|
||||||
curWeight = curWeightDown;
|
curWeight = curWeightDown;
|
||||||
}else{
|
}else{
|
||||||
float curWeightUp = _AnalyzeBySampleCt(samples, _SamplesPerPeriodPerToneFine[toneIndex * 2 + 1]);
|
float curWeightUp = _AnalyzeBySampleCt(samples, samplesWindowed, _SamplesPerPeriodPerToneFine[toneIndex * 2 + 1]);
|
||||||
if(curWeightUp > curWeightCenter){
|
if(curWeightUp > curWeight){
|
||||||
otherToneIndex = (toneIndex < _MaxHalfTone)? toneIndex + 1: -1; // If the other tone is invalid just set it to -1 which will be skipped below
|
otherToneIndex = (toneIndex < _MaxHalfTone) ? toneIndex + 1: -1; // If the other tone is invalid just set it to -1 which will be skipped below
|
||||||
otherToneFineIndex = 0;
|
otherToneFineIndex = 0;
|
||||||
curWeight = curWeightUp;
|
curWeight = curWeightUp;
|
||||||
}else
|
}else
|
||||||
@@ -196,7 +215,7 @@ int PtAKF::_GetNote(float* restrict samples, double* restrict maxVolume, float*
|
|||||||
|
|
||||||
// Now check also neighbouring tone
|
// Now check also neighbouring tone
|
||||||
if(otherToneIndex > 0){
|
if(otherToneIndex > 0){
|
||||||
float curWeightOther = _AnalyzeBySampleCt(samples, _SamplesPerPeriodPerToneFine[otherToneIndex * 2 + otherToneFineIndex]);
|
float curWeightOther = _AnalyzeBySampleCt(samples, samplesWindowed, _SamplesPerPeriodPerToneFine[otherToneIndex * 2 + otherToneFineIndex]);
|
||||||
if(curWeightOther > weights[otherToneIndex - _MinHalfTone]){
|
if(curWeightOther > weights[otherToneIndex - _MinHalfTone]){
|
||||||
weights[otherToneIndex - _MinHalfTone] = curWeightOther;
|
weights[otherToneIndex - _MinHalfTone] = curWeightOther;
|
||||||
if(curWeightOther > maxWeight){
|
if(curWeightOther > maxWeight){
|
||||||
@@ -209,45 +228,26 @@ int PtAKF::_GetNote(float* restrict samples, double* restrict maxVolume, float*
|
|||||||
}
|
}
|
||||||
|
|
||||||
float energy = _AKFBySampleCt(samples, 0);
|
float energy = _AKFBySampleCt(samples, 0);
|
||||||
float maxAKF = (maxToneFine < 0) ? _AKFByTone(samples, maxTone):_AKFBySampleCt(samples, _SamplesPerPeriodPerToneFine[maxTone * 2 + maxToneFine]);
|
float maxAKF = (maxToneFine < 0) ? _AKFByTone(samples, maxTone) : _AKFBySampleCt(samples, _SamplesPerPeriodPerToneFine[maxTone * 2 + maxToneFine]);
|
||||||
float aa = _AKFByTone(samples, maxTone);
|
|
||||||
|
|
||||||
//if(maxWeight - minWeight > 0.025){
|
//if(maxWeight - minWeight > 0.025){
|
||||||
if(maxAKF >= 0.4 * energy){
|
if(maxAKF >= 0.35f * energy){
|
||||||
return maxTone;
|
return maxTone;
|
||||||
}else return -1;
|
}else return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
float PtAKF::_AnalyzeByTone(float* restrict samples, int toneIndex){
|
float PtAKF::_AnalyzeByTone(float* restrict samples, float* restrict samplesWindowed, int toneIndex){
|
||||||
return _AnalyzeBySampleCt(samples, _SamplesPerPeriodPerTone[toneIndex]);
|
return _AnalyzeBySampleCt(samples, samplesWindowed, _SamplesPerPeriodPerTone[toneIndex]);
|
||||||
}
|
}
|
||||||
|
|
||||||
float PtAKF::_AnalyzeBySampleCt(float* restrict samples, float samplesPerPeriodD){
|
float PtAKF::_AnalyzeBySampleCt(float* restrict samples, float* restrict samplesWindowed, float samplesPerPeriodD){
|
||||||
// Use method by Kobayashi and Shimamura (2001): Combine AKF and AMDF to a new f(z)=AKF(z)/(AMDF(z)+k) with k=1
|
// Use method by Kobayashi and Shimamura (2001): Combine AKF and AMDF to a new f(z)=AKF(z)/(AMDF(z)+k) with k=1
|
||||||
int samplesPerPeriod = static_cast<int>(samplesPerPeriodD);
|
|
||||||
float fHigh = samplesPerPeriodD - samplesPerPeriod;
|
|
||||||
float fLow = 1.0f - fHigh;
|
|
||||||
|
|
||||||
float accumDistAKF = 0; // accumulated distances
|
float akf = _AKFBySampleCt(samplesWindowed, samplesPerPeriodD);
|
||||||
float accumDistAMDF = 0; // accumulated distances
|
float amdf = _AMDFBySampleCt(samples, samplesPerPeriodD);
|
||||||
|
|
||||||
// compare correlating samples
|
|
||||||
int sampleIndex = 0; // index of sample to analyze
|
|
||||||
// Start value= index of sample one period ahead
|
|
||||||
for (int correlatingSampleIndex = sampleIndex + samplesPerPeriod; correlatingSampleIndex + 1 < _SampleCt; correlatingSampleIndex++, sampleIndex++)
|
|
||||||
{
|
|
||||||
// calc distance to corresponding sample in next period
|
|
||||||
float xn = samples[sampleIndex];
|
|
||||||
float xnt = samples[correlatingSampleIndex] * fLow + samples[correlatingSampleIndex + 1] * fHigh;
|
|
||||||
accumDistAKF += xn * xnt;
|
|
||||||
accumDistAMDF += abs(xn - xnt);
|
|
||||||
}
|
|
||||||
|
|
||||||
accumDistAKF /= _SampleCt;
|
|
||||||
accumDistAMDF /= sampleIndex;
|
|
||||||
|
|
||||||
//return accumDistAKF / (accumDistAMDF * 32767.f + 32767.f * 32767.f); // Need to scale AKF by MAX^2 and AMDF by MAX, so do some maths to divide only once
|
//return accumDistAKF / (accumDistAMDF * 32767.f + 32767.f * 32767.f); // Need to scale AKF by MAX^2 and AMDF by MAX, so do some maths to divide only once
|
||||||
float result = accumDistAKF / (accumDistAMDF + 1.f);
|
float result = akf / (amdf + 1.f);
|
||||||
return result; // Need to scale AKF by MAX^2 and AMDF by MAX, so do some maths to divide only once
|
return result; // Need to scale AKF by MAX^2 and AMDF by MAX, so do some maths to divide only once
|
||||||
//{toneIndex}: {accumDistAKF} ; {accumDistAMDF}; {result}
|
//{toneIndex}: {accumDistAKF} ; {accumDistAMDF}; {result}
|
||||||
}
|
}
|
||||||
@@ -257,12 +257,11 @@ float PtAKF::_AKFByTone(float* restrict samples, int toneIndex){
|
|||||||
}
|
}
|
||||||
|
|
||||||
float PtAKF::_AKFBySampleCt(float* restrict samples, float samplesPerPeriodD){
|
float PtAKF::_AKFBySampleCt(float* restrict samples, float samplesPerPeriodD){
|
||||||
// Do a fast, non-scaled AKF (used e.g. for Lag 0 peak removal)
|
|
||||||
int samplesPerPeriod = static_cast<int>(samplesPerPeriodD);
|
int samplesPerPeriod = static_cast<int>(samplesPerPeriodD);
|
||||||
float fHigh = samplesPerPeriodD - samplesPerPeriod;
|
float fHigh = samplesPerPeriodD - samplesPerPeriod;
|
||||||
float fLow = 1.0f - fHigh;
|
float fLow = 1.0f - fHigh;
|
||||||
|
|
||||||
float accumDistAKF = 0; // accumulated distances
|
float accumDist = 0; // accumulated distances
|
||||||
|
|
||||||
// compare correlating samples
|
// compare correlating samples
|
||||||
int sampleIndex = 0; // index of sample to analyze
|
int sampleIndex = 0; // index of sample to analyze
|
||||||
@@ -272,10 +271,35 @@ float PtAKF::_AKFBySampleCt(float* restrict samples, float samplesPerPeriodD){
|
|||||||
// calc distance to corresponding sample in next period
|
// calc distance to corresponding sample in next period
|
||||||
float xn = samples[sampleIndex];
|
float xn = samples[sampleIndex];
|
||||||
float xnt = samples[correlatingSampleIndex] * fLow + samples[correlatingSampleIndex + 1] * fHigh;
|
float xnt = samples[correlatingSampleIndex] * fLow + samples[correlatingSampleIndex + 1] * fHigh;
|
||||||
accumDistAKF += xn * xnt;
|
accumDist += xn * xnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
return accumDistAKF;
|
return accumDist / _SampleCt;
|
||||||
|
}
|
||||||
|
|
||||||
|
float PtAKF::_AMDFByTone(float* restrict samples, int toneIndex){
|
||||||
|
return _AKFBySampleCt(samples, _SamplesPerPeriodPerTone[toneIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
float PtAKF::_AMDFBySampleCt(float* restrict samples, float samplesPerPeriodD){
|
||||||
|
int samplesPerPeriod = static_cast<int>(samplesPerPeriodD);
|
||||||
|
float fHigh = samplesPerPeriodD - samplesPerPeriod;
|
||||||
|
float fLow = 1.0f - fHigh;
|
||||||
|
|
||||||
|
float accumDist = 0; // accumulated distances
|
||||||
|
|
||||||
|
// compare correlating samples
|
||||||
|
int sampleIndex = 0; // index of sample to analyze
|
||||||
|
// Start value= index of sample one period ahead
|
||||||
|
for (int correlatingSampleIndex = sampleIndex + samplesPerPeriod; correlatingSampleIndex + 1 < _SampleCt; correlatingSampleIndex++, sampleIndex++)
|
||||||
|
{
|
||||||
|
// calc distance to corresponding sample in next period
|
||||||
|
float xn = samples[sampleIndex];
|
||||||
|
float xnt = samples[correlatingSampleIndex] * fLow + samples[correlatingSampleIndex + 1] * fHigh;
|
||||||
|
accumDist += abs(xn - xnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
return accumDist / sampleIndex;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
||||||
|
|||||||
@@ -41,19 +41,21 @@ private:
|
|||||||
static float* restrict _SamplesPerPeriodPerToneFine;
|
static float* restrict _SamplesPerPeriodPerToneFine;
|
||||||
static float* restrict _Window;
|
static float* restrict _Window;
|
||||||
static constexpr int _MinHalfTone = 0; //C2
|
static constexpr int _MinHalfTone = 0; //C2
|
||||||
static constexpr int _MaxHalfTone = 55;//47; //B5
|
static constexpr int _MaxHalfTone = 56;//47; //B5
|
||||||
static constexpr int _HalfTonesAdd = 4; //Additonal half tones to analyze to remove the peak at lag 0
|
static constexpr int _HalfTonesAdd = 4; //Additonal half tones to analyze to remove the peak at lag 0
|
||||||
static constexpr int _MaxPeaks = 3;
|
static constexpr int _MaxPeaks = 10;
|
||||||
|
|
||||||
constexpr static size_t _SampleCt = 2048;
|
constexpr static size_t _SampleCt = 2048;
|
||||||
RingBuffer<_SampleCt * 2> _AnalysisBuf;
|
RingBuffer<_SampleCt * 2> _AnalysisBuf;
|
||||||
unsigned _Step;
|
unsigned _Step;
|
||||||
|
|
||||||
static int _GetNote(float* restrict samples, double* restrict maxVolume, float* restrict weights);
|
static int _GetNote(float* restrict samples, double* restrict maxVolume, float* restrict weights);
|
||||||
static float _AnalyzeBySampleCt(float* restrict samples, float samplesPerPeriodD);
|
static float _AnalyzeBySampleCt(float* restrict samples, float* restrict samplesWindowed, float samplesPerPeriodD);
|
||||||
static inline float _AnalyzeByTone(float* restrict samples, int toneIndex);
|
static inline float _AnalyzeByTone(float* restrict samples, float* restrict samplesWindowed, int toneIndex);
|
||||||
static float _AKFBySampleCt(float* restrict samples, float samplesPerPeriodD);
|
static float _AKFBySampleCt(float* restrict samples, float samplesPerPeriodD);
|
||||||
static inline float _AKFByTone(float* restrict samples, int toneIndex);
|
static inline float _AKFByTone(float* restrict samples, int toneIndex);
|
||||||
|
static float _AMDFBySampleCt(float* restrict samples, float samplesPerPeriodD);
|
||||||
|
static inline float _AMDFByTone(float* restrict samples, int toneIndex);
|
||||||
static inline void InitPeaks(SPeak peaks[_MaxPeaks]);
|
static inline void InitPeaks(SPeak peaks[_MaxPeaks]);
|
||||||
static inline void AddPeak(SPeak peaks[_MaxPeaks], float curWeight, int toneIndex);
|
static inline void AddPeak(SPeak peaks[_MaxPeaks], float curWeight, int toneIndex);
|
||||||
};
|
};
|
||||||
@@ -193,8 +193,8 @@ namespace Vocaluxe.Lib.Sound.Record
|
|||||||
if (_TestFile("toneG4.wav", 31))
|
if (_TestFile("toneG4.wav", 31))
|
||||||
ok++;
|
ok++;
|
||||||
tests++;*/
|
tests++;*/
|
||||||
_TestFile("sClausVoc.wav", "sClausVoc.txt", ref tests, ref ok);
|
|
||||||
_TestFile("whistling3.wav", "whistling3.txt", ref tests, ref ok);
|
_TestFile("whistling3.wav", "whistling3.txt", ref tests, ref ok);
|
||||||
|
_TestFile("sClausVoc.wav", "sClausVoc.txt", ref tests, ref ok);
|
||||||
|
|
||||||
_GetSineWave(_BaseToneFreq * Math.Pow(_HalftoneBase, 5), 44100, ref angle, out data);
|
_GetSineWave(_BaseToneFreq * Math.Pow(_HalftoneBase, 5), 44100, ref angle, out data);
|
||||||
Stopwatch sw = new Stopwatch();
|
Stopwatch sw = new Stopwatch();
|
||||||
@@ -255,6 +255,22 @@ namespace Vocaluxe.Lib.Sound.Record
|
|||||||
return ok >= ct - 4;
|
return ok >= ct - 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool _IsNoteValid(int note, int time, IList<STimedNote> tones)
|
||||||
|
{
|
||||||
|
const int lastNoteMaxTimeDiff = 1024 * 1000 / 44100; // old note is valid for 1024 more samples
|
||||||
|
for (int i = 0; i < tones.Count; i++)
|
||||||
|
{
|
||||||
|
if (tones[i].Time > time)
|
||||||
|
break;
|
||||||
|
if (i + 1 == tones.Count || time <= tones[i + 1].Time + lastNoteMaxTimeDiff)
|
||||||
|
{
|
||||||
|
if (tones[i].Note == note)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private void _TestFile(string fileName, IList<STimedNote> tones, ref int ct, ref int ok)
|
private void _TestFile(string fileName, IList<STimedNote> tones, ref int ct, ref int ok)
|
||||||
{
|
{
|
||||||
CWavFile wavFile = new CWavFile();
|
CWavFile wavFile = new CWavFile();
|
||||||
@@ -270,9 +286,6 @@ namespace Vocaluxe.Lib.Sound.Record
|
|||||||
int samplesRead = 0;
|
int samplesRead = 0;
|
||||||
int curTimeIndex = -1;
|
int curTimeIndex = -1;
|
||||||
int curNote = -1;
|
int curNote = -1;
|
||||||
int lastNote = -1; //It is ok not to detect a note change immediately so the old note is kept for a bit as ok
|
|
||||||
int lastNoteEndTime = 0;
|
|
||||||
const int lastNoteMaxTimeDiff = 1024 * 1000 / 44100; // old note is valid for 1024 more samples
|
|
||||||
const int maxSamplesPerBatch = 512;
|
const int maxSamplesPerBatch = 512;
|
||||||
CAnalyzer analyzer2 = new CAnalyzer();
|
CAnalyzer analyzer2 = new CAnalyzer();
|
||||||
CPtDyWa analyzer3 = new CPtDyWa();
|
CPtDyWa analyzer3 = new CPtDyWa();
|
||||||
@@ -290,14 +303,10 @@ namespace Vocaluxe.Lib.Sound.Record
|
|||||||
while (curTimeIndex + 1 < tones.Count && time >= tones[curTimeIndex + 1].Time)
|
while (curTimeIndex + 1 < tones.Count && time >= tones[curTimeIndex + 1].Time)
|
||||||
{
|
{
|
||||||
curTimeIndex++;
|
curTimeIndex++;
|
||||||
lastNote = curNote;
|
|
||||||
lastNoteEndTime = tones[curTimeIndex].Time;
|
|
||||||
curNote = tones[curTimeIndex].Note;
|
curNote = tones[curTimeIndex].Note;
|
||||||
}
|
}
|
||||||
if (curNote < 0)
|
if (curNote < 0)
|
||||||
continue;
|
continue;
|
||||||
if (lastNoteEndTime + lastNoteMaxTimeDiff < time)
|
|
||||||
lastNote = curNote;
|
|
||||||
int tone1 = ToneValid ? ToneAbs : -1;
|
int tone1 = ToneValid ? ToneAbs : -1;
|
||||||
int tone2 = (int)Math.Round(analyzer2.FindNote(64, 1770));
|
int tone2 = (int)Math.Round(analyzer2.FindNote(64, 1770));
|
||||||
int tone3 = (int)Math.Round(analyzer3.GetNote());
|
int tone3 = (int)Math.Round(analyzer3.GetNote());
|
||||||
@@ -308,9 +317,9 @@ namespace Vocaluxe.Lib.Sound.Record
|
|||||||
CBase.Log.LogDebug("Note " + _ToneToNote(curNote) + " at " + time + "ms wrongly detected as " + _ToneToNote(ToneAbs));
|
CBase.Log.LogDebug("Note " + _ToneToNote(curNote) + " at " + time + "ms wrongly detected as " + _ToneToNote(ToneAbs));
|
||||||
else
|
else
|
||||||
ok++;*/
|
ok++;*/
|
||||||
bool ok1 = tone1 == curNote || tone1 == lastNote;
|
bool ok1 = _IsNoteValid(tone1, time, tones);
|
||||||
bool ok2 = tone2 == curNote || tone2 == lastNote;
|
bool ok2 = _IsNoteValid(tone2, time, tones);
|
||||||
bool ok3 = tone3 == curNote || tone3 == lastNote;
|
bool ok3 = _IsNoteValid(tone3, time, tones);
|
||||||
if (!ok1 || !ok2 || !ok3)
|
if (!ok1 || !ok2 || !ok3)
|
||||||
{
|
{
|
||||||
CBase.Log.LogDebug("Note " + _ToneToNote(curNote) + " at " + time + "ms detected as " + _ToneToNote(tone1) + (ok1 ? "" : "(!)") + "; " + _ToneToNote(tone2) +
|
CBase.Log.LogDebug("Note " + _ToneToNote(curNote) + " at " + time + "ms detected as " + _ToneToNote(tone1) + (ok1 ? "" : "(!)") + "; " + _ToneToNote(tone2) +
|
||||||
|
|||||||
Reference in new issue
Block a user