|
@@ -4548,297 +4548,3 @@ cmRC_t cmRecdPlayExec( cmRecdPlay* p, const cmSample_t** iChs, cmSample_
|
4548
|
4548
|
return cmOkRC;
|
4549
|
4549
|
}
|
4550
|
4550
|
|
4551
|
|
-//=======================================================================================================================
|
4552
|
|
-
|
4553
|
|
-cmFrqTrk* cmFrqTrkAlloc( cmCtx* c, cmFrqTrk* p, const cmFrqTrkArgs_t* a )
|
4554
|
|
-{
|
4555
|
|
- cmFrqTrk* op = cmObjAlloc(cmFrqTrk,c,p);
|
4556
|
|
-
|
4557
|
|
- op->bmf = cmBinMtxFileAlloc(c,NULL,NULL);
|
4558
|
|
-
|
4559
|
|
- if( cmFrqTrkInit(op,a) != cmOkRC )
|
4560
|
|
- cmFrqTrkFree(&op);
|
4561
|
|
-
|
4562
|
|
- return op;
|
4563
|
|
-
|
4564
|
|
-}
|
4565
|
|
-
|
4566
|
|
-cmRC_t cmFrqTrkFree( cmFrqTrk** pp )
|
4567
|
|
-{
|
4568
|
|
- cmRC_t rc = cmOkRC;
|
4569
|
|
-
|
4570
|
|
- if( pp==NULL || *pp==NULL )
|
4571
|
|
- return rc;
|
4572
|
|
-
|
4573
|
|
- cmFrqTrk* p = *pp;
|
4574
|
|
- if((rc = cmFrqTrkFinal(p)) != cmOkRC )
|
4575
|
|
- return rc;
|
4576
|
|
-
|
4577
|
|
- cmMemFree(p->ch);
|
4578
|
|
- cmMemFree(p->dbM);
|
4579
|
|
- cmMemFree(p->pkiV);
|
4580
|
|
- cmMemFree(p->dbV);
|
4581
|
|
- cmBinMtxFileFree(&p->bmf);
|
4582
|
|
- cmObjFree(pp);
|
4583
|
|
- return rc;
|
4584
|
|
-
|
4585
|
|
-}
|
4586
|
|
-
|
4587
|
|
-cmRC_t cmFrqTrkInit( cmFrqTrk* p, const cmFrqTrkArgs_t* a )
|
4588
|
|
-{
|
4589
|
|
- cmRC_t rc;
|
4590
|
|
- if((rc = cmFrqTrkFinal(p)) != cmOkRC )
|
4591
|
|
- return rc;
|
4592
|
|
-
|
4593
|
|
- p->a = *a;
|
4594
|
|
- p->ch = cmMemResizeZ(cmFrqTrkCh_t,p->ch,a->chCnt );
|
4595
|
|
- p->hN = cmMax(1,a->wndSecs * a->srate / a->hopSmpCnt );
|
4596
|
|
- p->bN = p->a.binCnt;
|
4597
|
|
- p->dbM = cmMemResizeZ(cmReal_t,p->dbM,p->hN*p->bN);
|
4598
|
|
- p->hi = 0;
|
4599
|
|
- p->dbV = cmMemResizeZ(cmReal_t,p->dbV,p->bN);
|
4600
|
|
- p->pkiV = cmMemResizeZ(unsigned,p->pkiV,p->bN);
|
4601
|
|
- p->deadN_max = a->maxTrkDeadSec * a->srate / a->hopSmpCnt;
|
4602
|
|
- p->minTrkN = a->minTrkSec * a->srate / a->hopSmpCnt;
|
4603
|
|
- p->nextTrkId = 0;
|
4604
|
|
-
|
4605
|
|
- if( a->logFn != NULL )
|
4606
|
|
- {
|
4607
|
|
- if( cmBinMtxFileInit(p->bmf, a->logFn ) != cmOkRC )
|
4608
|
|
- cmCtxRtCondition(&p->obj, cmSubSysFailRC, "Log file open failed on '%s'.",cmStringNullGuard(a->logFn));
|
4609
|
|
- }
|
4610
|
|
-
|
4611
|
|
- return rc;
|
4612
|
|
-}
|
4613
|
|
-
|
4614
|
|
-cmRC_t cmFrqTrkFinal( cmFrqTrk* p )
|
4615
|
|
-{
|
4616
|
|
- cmRC_t rc = cmOkRC;
|
4617
|
|
- cmBinMtxFileFinal(p->bmf);
|
4618
|
|
- return rc;
|
4619
|
|
-}
|
4620
|
|
-
|
4621
|
|
-// Return an available channel record or NULL if all channel records are in use.
|
4622
|
|
-cmFrqTrkCh_t* _cmFrqTrkFindAvailCh( cmFrqTrk* p )
|
4623
|
|
-{
|
4624
|
|
- unsigned i;
|
4625
|
|
- for(i=0; i<p->a.chCnt; ++i)
|
4626
|
|
- if( p->ch[i].activeFl == false )
|
4627
|
|
- return p->ch + i;
|
4628
|
|
-
|
4629
|
|
- return NULL;
|
4630
|
|
-}
|
4631
|
|
-
|
4632
|
|
-unsigned _cmFrqTrkActiveChCount( cmFrqTrk* p )
|
4633
|
|
-{
|
4634
|
|
- unsigned n = 0;
|
4635
|
|
- unsigned i;
|
4636
|
|
- for(i=0; i<p->a.chCnt; ++i)
|
4637
|
|
- if( p->ch[i].activeFl )
|
4638
|
|
- ++n;
|
4639
|
|
-
|
4640
|
|
- return n;
|
4641
|
|
-}
|
4642
|
|
-
|
4643
|
|
-void _cmFrqTrkWriteLog( cmFrqTrk* p )
|
4644
|
|
-{
|
4645
|
|
- unsigned n;
|
4646
|
|
-
|
4647
|
|
- if( cmBinMtxFileIsValid(p->bmf) == false )
|
4648
|
|
- return;
|
4649
|
|
-
|
4650
|
|
- if((n = _cmFrqTrkActiveChCount(p)) > 0 )
|
4651
|
|
- {
|
4652
|
|
- unsigned i,j;
|
4653
|
|
- unsigned nn = n*4;
|
4654
|
|
- cmReal_t* v = cmMemAllocZ(cmReal_t,nn);
|
4655
|
|
- cmReal_t* idV = v + n * 0;
|
4656
|
|
- cmReal_t* hzV = v + n * 1;
|
4657
|
|
- cmReal_t* dbV = v + n * 2;
|
4658
|
|
- cmReal_t* stV = v + n * 3;
|
4659
|
|
-
|
4660
|
|
- for(i=0,j=0; i<p->a.chCnt; ++i)
|
4661
|
|
- if( p->ch[i].activeFl )
|
4662
|
|
- {
|
4663
|
|
- assert(j < n);
|
4664
|
|
-
|
4665
|
|
- idV[j] = p->ch[i].id;
|
4666
|
|
- hzV[j] = p->ch[i].hz;
|
4667
|
|
- dbV[j] = p->ch[i].db;
|
4668
|
|
- stV[j] = p->ch[i].dN;
|
4669
|
|
-
|
4670
|
|
- ++j;
|
4671
|
|
- }
|
4672
|
|
-
|
4673
|
|
- cmBinMtxFileExecR(p->bmf, v, nn );
|
4674
|
|
- }
|
4675
|
|
-}
|
4676
|
|
-
|
4677
|
|
-void _cmFrqTrkPrintChs( const cmFrqTrk* p )
|
4678
|
|
-{
|
4679
|
|
- unsigned i;
|
4680
|
|
- for(i=0; i<p->a.chCnt; ++i)
|
4681
|
|
- {
|
4682
|
|
- cmFrqTrkCh_t* c = p->ch + i;
|
4683
|
|
- printf("%i : %i tN:%i hz:%f db:%f\n",i,c->activeFl,c->tN,c->hz,c->db);
|
4684
|
|
- }
|
4685
|
|
-}
|
4686
|
|
-
|
4687
|
|
-// Used to sort the channels into descending dB order.
|
4688
|
|
-int _cmFrqTrkChCompare( const void* p0, const void* p1 )
|
4689
|
|
-{ return ((cmFrqTrkCh_t*)p0)->db - ((cmFrqTrkCh_t*)p1)->db; }
|
4690
|
|
-
|
4691
|
|
-
|
4692
|
|
-// Return the index of the peak associated with pkiV[i] which best matches the tracker 'c'
|
4693
|
|
-// or cmInvalidIdx if no valid peaks were found.
|
4694
|
|
-// pkiV[ pkN ] holds the indexes into dbV[] and hzV[] which are peaks.
|
4695
|
|
-// Some elements of pkiV[] may be set to cmInvalidIdx if the associated peak has already
|
4696
|
|
-// been selected by another tracker.
|
4697
|
|
-unsigned _cmFrqTrkFindPeak( cmFrqTrk* p, const cmFrqTrkCh_t* c, const cmReal_t* dbV, const cmReal_t* hzV, unsigned* pkiV, unsigned pkN )
|
4698
|
|
-{
|
4699
|
|
- unsigned i,pki;
|
4700
|
|
- cmReal_t d_max = p->a.pkThreshDb;
|
4701
|
|
- unsigned d_idx = cmInvalidIdx;
|
4702
|
|
-
|
4703
|
|
- cmReal_t hz_min = c->hz * pow(2,-p->a.stRange/12.0);
|
4704
|
|
- cmReal_t hz_max = c->hz * pow(2,-p->a.stRange/12.0);
|
4705
|
|
-
|
4706
|
|
- // find the peak with the most energy inside the frequency range hz_min to hz_max.
|
4707
|
|
- for(i=0; i<pkN; ++i)
|
4708
|
|
- if( ((pki = pkiV[i]) != cmInvalidIdx) && hz_min <= hzV[pki] && hzV[pki] <= hz_max && dbV[pki]>d_max )
|
4709
|
|
- {
|
4710
|
|
- d_max= dbV[pki];
|
4711
|
|
- d_idx = i;
|
4712
|
|
- }
|
4713
|
|
-
|
4714
|
|
- return d_idx;
|
4715
|
|
-}
|
4716
|
|
-
|
4717
|
|
-// Extend the existing trackers
|
4718
|
|
-void _cmFrqTrkUpdateChs( cmFrqTrk* p, const cmReal_t* dbV, const cmReal_t* hzV, unsigned* pkiV, unsigned pkN )
|
4719
|
|
-{
|
4720
|
|
- unsigned i;
|
4721
|
|
-
|
4722
|
|
- // sort the channels in descending order
|
4723
|
|
- qsort(p->ch,p->a.chCnt,sizeof(cmFrqTrkCh_t),_cmFrqTrkChCompare);
|
4724
|
|
-
|
4725
|
|
- // for each active channel
|
4726
|
|
- for(i=0; i<p->a.chCnt; ++i)
|
4727
|
|
- {
|
4728
|
|
- cmFrqTrkCh_t* c = p->ch + i;
|
4729
|
|
-
|
4730
|
|
- if( c->activeFl )
|
4731
|
|
- {
|
4732
|
|
- unsigned pki;
|
4733
|
|
-
|
4734
|
|
- // if no matching peak was found to tracker 'c'.
|
4735
|
|
- if((pki = _cmFrqTrkFindPeak(p,c,dbV,hzV,pkiV,pkN)) == cmInvalidIdx )
|
4736
|
|
- {
|
4737
|
|
- c->dN += 1;
|
4738
|
|
- c->tN += 1;
|
4739
|
|
-
|
4740
|
|
- if( c->dN >= p->deadN_max )
|
4741
|
|
- c->activeFl = false;
|
4742
|
|
- }
|
4743
|
|
- else // ... update the tracker using the matching peak
|
4744
|
|
- {
|
4745
|
|
- unsigned j = pkiV[pki];
|
4746
|
|
- c->dN = 0;
|
4747
|
|
- c->db = dbV[ j ];
|
4748
|
|
- c->hz = hzV[ j ];
|
4749
|
|
- c->tN += 1;
|
4750
|
|
- pkiV[pki] = cmInvalidIdx; // mark the peak as unavailable.
|
4751
|
|
- }
|
4752
|
|
- }
|
4753
|
|
- }
|
4754
|
|
-}
|
4755
|
|
-
|
4756
|
|
-// Return the index into pkiV[] of the maximum energy peak in dbV[]
|
4757
|
|
-// that is also above kAtkThreshDb.
|
4758
|
|
-unsigned _cmFrqTrkMaxEnergyPeakIndex( const cmFrqTrk* p, const cmReal_t* dbV, const unsigned* pkiV, unsigned pkN )
|
4759
|
|
-{
|
4760
|
|
- cmReal_t mv = p->a.pkAtkThreshDb;
|
4761
|
|
- unsigned mi = cmInvalidIdx;
|
4762
|
|
- unsigned i;
|
4763
|
|
-
|
4764
|
|
- for(i=0; i<pkN; ++i)
|
4765
|
|
- if( pkiV[i] != cmInvalidIdx && dbV[pkiV[i]] >= mv )
|
4766
|
|
- {
|
4767
|
|
- mi = i;
|
4768
|
|
- mv = dbV[pkiV[i]];
|
4769
|
|
- }
|
4770
|
|
-
|
4771
|
|
- return mi;
|
4772
|
|
-}
|
4773
|
|
-
|
4774
|
|
-// start new trackers
|
4775
|
|
-void _cmFrqTrkNewChs( cmFrqTrk* p, const cmReal_t* dbV, const cmReal_t* hzV, unsigned* pkiV, unsigned pkN )
|
4776
|
|
-{
|
4777
|
|
-
|
4778
|
|
- while(1)
|
4779
|
|
- {
|
4780
|
|
- unsigned db_max_idx;
|
4781
|
|
- cmFrqTrkCh_t* c;
|
4782
|
|
-
|
4783
|
|
- if((c = _cmFrqTrkFindAvailCh(p)) == NULL )
|
4784
|
|
- break;
|
4785
|
|
-
|
4786
|
|
- if((db_max_idx = _cmFrqTrkMaxEnergyPeakIndex(p,dbV,pkiV,pkN)) == cmInvalidIdx )
|
4787
|
|
- break;
|
4788
|
|
-
|
4789
|
|
- c->activeFl = true;
|
4790
|
|
- c->tN = 1;
|
4791
|
|
- c->dN = 0;
|
4792
|
|
- c->hz = hzV[ pkiV[ db_max_idx ] ];
|
4793
|
|
- c->db = dbV[ pkiV[ db_max_idx ] ];
|
4794
|
|
- c->id = p->nextTrkId++;
|
4795
|
|
-
|
4796
|
|
- pkiV[ db_max_idx ] = cmInvalidIdx;
|
4797
|
|
- }
|
4798
|
|
-
|
4799
|
|
-}
|
4800
|
|
-
|
4801
|
|
-
|
4802
|
|
-cmRC_t cmFrqTrkExec( cmFrqTrk* p, const cmReal_t* magV, const cmReal_t* phsV, const cmReal_t* hzV )
|
4803
|
|
-{
|
4804
|
|
- cmRC_t rc = cmOkRC;
|
4805
|
|
-
|
4806
|
|
- // convert magV to Decibels
|
4807
|
|
- cmVOR_AmplitudeToDb(p->dbV,p->bN,magV);
|
4808
|
|
-
|
4809
|
|
- // copy p->dbV to dbM[hi,:]
|
4810
|
|
- cmVOR_CopyN(p->dbM + p->hi, p->hN, p->bN, p->dbV, 1 );
|
4811
|
|
-
|
4812
|
|
- // increment hi
|
4813
|
|
- p->hi = (p->hi + 1) % p->hN;
|
4814
|
|
-
|
4815
|
|
- // Form the spectral magnitude profile by taking the mean over time
|
4816
|
|
- // of the last hN magnitude vectors
|
4817
|
|
- cmVOR_MeanM(p->dbV, p->dbM, p->hN, p->bN, 0);
|
4818
|
|
-
|
4819
|
|
- // set the indexes of the peaks above pkThreshDb in i0[]
|
4820
|
|
- unsigned pkN = cmVOR_PeakIndexes(p->pkiV, p->bN, p->dbV, p->bN, p->a.pkThreshDb );
|
4821
|
|
-
|
4822
|
|
- // extend the existing trackers
|
4823
|
|
- _cmFrqTrkUpdateChs(p, p->dbV, hzV, p->pkiV, pkN );
|
4824
|
|
-
|
4825
|
|
- // create new trackers
|
4826
|
|
- _cmFrqTrkNewChs(p,p->dbV,hzV,p->pkiV,pkN);
|
4827
|
|
-
|
4828
|
|
- return rc;
|
4829
|
|
-}
|
4830
|
|
-
|
4831
|
|
-void cmFrqTrkPrint( cmFrqTrk* p )
|
4832
|
|
-{
|
4833
|
|
- printf("srate: %f\n",p->a.srate);
|
4834
|
|
- printf("chCnt: %i\n",p->a.chCnt);
|
4835
|
|
- printf("binCnt: %i\n",p->a.binCnt);
|
4836
|
|
- printf("hopSmpCnt: %i\n",p->a.hopSmpCnt);
|
4837
|
|
- printf("stRange: %f\n",p->a.stRange);
|
4838
|
|
- printf("wndSecs: %f (%i)\n",p->a.wndSecs,p->hN);
|
4839
|
|
- printf("minTrkSec: %f (%i)\n",p->a.minTrkSec,p->minTrkN);
|
4840
|
|
- printf("maxTrkDeadSec: %f (%i)\n",p->a.maxTrkDeadSec,p->deadN_max);
|
4841
|
|
- printf("pkThreshDb: %f\n",p->a.pkThreshDb);
|
4842
|
|
- printf("pkAtkThreshDb: %f\n",p->a.pkAtkThreshDb);
|
4843
|
|
-
|
4844
|
|
-}
|