|
@@ -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
|
|