Переглянути джерело

Merge branch 'master' of klarke.webfactional.com:webapps/git/repos/libcm

master
Kevin Larke 9 роки тому
джерело
коміт
1f74830cb8
15 змінених файлів з 1380 додано та 45 видалено
  1. 1
    1
      Makefile.am
  2. 3
    1
      cmAudioPort.c
  3. 60
    0
      cmComplexTypes.c
  4. 12
    0
      cmComplexTypes.h
  5. 142
    1
      cmMath.c
  6. 43
    0
      cmMath.h
  7. 1
    1
      cmProc.c
  8. 48
    9
      cmProc2.c
  9. 21
    7
      cmProc2.h
  10. 743
    0
      cmProc5.c
  11. 155
    0
      cmProc5.h
  12. 1
    1
      dsp/cmDspKr.c
  13. 4
    0
      dsp/cmDspPgm.c
  14. 2
    2
      dsp/cmDspPgmKr.c
  15. 144
    22
      linux/cmAudioPortAlsa.c

+ 1
- 1
Makefile.am Переглянути файл

@@ -4,7 +4,7 @@ cmHDR =
4 4
 cmSRC = 
5 5
 
6 6
 cmHDR += src/libcm/cmErr.h src/libcm/cmCtx.h src/libcm/cmRpt.h src/libcm/cmGlobal.h src/libcm/cmComplexTypes.h src/libcm/cmFloatTypes.h src/libcm/cmPrefix.h
7
-cmSRC += src/libcm/cmErr.c src/libcm/cmCtx.c src/libcm/cmRpt.c src/libcm/cmGlobal.c 
7
+cmSRC += src/libcm/cmErr.c src/libcm/cmCtx.c src/libcm/cmRpt.c src/libcm/cmGlobal.c src/libcm/cmComplexTypes.c
8 8
 
9 9
 cmHDR += src/libcm/cmSerialize.h src/libcm/cmSymTbl.h src/libcm/cmHashTbl.h src/libcm/cmFileSys.h src/libcm/cmFile.h 
10 10
 cmSRC += src/libcm/cmSerialize.c src/libcm/cmSymTbl.c src/libcm/cmHashTbl.c src/libcm/cmFileSys.c src/libcm/cmFile.c 

+ 3
- 1
cmAudioPort.c Переглянути файл

@@ -363,6 +363,8 @@ void cmApReport( cmRpt_t* rpt )
363 363
   
364 364
     }
365 365
   }
366
+
367
+  //cmApAlsaDeviceReport(rpt);
366 368
 }
367 369
 
368 370
 /// [cmAudioPortExample]
@@ -668,6 +670,7 @@ int cmApPortTest( bool runFl, cmRpt_t* rpt, int argc, const char* argv[] )
668 670
 
669 671
 
670 672
   runFl            = _cmApGetOpt(argc,argv,"-p",!runFl,true)?false:true;
673
+  r.srate          = _cmApGetOpt(argc,argv,"-r",44100,false);
671 674
   r.chIdx          = _cmApGetOpt(argc,argv,"-a",0,false);
672 675
   r.chCnt          = _cmApGetOpt(argc,argv,"-c",2,false);
673 676
   r.bufCnt         = _cmApGetOpt(argc,argv,"-b",3,false);
@@ -685,7 +688,6 @@ int cmApPortTest( bool runFl, cmRpt_t* rpt, int argc, const char* argv[] )
685 688
   r.outDevIdx  = _cmGlobalOutDevIdx = _cmApGetOpt(argc,argv,"-o",2,false); 
686 689
   r.phase      = 0;
687 690
   r.frqHz      = 2000;
688
-  r.srate      = 44100;
689 691
   r.bufInIdx   = 0;
690 692
   r.bufOutIdx  = 0;
691 693
   r.bufFullCnt = 0;

+ 60
- 0
cmComplexTypes.c Переглянути файл

@@ -0,0 +1,60 @@
1
+#include "cmPrefix.h"
2
+#include "cmGlobal.h"
3
+#include "cmFloatTypes.h"
4
+#include "cmComplexTypes.h"
5
+
6
+void cmVOCR_MultVVV( cmComplexR_t* y, const cmComplexS_t* x0, const cmComplexR_t* x1, unsigned n )
7
+{
8
+  unsigned i;
9
+  for(i=0; i<n; ++i)
10
+  {
11
+    y[i] = x0[i] * x1[i];
12
+    /*
13
+    cmReal_t ab = x0[i].r * x1[i].r;
14
+    cmReal_t bd = x0[i].i * x1[i].i;
15
+    cmReal_t bc = x0[i].i * x1[i].r;
16
+    cmReal_t ad = x0[i].r * x1[i].i;
17
+    y[i].r = ab - bd;
18
+    y[i].i = bc + ad;    
19
+    */
20
+  }
21
+
22
+}
23
+
24
+void cmVOCR_MultVFV(  cmComplexR_t* y, const float* x, unsigned n )
25
+{
26
+  unsigned i;
27
+  for(i=0; i<n; ++i)
28
+  {
29
+    y[i] *= x[i];
30
+  }
31
+}
32
+
33
+void cmVOCR_DivVFV(   cmComplexR_t* y, const float* x, unsigned n )
34
+{
35
+  unsigned i;
36
+  for(i=0; i<n; ++i)
37
+  {
38
+    y[i] /= x[i];
39
+  }  
40
+}
41
+
42
+
43
+void cmVOCR_Abs(     cmSample_t* y, const cmComplexR_t* x, unsigned n )
44
+{
45
+  unsigned i;
46
+  for(i=0; i<n; ++i)
47
+    y[i] = (cmSample_t)cmCabsR(x[i]);
48
+}
49
+
50
+
51
+void cmVOCR_DivR_VV(   cmComplexR_t* y, const cmReal_t* x, unsigned n )
52
+{
53
+  unsigned i;
54
+  for(i=0; i<n; ++i)
55
+  {
56
+    y[i] /= x[i];
57
+    //y[i].r /= x[i];
58
+    //y[i].i /= x[i];
59
+  }  
60
+}

+ 12
- 0
cmComplexTypes.h Переглянути файл

@@ -11,6 +11,7 @@
11 11
 #define cmCrealS crealf
12 12
 #define cmCimagS cimagf 
13 13
 #define cmCargS  cargf
14
+#define cmCconjS conjf
14 15
 
15 16
 #define cmFftPlanAllocS   fftwf_plan_dft_r2c_1d
16 17
 #define cmFft1dPlanAllocS fftwf_plan_dft_1d
@@ -29,6 +30,7 @@
29 30
 #define cmCrealS creal
30 31
 #define cmCimagS cimag 
31 32
 #define cmCargS  carg
33
+#define cmCconjS conj
32 34
 
33 35
 #define cmFftPlanAllocS   fftw_plan_dft_r2c_1d
34 36
 #define cmFft1dPlanAllocS fftw_plan_dft_1d
@@ -53,6 +55,7 @@
53 55
 #define cmCrealR crealf
54 56
 #define cmCimagR cimagf 
55 57
 #define cmCargR  cargf
58
+#define cmCconjR conjf
56 59
 
57 60
 #define cmFftPlanAllocR   fftwf_plan_dft_r2c_1d
58 61
 #define cmFft1dPlanAllocR fftwf_plan_dft_1d
@@ -71,6 +74,7 @@
71 74
 #define cmCrealR creal
72 75
 #define cmCimagR cimag 
73 76
 #define cmCargR  carg
77
+#define cmCconjR conj
74 78
 
75 79
 #define cmFftPlanAllocR   fftw_plan_dft_r2c_1d
76 80
 #define cmFft1dPlanAllocR fftw_plan_dft_1d
@@ -84,4 +88,12 @@
84 88
 
85 89
 #endif
86 90
 
91
+void cmVOCR_MultVVV( cmComplexR_t* y, const cmComplexS_t* x0, const cmComplexR_t* x1, unsigned n );
92
+void cmVOCR_MultVFV(  cmComplexR_t* y, const float* x, unsigned n );
93
+void cmVOCR_DivVFV(   cmComplexR_t* y, const float_t* x, unsigned n );
94
+void cmVOCR_Abs(     cmSample_t*   y, const cmComplexR_t* x, unsigned n );
95
+void cmVOCR_MultVS(  cmComplexR_t* y, cmReal_t v, unsigned n );
96
+void cmVOCR_DivVS(   cmComplexR_t* y, cmReal_t v, unsigned n );
97
+
98
+
87 99
 #endif

+ 142
- 1
cmMath.c Переглянути файл

@@ -1,5 +1,10 @@
1 1
 #include "cmPrefix.h"
2 2
 #include "cmGlobal.h"
3
+#include "cmRpt.h"
4
+#include "cmErr.h"
5
+#include "cmCtx.h"
6
+#include "cmMem.h"
7
+#include "cmMallocDebug.h"
3 8
 #include "cmFloatTypes.h"
4 9
 #include "cmMath.h"
5 10
 #include <sys/types.h> // u_char
@@ -149,6 +154,20 @@ unsigned cmPrevOddU(  unsigned v ) { return cmIsOddU(v)  ? v : v-1; }
149 154
 unsigned cmNextEvenU( unsigned v ) { return cmIsEvenU(v) ? v : v+1; }
150 155
 unsigned cmPrevEvenU( unsigned v ) { return cmIsEvenU(v) ? v : v-1; }
151 156
 
157
+unsigned cmModIncr(int idx, int delta, int maxN )
158
+{
159
+  int sum = idx + delta;
160
+
161
+  if( sum >= maxN )
162
+    return sum - maxN;
163
+
164
+  if( sum < 0 )
165
+    return maxN + sum;
166
+
167
+  return sum;
168
+}
169
+
170
+
152 171
 // modified bessel function of first kind, order 0
153 172
 // ref: orfandis appendix B io.m
154 173
 double	cmBessel0( double x )
@@ -464,6 +483,128 @@ bool cmIsCloseU( unsigned x0, unsigned x1, double eps )
464 483
 {
465 484
   if( x0 == x1 )
466 485
     return true;
486
+  if( x0 > x1 )
487
+    return (x0-x1)/(x0+x1) < eps;
488
+  else
489
+    return (x1-x0)/(x0+x1) < eps;
490
+}
491
+
492
+//=================================================================
493
+
494
+// cmLFSR() implementation based on note at bottom of:
495
+// http://www.ece.cmu.edu/~koopman/lfsr/index.html
496
+void cmLFSR( unsigned lfsrN, unsigned tapMask, unsigned seed, unsigned* yV, unsigned yN )
497
+{
498
+  assert( 0 < lfsrN && lfsrN < 32 );
499
+  
500
+  unsigned i;
501
+  for(i=0; i<yN; ++i)
502
+  {
503
+    if( (yV[i] = seed & 1)==1 )
504
+      seed = (seed >> 1) ^ tapMask;
505
+    else
506
+      seed = (seed >> 1);
507
+
508
+  }
509
+}
510
+
511
+bool cmMLS_IsBalanced( const unsigned* xV, int xN)
512
+{
513
+  int      a = 0;
514
+  unsigned i;
515
+
516
+  for(i=0; i<xN; ++i)
517
+    if( xV[i] == 1 )
518
+      ++a;
519
+
520
+  return abs(a - (xN-a)) == 1;
521
+}
522
+
523
+unsigned _cmGenGoldCopy( int* y, unsigned yi, unsigned yN, unsigned* x, unsigned xN)
524
+{
525
+  unsigned i;
526
+  for(i=0; i<xN; ++i,++yi)
527
+    y[yi] = x[i]==1 ? -1 : 1;
528
+
529
+  assert(yi <= yN);
530
+  return yi;
531
+}
532
+
533
+bool cmGenGoldCodes( unsigned lfsrN, unsigned poly_coeff0, unsigned poly_coeff1, unsigned goldN, int* yM, unsigned mlsN  )
534
+{
535
+  bool      retFl = true;
536
+  unsigned  yi    = 0;
537
+  unsigned  yN    = goldN * mlsN;
538
+  unsigned* mls0V = cmMemAllocZ(unsigned,mlsN);
539
+  unsigned* mls1V = cmMemAllocZ(unsigned,mlsN);
540
+  unsigned* xorV  = cmMemAllocZ(unsigned,mlsN);
541
+  
542
+  unsigned  i,j;
543
+  
544
+  cmLFSR(lfsrN, poly_coeff0, 1 << (lfsrN-1), mls0V, mlsN);
545
+
546
+  cmLFSR(lfsrN, poly_coeff1, 1 << (lfsrN-1), mls1V, mlsN);
547
+
548
+  if( cmMLS_IsBalanced(mls0V,mlsN) )
549
+    yi = _cmGenGoldCopy(yM, yi, yN, mls0V, mlsN);
550
+
551
+  if( yi<yN && cmMLS_IsBalanced(mls1V,mlsN) )
552
+    yi = _cmGenGoldCopy(yM, yi, yN, mls1V, mlsN);
553
+
467 554
   
468
-  return abs(x0-x1)/(x0+x1) < eps;
555
+  for(i=0;  yi < yN && i<mlsN-1; ++i )
556
+  {
557
+    for(j=0; j<mlsN; ++j)
558
+      xorV[j] = (mls0V[j] + mls1V[ (i+j) % mlsN ]) % 2;
559
+    
560
+    if( cmMLS_IsBalanced(xorV,mlsN) )
561
+      yi = _cmGenGoldCopy(yM,yi,yN,xorV,mlsN);
562
+  }
563
+
564
+  if(yi < yN )
565
+  {    
566
+    //rc = cmErrMsg(err,kOpFailAtRC,"Gold code generation failed.  Insuffient balanced pairs.");
567
+    retFl = false;
568
+  }
569
+  
570
+  cmMemFree(mls0V);
571
+  cmMemFree(mls1V);
572
+  cmMemFree(xorV);
573
+
574
+  return retFl;
575
+
576
+}
577
+
578
+bool  cmLFSR_Test()
579
+{
580
+  // lfsrN          = 5;   % 5    6    7;
581
+  // poly_coeff0    = 0x12;  % 0x12 0x21 0x41;
582
+  // poly_coeff1    = 0x1e;  % 0x1e 0x36 0x72;
583
+
584
+  unsigned lfsrN = 7;
585
+  unsigned pc0   = 0x41;
586
+  unsigned pc1   = 0x72;
587
+  unsigned mlsN    = (1 << lfsrN)-1;
588
+
589
+  unsigned yN = mlsN*2;
590
+  unsigned yV[ yN ];
591
+  unsigned i;
592
+
593
+  cmLFSR( lfsrN, pc0, 1 << (lfsrN-1), yV, yN );
594
+
595
+  for(i=0; i<mlsN; ++i)
596
+    if( yV[i] != yV[i+mlsN] )
597
+      return false;
598
+
599
+  //atVOU_PrintL(NULL,"0x12",yV,mlsN,2);
600
+
601
+  cmLFSR( lfsrN, pc1, 1 << (lfsrN-1), yV, yN );
602
+
603
+  //atVOU_PrintL(NULL,"0x17",yV,mlsN,2);
604
+
605
+  for(i=0; i<mlsN; ++i)
606
+    if( yV[i] != yV[i+mlsN] )
607
+      return false;
608
+
609
+  return true;
469 610
 }

+ 43
- 0
cmMath.h Переглянути файл

@@ -15,6 +15,12 @@ unsigned cmPrevOddU(  unsigned v );
15 15
 unsigned cmNextEvenU( unsigned v );
16 16
 unsigned cmPrevEvenU( unsigned v );
17 17
 
18
+/// Increment or decrement 'idx' by 'delta' always wrapping the result into the range
19
+/// 0 to (maxN-1).
20
+/// 'idx': initial value 
21
+/// 'delta':  incremental amount
22
+/// 'maxN' - 1 : maximum return value.
23
+unsigned cmModIncr(int idx, int delta, int maxN );
18 24
 
19 25
 // modified bessel function of first kind, order 0
20 26
 // ref: orfandis appendix B io.m
@@ -74,4 +80,41 @@ bool cmIsCloseF( float    x0, float    x1, double eps );
74 80
 bool cmIsCloseI( int      x0, int      x1, double eps );
75 81
 bool cmIsCloseU( unsigned x0, unsigned x1, double eps );
76 82
 
83
+//=================================================================
84
+// Run a length 'lfsrN' linear feedback shift register (LFSR) for 'yN' iterations to
85
+// produce a length 'yN' bit string in yV[yN].
86
+// 'lfsrN' count of bits in the shift register range: 2<= lfsrN <= 32.
87
+// 'tapMask' is a bit mask which gives the tap indexes positions for the LFSR. 
88
+// The least significant bit corresponds to the maximum delay tap position.  
89
+// The min tap position is therefore denoted by the tap mask bit location 1 << (lfsrN-1).
90
+// A minimum of two taps must exist.
91
+// 'seed' sets the initial delay state.
92
+// 'yV[yN]' is the the output vector
93
+// 'yN' is count of elements in yV.
94
+// The function resturn kOkAtRC on success or kInvalidArgsRCRC if any arguments are invalid.
95
+// /sa cmLFSR_Test.
96
+void   cmLFSR( unsigned lfsrN, unsigned tapMask, unsigned seed, unsigned* yV, unsigned yN );
97
+
98
+// Example and test code for cmLFSR() 
99
+bool cmLFSR_Test();
100
+
101
+
102
+// Generate a set of 'goldN' Gold codes using the Maximum Length Sequences (MLS) generated
103
+// by a length 'lfsrN' linear feedback shift register.
104
+// 'err' is an error object to be set if the the function fails.
105
+// 'lfsrN' is the length of the Linear Feedback Shift Registers (LFSR) used to generate the MLS.
106
+// 'poly_coeff0' tap mask for the first LFSR.
107
+// 'coeff1' tap mask the the second LFSR.
108
+// 'goldN' is the count of Gold codes to generate. 
109
+// 'yM[mlsN', goldN] is a column major output matrix where each column contains a Gold code.
110
+// 'mlsN' is the length of the maximum length sequence for each Gold code which can be
111
+// calculated as mlsN = (1 << a->lfsrN) - 1.
112
+// Note that values of 'lfsrN' and the 'poly_coeffx' must be carefully selected such that
113
+// they will produce a MLS.  For example to generate a MLS with length 31 set 'lfsrN' to 5 and
114
+// then select poly_coeff from two different elements of the set {0x12 0x14 0x17 0x1B 0x1D 0x1E}.
115
+// See http://www.ece.cmu.edu/~koopman/lfsr/index.html for a complete set of MSL polynomial
116
+// coefficients for given LFSR lengths.
117
+// Returns false if insufficient balanced pairs exist.
118
+bool   cmGenGoldCodes( unsigned lfsrN, unsigned poly_coeff0, unsigned poly_coeff1, unsigned goldN, int* yM, unsigned mlsN  );
119
+
77 120
 #endif

+ 1
- 1
cmProc.c Переглянути файл

@@ -4393,7 +4393,7 @@ cmRC_t    cmChmmTrain( cmChmm_t* p, const cmReal_t* oM, unsigned T, unsigned ite
4393 4393
     cmReal_t logProb0 =  cmChmmForward( p, oM, T, alphaM, logPrV );
4394 4394
 
4395 4395
     // check for convergence
4396
-    cmReal_t dLogProb =  labs(logProb0-logProb) / ((labs(logProb0)+labs(logProb)+cmReal_EPSILON)/2);
4396
+    cmReal_t dLogProb =  fabs(logProb0-logProb) / ((fabs(logProb0)+fabs(logProb)+cmReal_EPSILON)/2);
4397 4397
     if( dLogProb < thresh )
4398 4398
       break;
4399 4399
 

+ 48
- 9
cmProc2.c Переглянути файл

@@ -823,7 +823,7 @@ cmRC_t cmFIRInitKaiser( cmFIR* p, unsigned procSmpCnt, double srate, double pass
823 823
   // in practice the ripple must be equal in the stop and pass band - so take the minimum between the two
824 824
   double d        = cmMin(dPass,dStop);
825 825
 
826
-  // convert the ripple bcmk to db
826
+  // convert the ripple back to db
827 827
   double A = -20 * log10(d);
828 828
 
829 829
   // compute the kaiser alpha coeff
@@ -914,7 +914,7 @@ cmRC_t cmFIRExec( cmFIR* p, const cmSample_t* sbp, unsigned sn )
914 914
     // calc the output sample
915 915
     while( cbp<cep)
916 916
     {
917
-      // note that the delay is being iterated bcmkwards
917
+      // note that the delay is being iterated backwards
918 918
       if( di == -1 )
919 919
       di=delayCnt-1;
920 920
 
@@ -936,7 +936,7 @@ cmRC_t cmFIRExec( cmFIR* p, const cmSample_t* sbp, unsigned sn )
936 936
   return cmOkRC;
937 937
 }
938 938
 
939
-void cmFIRTest( cmRpt_t* rpt, cmLHeapH_t lhH, cmSymTblH_t stH )
939
+void cmFIRTest0( cmRpt_t* rpt, cmLHeapH_t lhH, cmSymTblH_t stH )
940 940
 {
941 941
   unsigned N = 512;
942 942
   cmKbRecd kb;
@@ -978,6 +978,37 @@ void cmFIRTest( cmRpt_t* rpt, cmLHeapH_t lhH, cmSymTblH_t stH )
978 978
   cmFIRFree(&ffp);
979 979
 }
980 980
 
981
+void cmFIRTest1( cmCtx* ctx )
982
+{
983
+  const char* sfn        = "/home/kevin/temp/sig.va";
984
+  const char* ffn        = "/home/kevin/temp/fir.va";
985
+  unsigned    N          = 44100;
986
+  unsigned    srate      = N;
987
+  unsigned    procSmpCnt = N;
988
+  double      passHz     = 15000;
989
+  double      stopHz     = 14000;
990
+  double      passDb     = 1.0;
991
+  double      stopDb     = 60.0;
992
+  unsigned    flags      = kHighPassFIRFl;
993
+  
994
+  cmSample_t x[ procSmpCnt ];
995
+  
996
+  cmVOS_Fill(x,procSmpCnt,0);
997
+  x[0] = 1;
998
+
999
+  cmVOS_Random(x,procSmpCnt, -1.0, 1.0 );
1000
+
1001
+  cmFIR* f = cmFIRAllocKaiser( ctx, NULL, procSmpCnt, srate, passHz, stopHz, stopDb, passDb, flags );
1002
+
1003
+  cmFIRExec( f, x, procSmpCnt ); 
1004
+
1005
+  cmVectArrayWriteMatrixS(ctx, ffn, f->outV, 1, f->outN );
1006
+  cmVectArrayWriteMatrixS(ctx, sfn, x,       1, N );
1007
+
1008
+  cmFIRFree(&f);
1009
+  
1010
+}
1011
+
981 1012
 //------------------------------------------------------------------------------------------------------------
982 1013
 
983 1014
 
@@ -3966,6 +3997,14 @@ cmRC_t cmVectArrayWrite( cmVectArray_t* p, const char* fn )
3966 3997
   return rc;
3967 3998
 }
3968 3999
 
4000
+cmRC_t cmVectArrayWriteDirFn(cmVectArray_t* p, const char* dir, const char* fn )
4001
+{
4002
+  assert( dir!=NULL && fn!=NULL );
4003
+  const cmChar_t* path = cmFsMakeFn( dir, fn, NULL, NULL );
4004
+  cmRC_t rc = cmVectArrayWrite(p,path);
4005
+  cmFsFreeFn(path);
4006
+  return rc;
4007
+}
3969 4008
 
3970 4009
 cmRC_t cmVectArrayPrint( cmVectArray_t* p, cmRpt_t* rpt )
3971 4010
 {
@@ -4054,7 +4093,7 @@ cmRC_t _cmVectArrayWriteMatrix( cmCtx* ctx, const char* fn, unsigned flags, cons
4054 4093
       memcpy(vv + ci*tbc, v + ci*rn*tbc, tbc );
4055 4094
 
4056 4095
     // append the row to the VectArray
4057
-    if((rc = cmVectArrayAppendV(p,v,cn)) != cmOkRC )
4096
+    if((rc = cmVectArrayAppendV(p,vv,cn)) != cmOkRC )
4058 4097
     {
4059 4098
       rc = cmCtxRtCondition(&p->obj,rc,"Vector append failed in %s().",__FUNCTION__);
4060 4099
       goto errLabel;
@@ -5660,7 +5699,7 @@ cmRC_t      cmExpanderInit( cmExpander* p,
5660 5699
     p->envV[atkN+i] = p->rlsLvl + (G*i/rlsN);
5661 5700
   }
5662 5701
 
5663
-  printf("rmsN:%i atkN:%i rlsN:%i thr:%f %f rls:%f %f\n",p->rmsN,atkN,rlsN,threshDb,p->threshLvl,rlsDb,p->rlsLvl);
5702
+  //printf("rmsN:%i atkN:%i rlsN:%i thr:%f %f rls:%f %f\n",p->rmsN,atkN,rlsN,threshDb,p->threshLvl,rlsDb,p->rlsLvl);
5664 5703
 
5665 5704
   //for(i=0; i<p->envN; ++i)
5666 5705
   //  printf("%i %f\n",i,p->envV[i]);
@@ -5680,7 +5719,7 @@ cmRC_t      cmExpanderExec( cmExpander* p, cmSample_t* x, cmSample_t* y, unsigne
5680 5719
   for(i=0; i<xyN; ++i)
5681 5720
   {
5682 5721
     // NOTE: using abs() instead of pow(x,2)
5683
-    p->rmsV[p->rmsIdx] = abs(x[i]);
5722
+    p->rmsV[p->rmsIdx] = fabsf(x[i]);
5684 5723
 
5685 5724
     if( ++p->rmsIdx >= p->rmsN )
5686 5725
       p->rmsIdx = 0;
@@ -5910,7 +5949,7 @@ cmSpecDist_t* cmSpecDistAlloc( cmCtx* ctx,cmSpecDist_t* ap, unsigned procSmpCnt,
5910 5949
   cmSpecDist_t* p = cmObjAlloc( cmSpecDist_t, ctx, ap );
5911 5950
 
5912 5951
   //p->iSpecVa   = cmVectArrayAlloc(ctx,kRealVaFl);
5913
-  p->oSpecVa   = cmVectArrayAlloc(ctx,kRealVaFl);
5952
+  //p->oSpecVa   = cmVectArrayAlloc(ctx,kRealVaFl);
5914 5953
 
5915 5954
   if( procSmpCnt != 0 )
5916 5955
   {
@@ -5931,7 +5970,7 @@ cmRC_t cmSpecDistFree( cmSpecDist_t** pp )
5931 5970
   
5932 5971
   cmSpecDistFinal(p);
5933 5972
   //cmVectArrayFree(&p->iSpecVa);
5934
-  cmVectArrayFree(&p->oSpecVa);
5973
+  //cmVectArrayFree(&p->oSpecVa);
5935 5974
   cmMemPtrFree(&p->hzV);
5936 5975
   cmMemPtrFree(&p->iSpecM);
5937 5976
   cmMemPtrFree(&p->oSpecM);
@@ -6055,7 +6094,7 @@ cmRC_t cmSpecDistFinal(cmSpecDist_t* p )
6055 6094
   cmRC_t rc = cmOkRC;
6056 6095
 
6057 6096
   //cmVectArrayWrite(p->iSpecVa, "/home/kevin/temp/frqtrk/iSpec.va");
6058
-  cmVectArrayWrite(p->oSpecVa, "/home/kevin/temp/expand/oSpec.va");
6097
+  //cmVectArrayWrite(p->oSpecVa, "/home/kevin/temp/expand/oSpec.va");
6059 6098
 
6060 6099
   cmPvAnlFree(&p->pva);
6061 6100
   cmPvSynFree(&p->pvs);

+ 21
- 7
cmProc2.h Переглянути файл

@@ -190,8 +190,9 @@ extern "C" {
190 190
   cmRC_t cmFIRInitSinc(   cmFIR* p, unsigned procSmpCnt, double srate, unsigned sincSmpCnt, double fcHz,   unsigned flags, const double* wndV );
191 191
   cmRC_t cmFIRFinal(      cmFIR* p );
192 192
   cmRC_t cmFIRExec(       cmFIR* p, const cmSample_t* sp, unsigned sn );
193
-  void   cmFIRTest();
194
-
193
+  void   cmFIRTest0( cmRpt_t* rpt, cmLHeapH_t lhH, cmSymTblH_t stH );
194
+  void   cmFIRTest1( cmCtx* ctx );
195
+  
195 196
   //------------------------------------------------------------------------------------------------------------
196 197
   // Apply a generic function to a windowed signal with a one sample hop size.
197 198
 
@@ -771,7 +772,7 @@ extern "C" {
771 772
 
772 773
 
773 774
   //------------------------------------------------------------------------------------------------------------
774
-  // cmVectArray buffers row vectors of arbitrary lenght in  memory.
775
+  // cmVectArray buffers row vectors of arbitrary length in  memory.
775 776
   // The buffers may then be access using the cmVectArrayGetXXX() functions.
776 777
   // The entire contents of the file may be written to a file using atVectArrayWrite().
777 778
   // The file may then be read in back into memory using cmVectArrayAllocFromFile()
@@ -837,8 +838,12 @@ extern "C" {
837 838
   unsigned cmVectArrayMaxRowCount( const cmVectArray_t* p );
838 839
 
839 840
   // Store a new vector by appending it to the end of the internal vector list.
840
-  // Note that the true type of v[] in the call to cmVectArrayAppendV() must match
841
+  // Note:
842
+  // 1. The true type of v[] in the call to cmVectArrayAppendV() must match
841 843
   // the data type set in p->flags.
844
+  // 2. The 'vn' argument to atVectArrayAppendV() is an element count not
845
+  // a byte count.  The size of each element is determined by the data type
846
+  // as set by atVectArrayAlloc().  
842 847
   cmRC_t cmVectArrayAppendV( cmVectArray_t* p, const void* v,       unsigned vn );
843 848
   cmRC_t cmVectArrayAppendS( cmVectArray_t* p, const cmSample_t* v, unsigned vn );
844 849
   cmRC_t cmVectArrayAppendR( cmVectArray_t* p, const cmReal_t* v,   unsigned vn );
@@ -848,7 +853,8 @@ extern "C" {
848 853
   cmRC_t cmVectArrayAppendU( cmVectArray_t* p, const unsigned* v,   unsigned vn );
849 854
 
850 855
   // Write a vector array in a format that can be read by readVectArray.m.
851
-  cmRC_t cmVectArrayWrite(   cmVectArray_t* p, const char* fn );
856
+  cmRC_t cmVectArrayWrite(     cmVectArray_t* p, const char* fn );
857
+  cmRC_t cmVectArrayWriteDirFn(cmVectArray_t* p, const char* dir, const char* fn );
852 858
 
853 859
   // Print the vector array to rpt.
854 860
   cmRC_t cmVectArrayPrint( cmVectArray_t* p, cmRpt_t* rpt );
@@ -857,8 +863,12 @@ extern "C" {
857 863
   unsigned cmVectArrayForEachS( cmVectArray_t* p, unsigned idx, unsigned cnt, cmVectArrayForEachFuncS_t func, void* arg ); 
858 864
 
859 865
   // Write the vector v[vn] in the VectArray file format.
860
-  // Note that the true type of v[] in cmVectArrayWriteVectoV() must match the
866
+  // Note:
867
+  // 1. The true type of v[] in cmVectArrayWriteVectoV() must match the
861 868
   // data type set in the 'flags' parameter.
869
+  // 2. The 'vn' argument to atVectArrayWriteVectorV() is an element count not
870
+  // a byte count.  The size of each element is determined by the data type
871
+  // as set by atVectArrayAlloc().   
862 872
   cmRC_t cmVectArrayWriteVectorV( cmCtx* ctx, const char* fn, const void*       v, unsigned  vn, unsigned flags );
863 873
   cmRC_t cmVectArrayWriteVectorS( cmCtx* ctx, const char* fn, const cmSample_t* v, unsigned  vn );
864 874
   cmRC_t cmVectArrayWriteVectorR( cmCtx* ctx, const char* fn, const cmReal_t*   v, unsigned  vn );  
@@ -868,8 +878,12 @@ extern "C" {
868 878
   cmRC_t cmVectArrayWriteVectorU( cmCtx* ctx, const char* fn, const unsigned*   v, unsigned  vn );
869 879
 
870 880
   // Write the column-major matrix m[rn,cn] to the file 'fn'.
871
-  // Note that the true type of m[] in cmVectArrayWriteMatrixV() must match the
881
+  // Notes:
882
+  // 1. The true type of m[] in cmVectArrayWriteMatrixV() must match the
872 883
   // data type set in the 'flags' parameter.
884
+  // 2. The 'rn','cn' arguments to atVectWriteMatrixV() is are element counts not
885
+  // byte counts.  The size of each element is determined by the data type
886
+  // as set by atVectArrayAlloc().
873 887
   cmRC_t cmVectArrayWriteMatrixV( cmCtx* ctx, const char* fn, const void*       m, unsigned  rn, unsigned cn, unsigned flags );
874 888
   cmRC_t cmVectArrayWriteMatrixS( cmCtx* ctx, const char* fn, const cmSample_t* m, unsigned  rn, unsigned cn );
875 889
   cmRC_t cmVectArrayWriteMatrixR( cmCtx* ctx, const char* fn, const cmReal_t*   m, unsigned  rn, unsigned cn );  

+ 743
- 0
cmProc5.c Переглянути файл

@@ -16,7 +16,11 @@
16 16
 #include "cmProcObj.h"
17 17
 #include "cmProcTemplate.h"
18 18
 #include "cmMath.h"
19
+#include "cmFile.h"
20
+#include "cmTime.h"
21
+#include "cmMidi.h"
19 22
 #include "cmProc.h"
23
+#include "cmProc2.h"
20 24
 #include "cmProc5.h"
21 25
 
22 26
 #include "cmVectOps.h"
@@ -123,3 +127,742 @@ cmRC_t cmGoertzelExec( cmGoertzel* p, const cmSample_t* inpV, unsigned procSmpCn
123 127
 }
124 128
 
125 129
 
130
+//=======================================================================================================================
131
+double _cmGoldSigSinc( double t, double T )
132
+{
133
+  double x = t/T;
134
+  return x == 0 ? 1.0 : sin(M_PI*x)/(M_PI*x);         
135
+}
136
+
137
+void _cmGoldSigRaisedCos(  cmSample_t* yV, int yN, double sPc, double beta )
138
+{
139
+  int i;
140
+  
141
+  for(i=0; i<yN; ++i)
142
+  {
143
+    double t   = i - yN/2;
144
+    double den = 1 - (4*(beta*beta)*(t*t) / (sPc*sPc));
145
+    double a;
146
+      
147
+    if(fabs(den) < 0.00001 )
148
+      a = 1;
149
+    else
150
+      a = cos(M_PI * beta * t/ sPc ) / den;
151
+
152
+    yV[i] = _cmGoldSigSinc(t,sPc) * a;  
153
+  }
154
+}
155
+
156
+void _cmGoldSigConv( cmGoldSig_t* p, unsigned chIdx )
157
+{
158
+  int i;
159
+  int sPc = p->a.samplesPerChip;
160
+  int osf = p->a.rcosOSFact;
161
+
162
+  // for each bit in the spreading-code
163
+  for(i=0; i<p->mlsN; ++i)
164
+  {
165
+    int j = (i*sPc) + sPc/2;  // index into bbV[] of center of impulse response
166
+    int k = j - (sPc*osf)/2;  // index into bbV[] of start of impulse response
167
+    int h;
168
+
169
+    // for each sample in the impulse response
170
+    for(h=0; h<p->rcosN; ++h,++k)
171
+    {
172
+     
173
+      while( k<0 )
174
+        k += p->sigN;
175
+
176
+      while( k>=p->sigN )
177
+        k -= p->sigN;
178
+
179
+      p->ch[chIdx].bbV[k] += p->ch[chIdx].pnV[i] * p->rcosV[h];     
180
+    }
181
+  }
182
+}
183
+
184
+void _cmGoldSigModulate( cmGoldSig_t* p, unsigned chIdx )
185
+{
186
+  unsigned    i;
187
+  double      rps = 2.0 * M_PI * p->a.carrierHz / p->a.srate;
188
+  cmSample_t* yV  = p->ch[chIdx].mdV;
189
+  cmSample_t* bbV = p->ch[chIdx].bbV;
190
+
191
+  for(i=0; i<p->sigN; ++i)
192
+    yV[ i ] = bbV[i]*cos(rps*i) + bbV[i]*sin(rps*i);
193
+
194
+  // apply a half Hann envelope to the onset/offset of the id signal
195
+  if( p->a.envMs > 0 )
196
+  {
197
+    unsigned   wndMs = p->a.envMs * 2;
198
+    unsigned   wndN  = wndMs * p->a.srate / 1000;
199
+    wndN += wndN % 2 ? 0 : 1;   // force the window length to be odd
200
+    unsigned   wNo2 = wndN/2 + 1;
201
+    cmSample_t wndV[ wndN ];
202
+    cmVOS_Hann(wndV,wndN);
203
+    cmVOS_MultVV(yV,wNo2,wndV);
204
+    cmVOS_MultVV(yV + p->sigN - wNo2, wNo2, wndV + wNo2 - 1);
205
+  }
206
+
207
+}
208
+
209
+cmGoldSig_t* cmGoldSigAlloc( cmCtx* ctx, cmGoldSig_t* p, const cmGoldSigArg_t* a )
210
+{
211
+  cmGoldSig_t* op = cmObjAlloc(cmGoldSig_t,ctx,p);
212
+  
213
+  if( a != NULL )  
214
+    if( cmGoldSigInit(op,a) != cmOkRC )
215
+      cmGoldSigFree(&op);
216
+
217
+  return op;
218
+
219
+}
220
+
221
+cmRC_t cmGoldSigFree( cmGoldSig_t** pp )
222
+{
223
+  cmRC_t rc = cmOkRC;
224
+
225
+  if( pp == NULL || *pp == NULL )
226
+    return rc;
227
+
228
+  cmGoldSig_t* p = *pp;
229
+
230
+  if((rc = cmGoldSigFinal(p)) != cmOkRC )
231
+    return rc;
232
+  
233
+  unsigned i;
234
+  for(i=0; i<p->a.chN; ++i)
235
+  {
236
+    cmMemFree(p->ch[i].bbV);
237
+    cmMemFree(p->ch[i].mdV);
238
+  }
239
+  
240
+  cmMemFree(p->ch);
241
+  cmMemFree(p->rcosV);
242
+  cmMemFree(p->pnM);
243
+  cmMemFree(p);
244
+  *pp = NULL;
245
+
246
+  return rc;
247
+}
248
+
249
+cmRC_t cmGoldSigInit( cmGoldSig_t* p, const cmGoldSigArg_t* a )
250
+{
251
+  cmRC_t      rc = cmOkRC;
252
+  unsigned    i;
253
+  
254
+  p->a      = *a;                                            // store arg recd
255
+  p->ch     = cmMemResizeZ(cmGoldSigCh_t,p->ch,a->chN);  // alloc channel array
256
+  p->mlsN   = (1 << a->lfsrN) - 1;                           // calc spreading code length
257
+  p->rcosN  = a->samplesPerChip * a->rcosOSFact;             // calc rcos imp. resp. length
258
+  p->rcosN += (p->rcosN % 2)==0;                             // force rcos imp. length odd               
259
+  p->rcosV  = cmMemResizeZ(cmSample_t,p->rcosV,p->rcosN);  // alloc rcos imp. resp. vector
260
+  p->pnM    = cmMemResizeZ(int,p->pnM,p->mlsN*a->chN);   // alloc spreading-code mtx
261
+  p->sigN   = p->mlsN * a->samplesPerChip;                   // calc audio signal length
262
+
263
+  // generate spreading codes
264
+  if( cmGenGoldCodes(a->lfsrN, a->mlsCoeff0, a->mlsCoeff1, a->chN, p->pnM, p->mlsN ) == false )
265
+  {
266
+    rc = cmCtxRtCondition(&p->obj,cmSubSysFailRC,"Unable to generate sufficient balanced Gold codes.");
267
+    goto errLabel;
268
+  }
269
+
270
+  // generate the rcos impulse response
271
+  _cmGoldSigRaisedCos(p->rcosV,p->rcosN,a->samplesPerChip,a->rcosBeta);
272
+
273
+  // for each channel
274
+  for(i=0; i<a->chN; ++i)
275
+  {
276
+    // Note: if (i*p->mlsN) is set to 0 in the following line then all channels
277
+    // will use the same spreading code.
278
+    p->ch[i].pnV = p->pnM + (i*p->mlsN);                        // get ch. spreading code
279
+    p->ch[i].bbV = cmMemResizeZ(cmSample_t,p->ch[i].bbV,p->sigN); // alloc baseband signal vector
280
+    p->ch[i].mdV = cmMemResizeZ(cmSample_t,p->ch[i].mdV,p->sigN); // alloc output audio vector
281
+
282
+    // Convolve spreading code with rcos impulse reponse to form baseband signal.
283
+    _cmGoldSigConv(p, i );     
284
+
285
+    // Modulate baseband signal to carrier frq. and apply attack/decay envelope.
286
+    _cmGoldSigModulate(p, i );
287
+  }
288
+
289
+ errLabel:
290
+  if((rc = cmErrLastRC(&p->obj.err)) != cmOkRC )
291
+    cmGoldSigFree(&p);
292
+
293
+  return rc;
294
+}
295
+
296
+cmRC_t cmGoldSigFinal( cmGoldSig_t* p )
297
+{ return cmOkRC; }
298
+
299
+cmRC_t cmGoldSigWrite( cmCtx* ctx, cmGoldSig_t* p, const char* fn )
300
+{
301
+  cmVectArray_t* vap = NULL;
302
+  unsigned       i;
303
+
304
+  vap = cmVectArrayAlloc(ctx,kSampleVaFl);
305
+
306
+  for(i=0; i<p->a.chN; ++i)
307
+  {
308
+    cmVectArrayAppendS(vap,p->ch[i].bbV,p->sigN);
309
+    cmVectArrayAppendS(vap,p->ch[i].mdV,p->sigN);
310
+  }
311
+
312
+  cmVectArrayWrite(vap,fn);
313
+
314
+  cmVectArrayFree(&vap);
315
+
316
+  return cmOkRC;
317
+}
318
+
319
+
320
+cmRC_t cmGoldSigGen( cmGoldSig_t* p, unsigned chIdx, unsigned prefixN, unsigned dsN, unsigned *bsiV, unsigned bsiN, double noiseGain, cmSample_t** yVRef, unsigned* yNRef )
321
+{
322
+  unsigned    yN = prefixN + bsiN * (p->sigN + dsN);
323
+  cmSample_t* yV = cmMemAllocZ(cmSample_t,yN);
324
+  unsigned    i;
325
+
326
+  cmVOS_Random(yV, yN, -noiseGain, noiseGain );
327
+
328
+  for(i=0; i<bsiN; ++i)
329
+  {
330
+    bsiV[i] = prefixN + i*(p->sigN + dsN);
331
+    
332
+    cmVOS_AddVV(yV + bsiV[i], p->sigN, p->ch[chIdx].mdV );
333
+  }
334
+  
335
+  if( yVRef != NULL )
336
+    *yVRef = yV;
337
+
338
+  if( yNRef != NULL )
339
+    *yNRef = yN;
340
+
341
+  return cmOkRC;  
342
+}
343
+
344
+
345
+//=======================================================================================================================
346
+cmPhat_t*   cmPhatAlloc(  cmCtx* ctx, cmPhat_t* ap, unsigned chN, unsigned hN, float alpha, unsigned mult, unsigned flags )
347
+{
348
+  cmPhat_t* p = cmObjAlloc(cmPhat_t,ctx,ap);
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
+  unsigned fhN = cmNextPowerOfTwo(mult*hN);
356
+
357
+  // allocate the FFT object
358
+  cmFftAllocSR(ctx,&p->fft,NULL,fhN,kToPolarFftFl);
359
+  cmIFftAllocRS(ctx,&p->ifft,fhN/2 + 1 );
360
+  
361
+  if( chN != 0 )  
362
+    if( cmPhatInit(p,chN,hN,alpha,mult,flags) != cmOkRC )
363
+      cmPhatFree(&p);
364
+
365
+  return p;
366
+
367
+}
368
+
369
+cmRC_t   cmPhatFree(   cmPhat_t** pp )
370
+{
371
+  cmRC_t rc = cmOkRC;
372
+
373
+  if( pp == NULL || *pp == NULL )
374
+    return rc;
375
+
376
+  cmPhat_t* p = *pp;
377
+  if((rc = cmPhatFinal(p)) != cmOkRC )
378
+    return rc;
379
+
380
+  cmMemFree(p->t0V);
381
+  cmMemFree(p->t1V);
382
+  cmMemFree(p->dV);
383
+  cmMemFree(p->xV);
384
+  cmMemFree(p->fhM);
385
+  cmMemFree(p->mhM);
386
+  cmMemFree(p->wndV);
387
+  cmObjFreeStatic(cmFftFreeSR, cmFftSR, p->fft);
388
+  cmObjFreeStatic(cmIFftFreeRS, cmIFftRS, p->ifft);
389
+  cmVectArrayFree(&p->ftVa);
390
+  cmObjFree(pp);
391
+
392
+  return rc;
393
+
394
+}
395
+
396
+
397
+cmRC_t   cmPhatInit(  cmPhat_t* p, unsigned chN, unsigned hN, float alpha, unsigned mult, unsigned flags )
398
+{
399
+  cmRC_t   rc = cmOkRC;
400
+  if((rc = cmPhatFinal(cmOkRC)) != cmOkRC )
401
+    return rc;
402
+
403
+  p->fhN = cmNextPowerOfTwo(mult*hN);
404
+  
405
+  if((cmFftInitSR(&p->fft, NULL, p->fhN, kToPolarFftFl)) != cmOkRC )
406
+    return rc;
407
+
408
+  if((cmFftInitRS(&p->ifft, NULL, p->fft->binCnt )) != cmOkRC )
409
+    return rc;
410
+
411
+  p->alpha = alpha;
412
+  p->flags = flags;
413
+
414
+  // allocate the delay line
415
+  p->dV = cmMemResizeZ(cmSample_t,p->dV,p->fhN);
416
+  p->di = 0;
417
+
418
+  // allocate the linear buffer
419
+  p->xV  = cmMemResizeZ(cmSample_t,p->xV,p->fhN);
420
+  p->t0V = cmMemResizeZ(cmComplexR_t,p->t0V,p->fhN);
421
+  p->t1V = cmMemResizeZ(cmComplexR_t,p->t1V,p->fhN);
422
+
423
+  // allocate the window function
424
+  p->wndV = cmMemResizeZ(cmSample_t,p->wndV,p->fhN);
425
+  cmVOS_Hann(p->wndV,p->fhN);
426
+
427
+  // allocate the signal id matrix
428
+  p->chN = chN;
429
+  p->hN  = hN;
430
+  p->binN = p->fft.binCnt; //atFftRealBinCount(p->fftH);
431
+  p->fhM = cmMemResizeZ(cmComplexR_t, p->fhM, p->fhN  * chN);
432
+  p->mhM = cmMemResizeZ(float,        p->mhM, p->binN * chN);
433
+  cmPhatReset(p);
434
+
435
+  //if( cmIsFlag(p->flags,kDebugAtPhatFl)) 
436
+  //  cmVectArrayAlloc(ctx, &p->ftVa,  kSampleVaFl );
437
+  //else
438
+  //  p->ftVa = NULL;
439
+
440
+  return rc;
441
+
442
+}
443
+
444
+cmRC_t cmPhatFinal( cmPhat_t* p )
445
+{ return cmOkRC; }
446
+
447
+cmRC_t cmPhatReset(  cmPhat_t* p )
448
+{
449
+  p->di     = 0;
450
+  p->absIdx = 0;
451
+  cmVOS_Zero(p->dV,p->fhN);
452
+  return cmOkRC;
453
+}
454
+
455
+cmRC_t cmPhatSetId(  cmPhat_t* p, unsigned chIdx, const cmSample_t* hV, unsigned hN )
456
+{
457
+  unsigned i;
458
+  assert( chIdx < p->chN );
459
+  assert( hN == p->hN );
460
+
461
+  // Allocate a window vector
462
+  cmSample_t* wndV = cmMemAllocZ(cmSample_t,hN);
463
+  cmVOS_Hann(wndV,hN);
464
+
465
+  // get ptr to output column in p->fhM[].
466
+  cmComplexR_t* yV = p->fhM + (chIdx*p->fhN);
467
+
468
+  // Zero pad hV[hN] to p->fhN;
469
+  assert( hN <= p->fhN );
470
+  cmVOS_Zero(p->xV,p->fhN);
471
+  cmVOS_Copy(p->xV,hN,hV);
472
+
473
+  // Apply the window function to the id signal
474
+  if(cmIsFlag(p->flags,kHannAtPhatFl) )
475
+    cmVOS_MultVVV(p->xV,hN,hV,wndV);
476
+
477
+  // take FFT of id signal. The result is in fft->complexV and fft->magV,phsV
478
+  cmFftExecSR(&p->fft, p->xV, p->fhN );
479
+
480
+  // Store the magnitude of the id signal
481
+  //atFftComplexAbs(p->mhM + (chIdx*p->binN), yV,     p->binN);
482
+  cmVOF_CopyR(p->mhM + (chIdx*p->binN), p->binN, p->fft.magV );
483
+
484
+  // Scale the magnitude
485
+  cmVOS_MultVS(   p->mhM + (chIdx*p->binN), p->binN, p->alpha);
486
+
487
+  // store the complex conjugate of the FFT result in yV[]
488
+  //atFftComplexConj(yV,p->binN);
489
+  for(i=0; i<p->binN; ++i)
490
+    yV[i] = cmCconjR(p->fft.complexV[i]);
491
+
492
+  cmMemFree(wndV);
493
+
494
+  return cmOkRC;
495
+}
496
+
497
+cmSample_t* _cmPhatReadVector( cmCtx* ctx, cmPhat_t* p, const char* fn, unsigned* vnRef )
498
+{
499
+  cmVectArray_t* vap = NULL;
500
+  cmSample_t*    v   = NULL;
501
+  cmRC_t         rc  = cmOkRC;
502
+  
503
+  // instantiate a VectArray from a file
504
+  if( (vap = cmVectArrayAllocFromFile(ctx, fn )) == NULL )
505
+  {
506
+    rc = cmCtxRtCondition(&p->obj,cmSubSysFailRC,"Id component vector file read failed '%s'.",fn);
507
+    goto errLabel;
508
+  }
509
+
510
+  // get the count of elements in the vector
511
+  *vnRef = cmVectArrayEleCount(vap);
512
+
513
+  // allocate memory to hold the vector
514
+  v = cmMemAlloc(cmSample_t,*vnRef);
515
+
516
+  // copy the vector from the vector array object into v[]
517
+  if((rc = cmVectArrayGetF(vap,v,vnRef)) != cmOkRC )
518
+  {
519
+    cmMemFree(v);
520
+    v = NULL;
521
+    rc = cmCtxRtCondition(&p->obj,cmSubSysFailRC,"Id component vector copy out failed '%s'.",fn);
522
+    goto errLabel;
523
+  }
524
+
525
+  cmRptPrintf(p->obj.err.rpt,"%i : %s",*vnRef,fn);
526
+  
527
+
528
+ errLabel:
529
+  cmVectArrayFree(&vap);
530
+
531
+  return v;
532
+}
533
+
534
+
535
+cmRC_t   cmPhatExec(   cmPhat_t* p, const cmSample_t* xV, unsigned xN )
536
+{
537
+  unsigned n = cmMin(xN,p->fhN-p->di);
538
+
539
+  // update the delay line
540
+  cmVOS_Copy(p->dV+p->di,n,xV);
541
+
542
+  if( n < xN )
543
+    cmVOS_Copy(p->dV,xN-n,xV+n);
544
+
545
+  p->di      = cmModIncr(p->di,xN,p->fhN);
546
+
547
+  // p->absIdx is the absolute sample index associated with di
548
+  p->absIdx += xN;  
549
+
550
+  return cmOkRC;
551
+}
552
+
553
+
554
+void cmPhatChExec( 
555
+    cmPhat_t* p, 
556
+    unsigned  chIdx,
557
+    unsigned  sessionId,
558
+    unsigned  roleId)
559
+{
560
+
561
+  unsigned n0 = p->fhN - p->di;
562
+  unsigned n1 = p->fhN - n0;
563
+
564
+  // Linearize the delay line into xV[]
565
+  cmVOS_Copy(p->xV,    n0, p->dV + p->di );
566
+  cmVOS_Copy(p->xV+n0, n1, p->dV         );
567
+
568
+  if( cmIsFlag(p->flags,kDebugAtPhatFl)) 
569
+    cmVectArrayAppendS(p->ftVa, p->xV, p->fhN );
570
+
571
+  // apply a window function to the incoming signal
572
+  if( cmIsFlag(p->flags,kHannAtPhatFl) )
573
+    cmVOS_MultVV(p->xV,p->fhN,p->wndV);
574
+  
575
+  // Take the FFT of the delay line.
576
+  // p->t0V[p->binN] = fft(p->xV)
577
+  //atFftRealForward(p->fftH, p->xV, p->fhN, p->t0V, p->binN );
578
+  cmFftExecSR(&p->fft, p->xV, p->fhN );
579
+ 
580
+  // Calc. the Cross Power Spectrum (aka cross spectral density) of the
581
+  // input signal with the id signal.
582
+  // Note that the CPS is equivalent to the Fourier Transform of the
583
+  // cross-correlation of the two signals.
584
+  // t0V[] *= p->fhM[:,chIdx]
585
+  //atFftComplexMult( p->t0V, p->fhM + (chIdx * p->fhN), p->binN );
586
+  cmVOCR_MultVVV( p->t0V, p->fft.complexV, p->fhM + (chIdx * p->fhN), p->binN);
587
+  
588
+  // Calculate the magnitude of the CPS.
589
+  // xV[] = | t0V[] |
590
+  cmVOCR_Abs( p->xV, p->t0V, p->binN );
591
+  
592
+  // Weight the CPS by the scaled magnitude of the id signal
593
+  // (we want to emphasize the limited frequencies where the
594
+  //  id signal contains energy)
595
+  // t0V[] *= p->mhM[:,chIdx]
596
+  if( p->alpha > 0 )
597
+    cmVOCR_MultVFV( p->t0V, p->mhM + (chIdx*p->binN), p->binN);
598
+
599
+  // Divide through by the magnitude of the CPS
600
+  // This has the effect of whitening the spectram and thereby
601
+  // minimizing the effect of the magnitude correlation 
602
+  // while maximimizing the effect of the phase correlation.
603
+  // 
604
+  // t0V[] /= xV[]
605
+  cmVOCR_DivVFV( p->t0V, p->xV, p->binN );
606
+  
607
+  // Take the IFFT of the weighted CPS to recover the cross correlation.
608
+  // xV[] = IFFT(t0V[])
609
+  cmIFftExecRS( p->ifft,  );
610
+
611
+  //// ***** atFftRealInverse( p->fftH, p->t0V, p->xV, p->fhN );
612
+  
613
+  // Shift the correlation spike to mark the end of the id
614
+  cmVOS_Rotate( p->xV, p->fhN, -((int)p->hN) );
615
+
616
+  // normalize by the length of the correlation
617
+  cmVOS_DivVS(p->xV,p->fhN,p->fhN);
618
+
619
+  if( cmIsFlag(p->flags,kDebugAtPhatFl))
620
+  {
621
+    cmVectArrayAppendS(p->ftVa, p->xV, p->fhN );
622
+
623
+    cmSample_t v[] = { sessionId, roleId };
624
+    cmVectArrayAppendS(p->ftVa, v, sizeof(v)/sizeof(v[0]));
625
+  }
626
+
627
+}
628
+
629
+cmRC_t cmPhatWrite( cmPhat_t* p, const char* dirStr )
630
+{
631
+  cmRC_t rc = cmOkRC;
632
+  
633
+  if( cmIsFlag(p->flags, kDebugAtPhatFl)) 
634
+  {
635
+    const char* path = NULL;
636
+
637
+    if( p->ftVa != NULL )
638
+      if((rc = cmVectArrayWrite(p->ftVa, path = cmFsMakeFn(path,"cmPhatFT","va",dirStr,NULL) )) != cmOkRC )
639
+        rc = cmCtxRtCondition(&p->obj,cmSubSysFailRC,"PHAT debug file write failed.");
640
+    
641
+    cmFsFreeFn(path);
642
+  }
643
+  
644
+  return rc;
645
+}
646
+
647
+#ifdef NOTDEF
648
+cmRC_t cmPhatTest1( cmCtx* ctx, const char* dirStr )
649
+{
650
+  cmRC_t         rc             = cmOkRC;
651
+  cmGoldSigArg_t sa;
652
+  cmGoldSig_t*   s              = NULL;
653
+  cmPhat_t*      p              = NULL;
654
+  char*          path           = NULL;
655
+  unsigned       dspFrmCnt      = 256;
656
+  unsigned       listenDelaySmp = 8196;
657
+  double         noiseGain      = 0.05;
658
+  unsigned       chIdx          = 0;
659
+  cmSample_t*    yV             = NULL;
660
+  unsigned       yN             = 0;
661
+  double         phatAlpha      = 0.5;
662
+  unsigned       phatMult       = 4.0;
663
+  double         nonLinExpo     = 4.0;
664
+  cmVectArray_t* outVA          = NULL; 
665
+  cmVectArray_t* inVA           = NULL;
666
+  cmVectArray_t* statusVA       = NULL;
667
+  unsigned       bsiN           = 4;
668
+  unsigned       bsiV[bsiN];  // known signal onset in absolute samples 
669
+  unsigned       esiV[bsiN];  // known signal offset
670
+  unsigned       lsiV[bsiN];  // end of listen time (when cmPhatChExec()) is run.
671
+  unsigned       dsiV[bsiN];  // detection time
672
+  unsigned       i,j;
673
+  
674
+  sa.chN             =     1;
675
+  sa.srate           = 44100.0;
676
+  sa.lfsrN           =     8;
677
+  sa.mlsCoeff0       =  0x8e;
678
+  sa.mlsCoeff1       =  0x96;
679
+  sa.samplesPerChip  =    64;
680
+  sa.rcosBeta        =     0.5;
681
+  sa.rcosOSFact      =     4;
682
+  sa.carrierHz       = 17000.0;
683
+  sa.envMs           =    50.0;
684
+  
685
+  // allocate the the id signals
686
+  if( (s = cmGoldSigAlloc( ctx, NULL, &sa ) == NULL )
687
+    return cmErrMsg(&ctx->err, cmSubSysFailRC, "Signal allocate failed.");
688
+
689
+  // set the post signal listen delay to half the signal length
690
+  listenDelaySmp = s->sigN/2; 
691
+
692
+  // allocate a PHAT detector
693
+    if( (p = cmPhatAlloc(ctx,NULL,sa.chN,s->sigN, phatAlpha, phatMult, kDebugAtPhatFl ) == NULL )
694
+  {
695
+    rc = cmErrMsg(&ctx->err, cmSubSysFailRC, "PHAT allocate failed.");
696
+    goto errLabel;
697
+  }
698
+
699
+  // register an id signal with the PHAT detector
700
+  if( cmPhatSetId(p, chIdx, s->ch[chIdx].mdV, s->sigN ) != cmOkRC )
701
+  {
702
+    rc = cmErrMsg(&ctx->err, cmSubSysFailRC, "PHAT setId failed.");
703
+    goto errLabel;
704
+  }
705
+
706
+  // generate an input test signal containing bsiN id signals
707
+  if( atSignalGen(s,chIdx,p->fhN,s->sigN,bsiV,bsiN,noiseGain,&yV,&yN) != cmOkRC )
708
+  {
709
+    rc = cmErrMsg(&ctx->err,cmSubSysFailRC,"Signal generation failed.");
710
+    goto errLabel;
711
+  }
712
+
713
+  // bsiV[] now holds signal onsets. Set esiV[] to  signal offsets.
714
+  atVOU_AddVVS(esiV,bsiV,bsiN,s->sigN );
715
+
716
+  // set lsiV[] to end-of-listen location 
717
+  atVOU_AddVVS(lsiV,esiV,bsiN,listenDelaySmp);
718
+
719
+  // zero the detection vector
720
+  atVOU_Zero(dsiV,bsiN);
721
+
722
+  // allocate a vector array to record the PHAT input signals
723
+  if( cmVectArrayAlloc(ctx,&inVA,kSampleVaFl) != cmOkRC )
724
+  {
725
+    rc = cmErrMsg(&ctx->err, cmSubSysFailRC, "vectArray inVA alloc failed.");
726
+    goto errLabel;
727
+  }
728
+
729
+  // allocate a vector array to record the PHAT correlation output signals
730
+  if( cmVectArrayAlloc(ctx,&outVA,kSampleVaFl) != cmOkRC )
731
+  {
732
+    rc = cmErrMsg(&ctx->err, cmSubSysFailRC, "vectArray outVA alloc failed.");
733
+    goto errLabel;
734
+  }
735
+
736
+  // allocate a vector array to record the PHAT status
737
+  if( cmVectArrayAlloc(ctx,&statusVA,kSampleVaFl) != cmOkRC )
738
+  {
739
+    rc = cmErrMsg(&ctx->err, cmSubSysFailRC, "vectArray statusVA alloc failed.");
740
+    goto errLabel;
741
+  }
742
+
743
+  
744
+  // for each 'dspFrmCnt' samples in the input signal
745
+  for(i=0,j=0; j<bsiN && i<=yN-dspFrmCnt; i+=dspFrmCnt)
746
+  {
747
+    // store a copy of the input signal
748
+    cmVectArrayAppendS(inVA,yV+i,dspFrmCnt);
749
+
750
+    // feed the next dspFrmCnt samples to the PHAT detector
751
+    cmPhatExec(p,yV+i,dspFrmCnt);
752
+
753
+    // if the approximate end of an id signal is encountered
754
+    if( lsiV[j] <= i && i < lsiV[j] + dspFrmCnt )
755
+    {
756
+      // execute the PHAT correlator
757
+      cmPhatChExec( p, chIdx, -1, -1 );
758
+
759
+      // apply non-linear exponent to the correlation vector
760
+      cmVOS_PowV(p->xV,p->fhN,nonLinExpo);
761
+
762
+      // locate the corr. peak inside the listening window
763
+      // (the detection window is last 'detectWndSmp' samples in the corr. vector )
764
+      unsigned detectWndSmp = 2*listenDelaySmp;
765
+      dsiV[j] = cmVOS_ArgMax( p->xV + p->fhN - detectWndSmp,  detectWndSmp);
766
+
767
+      // convert the pk index to absolute time
768
+      dsiV[j] = i + dspFrmCnt - detectWndSmp + dsiV[j];
769
+
770
+      //                 sig beg  sig end  detect begin          dtct end    detect
771
+      cmSample_t v[] = { bsiV[j], esiV[j], lsiV[j]-detectWndSmp, lsiV[j],    dsiV[j] };
772
+
773
+      // store the detection information
774
+      cmVectArrayAppendS(statusVA,v,sizeof(v)/sizeof(v[0]));
775
+
776
+      // store the correlation output vector
777
+      cmVectArrayAppendS(outVA,p->xV,p->fhN);
778
+      
779
+      j += 1;
780
+    }
781
+  }
782
+
783
+  // write inVA
784
+  if( cmVectArrayWrite(inVA,path = atMakePath(&ctx->err,path,"phatIn","va",dirStr,NULL)) != cmOkRC )
785
+  {
786
+    rc = cmErrMsg(&ctx->err, cmSubSysFailRC, "vectArray outVA write failed.");
787
+    goto errLabel;
788
+  }
789
+
790
+  // write outVA
791
+  if( cmVectArrayWrite(outVA,path = atMakePath(&ctx->err,path,"phatOut","va",dirStr,NULL)) != cmOkRC )
792
+  {
793
+    rc = cmErrMsg(&ctx->err, cmSubSysFailRC, "vectArray outVA write failed.");
794
+    goto errLabel;
795
+  }
796
+
797
+  // write statusVA
798
+  if( cmVectArrayWrite(statusVA,path = atMakePath(&ctx->err,path,"phatStatus","va",dirStr,NULL)) != cmOkRC )
799
+  {
800
+    rc = cmErrMsg(&ctx->err, cmSubSysFailRC, "vectArray statusVA write failed.");
801
+    goto errLabel;
802
+  }
803
+
804
+ errLabel:
805
+  cmVectArrayFree(&outVA);
806
+  cmVectArrayFree(&inVA);
807
+
808
+  if( cmPhatFree(&p) != cmOkRC )
809
+    cmErrMsg(&ctx->err,cmSubSysFailRC,"PHAT free failed.");
810
+
811
+  if( atSignalFree(&s) != cmOkRC )
812
+    cmErrMsg(&ctx->err,cmSubSysFailRC,"Signal free failed.");
813
+
814
+  return rc;
815
+}
816
+
817
+cmRC_t cmPhatTest2( cmCtx* ctx )
818
+{
819
+  cmRC_t    rc    = cmOkRC;
820
+  cmPhat_t* p     = NULL;
821
+  unsigned  hN    = 16;
822
+  float     alpha = 1.0;
823
+  unsigned  mult  = 4;
824
+
825
+  cmSample_t hV[]  = { 4,3,2,1, 0,0,0,0, 0,0,0,0, 0,0,0,0 };
826
+  cmSample_t x0V[] = { 4,3,2,1, 0,0,0,0, 0,0,0,0, 0,0,0,0 };
827
+  cmSample_t x1V[] = { 0,0,0,0, 4,3,2,1, 0,0,0,0, 0,0,0,0 };
828
+  cmSample_t x2V[] = { 0,0,0,0, 0,0,0,0, 4,3,2,1, 0,0,0,0 };
829
+  cmSample_t x3V[] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 4,3,2,1 };
830
+
831
+  cmSample_t* xV[] = { x0V, x1V, x2V, x3V };
832
+  unsigned    chN  = sizeof(xV)/sizeof(xV[0]);
833
+  unsigned    i;
834
+  
835
+  if(cmPhatAlloc(ctx,&p,chN,hN,alpha,mult,kNoFlagsAtPhatFl) != cmOkRC )
836
+  {
837
+    rc = cmErrMsg(&ctx->err,cmSubSysFailRC,"cmPhatAlloc() failed.");
838
+    goto errLabel;
839
+  }
840
+
841
+  for(i=0; i<chN; ++i)
842
+    if( cmPhatSetId(p,i,hV,hN) != cmOkRC )
843
+      rc = cmErrMsg(&ctx->err,cmSubSysFailRC,"cmPhatSetId() failed.");
844
+  
845
+  
846
+  for(i=0; i<chN; ++i)
847
+  {
848
+    cmPhatReset(p);
849
+    
850
+    if( cmPhatExec(p,xV[i],hN) != cmOkRC )
851
+    {
852
+      rc = cmErrMsg(&ctx->err,cmSubSysFailRC,"cmPhatExec() failed.");
853
+      goto errLabel;
854
+    }
855
+
856
+    cmPhatChExec(p, i, -1, -1);
857
+    cmVOS_PrintL(&ctx->printRpt,"x:",p->xV,1,p->fhN);
858
+  }
859
+
860
+
861
+  errLabel:
862
+
863
+  cmPhatFree(&p);
864
+
865
+    
866
+  return rc;
867
+}
868
+#endif

+ 155
- 0
cmProc5.h Переглянути файл

@@ -39,7 +39,162 @@ extern "C" {
39 39
   cmRC_t cmGoertzelExec( cmGoertzel* p, const cmSample_t* in, unsigned procSmpCnt,  double* outV, unsigned chCnt );
40 40
 
41 41
 
42
+  //=======================================================================================================================
43
+  // Gold Code Signal Generator
44
+  //
45
+
46
+  typedef struct
47
+  {
48
+    unsigned chN;              // count of channels (each channel has a unique id)   
49
+    double   srate;            // system sample rate (samples/second)
50
+    unsigned lfsrN;            // linear feedback shift register (LFSR) length used to form Gold codes
51
+    unsigned mlsCoeff0;        // LFSR coeff. 0
52
+    unsigned mlsCoeff1;        // LFSR coeff. 1
53
+    unsigned samplesPerChip;   // samples per spreading code bit
54
+    double   rcosBeta;         // raised cosine impulse response beta coeff.
55
+    unsigned rcosOSFact;       // raised cosine impulse response oversample factor
56
+    double   carrierHz;        // carrier frequency
57
+    double   envMs;            // attack/decay envelope duration
58
+  } cmGoldSigArg_t;
59
+
60
+  typedef struct
61
+  {
62
+    int*        pnV;  // pnV[ mlsN ]  spread code (aliased from pnM[:,i])
63
+    cmSample_t* bbV;  // bbV[ sigN ]  baseband signal  at audio rate
64
+    cmSample_t* mdV;  // mdV[ sigN ]  modulated signal at audio rate
65
+  } cmGoldSigCh_t;
66
+
67
+  typedef struct 
68
+  {
69
+    cmObj          obj;         // 
70
+    cmGoldSigArg_t a;           // argument record
71
+    cmGoldSigCh_t* ch;          // ch[ chN ] channel array
72
+    int*           pnM;         // pnM[mlsN,chN] (aliased to ch[].pnV)
73
+    cmSample_t*    rcosV;       // rcosV[rcosN] raised cosine impulse response
74
+    unsigned       rcosN;       // length of raised cosine impulse response
75
+    unsigned       mlsN;        // length of Gold codes (Maximum length sequence length)
76
+    unsigned       sigN;        // length of channel signals bbV[] and mdV[]  
77
+  } cmGoldSig_t;
78
+
79
+
80
+  cmGoldSig_t* cmGoldSigAlloc( cmCtx* ctx, cmGoldSig_t* p, const cmGoldSigArg_t* a );
81
+  cmRC_t cmGoldSigFree( cmGoldSig_t** pp );
82
+
83
+  cmRC_t cmGoldSigInit( cmGoldSig_t* p, const cmGoldSigArg_t* a );
84
+  cmRC_t cmGoldSigFinal( cmGoldSig_t* p );
85
+  
86
+  cmRC_t cmGoldSigWrite( cmCtx* ctx, cmGoldSig_t* p, const char* fn );
87
+
88
+  // Generate a signal consisting of  underlying white noise with 
89
+  // bsiN repeated copies of the id signal associated with 
90
+  // channel 'chIdx'. Each discrete id signal copy is separated by 'dsN' samples.
91
+  // The signal will be prefixed with 'prefixN' samples of silence (noise).
92
+  // On return sets 'yVRef' to point to the generated signal and 'yNRef'
93
+  // to the count of samples in 'yVRef'.
94
+  // On error sets yVRef to NULL and  yNRef to zero.
95
+  // The vector returned in 'yVRef' should be freed via atMemFree().
96
+  // On return sets bsiV[bsiN] to the onset sample index of each id signal copy.
97
+  // The background noise signal is limited to the range -noiseGain to noiseGain.
98
+  cmRC_t cmGoldSigGen( 
99
+    cmGoldSig_t*   p, 
100
+    unsigned      chIdx, 
101
+    unsigned      prefixN, 
102
+    unsigned      dsN, 
103
+    unsigned     *bsiV, 
104
+    unsigned      bsiN, 
105
+    double        noiseGain, 
106
+    cmSample_t**  yVRef, 
107
+    unsigned*     yNRef );
108
+
109
+  cmRC_t cmGoldSigTest( cmCtx* ctx );
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
+    cmIFftRS         ifft;
129
+    
130
+    float            alpha;
131
+    unsigned         flags;
132
+
133
+    cmComplexR_t*    fhM;      // fhM[fhN,chN]  FT of each id signal stored in complex form
134
+    float*           mhM;      // mhM[binN,chN]  magnitude of each fhM column
135
+    unsigned         chN;      // count of id signals
136
+    unsigned         fhN;      // length of each FT id signal (fft->xN)
137
+    unsigned        binN;      // length of each mhM column (fft->xN/2);
138
+    unsigned          hN;      // length of each time domain id signal (hN<=fhN/2)
139
+
140
+    unsigned         absIdx;   // abs. sample index of p->di
141
+
142
+    cmSample_t*      dV;       // dV[fhN] delay line
143
+    unsigned         di;       // next input into delay line
144
+
145
+    cmSample_t*      xV;       // xV[fhN] linear delay buffer
146
+    cmComplexR_t*   t0V;       // t0V[fhN]
147
+    cmComplexR_t*   t1V;       // t1V[fhN]
148
+
149
+    cmSample_t*      wndV;
150
+
151
+    cmVectArray_t*   ftVa; 
152
+
153
+  } cmPhat_t;
154
+
155
+
156
+  // Allocate a PHAT based multi-channel correlator.
157
+  // 'chN'  is the maximum count of id signals to be set via cmPhatSetId().
158
+  // 'hN' is the the length of the id signal in samples.
159
+  // 'alpha' weight used to emphasize the frequencies where the
160
+  // id signal contains energy.
161
+  // 'mult' * 'hN' is the correlation length (fhN)
162
+  // 'flags' See kDebugAtPhatFl and kWndAtPhatFl.
163
+  cmPhat_t* cmPhatAlloc(  cmCtx* ctx, cmPhat_t* p, unsigned chN, unsigned hN, float alpha, unsigned mult, unsigned flags );
164
+  cmRC_t    cmPhatFree(   cmPhat_t** pp );
165
+
166
+  cmRC_t   cmPhatInit(  cmPhat_t* p, unsigned chN, unsigned hN, float alpha, unsigned mult, unsigned flags );  
167
+  cmRC_t   cmPhatFinal( cmPhat_t* p );
168
+
169
+  // Zero the audio delay line and reset the current input sample (di)
170
+  // and absolute time index (absIdx) to 0.
171
+  cmRC_t   cmPhatReset(  cmPhat_t* p );
172
+
173
+  // Register an id signal with the correlator.
174
+  cmRC_t   cmPhatSetId(  cmPhat_t* p, unsigned chIdx, const cmSample_t* hV, unsigned hN );
175
+
176
+  // Update the correlators internal delay buffer.
177
+  cmRC_t   cmPhatExec(   cmPhat_t* p, const cmSample_t* xV, unsigned xN );
178
+
179
+  // Set p->xV[0:fhN-1] to the correlation function based on
180
+  // correlation between the current audio delay line d[] and
181
+  // the id signal in fhM[:,chIdx].
182
+  // 'sessionId' and 'roleId' are only used to label the
183
+  // data stored in the debug file and may be set to any
184
+  // arbitrary value if the debug files are not being generated.
185
+  void cmPhatChExec( 
186
+    cmPhat_t* p,
187
+    unsigned  chIdx,
188
+    unsigned  sessionId,
189
+    unsigned  roleId);
190
+
191
+
192
+  cmRC_t cmPhatWrite( cmPhat_t* p, const char* dirStr );
193
+
194
+  cmRC_t cmPhatTest1( cmCtx* ctx, const char* dirFn );
195
+  cmRC_t cmPhatTest2( cmCtx* ctx );
42 196
 
197
+  
43 198
 #ifdef __cplusplus
44 199
 }
45 200
 #endif

+ 1
- 1
dsp/cmDspKr.c Переглянути файл

@@ -2534,7 +2534,7 @@ cmDspRC_t _cmDspRecdPlayParseRsrc( cmDspCtx_t* ctx, cmDspInst_t* inst, cmRecdPla
2534 2534
   if( jnp == NULL || cmJsonIsArray(jnp)==false )
2535 2535
   {
2536 2536
     // this is really a warning - the object does not require preloaded segments.
2537
-    cmDspInstErr(ctx,inst,kRsrcNotFoundDspRC,"The 'recdPlay' resource used to define pre-loaded segments was not found.");
2537
+    cmDspInstErr(ctx,inst,kRsrcNotFoundDspRC,"Warning: The 'recdPlay' resource used to define pre-loaded segments was not found.");
2538 2538
     return kOkDspRC;
2539 2539
   }
2540 2540
 

+ 4
- 0
dsp/cmDspPgm.c Переглянути файл

@@ -334,6 +334,7 @@ cmDspRC_t _cmDspSysPgm_PlaySine( cmDspSysH_t h, void** userPtrPtr )
334 334
   cmDspInst_t* ao1p = cmDspSysAllocInst(h,"AudioOut",  NULL,   1, useBuiltInFl ? 1 : 3 );
335 335
   cmDspInst_t* om0p = cmDspSysAllocInst(h,"AMeter","Out", 0);
336 336
   
337
+  cmDspInst_t* gain= cmDspSysAllocInst( h,"Scalar", "Gain",     5, kNumberDuiId, 0.0,  10.0,  0.01,  0.0);
337 338
 
338 339
   cmDspSysConnectAudio(h, php, "out", wtp,  "phs" );  // phasor -> wave table
339 340
   cmDspSysConnectAudio(h, wtp, "out", ao0p, "in" );   // wave table -> audio out
@@ -341,6 +342,9 @@ cmDspRC_t _cmDspSysPgm_PlaySine( cmDspSysH_t h, void** userPtrPtr )
341 342
   cmDspSysConnectAudio(h, wtp, "out", om0p, "in" );
342 343
 
343 344
   cmDspSysInstallCb( h, chp, "val", ao0p, "ch", NULL);
345
+  cmDspSysInstallCb( h, gain, "val", ao0p, "gain", NULL);
346
+  cmDspSysInstallCb( h, gain, "val", ao1p, "gain", NULL);
347
+  
344 348
   return kOkDspRC;
345 349
 }
346 350
 

+ 2
- 2
dsp/cmDspPgmKr.c Переглянути файл

@@ -382,7 +382,7 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
382 382
   cmErr_t         err;
383 383
   krRsrc_t        r;
384 384
   bool     fragFl       = false;
385
-  bool     useWtFl      = false;
385
+  bool     useWtFl      = true;
386 386
   bool     useChain1Fl  = true;
387 387
   bool     useInputEqFl = false;
388 388
   bool     useInCompFl  = true;
@@ -1048,7 +1048,7 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
1048 1048
   cmDspSysInstallCb(h, siRt, "f-out-1", sfp,  "smpidx",NULL ); 
1049 1049
   // leave siRt.f-out-1 unconnected because it should be ignored in 'simulate mode'
1050 1050
 
1051
-  cmDspSysInstallCb(h, mfp,  "mu",      muRt, "f-in",  NULL );
1051
+  cmDspSysInstallCb(h, mfp,  "id",      muRt, "f-in",  NULL );
1052 1052
   cmDspSysInstallCb(h, muRt, "f-out-1", sfp,  "muid",    NULL );
1053 1053
   // leave muRt.f-out-1 unconnected because it should be ignored in 'simulate mode'
1054 1054
 

+ 144
- 22
linux/cmAudioPortAlsa.c Переглянути файл

@@ -40,11 +40,17 @@ typedef struct devRecd_str
40 40
   snd_async_handler_t* ahandler;
41 41
   unsigned             srate;          // device sample rate
42 42
 
43
-  unsigned             iChCnt;  // ch count 
43
+  unsigned             iChCnt;         // ch count 
44 44
   unsigned             oChCnt;
45 45
 
46 46
   unsigned             iBits;          // bits per sample
47
-  unsigned             oBits; 
47
+  unsigned             oBits;
48
+
49
+  bool                 iSignFl;        // sample type is signed
50
+  bool                 oSignFl;
51
+
52
+  bool                 iSwapFl;        // swap the sample bytes
53
+  bool                 oSwapFl;
48 54
 
49 55
   unsigned             iSigBits;       // significant bits in each sample beginning
50 56
   unsigned             oSigBits;       // with the most sig. bit.
@@ -362,6 +368,77 @@ void _cmApDevRtReport( cmRpt_t* rpt, cmApDevRecd_t* drp )
362 368
 
363 369
 }
364 370
 
371
+void _cmApDevReportFormats( cmRpt_t* rpt, snd_pcm_hw_params_t* hwParams )
372
+{
373
+  snd_pcm_format_mask_t* mask;
374
+
375
+  snd_pcm_format_t fmt[] =
376
+  {
377
+     SND_PCM_FORMAT_S8,
378
+     SND_PCM_FORMAT_U8,
379
+     SND_PCM_FORMAT_S16_LE,
380
+     SND_PCM_FORMAT_S16_BE,
381
+     SND_PCM_FORMAT_U16_LE,
382
+     SND_PCM_FORMAT_U16_BE,
383
+     SND_PCM_FORMAT_S24_LE,
384
+     SND_PCM_FORMAT_S24_BE,
385
+     SND_PCM_FORMAT_U24_LE,
386
+     SND_PCM_FORMAT_U24_BE,
387
+     SND_PCM_FORMAT_S32_LE,
388
+     SND_PCM_FORMAT_S32_BE,
389
+     SND_PCM_FORMAT_U32_LE,
390
+     SND_PCM_FORMAT_U32_BE,
391
+     SND_PCM_FORMAT_FLOAT_LE,
392
+     SND_PCM_FORMAT_FLOAT_BE,
393
+     SND_PCM_FORMAT_FLOAT64_LE,
394
+     SND_PCM_FORMAT_FLOAT64_BE,
395
+     SND_PCM_FORMAT_IEC958_SUBFRAME_LE,
396
+     SND_PCM_FORMAT_IEC958_SUBFRAME_BE,
397
+     SND_PCM_FORMAT_MU_LAW,
398
+     SND_PCM_FORMAT_A_LAW,
399
+     SND_PCM_FORMAT_IMA_ADPCM,
400
+     SND_PCM_FORMAT_MPEG,
401
+     SND_PCM_FORMAT_GSM,
402
+     SND_PCM_FORMAT_SPECIAL,
403
+     SND_PCM_FORMAT_S24_3LE,
404
+     SND_PCM_FORMAT_S24_3BE,
405
+     SND_PCM_FORMAT_U24_3LE,
406
+     SND_PCM_FORMAT_U24_3BE,
407
+     SND_PCM_FORMAT_S20_3LE,
408
+     SND_PCM_FORMAT_S20_3BE,
409
+     SND_PCM_FORMAT_U20_3LE,
410
+     SND_PCM_FORMAT_U20_3BE,
411
+     SND_PCM_FORMAT_S18_3LE,
412
+     SND_PCM_FORMAT_S18_3BE,
413
+     SND_PCM_FORMAT_U18_3LE,
414
+     SND_PCM_FORMAT_U18_3BE,
415
+     SND_PCM_FORMAT_G723_24,
416
+     SND_PCM_FORMAT_G723_24_1B,
417
+     SND_PCM_FORMAT_G723_40,
418
+     SND_PCM_FORMAT_G723_40_1B,
419
+     SND_PCM_FORMAT_DSD_U8,
420
+     //SND_PCM_FORMAT_DSD_U16_LE,
421
+     //SND_PCM_FORMAT_DSD_U32_LE,
422
+     //SND_PCM_FORMAT_DSD_U16_BE,
423
+     //SND_PCM_FORMAT_DSD_U32_BE,
424
+     SND_PCM_FORMAT_UNKNOWN 
425
+  };
426
+
427
+  snd_pcm_format_mask_alloca(&mask);
428
+
429
+  snd_pcm_hw_params_get_format_mask(hwParams,mask);
430
+
431
+  cmRptPrintf(rpt,"Formats: " );
432
+  
433
+  int i;
434
+  for(i=0; fmt[i]!=SND_PCM_FORMAT_UNKNOWN; ++i)
435
+    if( snd_pcm_format_mask_test(mask, fmt[i] ))
436
+      cmRptPrintf(rpt,"%s%s",snd_pcm_format_name(fmt[i]), snd_pcm_format_cpu_endian(fmt[i]) ? " " : " (swap) ");
437
+  
438
+  cmRptPrintf(rpt,"\n");
439
+  
440
+}
441
+
365 442
 void _cmApDevReport( cmRpt_t* rpt, cmApDevRecd_t* drp )
366 443
 {
367 444
   bool       inputFl = true;
@@ -377,7 +454,7 @@ void _cmApDevReport( cmRpt_t* rpt, cmApDevRecd_t* drp )
377 454
   {
378 455
     if( ((inputFl==true) && (drp->flags&kInFl)) || (((inputFl==false) && (drp->flags&kOutFl))))
379 456
     {
380
-      const char* ioLabel = inputFl ? "In" : "Out";
457
+      const char* ioLabel = inputFl ? "In " : "Out";
381 458
 
382 459
       // attempt to open the sub-device
383 460
       if((err = snd_pcm_open(&pcmH,drp->nameStr,inputFl ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK,0)) < 0 )
@@ -435,6 +512,8 @@ void _cmApDevReport( cmRpt_t* rpt, cmApDevRecd_t* drp )
435 512
             ioLabel,minChCnt,maxChCnt,minSrate,maxSrate,minPeriodFrmCnt,maxPeriodFrmCnt,minBufFrmCnt,maxBufFrmCnt,
436 513
             (snd_pcm_hw_params_is_half_duplex(hwParams)  ? "yes" : "no"),
437 514
             (snd_pcm_hw_params_is_joint_duplex(hwParams) ? "yes" : "no"));
515
+          
516
+          _cmApDevReportFormats( rpt, hwParams );
438 517
         }
439 518
 
440 519
         if((err = snd_pcm_close(pcmH)) < 0)
@@ -610,6 +689,28 @@ void _cmApStateRecover( snd_pcm_t* pcmH, cmApDevRecd_t* drp, bool inputFl  )
610 689
   
611 690
 }
612 691
 
692
+void _cmApS24_3BE_to_Float( const char* x, cmApSample_t* y, unsigned n )
693
+{
694
+  unsigned i;
695
+  for(i=0; i<n; ++i,x+=3)
696
+  {
697
+    int s = (((int)x[0])<<16) + (((int)x[1])<<8) + (((int)x[2]));
698
+    y[i] = ((cmApSample_t)s)/0x7fffff;
699
+  }
700
+}
701
+
702
+void _cmApS24_3BE_from_Float( const cmApSample_t* x, char* y, unsigned n )
703
+{
704
+  unsigned i;
705
+  for(i=0; i<n; ++i)
706
+  {
707
+    int s = x[i] * 0x7fffff;
708
+    y[i*3+2] = (char)((s & 0x7f0000) >> 16);
709
+    y[i*3+1] = (char)((s & 0x00ff00) >>  8);
710
+    y[i*3+0] = (char)((s & 0x0000ff) >>  0);
711
+  }
712
+}
713
+
613 714
 
614 715
 // Returns count of frames written on success or < 0 on error;
615 716
 // set smpPtr to NULL to write a buffer of silence
@@ -648,9 +749,13 @@ int _cmApWriteBuf( cmApDevRecd_t* drp, snd_pcm_t* pcmH, const cmApSample_t* sp,
648 749
 
649 750
       case 24:
650 751
         {
752
+          // for use w/ MBox
753
+          //_cmApS24_3BE_from_Float(sp, obuf, ep-sp );
754
+          
651 755
           int* dp = (int*)obuf;
652 756
           while( sp < ep )
653 757
             *dp++ = (int)(*sp++ * 0x7fffff);        
758
+            
654 759
         }
655 760
         break;
656 761
 
@@ -696,7 +801,6 @@ int _cmApWriteBuf( cmApDevRecd_t* drp, snd_pcm_t* pcmH, const cmApSample_t* sp,
696 801
 }
697 802
 
698 803
 
699
-
700 804
 // Returns frames read on success or < 0 on error.
701 805
 // Set smpPtr to NULL to read the incoming buffer and discard it
702 806
 int _cmApReadBuf( cmApDevRecd_t* drp, snd_pcm_t* pcmH, cmApSample_t* smpPtr, unsigned chCnt, unsigned frmCnt, unsigned bits, unsigned sigBits )
@@ -729,7 +833,6 @@ int _cmApReadBuf( cmApDevRecd_t* drp, snd_pcm_t* pcmH, cmApSample_t* smpPtr, uns
729 833
 
730 834
   // setup the return buffer
731 835
   cmApSample_t* dp = smpPtr;
732
-
733 836
   cmApSample_t* ep = dp + cmMin(smpCnt,err*chCnt);
734 837
   
735 838
   switch(bits)
@@ -752,6 +855,8 @@ int _cmApReadBuf( cmApDevRecd_t* drp, snd_pcm_t* pcmH, cmApSample_t* smpPtr, uns
752 855
 
753 856
     case 24:
754 857
       {
858
+        // For use with MBox
859
+        //_cmApS24_3BE_to_Float(buf, dp, ep-dp );
755 860
         int* sp = (int*)buf;
756 861
         while(dp < ep)
757 862
           *dp++ = ((cmApSample_t)*sp++) /  0x7fffff;
@@ -819,7 +924,7 @@ void _cmApStaticAsyncHandler( snd_async_handler_t* ahandler )
819 924
   while( (avail = snd_pcm_avail_update(pcmH)) >= (snd_pcm_sframes_t)frmCnt )
820 925
   {
821 926
 
822
-    // Handle inpuut
927
+    // Handle input
823 928
     if( inputFl )
824 929
     {
825 930
       // read samples from the device
@@ -1024,7 +1129,21 @@ bool _cmApDevSetup( cmApDevRecd_t *drp, unsigned srate, unsigned framesPerCycle,
1024 1129
   snd_pcm_uframes_t bufferFrameCnt;
1025 1130
   unsigned          bits           = 0;
1026 1131
   int               sig_bits       = 0;
1132
+  bool              signFl         = true;
1133
+  bool              swapFl         = false;
1027 1134
   cmApRoot_t*       p              = drp->rootPtr;
1135
+
1136
+  snd_pcm_format_t fmt[] =
1137
+  {
1138
+    SND_PCM_FORMAT_S32_LE,
1139
+    SND_PCM_FORMAT_S32_BE,
1140
+    SND_PCM_FORMAT_S24_LE,
1141
+    SND_PCM_FORMAT_S24_BE,
1142
+    SND_PCM_FORMAT_S24_3LE,
1143
+    SND_PCM_FORMAT_S24_3BE,
1144
+    SND_PCM_FORMAT_S16_LE,
1145
+    SND_PCM_FORMAT_S16_BE,
1146
+  };
1028 1147
   
1029 1148
 
1030 1149
   // setup input, then output device
@@ -1041,7 +1160,6 @@ bool _cmApDevSetup( cmApDevRecd_t *drp, unsigned srate, unsigned framesPerCycle,
1041 1160
       if( _cmApDevShutdown(p, drp, inputFl ) != kOkApRC )
1042 1161
         retFl = false;
1043 1162
 
1044
-
1045 1163
       // attempt to open the sub-device
1046 1164
       if((err = snd_pcm_open(&pcmH,drp->nameStr, inputFl ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK, 0)) < 0 )
1047 1165
         retFl = _cmApDevSetupError(p,err,inputFl,drp,"Unable to open the PCM handle");
@@ -1075,23 +1193,23 @@ bool _cmApDevSetup( cmApDevRecd_t *drp, unsigned srate, unsigned framesPerCycle,
1075 1193
 
1076 1194
           if((err = snd_pcm_hw_params_set_access(pcmH,hwParams,SND_PCM_ACCESS_RW_INTERLEAVED )) < 0 )
1077 1195
             retFl = _cmApDevSetupError(p,err,inputFl, drp, "Unable to set access to: RW Interleaved");
1078
-		  
1079
-          // select the widest possible sample width
1080
-          if((err = snd_pcm_hw_params_set_format(pcmH,hwParams,SND_PCM_FORMAT_S32)) >= 0 )
1081
-            bits = 32;
1196
+          
1197
+          // select the format width
1198
+          int j;
1199
+          int fmtN = sizeof(fmt)/sizeof(fmt[0]);
1200
+          for(j=0; j<fmtN; ++j)
1201
+            if((err = snd_pcm_hw_params_set_format(pcmH,hwParams,fmt[j])) >= 0 )
1202
+              break;
1203
+
1204
+          if( j == fmtN )
1205
+            retFl = _cmApDevSetupError(p,err,inputFl, drp, "Unable to set format to: S16");
1082 1206
           else
1083 1207
           {
1084
-            if((err = snd_pcm_hw_params_set_format(pcmH,hwParams,SND_PCM_FORMAT_S24)) >= 0 )
1085
-              bits = 24;
1086
-            else
1087
-            {
1088
-              if((err = snd_pcm_hw_params_set_format(pcmH,hwParams,SND_PCM_FORMAT_S16)) >= 0 )
1089
-                bits = 16;
1090
-              else
1091
-                retFl = _cmApDevSetupError(p,err,inputFl, drp, "Unable to set format to: S16");
1092
-            }
1208
+            bits = snd_pcm_format_width(fmt[j]); // bits per sample
1209
+            signFl = snd_pcm_format_signed(fmt[j]);
1210
+            swapFl = !snd_pcm_format_cpu_endian(fmt[j]);
1093 1211
           }
1094
-
1212
+          
1095 1213
           sig_bits = snd_pcm_hw_params_get_sbits(hwParams);
1096 1214
 
1097 1215
           snd_pcm_uframes_t ps_min,ps_max;
@@ -1167,6 +1285,8 @@ bool _cmApDevSetup( cmApDevRecd_t *drp, unsigned srate, unsigned framesPerCycle,
1167 1285
         {
1168 1286
           drp->iBits    = bits;
1169 1287
           drp->iSigBits = sig_bits;
1288
+          drp->iSignFl  = signFl;
1289
+          drp->iSwapFl  = swapFl;
1170 1290
           drp->iPcmH    = pcmH;
1171 1291
           drp->iBuf     = cmMemResizeZ( cmApSample_t, drp->iBuf, actFpC * drp->iChCnt );
1172 1292
           drp->iFpC     = actFpC;
@@ -1175,6 +1295,8 @@ bool _cmApDevSetup( cmApDevRecd_t *drp, unsigned srate, unsigned framesPerCycle,
1175 1295
         {
1176 1296
           drp->oBits    = bits;
1177 1297
           drp->oSigBits = sig_bits;
1298
+          drp->oSignFl  = signFl;
1299
+          drp->oSwapFl  = swapFl;
1178 1300
           drp->oPcmH    = pcmH;
1179 1301
           drp->oBuf     = cmMemResizeZ( cmApSample_t, drp->oBuf, actFpC * drp->oChCnt );
1180 1302
           drp->oFpC     = actFpC;
@@ -1448,7 +1570,7 @@ cmApRC_t      cmApAlsaInitialize( cmRpt_t* rpt, unsigned baseApDevIdx )
1448 1570
                 // this device uses this subdevice in the current direction 
1449 1571
                 dr.flags += inputFl ? kInFl : kOutFl;
1450 1572
 
1451
-              printf("%s in:%i chs:%i rate:%i\n",dr.nameStr,inputFl,*chCntPtr,rate);
1573
+              //printf("%s in:%i chs:%i rate:%i\n",dr.nameStr,inputFl,*chCntPtr,rate);
1452 1574
               
1453 1575
             }                        
1454 1576
 

Завантаження…
Відмінити
Зберегти