cmAudioPortAlsa.c : Added _cmApDevReportFormats().

Added, but disabled, _cmApS24_3BE*().
Added i/oSignFl and i/oSwapFl to device record.
Changed sample format selection algorithm to use fmt[].
This commit is contained in:
Kevin Larke 2015-05-29 11:49:29 -07:00
parent ba5cd463f0
commit f48cc2e7f7

View File

@ -46,6 +46,12 @@ typedef struct devRecd_str
unsigned iBits; // bits per sample unsigned iBits; // bits per sample
unsigned oBits; unsigned oBits;
bool iSignFl; // sample type is signed
bool oSignFl;
bool iSwapFl; // swap the sample bytes
bool oSwapFl;
unsigned iSigBits; // significant bits in each sample beginning unsigned iSigBits; // significant bits in each sample beginning
unsigned oSigBits; // with the most sig. bit. unsigned oSigBits; // with the most sig. bit.
@ -362,6 +368,77 @@ void _cmApDevRtReport( cmRpt_t* rpt, cmApDevRecd_t* drp )
} }
void _cmApDevReportFormats( cmRpt_t* rpt, snd_pcm_hw_params_t* hwParams )
{
snd_pcm_format_mask_t* mask;
snd_pcm_format_t fmt[] =
{
SND_PCM_FORMAT_S8,
SND_PCM_FORMAT_U8,
SND_PCM_FORMAT_S16_LE,
SND_PCM_FORMAT_S16_BE,
SND_PCM_FORMAT_U16_LE,
SND_PCM_FORMAT_U16_BE,
SND_PCM_FORMAT_S24_LE,
SND_PCM_FORMAT_S24_BE,
SND_PCM_FORMAT_U24_LE,
SND_PCM_FORMAT_U24_BE,
SND_PCM_FORMAT_S32_LE,
SND_PCM_FORMAT_S32_BE,
SND_PCM_FORMAT_U32_LE,
SND_PCM_FORMAT_U32_BE,
SND_PCM_FORMAT_FLOAT_LE,
SND_PCM_FORMAT_FLOAT_BE,
SND_PCM_FORMAT_FLOAT64_LE,
SND_PCM_FORMAT_FLOAT64_BE,
SND_PCM_FORMAT_IEC958_SUBFRAME_LE,
SND_PCM_FORMAT_IEC958_SUBFRAME_BE,
SND_PCM_FORMAT_MU_LAW,
SND_PCM_FORMAT_A_LAW,
SND_PCM_FORMAT_IMA_ADPCM,
SND_PCM_FORMAT_MPEG,
SND_PCM_FORMAT_GSM,
SND_PCM_FORMAT_SPECIAL,
SND_PCM_FORMAT_S24_3LE,
SND_PCM_FORMAT_S24_3BE,
SND_PCM_FORMAT_U24_3LE,
SND_PCM_FORMAT_U24_3BE,
SND_PCM_FORMAT_S20_3LE,
SND_PCM_FORMAT_S20_3BE,
SND_PCM_FORMAT_U20_3LE,
SND_PCM_FORMAT_U20_3BE,
SND_PCM_FORMAT_S18_3LE,
SND_PCM_FORMAT_S18_3BE,
SND_PCM_FORMAT_U18_3LE,
SND_PCM_FORMAT_U18_3BE,
SND_PCM_FORMAT_G723_24,
SND_PCM_FORMAT_G723_24_1B,
SND_PCM_FORMAT_G723_40,
SND_PCM_FORMAT_G723_40_1B,
SND_PCM_FORMAT_DSD_U8,
//SND_PCM_FORMAT_DSD_U16_LE,
//SND_PCM_FORMAT_DSD_U32_LE,
//SND_PCM_FORMAT_DSD_U16_BE,
//SND_PCM_FORMAT_DSD_U32_BE,
SND_PCM_FORMAT_UNKNOWN
};
snd_pcm_format_mask_alloca(&mask);
snd_pcm_hw_params_get_format_mask(hwParams,mask);
cmRptPrintf(rpt,"Formats: " );
int i;
for(i=0; fmt[i]!=SND_PCM_FORMAT_UNKNOWN; ++i)
if( snd_pcm_format_mask_test(mask, fmt[i] ))
cmRptPrintf(rpt,"%s%s",snd_pcm_format_name(fmt[i]), snd_pcm_format_cpu_endian(fmt[i]) ? " " : " (swap) ");
cmRptPrintf(rpt,"\n");
}
void _cmApDevReport( cmRpt_t* rpt, cmApDevRecd_t* drp ) void _cmApDevReport( cmRpt_t* rpt, cmApDevRecd_t* drp )
{ {
bool inputFl = true; bool inputFl = true;
@ -435,6 +512,8 @@ void _cmApDevReport( cmRpt_t* rpt, cmApDevRecd_t* drp )
ioLabel,minChCnt,maxChCnt,minSrate,maxSrate,minPeriodFrmCnt,maxPeriodFrmCnt,minBufFrmCnt,maxBufFrmCnt, ioLabel,minChCnt,maxChCnt,minSrate,maxSrate,minPeriodFrmCnt,maxPeriodFrmCnt,minBufFrmCnt,maxBufFrmCnt,
(snd_pcm_hw_params_is_half_duplex(hwParams) ? "yes" : "no"), (snd_pcm_hw_params_is_half_duplex(hwParams) ? "yes" : "no"),
(snd_pcm_hw_params_is_joint_duplex(hwParams) ? "yes" : "no")); (snd_pcm_hw_params_is_joint_duplex(hwParams) ? "yes" : "no"));
_cmApDevReportFormats( rpt, hwParams );
} }
if((err = snd_pcm_close(pcmH)) < 0) if((err = snd_pcm_close(pcmH)) < 0)
@ -610,6 +689,28 @@ void _cmApStateRecover( snd_pcm_t* pcmH, cmApDevRecd_t* drp, bool inputFl )
} }
void _cmApS24_3BE_to_Float( const char* x, cmApSample_t* y, unsigned n )
{
unsigned i;
for(i=0; i<n; ++i,x+=3)
{
int s = (((int)x[0])<<16) + (((int)x[1])<<8) + (((int)x[2]));
y[i] = ((cmApSample_t)s)/0x7fffff;
}
}
void _cmApS24_3BE_from_Float( const cmApSample_t* x, char* y, unsigned n )
{
unsigned i;
for(i=0; i<n; ++i)
{
int s = x[i] * 0x7fffff;
y[i*3+2] = (char)((s & 0x7f0000) >> 16);
y[i*3+1] = (char)((s & 0x00ff00) >> 8);
y[i*3+0] = (char)((s & 0x0000ff) >> 0);
}
}
// Returns count of frames written on success or < 0 on error; // Returns count of frames written on success or < 0 on error;
// set smpPtr to NULL to write a buffer of silence // 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,
case 24: case 24:
{ {
// for use w/ MBox
//_cmApS24_3BE_from_Float(sp, obuf, ep-sp );
int* dp = (int*)obuf; int* dp = (int*)obuf;
while( sp < ep ) while( sp < ep )
*dp++ = (int)(*sp++ * 0x7fffff); *dp++ = (int)(*sp++ * 0x7fffff);
} }
break; break;
@ -696,7 +801,6 @@ int _cmApWriteBuf( cmApDevRecd_t* drp, snd_pcm_t* pcmH, const cmApSample_t* sp,
} }
// Returns frames read on success or < 0 on error. // Returns frames read on success or < 0 on error.
// Set smpPtr to NULL to read the incoming buffer and discard it // Set smpPtr to NULL to read the incoming buffer and discard it
int _cmApReadBuf( cmApDevRecd_t* drp, snd_pcm_t* pcmH, cmApSample_t* smpPtr, unsigned chCnt, unsigned frmCnt, unsigned bits, unsigned sigBits ) 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
// setup the return buffer // setup the return buffer
cmApSample_t* dp = smpPtr; cmApSample_t* dp = smpPtr;
cmApSample_t* ep = dp + cmMin(smpCnt,err*chCnt); cmApSample_t* ep = dp + cmMin(smpCnt,err*chCnt);
switch(bits) switch(bits)
@ -752,6 +855,8 @@ int _cmApReadBuf( cmApDevRecd_t* drp, snd_pcm_t* pcmH, cmApSample_t* smpPtr, uns
case 24: case 24:
{ {
// For use with MBox
//_cmApS24_3BE_to_Float(buf, dp, ep-dp );
int* sp = (int*)buf; int* sp = (int*)buf;
while(dp < ep) while(dp < ep)
*dp++ = ((cmApSample_t)*sp++) / 0x7fffff; *dp++ = ((cmApSample_t)*sp++) / 0x7fffff;
@ -819,7 +924,7 @@ void _cmApStaticAsyncHandler( snd_async_handler_t* ahandler )
while( (avail = snd_pcm_avail_update(pcmH)) >= (snd_pcm_sframes_t)frmCnt ) while( (avail = snd_pcm_avail_update(pcmH)) >= (snd_pcm_sframes_t)frmCnt )
{ {
// Handle inpuut // Handle input
if( inputFl ) if( inputFl )
{ {
// read samples from the device // read samples from the device
@ -1024,8 +1129,22 @@ bool _cmApDevSetup( cmApDevRecd_t *drp, unsigned srate, unsigned framesPerCycle,
snd_pcm_uframes_t bufferFrameCnt; snd_pcm_uframes_t bufferFrameCnt;
unsigned bits = 0; unsigned bits = 0;
int sig_bits = 0; int sig_bits = 0;
bool signFl = true;
bool swapFl = false;
cmApRoot_t* p = drp->rootPtr; cmApRoot_t* p = drp->rootPtr;
snd_pcm_format_t fmt[] =
{
SND_PCM_FORMAT_S32_LE,
SND_PCM_FORMAT_S32_BE,
SND_PCM_FORMAT_S24_LE,
SND_PCM_FORMAT_S24_BE,
SND_PCM_FORMAT_S24_3LE,
SND_PCM_FORMAT_S24_3BE,
SND_PCM_FORMAT_S16_LE,
SND_PCM_FORMAT_S16_BE,
};
// setup input, then output device // setup input, then output device
for(i=0; i<2; i++,inputFl=!inputFl) for(i=0; i<2; i++,inputFl=!inputFl)
@ -1041,7 +1160,6 @@ bool _cmApDevSetup( cmApDevRecd_t *drp, unsigned srate, unsigned framesPerCycle,
if( _cmApDevShutdown(p, drp, inputFl ) != kOkApRC ) if( _cmApDevShutdown(p, drp, inputFl ) != kOkApRC )
retFl = false; retFl = false;
// attempt to open the sub-device // attempt to open the sub-device
if((err = snd_pcm_open(&pcmH,drp->nameStr, inputFl ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK, 0)) < 0 ) if((err = snd_pcm_open(&pcmH,drp->nameStr, inputFl ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK, 0)) < 0 )
retFl = _cmApDevSetupError(p,err,inputFl,drp,"Unable to open the PCM handle"); retFl = _cmApDevSetupError(p,err,inputFl,drp,"Unable to open the PCM handle");
@ -1076,20 +1194,20 @@ bool _cmApDevSetup( cmApDevRecd_t *drp, unsigned srate, unsigned framesPerCycle,
if((err = snd_pcm_hw_params_set_access(pcmH,hwParams,SND_PCM_ACCESS_RW_INTERLEAVED )) < 0 ) if((err = snd_pcm_hw_params_set_access(pcmH,hwParams,SND_PCM_ACCESS_RW_INTERLEAVED )) < 0 )
retFl = _cmApDevSetupError(p,err,inputFl, drp, "Unable to set access to: RW Interleaved"); retFl = _cmApDevSetupError(p,err,inputFl, drp, "Unable to set access to: RW Interleaved");
// select the widest possible sample width // select the format width
if((err = snd_pcm_hw_params_set_format(pcmH,hwParams,SND_PCM_FORMAT_S32)) >= 0 ) int j;
bits = 32; int fmtN = sizeof(fmt)/sizeof(fmt[0]);
else for(j=0; j<fmtN; ++j)
{ if((err = snd_pcm_hw_params_set_format(pcmH,hwParams,fmt[j])) >= 0 )
if((err = snd_pcm_hw_params_set_format(pcmH,hwParams,SND_PCM_FORMAT_S24)) >= 0 ) break;
bits = 24;
else if( j == fmtN )
{
if((err = snd_pcm_hw_params_set_format(pcmH,hwParams,SND_PCM_FORMAT_S16)) >= 0 )
bits = 16;
else
retFl = _cmApDevSetupError(p,err,inputFl, drp, "Unable to set format to: S16"); retFl = _cmApDevSetupError(p,err,inputFl, drp, "Unable to set format to: S16");
} else
{
bits = snd_pcm_format_width(fmt[j]); // bits per sample
signFl = snd_pcm_format_signed(fmt[j]);
swapFl = !snd_pcm_format_cpu_endian(fmt[j]);
} }
sig_bits = snd_pcm_hw_params_get_sbits(hwParams); sig_bits = snd_pcm_hw_params_get_sbits(hwParams);
@ -1167,6 +1285,8 @@ bool _cmApDevSetup( cmApDevRecd_t *drp, unsigned srate, unsigned framesPerCycle,
{ {
drp->iBits = bits; drp->iBits = bits;
drp->iSigBits = sig_bits; drp->iSigBits = sig_bits;
drp->iSignFl = signFl;
drp->iSwapFl = swapFl;
drp->iPcmH = pcmH; drp->iPcmH = pcmH;
drp->iBuf = cmMemResizeZ( cmApSample_t, drp->iBuf, actFpC * drp->iChCnt ); drp->iBuf = cmMemResizeZ( cmApSample_t, drp->iBuf, actFpC * drp->iChCnt );
drp->iFpC = actFpC; drp->iFpC = actFpC;
@ -1175,6 +1295,8 @@ bool _cmApDevSetup( cmApDevRecd_t *drp, unsigned srate, unsigned framesPerCycle,
{ {
drp->oBits = bits; drp->oBits = bits;
drp->oSigBits = sig_bits; drp->oSigBits = sig_bits;
drp->oSignFl = signFl;
drp->oSwapFl = swapFl;
drp->oPcmH = pcmH; drp->oPcmH = pcmH;
drp->oBuf = cmMemResizeZ( cmApSample_t, drp->oBuf, actFpC * drp->oChCnt ); drp->oBuf = cmMemResizeZ( cmApSample_t, drp->oBuf, actFpC * drp->oChCnt );
drp->oFpC = actFpC; drp->oFpC = actFpC;
@ -1448,7 +1570,7 @@ cmApRC_t cmApAlsaInitialize( cmRpt_t* rpt, unsigned baseApDevIdx )
// this device uses this subdevice in the current direction // this device uses this subdevice in the current direction
dr.flags += inputFl ? kInFl : kOutFl; dr.flags += inputFl ? kInFl : kOutFl;
printf("%s in:%i chs:%i rate:%i\n",dr.nameStr,inputFl,*chCntPtr,rate); //printf("%s in:%i chs:%i rate:%i\n",dr.nameStr,inputFl,*chCntPtr,rate);
} }