Browse Source

cmProc5.h/c : Added cmPhat. Does not yet compile.

master
kevin 9 years ago
parent
commit
384dc72cc1
2 changed files with 601 additions and 0 deletions
  1. 516
    0
      cmProc5.c
  2. 85
    0
      cmProc5.h

+ 516
- 0
cmProc5.c View File

@@ -342,4 +342,520 @@ cmRC_t cmGoldSigGen( cmGoldSig_t* p, unsigned chIdx, unsigned prefixN, unsigned
342 342
 }
343 343
 
344 344
 
345
+//=======================================================================================================================
346
+cmPhat_t*   cmPhatAlloc(  cmCtx* ctx, cmPhat_t* p, unsigned chN, unsigned hN, float alpha, unsigned mult, unsigned flags )
347
+{
348
+  cmPhat_t* op = cmObjAlloc(cmPhat_t,ctx,p);
349
+
350
+  // The FFT buffer and the delay line is at least twice the size of the 
351
+  // id signal. This will guarantee that at least one complete id signal
352
+  // is inside the buffer.  In practice it means that it is possible
353
+  // that there will be two id's in the buffer therefore if there are
354
+  // two correlation spikes it is important that we take the second.
355
+  p->fhN = cmNextPowerOfTwo(mult*hN);
356
+
357
+  // allocate the FFT object
358
+  cmFftAllocSR(ctx,&p->fft,NULL,p->fhN,kToPolarFftFl);
359
+  
360
+  if( chN != 0 )  
361
+    if( cmPhatInit(op,chN,hN,alpha,mult,flags) != cmOkRC )
362
+      cmPhatFree(&op);
363
+
364
+  return op;
365
+
366
+}
367
+
368
+cmRC_t   cmPhatFree(   cmPhat_t** pp )
369
+{
370
+  cmRC_t rc = cmOkRC;
371
+
372
+  if( pp == NULL || *pp == NULL )
373
+    return rc;
374
+
375
+  cmPhat_t* p = *pp;
376
+  if((rc = cmPhatFinal(p)) != cmOkRC )
377
+    return rc;
378
+
379
+  cmMemFree(p->t0V);
380
+  cmMemFree(p->t1V);
381
+  cmMemFree(p->dV);
382
+  cmMemFree(p->xV);
383
+  cmMemFree(p->fhM);
384
+  cmMemFree(p->mhM);
385
+  cmMemFree(p->wndV);
386
+  cmObjFreeStatic(cmFftFreeSR, cmFftSR, p->fft);
387
+  cmVectArrayFree(&p->ftVa);
388
+  cmObjFree(pp);
389
+
390
+  return rc;
391
+
392
+}
393
+
394
+
395
+cmRC_t   cmPhatInit(  cmPhat_t* p, unsigned chN, unsigned hN, float alpha, unsigned mult, unsigned flags )
396
+{
397
+  cmRC_t   rc = cmOkRC;
398
+  if((rc = cmPhatFinal(cmOkRC)) != cmOkRC )
399
+    return rc;
400
+
401
+  p->fhN = cmNextPowerOfTwo(mult*hN);
402
+  
403
+  if((cmFftInitSR(&p->fft, NULL, p->fhN, kToPolarFftFl)) != cmOkRC )
404
+    return rc;
405
+
406
+  p->alpha = alpha;
407
+  p->flags = flags;
408
+
409
+  // allocate the delay line
410
+  p->dV = cmMemResizeZ(cmSample_t,p->dV,p->fhN);
411
+  p->di = 0;
412
+
413
+  // allocate the linear buffer
414
+  p->xV  = cmMemResizeZ(cmSample_t,p->xV,p->fhN);
415
+  p->t0V = cmMemResizeZ(cmComplexR_t,p->t0V,p->fhN);
416
+  p->t1V = cmMemResizeZ(cmComplexR_t,p->t1V,p->fhN);
417
+
418
+  // allocate the window function
419
+  p->wndV = cmMemResizeZ(cmSample_t,p->wndV,p->fhN);
420
+  cmVOS_Hann(p->wndV,p->fhN);
421
+
422
+  // allocate the signal id matrix
423
+  p->chN = chN;
424
+  p->hN  = hN;
425
+  p->binN = p->fft.binCnt; //atFftRealBinCount(p->fftH);
426
+  p->fhM = cmMemResizeZ(cmComplexR_t, p->fhM, p->fhN  * chN);
427
+  p->mhM = cmMemResizeZ(float,        p->mhM, p->binN * chN);
428
+  cmPhatReset(p);
429
+
430
+  //if( cmIsFlag(p->flags,kDebugAtPhatFl)) 
431
+  //  cmVectArrayAlloc(ctx, &p->ftVa,  kSampleVaFl );
432
+  //else
433
+  //  p->ftVa = NULL;
434
+
435
+  return rc;
436
+
437
+}
438
+
439
+cmRC_t cmPhatFinal( cmPhat_t* p )
440
+{ return cmOkRC; }
441
+
442
+cmRC_t cmPhatReset(  cmPhat_t* p )
443
+{
444
+  p->di     = 0;
445
+  p->absIdx = 0;
446
+  cmVOS_Zero(p->dV,p->fhN);
447
+  return cmOkRC;
448
+}
449
+
450
+cmRC_t cmPhatSetId(  cmPhat_t* p, unsigned chIdx, const cmSample_t* hV, unsigned hN )
451
+{
452
+  unsigned i;
453
+  assert( chIdx < p->chN );
454
+  assert( hN == p->hN );
455
+
456
+  // Allocate a window vector
457
+  cmSample_t* wndV = cmMemAllocZ(cmSample_t,hN);
458
+  cmVOS_Hann(wndV,hN);
459
+
460
+  // get ptr to output column in p->fhM[].
461
+  cmComplexR_t* yV = p->fhM + (chIdx*p->fhN);
462
+
463
+  // Zero pad hV[hN] to p->fhN;
464
+  assert( hN <= p->fhN );
465
+  cmVOS_Zero(p->xV,p->fhN);
466
+  cmVOS_Copy(p->xV,hV,hN);
467
+
468
+  // Apply the window function to the id signal
469
+  if(atIsFlag(p->flags,kHannAtPhatFl) )
470
+    cmVOS_MultVVV(p->xV,hV,wndV,hN);
345 471
 
472
+  // take FFT of id signal. The result is in fft->complexV and fft->magV,phsV
473
+  cmFftExecSR(p->fft, p->xV, p->fhN );
474
+
475
+  // Store the magnitude of the id signal
476
+  //atFftComplexAbs(p->mhM + (chIdx*p->binN), yV,     p->binN);
477
+  cmVOR_Copy(p->mhM + (chIdx*p->binN), p->fft->magV, p->binN );
478
+
479
+  // Scale the magnitude
480
+  cmVOS_MultVS(   p->mhM + (chIdx*p->binN), p->binN, p->alpha);
481
+
482
+  // store the complex conjugate of the FFT result in yV[]
483
+  //atFftComplexConj(yV,p->binN);
484
+  for(i=0; i<p->binN; ++i)
485
+    yV[i].i = -(p->fft->complexV[i].i);
486
+
487
+  cmMemFree(wndV);
488
+
489
+  return kOkAtRC;
490
+}
491
+
492
+cmSample_t* _cmPhatReadVector( cmCtx* ctx, cmPhat_t* p, const char* fn, unsigned* vnRef )
493
+{
494
+  cmVectArray_t* vap = NULL;
495
+  cmSample_t*    v   = NULL;
496
+  
497
+  // instantiate a VectArray from a file
498
+  if( cmVectArrayAllocFromFile(ctx, &vap, fn ) != kOkAtRC )
499
+  {
500
+    atErrMsg(&p->obj.err,kFileReadFailAtRC,"Id component vector file read failed '%s'.",fn);
501
+    goto errLabel;
502
+  }
503
+
504
+  // get the count of elements in the vector
505
+  *vnRef = cmVectArrayEleCount(vap);
506
+
507
+  // allocate memory to hold the vector
508
+  v = cmMemAlloc(&p->obj.err,cmSample_t,*vnRef);
509
+
510
+  // copy the vector from the vector array object into v[]
511
+  if( cmVectArrayGetF(vap,v,vnRef) != kOkAtRC )
512
+  {
513
+    cmMemFree(v);
514
+    v = NULL;
515
+    atErrMsg(&p->obj.err,kFileReadFailAtRC,"Id component vector copy out failed '%s'.",fn);
516
+    goto errLabel;
517
+  }
518
+
519
+  cmRptPrintf(p->obj.err.rpt,"%i : %s",*vnRef,fn);
520
+  
521
+
522
+ errLabel:
523
+  cmVectArrayFree(&vap);
524
+
525
+  return v;
526
+}
527
+
528
+
529
+cmRC_t   cmPhatExec(   cmPhat_t* p, const cmSample_t* xV, unsigned xN )
530
+{
531
+  unsigned n = atMin(xN,p->fhN-p->di);
532
+
533
+  // update the delay line
534
+  cmVOS_Copy(p->dV+p->di,xV,n);
535
+
536
+  if( n < xN )
537
+    cmVOS_Copy(p->dV,xV+n,xN-n);
538
+
539
+  p->di      = atModIncr(p->di,xN,p->fhN);
540
+
541
+  // p->absIdx is the absolute sample index associated with di
542
+  p->absIdx += xN;  
543
+
544
+  return kOkAtRC;
545
+}
546
+
547
+
548
+void cmPhatChExec( 
549
+    cmPhat_t* p, 
550
+    unsigned  chIdx,
551
+    unsigned  sessionId,
552
+    unsigned  roleId)
553
+{
554
+
555
+  unsigned n0 = p->fhN - p->di;
556
+  unsigned n1 = p->fhN - n0;
557
+
558
+  // Linearize the delay line into xV[]
559
+  cmVOS_Copy(p->xV,    p->dV + p->di, n0 );
560
+  cmVOS_Copy(p->xV+n0, p->dV,         n1 );
561
+
562
+  if( atIsFlag(p->flags,kDebugAtPhatFl)) 
563
+    cmVectArrayAppendS(p->ftVa, p->xV, p->fhN );
564
+
565
+  // apply a window function to the incoming signal
566
+  if( atIsFlag(p->flags,kHannAtPhatFl) )
567
+    cmVOS_MultVV(p->xV,p->fhN,p->wndV);
568
+  
569
+  // Take the FFT of the delay line.
570
+  // p->t0V[p->binN] = fft(p->xV)
571
+  //atFftRealForward(p->fftH, p->xV, p->fhN, p->t0V, p->binN );
572
+  cmFftExecSR(p->fft, p->xV, p->fhN );
573
+ 
574
+  // Calc. the Cross Power Spectrum (aka cross spectral density) of the
575
+  // input signal with the id signal.
576
+  // Note that the CPS is equivalent to the Fourier Transform of the
577
+  // cross-correlation of the two signals.
578
+  // t0V[] *= p->fhM[:,chIdx]
579
+  //atFftComplexMult( p->t0V, p->fhM + (chIdx * p->fhN), p->binN );
580
+  cmVOCR_MultVVV( p->t0V, p->fft->complexV, p->fhM + (chIdx * p->fhN), p->binN)
581
+  
582
+  // Calculate the magnitude of the CPS.
583
+  // xV[] = | t0V[] |
584
+  cmVOCR_Abs( p->xV, p->t0V, p->binN );
585
+  
586
+  // Weight the CPS by the scaled magnitude of the id signal
587
+  // (we want to emphasize the limited frequencies where the
588
+  //  id signal contains energy)
589
+  // t0V[] *= p->mhM[:,chIdx]
590
+  if( p->alpha > 0 )
591
+    cmVOCR_MultR_VV( p->t0V, p->mhM + (chIdx*p->binN), p->binN);
592
+
593
+  // Divide through by the magnitude of the CPS
594
+  // This has the effect of whitening the spectram and thereby
595
+  // minimizing the effect of the magnitude correlation 
596
+  // while maximimizing the effect of the phase correlation.
597
+  // 
598
+  // t0V[] /= xV[]
599
+  cmVOCR_DivR_VV( p->t0V, p->xV, p->binN );
600
+  
601
+  // Take the IFFT of the weighted CPS to recover the cross correlation.
602
+  // xV[] = IFFT(t0V[])
603
+
604
+
605
+  //// ***** atFftRealInverse( p->fftH, p->t0V, p->xV, p->fhN );
606
+  
607
+  // Shift the correlation spike to mark the end of the id
608
+  cmVOS_Rotate( p->xV, p->fhN, -((int)p->hN) );
609
+
610
+  // normalize by the length of the correlation
611
+  cmVOS_DivVS(p->xV,p->fhN,p->fhN);
612
+
613
+  if( atIsFlag(p->flags,kDebugAtPhatFl))
614
+  {
615
+    cmVectArrayAppendS(p->ftVa, p->xV, p->fhN );
616
+
617
+    cmSample_t v[] = { sessionId, roleId };
618
+    cmVectArrayAppendS(p->ftVa, v, sizeof(v)/sizeof(v[0]));
619
+  }
620
+
621
+}
622
+
623
+cmRC_t cmPhatWrite( cmPhat_t* p, const char* dirStr )
624
+{
625
+  cmRC_t rc = kOkAtRC;
626
+  
627
+  if( atIsFlag(p->flags, kDebugAtPhatFl)) 
628
+  {
629
+    char* path = NULL;
630
+
631
+    if( p->ftVa != NULL )
632
+      if((rc = cmVectArrayWrite(p->ftVa, path = atMakePath(&p->obj.err,path,"cmPhatFT","va",dirStr,NULL) )) != kOkAtRC )
633
+        rc = atErrMsg(&p->obj.err,rc,"PHAT debug file write failed.");
634
+    
635
+    cmMemFree(path);
636
+  }
637
+  
638
+  return rc;
639
+}
640
+
641
+
642
+cmRC_t cmPhatTest1( cmCtx* ctx, const char* dirStr )
643
+{
644
+  cmRC_t         rc             = kOkAtRC;
645
+  atSignalArg_t  sa;
646
+  atSignal_t*    s              = NULL;
647
+  cmPhat_t*      p              = NULL;
648
+  char*          path           = NULL;
649
+  unsigned       dspFrmCnt      = 256;
650
+  unsigned       listenDelaySmp = 8196;
651
+  double         noiseGain      = 0.05;
652
+  unsigned       chIdx          = 0;
653
+  cmSample_t*    yV             = NULL;
654
+  unsigned       yN             = 0;
655
+  double         phatAlpha      = 0.5;
656
+  unsigned       phatMult       = 4.0;
657
+  double         nonLinExpo     = 4.0;
658
+  cmVectArray_t* outVA          = NULL; 
659
+  cmVectArray_t* inVA           = NULL;
660
+  cmVectArray_t* statusVA       = NULL;
661
+  unsigned       bsiN           = 4;
662
+  unsigned       bsiV[bsiN];  // known signal onset in absolute samples 
663
+  unsigned       esiV[bsiN];  // known signal offset
664
+  unsigned       lsiV[bsiN];  // end of listen time (when cmPhatChExec()) is run.
665
+  unsigned       dsiV[bsiN];  // detection time
666
+  unsigned       i,j;
667
+  
668
+  sa.chN             =     1;
669
+  sa.srate           = 44100.0;
670
+  sa.lfsrN           =     8;
671
+  sa.mlsCoeff0       =  0x8e;
672
+  sa.mlsCoeff1       =  0x96;
673
+  sa.samplesPerChip  =    64;
674
+  sa.rcosBeta        =     0.5;
675
+  sa.rcosOSFact      =     4;
676
+  sa.carrierHz       = 17000.0;
677
+  sa.envMs           =    50.0;
678
+  
679
+  // allocate the the id signals
680
+  if( atSignalAlloc( ctx, &s, &sa ) != kOkAtRC )
681
+    return atErrMsg(&ctx->err, kTestFailAtRC, "Signal allocate failed.");
682
+
683
+  // set the post signal listen delay to half the signal length
684
+  listenDelaySmp = s->sigN/2; 
685
+
686
+  // allocate a PHAT detector
687
+  if( cmPhatAlloc(ctx,&p,sa.chN,s->sigN, phatAlpha, phatMult, kDebugAtPhatFl ) != kOkAtRC )
688
+  {
689
+    rc = atErrMsg(&ctx->err, kTestFailAtRC, "PHAT allocate failed.");
690
+    goto errLabel;
691
+  }
692
+
693
+  // register an id signal with the PHAT detector
694
+  if( cmPhatSetId(p, chIdx, s->ch[chIdx].mdV, s->sigN ) != kOkAtRC )
695
+  {
696
+    rc = atErrMsg(&ctx->err, kTestFailAtRC, "PHAT setId failed.");
697
+    goto errLabel;
698
+  }
699
+
700
+  // generate an input test signal containing bsiN id signals
701
+  if( atSignalGen(s,chIdx,p->fhN,s->sigN,bsiV,bsiN,noiseGain,&yV,&yN) != kOkAtRC )
702
+  {
703
+    rc = atErrMsg(&ctx->err,kTestFailAtRC,"Signal generation failed.");
704
+    goto errLabel;
705
+  }
706
+
707
+  // bsiV[] now holds signal onsets. Set esiV[] to  signal offsets.
708
+  atVOU_AddVVS(esiV,bsiV,bsiN,s->sigN );
709
+
710
+  // set lsiV[] to end-of-listen location 
711
+  atVOU_AddVVS(lsiV,esiV,bsiN,listenDelaySmp);
712
+
713
+  // zero the detection vector
714
+  atVOU_Zero(dsiV,bsiN);
715
+
716
+  // allocate a vector array to record the PHAT input signals
717
+  if( cmVectArrayAlloc(ctx,&inVA,kSampleVaFl) != kOkAtRC )
718
+  {
719
+    rc = atErrMsg(&ctx->err, kTestFailAtRC, "vectArray inVA alloc failed.");
720
+    goto errLabel;
721
+  }
722
+
723
+  // allocate a vector array to record the PHAT correlation output signals
724
+  if( cmVectArrayAlloc(ctx,&outVA,kSampleVaFl) != kOkAtRC )
725
+  {
726
+    rc = atErrMsg(&ctx->err, kTestFailAtRC, "vectArray outVA alloc failed.");
727
+    goto errLabel;
728
+  }
729
+
730
+  // allocate a vector array to record the PHAT status
731
+  if( cmVectArrayAlloc(ctx,&statusVA,kSampleVaFl) != kOkAtRC )
732
+  {
733
+    rc = atErrMsg(&ctx->err, kTestFailAtRC, "vectArray statusVA alloc failed.");
734
+    goto errLabel;
735
+  }
736
+
737
+  
738
+  // for each 'dspFrmCnt' samples in the input signal
739
+  for(i=0,j=0; j<bsiN && i<=yN-dspFrmCnt; i+=dspFrmCnt)
740
+  {
741
+    // store a copy of the input signal
742
+    cmVectArrayAppendS(inVA,yV+i,dspFrmCnt);
743
+
744
+    // feed the next dspFrmCnt samples to the PHAT detector
745
+    cmPhatExec(p,yV+i,dspFrmCnt);
746
+
747
+    // if the approximate end of an id signal is encountered
748
+    if( lsiV[j] <= i && i < lsiV[j] + dspFrmCnt )
749
+    {
750
+      // execute the PHAT correlator
751
+      cmPhatChExec( p, chIdx, -1, -1 );
752
+
753
+      // apply non-linear exponent to the correlation vector
754
+      cmVOS_PowV(p->xV,p->fhN,nonLinExpo);
755
+
756
+      // locate the corr. peak inside the listening window
757
+      // (the detection window is last 'detectWndSmp' samples in the corr. vector )
758
+      unsigned detectWndSmp = 2*listenDelaySmp;
759
+      dsiV[j] = cmVOS_ArgMax( p->xV + p->fhN - detectWndSmp,  detectWndSmp);
760
+
761
+      // convert the pk index to absolute time
762
+      dsiV[j] = i + dspFrmCnt - detectWndSmp + dsiV[j];
763
+
764
+      //                 sig beg  sig end  detect begin          dtct end    detect
765
+      cmSample_t v[] = { bsiV[j], esiV[j], lsiV[j]-detectWndSmp, lsiV[j],    dsiV[j] };
766
+
767
+      // store the detection information
768
+      cmVectArrayAppendS(statusVA,v,sizeof(v)/sizeof(v[0]));
769
+
770
+      // store the correlation output vector
771
+      cmVectArrayAppendS(outVA,p->xV,p->fhN);
772
+      
773
+      j += 1;
774
+    }
775
+  }
776
+
777
+  // write inVA
778
+  if( cmVectArrayWrite(inVA,path = atMakePath(&ctx->err,path,"phatIn","va",dirStr,NULL)) != kOkAtRC )
779
+  {
780
+    rc = atErrMsg(&ctx->err, kTestFailAtRC, "vectArray outVA write failed.");
781
+    goto errLabel;
782
+  }
783
+
784
+  // write outVA
785
+  if( cmVectArrayWrite(outVA,path = atMakePath(&ctx->err,path,"phatOut","va",dirStr,NULL)) != kOkAtRC )
786
+  {
787
+    rc = atErrMsg(&ctx->err, kTestFailAtRC, "vectArray outVA write failed.");
788
+    goto errLabel;
789
+  }
790
+
791
+  // write statusVA
792
+  if( cmVectArrayWrite(statusVA,path = atMakePath(&ctx->err,path,"phatStatus","va",dirStr,NULL)) != kOkAtRC )
793
+  {
794
+    rc = atErrMsg(&ctx->err, kTestFailAtRC, "vectArray statusVA write failed.");
795
+    goto errLabel;
796
+  }
797
+
798
+ errLabel:
799
+  cmVectArrayFree(&outVA);
800
+  cmVectArrayFree(&inVA);
801
+
802
+  if( cmPhatFree(&p) != kOkAtRC )
803
+    atErrMsg(&ctx->err,kTestFailAtRC,"PHAT free failed.");
804
+
805
+  if( atSignalFree(&s) != kOkAtRC )
806
+    atErrMsg(&ctx->err,kTestFailAtRC,"Signal free failed.");
807
+
808
+  return rc;
809
+}
810
+
811
+cmRC_t cmPhatTest2( cmCtx* ctx )
812
+{
813
+  cmRC_t    rc    = kOkAtRC;
814
+  cmPhat_t* p     = NULL;
815
+  unsigned  hN    = 16;
816
+  float     alpha = 1.0;
817
+  unsigned  mult  = 4;
818
+
819
+  cmSample_t hV[]  = { 4,3,2,1, 0,0,0,0, 0,0,0,0, 0,0,0,0 };
820
+  cmSample_t x0V[] = { 4,3,2,1, 0,0,0,0, 0,0,0,0, 0,0,0,0 };
821
+  cmSample_t x1V[] = { 0,0,0,0, 4,3,2,1, 0,0,0,0, 0,0,0,0 };
822
+  cmSample_t x2V[] = { 0,0,0,0, 0,0,0,0, 4,3,2,1, 0,0,0,0 };
823
+  cmSample_t x3V[] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 4,3,2,1 };
824
+
825
+  cmSample_t* xV[] = { x0V, x1V, x2V, x3V };
826
+  unsigned    chN  = sizeof(xV)/sizeof(xV[0]);
827
+  unsigned    i;
828
+  
829
+  if(cmPhatAlloc(ctx,&p,chN,hN,alpha,mult,kNoFlagsAtPhatFl) != kOkAtRC )
830
+  {
831
+    rc = atErrMsg(&ctx->err,kTestFailAtRC,"cmPhatAlloc() failed.");
832
+    goto errLabel;
833
+  }
834
+
835
+  for(i=0; i<chN; ++i)
836
+    if( cmPhatSetId(p,i,hV,hN) != kOkAtRC )
837
+      rc = atErrMsg(&ctx->err,kTestFailAtRC,"cmPhatSetId() failed.");
838
+  
839
+  
840
+  for(i=0; i<chN; ++i)
841
+  {
842
+    cmPhatReset(p);
843
+    
844
+    if( cmPhatExec(p,xV[i],hN) != kOkAtRC )
845
+    {
846
+      rc = atErrMsg(&ctx->err,kTestFailAtRC,"cmPhatExec() failed.");
847
+      goto errLabel;
848
+    }
849
+
850
+    cmPhatChExec(p, i, -1, -1);
851
+    cmVOS_PrintL(&ctx->printRpt,"x:",p->xV,1,p->fhN);
852
+  }
853
+
854
+
855
+  errLabel:
856
+
857
+  cmPhatFree(&p);
858
+
859
+    
860
+  return rc;
861
+}

+ 85
- 0
cmProc5.h View File

@@ -108,6 +108,91 @@ extern "C" {
108 108
 
109 109
   cmRC_t cmGoldSigTest( cmCtx* ctx );
110 110
 
111
+
112
+  //=======================================================================================================================
113
+  // Phase aligned transform generalized cross correlator
114
+  //
115
+
116
+  // Flags for use with the 'flags' argument to cmPhatAlloc() 
117
+  enum
118
+  {
119
+    kNoFlagsAtPhatFl= 0x00,
120
+    kDebugAtPhatFl  = 0x01,  // generate debugging file
121
+    kHannAtPhatFl   = 0x02   // apply a hann window function to the id/audio signals prior to correlation. 
122
+  };
123
+
124
+  typedef struct
125
+  {
126
+    cmObj            obj;
127
+    cmFftSR          fft;
128
+    
129
+    float            alpha;
130
+    unsigned         flags;
131
+
132
+    cmComplexR_t*    fhM;      // fhM[fhN,chN]  FT of each id signal stored in complex form
133
+    float*           mhM;      // mhM[binN,chN]  magnitude of each fhM column
134
+    unsigned         chN;      // count of id signals
135
+    unsigned         fhN;      // length of each FT id signal (fft->xN)
136
+    unsigned        binN;      // length of each mhM column (fft->xN/2);
137
+    unsigned          hN;      // length of each time domain id signal (hN<=fhN/2)
138
+
139
+    unsigned         absIdx;   // abs. sample index of p->di
140
+
141
+    cmSample_t*      dV;       // dV[fhN] delay line
142
+    unsigned         di;       // next input into delay line
143
+
144
+    cmSample_t*      xV;       // xV[fhN] linear delay buffer
145
+    cmComplexR_t*   t0V;       // t0V[fhN]
146
+    cmComplexR_t*   t1V;       // t1V[fhN]
147
+
148
+    cmSample_t*      wndV;
149
+
150
+    cmVectArray_t*   ftVa; 
151
+
152
+  } cmPhat_t;
153
+
154
+
155
+  // Allocate a PHAT based multi-channel correlator.
156
+  // 'chN'  is the maximum count of id signals to be set via cmPhatSetId().
157
+  // 'hN' is the the length of the id signal in samples.
158
+  // 'alpha' weight used to emphasize the frequencies where the
159
+  // id signal contains energy.
160
+  // 'mult' * 'hN' is the correlation length (fhN)
161
+  // 'flags' See kDebugAtPhatFl and kWndAtPhatFl.
162
+  cmPhat_t* cmPhatAlloc(  cmCtx* ctx, cmPhat_t* pp, unsigned chN, unsigned hN, float alpha, unsigned mult, unsigned flags );
163
+  cmRC_t    cmPhatFree(   cmPhat_t** pp );
164
+
165
+  cmRC_t   cmPhatInit(  cmPhat_t* p, unsigned chN, unsigned hN, float alpha, unsigned mult, unsigned flags );  
166
+  cmRC_t   cmPhatFinal( cmPhat_t* p );
167
+
168
+  // Zero the audio delay line and reset the current input sample (di)
169
+  // and absolute time index (absIdx) to 0.
170
+  cmRC_t   cmPhatReset(  cmPhat_t* p );
171
+
172
+  // Register an id signal with the correlator.
173
+  cmRC_t   cmPhatSetId(  cmPhat_t* p, unsigned chIdx, const cmSample_t* hV, unsigned hN );
174
+
175
+  // Update the correlators internal delay buffer.
176
+  cmRC_t   cmPhatExec(   cmPhat_t* p, const cmSample_t* xV, unsigned xN );
177
+
178
+  // Set p->xV[0:fhN-1] to the correlation function based on
179
+  // correlation between the current audio delay line d[] and
180
+  // the id signal in fhM[:,chIdx].
181
+  // 'sessionId' and 'roleId' are only used to label the
182
+  // data stored in the debug file and may be set to any
183
+  // arbitrary value if the debug files are not being generated.
184
+  void cmPhatChExec( 
185
+    cmPhat_t* p,
186
+    unsigned  chIdx,
187
+    unsigned  sessionId,
188
+    unsigned  roleId);
189
+
190
+
191
+  cmRC_t cmPhatWrite( cmPhat_t* p, const char* dirStr );
192
+
193
+  cmRC_t cmPhatTest1( cmCtx* ctx, const char* dirFn );
194
+  cmRC_t cmPhatTest2( cmCtx* ctx );
195
+
111 196
   
112 197
 #ifdef __cplusplus
113 198
 }

Loading…
Cancel
Save