From 20175d29f9c69e9e293b735d34339623af33412e Mon Sep 17 00:00:00 2001 From: kevin Date: Sun, 19 Feb 2023 14:16:37 -0500 Subject: [PATCH] cwAudioDevice*.h,cpp, cwIo.h,cpp, cwIoAudioPanel.cpp : Added deviceEnable(), deviceSeek() to audio device driver. Change io::cwAudioDeviceIsEnabled() to cwAudioDeviceIsActive(). --- cwAudioDevice.cpp | 48 +++++++++++---- cwAudioDevice.h | 19 +++++- cwAudioDeviceAlsa.cpp | 136 ++++++++++++++++++++++++++---------------- cwAudioDeviceAlsa.h | 2 + cwAudioDeviceFile.cpp | 97 +++++++++++++++++++++++------- cwAudioDeviceFile.h | 4 +- cwIo.cpp | 31 ++++++---- cwIo.h | 4 +- cwIoAudioPanel.cpp | 2 +- 9 files changed, 246 insertions(+), 97 deletions(-) diff --git a/cwAudioDevice.cpp b/cwAudioDevice.cpp index 552ac04..b46e81d 100644 --- a/cwAudioDevice.cpp +++ b/cwAudioDevice.cpp @@ -196,6 +196,43 @@ bool cw::audio::device::isStarted(handle_t h, unsigned devIdx ) return false; } + +cw::rc_t cw::audio::device::execute( handle_t h, unsigned devIdx ) +{ + rc_t rc = kOkRC; + drv_t* d; + if((d = _indexToDriver(h,devIdx)) == nullptr ) + rc = kInvalidArgRC; + else + rc = d->drv->deviceExecute( d->drv, devIdx - d->begIdx ); + + return rc; +} + +cw::rc_t cw::audio::device::enable( handle_t h, unsigned devIdx, bool inputFl, bool enableFl ) +{ + rc_t rc = kOkRC; + drv_t* d; + if((d = _indexToDriver(h,devIdx)) == nullptr ) + rc = kInvalidArgRC; + else + rc = d->drv->deviceEnable( d->drv, devIdx - d->begIdx, inputFl, enableFl ); + + return rc; +} + +cw::rc_t cw::audio::device::seek( handle_t h, unsigned devIdx, bool inputFl, unsigned frameOffset ) +{ + rc_t rc = kOkRC; + drv_t* d; + if((d = _indexToDriver(h,devIdx)) == nullptr ) + rc = kInvalidArgRC; + else + rc = d->drv->deviceSeek( d->drv, devIdx - d->begIdx, inputFl, frameOffset ); + + return rc; +} + void cw::audio::device::realTimeReport( handle_t h, unsigned devIdx ) { drv_t* d; @@ -203,17 +240,6 @@ void cw::audio::device::realTimeReport( handle_t h, unsigned devIdx ) d->drv->deviceRealTimeReport( d->drv, devIdx - d->begIdx ); } -cw::rc_t cw::audio::device::execute( handle_t h, unsigned devIdx ) -{ - rc_t rc = kOkRC; - drv_t* d; - if((d = _indexToDriver(h,devIdx)) != nullptr ) - rc = d->drv->deviceExecute( d->drv, devIdx - d->begIdx ); - - return rc; -} - - void cw::audio::device::report( handle_t h ) { for(unsigned i=0; ioEnableFl == false) memset(obuf,0,byteCnt); else { @@ -675,58 +678,66 @@ namespace cw if( smpPtr == NULL ) return err; - // setup the return buffer - device::sample_t* dp = smpPtr; - device::sample_t* ep = dp + std::min(smpCnt,err*chCnt); - - switch(bits) + + if( !drp->iEnableFl ) { - case 8: - { - char* sp = buf; - while(dp < ep) - *dp++ = ((device::sample_t)*sp++) / 0x7f; - } - break; - - case 16: - { - short* sp = (short*)buf; - while(dp < ep) - *dp++ = ((device::sample_t)*sp++) / 0x7fff; - } - break; - - case 24: - { - // For use with MBox - //_devS24_3BE_to_Float(buf, dp, ep-dp ); - int* sp = (int*)buf; - while(dp < ep) - *dp++ = ((device::sample_t)*sp++) / 0x7fffff; - } - break; - - - case 32: - { - int* sp = (int*)buf; - // The delta1010 (ICE1712) uses only the 24 highest bits according to - // - // http://www.alsa-project.org/alsa-doc/alsa-lib/pcm.html - // The example: ICE1712 chips support 32-bit sample processing, - // but low byte is ignored (playback) or zero (capture). - // - int mv = sigBits==24 ? 0x7fffff00 : 0x7fffffff; - while(dp < ep) - *dp++ = ((device::sample_t)*sp++) / mv; - - } - break; - default: - { cwAssert(0); } + memset(smpPtr,0,smpCnt*sizeof(sample_t)); } + else + { + + // setup the return buffer + device::sample_t* dp = smpPtr; + device::sample_t* ep = dp + std::min(smpCnt,err*chCnt); + + switch(bits) + { + case 8: + { + char* sp = buf; + while(dp < ep) + *dp++ = ((device::sample_t)*sp++) / 0x7f; + } + break; + case 16: + { + short* sp = (short*)buf; + while(dp < ep) + *dp++ = ((device::sample_t)*sp++) / 0x7fff; + } + break; + + case 24: + { + // For use with MBox + //_devS24_3BE_to_Float(buf, dp, ep-dp ); + int* sp = (int*)buf; + while(dp < ep) + *dp++ = ((device::sample_t)*sp++) / 0x7fffff; + } + break; + + + case 32: + { + int* sp = (int*)buf; + // The delta1010 (ICE1712) uses only the 24 highest bits according to + // + // http://www.alsa-project.org/alsa-doc/alsa-lib/pcm.html + // The example: ICE1712 chips support 32-bit sample processing, + // but low byte is ignored (playback) or zero (capture). + // + int mv = sigBits==24 ? 0x7fffff00 : 0x7fffffff; + while(dp < ep) + *dp++ = ((device::sample_t)*sp++) / mv; + + } + break; + default: + { cwAssert(0); } + } + } return err; } @@ -1102,6 +1113,7 @@ namespace cw drp->iPcmH = pcmH; drp->iBuf = mem::resizeZ( drp->iBuf, actFpC * drp->iChCnt ); drp->iFpC = actFpC; + drp->iEnableFl= true; } else { @@ -1112,6 +1124,7 @@ namespace cw drp->oPcmH = pcmH; drp->oBuf = mem::resizeZ( drp->oBuf, actFpC * drp->oChCnt ); drp->oFpC = actFpC; + drp->oEnableFl= true; } if( p->asyncFl == false ) @@ -1376,6 +1389,8 @@ cw::rc_t cw::audio::device::alsa::create( handle_t& hRef, struct driver_str*& dr p->driver.deviceStop = deviceStop; p->driver.deviceIsStarted = deviceIsStarted; p->driver.deviceExecute = deviceExecute; + p->driver.deviceEnable = deviceEnable; + p->driver.deviceSeek = deviceSeek; p->driver.deviceRealTimeReport = deviceRealTimeReport; @@ -1588,6 +1603,27 @@ cw::rc_t cw::audio::device::alsa::deviceExecute(struct driver_str* drv, unsigne return kOkRC; } +cw::rc_t cw::audio::device::alsa::deviceEnable( struct driver_str* drv, unsigned devIdx, bool inputFl, bool enableFl ) +{ + cwAssert(devIdx < deviceCount(drv)); + + alsa_t* p = static_cast(drv->drvArg); + devRecd_t* drp = p->devArray + devIdx; + + if( inputFl ) + drp->iEnableFl = enableFl; + else + drp->oEnableFl = enableFl; + + return kOkRC; +} + +cw::rc_t cw::audio::device::alsa::deviceSeek( struct driver_str* drv, unsigned devIdx, bool inputFl, unsigned frameOffset ) +{ + return kOkRC; +} + + void cw::audio::device::alsa::deviceRealTimeReport(struct driver_str* drv, unsigned devIdx ) { alsa_t* p = static_cast(drv->drvArg); diff --git a/cwAudioDeviceAlsa.h b/cwAudioDeviceAlsa.h index 7dd10cb..a259deb 100644 --- a/cwAudioDeviceAlsa.h +++ b/cwAudioDeviceAlsa.h @@ -25,6 +25,8 @@ namespace cw rc_t deviceStop( struct driver_str* drv, unsigned devIdx ); bool deviceIsStarted( struct driver_str* drv, unsigned devIdx ); rc_t deviceExecute( struct driver_str* drv, unsigned devIdx ); + rc_t deviceEnable( struct driver_str* drv, unsigned devIdx, bool inputFl, bool enableFl ); + rc_t deviceSeek( struct driver_str* drv, unsigned devIdx, bool inputFl, unsigned frameOffset ); void deviceRealTimeReport( struct driver_str* drv, unsigned devIdx ); rc_t report(handle_t h ); diff --git a/cwAudioDeviceFile.cpp b/cwAudioDeviceFile.cpp index 4230d3c..fdb6da9 100644 --- a/cwAudioDeviceFile.cpp +++ b/cwAudioDeviceFile.cpp @@ -46,6 +46,7 @@ namespace cw audiofile::handle_t iFileH; unsigned iFlags; unsigned iChCnt; + bool iEnableFl; audioPacket_t iPkt; float* iPktAudioBuf; unsigned iCbCnt; @@ -58,6 +59,7 @@ namespace cw audiofile::handle_t oFileH; unsigned oFlags; unsigned oChCnt; + bool oEnableFl; unsigned oBitsPerSample; audioPacket_t oPkt; float* oPktAudioBuf; @@ -201,6 +203,7 @@ namespace cw d->iChArray = mem::resize(d->iChArray,info.chCnt); d->iChSmpBuf = mem::resize(d->iChSmpBuf, d->framesPerCycle*info.chCnt ); d->iChCnt = info.chCnt; + d->iEnableFl = true; d->iErrCnt = 0; d->iFrmCnt = 0; d->iPkt.devIdx = d->cbDevIdx; @@ -224,26 +227,32 @@ namespace cw rc_t rc = kOkRC; unsigned actualFrameCnt = 0; - - // read the file - if((rc = readFloat(d->iFileH, d->framesPerCycle, 0, d->iChCnt, d->iChArray, &actualFrameCnt)) == kOkRC ) - d->iFrmCnt += actualFrameCnt; + + if( !d->iEnableFl ) + { + memset(d->iPkt.audioBytesPtr,0,d->iChCnt*d->framesPerCycle*sizeof(sample_t)); + } else - { - rc = cwLogError(rc,"File read failed on audio device file: %s.",cwStringNullGuard(d->label)); - d->iErrCnt += 1; - goto errLabel; + { + // read the file + if((rc = readFloat(d->iFileH, d->framesPerCycle, 0, d->iChCnt, d->iChArray, &actualFrameCnt)) == kOkRC ) + d->iFrmCnt += actualFrameCnt; + else + { + rc = cwLogError(rc,"File read failed on audio device file: %s.",cwStringNullGuard(d->label)); + d->iErrCnt += 1; + goto errLabel; + } + + // interleave into the iPkt audio buffer + vop::interleave( d->iPktAudioBuf, d->iChSmpBuf, actualFrameCnt, d->iChCnt ); + + if( actualFrameCnt < d->framesPerCycle ) + { + for(unsigned i=0; iiChCnt; ++i) + vop::fill( d->iPktAudioBuf + (actualFrameCnt * d->iChCnt) + i, 0, d->framesPerCycle-actualFrameCnt, d->iChCnt ); + } } - - // interleave into the iPkt audio buffer - vop::interleave( d->iPktAudioBuf, d->iChSmpBuf, actualFrameCnt, d->iChCnt ); - - if( actualFrameCnt < d->framesPerCycle ) - { - for(unsigned i=0; iiChCnt; ++i) - vop::fill( d->iPktAudioBuf + (actualFrameCnt * d->iChCnt) + i, 0, d->framesPerCycle-actualFrameCnt, d->iChCnt ); - } - errLabel: return rc; } @@ -280,6 +289,7 @@ namespace cw d->oPktAudioBuf = mem::resize(d->oPktAudioBuf,d->framesPerCycle*d->oChCnt); d->oChArray = mem::resize(d->oChArray,d->oChCnt); d->oChSmpBuf = mem::resize(d->oChSmpBuf, d->framesPerCycle*d->oChCnt ); + d->oEnableFl = true; d->oFrmCnt = 0; d->oErrCnt = 0; d->oPkt.devIdx = d->cbDevIdx; @@ -302,7 +312,7 @@ namespace cw { rc_t rc = kOkRC; - if( d->oFileH.isValid() ) + if( d->oFileH.isValid() && d->oEnableFl ) { /* // deinterleave the audio into d->oChArray[] @@ -460,6 +470,8 @@ cw::rc_t cw::audio::device::file::create( handle_t& hRef, struct driver_str*& p->driver.deviceStop = deviceStop; p->driver.deviceIsStarted = deviceIsStarted; p->driver.deviceExecute = deviceExecute; + p->driver.deviceEnable = deviceEnable; + p->driver.deviceSeek = deviceSeek; p->driver.deviceRealTimeReport = deviceRealTimeReport; if((rc = create( p->threadH, _threadCbFunc, p )) != kOkRC ) @@ -705,8 +717,53 @@ cw::rc_t cw::audio::device::file::deviceExecute( struct driver_str* dr mutex::signalCondVar(p->mutexH); errLabel: - return rc; + return rc; +} + +cw::rc_t cw::audio::device::file::deviceEnable( struct driver_str* drv, unsigned devIdx, bool inputFl, bool enableFl ) +{ + rc_t rc = kOkRC; + dev_mgr_t* p = _driverToPtr(drv); + dev_t* d = nullptr; + if((rc = _indexToDev( p, devIdx, d )) != kOkRC ) + goto errLabel; + + if( inputFl ) + d->iEnableFl = enableFl; + else + d->oEnableFl = enableFl; + + printf("Enable i:%i o:%i\n",d->iEnableFl,d->oEnableFl); + + errLabel: + return rc; +} + +cw::rc_t cw::audio::device::file::deviceSeek( struct driver_str* drv, unsigned devIdx, bool inputFl, unsigned frameOffset ) +{ + rc_t rc = kOkRC; + dev_mgr_t* p = _driverToPtr(drv); + dev_t* d = nullptr; + + if((rc = _indexToDev( p, devIdx, d )) != kOkRC ) + goto errLabel; + + if( inputFl ) + { + if( d->iFileH.isValid() ) + if((rc = seek(d->iFileH,frameOffset)) != kOkRC ) + rc = cwLogError(rc,"Seek failed on the audio device file input file."); + } + else + { + if( d->oFileH.isValid()) + if((rc = seek(d->oFileH,frameOffset)) != kOkRC ) + rc = cwLogError(rc,"Seek failed on the audio device file output file."); + } + + errLabel: + return rc; } void cw::audio::device::file::deviceRealTimeReport( struct driver_str* drv, unsigned devIdx ) diff --git a/cwAudioDeviceFile.h b/cwAudioDeviceFile.h index 6102f9f..b2d43ad 100644 --- a/cwAudioDeviceFile.h +++ b/cwAudioDeviceFile.h @@ -26,7 +26,9 @@ namespace cw rc_t deviceStart( struct driver_str* drv, unsigned devIdx ); rc_t deviceStop( struct driver_str* drv, unsigned devIdx ); bool deviceIsStarted( struct driver_str* drv, unsigned devIdx ); - rc_t deviceExecute( struct driver_str* drv, unsigned devIdx ); + rc_t deviceExecute( struct driver_str* drv, unsigned devIdx ); + rc_t deviceEnable( struct driver_str* drv, unsigned devIdx, bool inputFl, bool enableFl ); + rc_t deviceSeek( struct driver_str* drv, unsigned devIdx, bool inputFl, unsigned frameOffset ); void deviceRealTimeReport( struct driver_str* drv, unsigned devIdx ); enum { diff --git a/cwIo.cpp b/cwIo.cpp index 857234b..f1cf723 100644 --- a/cwIo.cpp +++ b/cwIo.cpp @@ -82,7 +82,7 @@ namespace cw typedef struct audioDev_str { - bool enableFl; // True if this device was enabled by the user + bool activeFl; // True if this device was enabled by the user bool meterFl; // True if meters are enabled on this device const char* label; // User label unsigned userId; // User id @@ -843,7 +843,7 @@ namespace cw rc_t rc1 = kOkRC; for(unsigned i=0; iaudioDevN; ++i) - if( p->audioDevA[i].enableFl ) + if( p->audioDevA[i].activeFl ) { rc_t rc0 = kOkRC; if( startFl ) @@ -1007,7 +1007,7 @@ namespace cw if( time::isGTE(p->t0,p->audioMeterNextTime) ) { for(unsigned i=0; iaudioDevN; ++i) - if( p->audioDevA[i].enableFl ) + if( p->audioDevA[i].activeFl ) { audioDev_t* ad = p->audioDevA + i; rc_t rc0; @@ -1575,7 +1575,7 @@ namespace cw for(unsigned i=0; ichild_count(); ++i) { audioDev_t* ad = nullptr; //p->audioDevA + i; - bool enableFl = false; + bool activeFl = false; bool meterFl = false; char* userLabel = nullptr; unsigned userId = kInvalidId; @@ -1605,7 +1605,7 @@ namespace cw if((node = deviceL_Node->child_ele(i)) != nullptr ) { if(( rc = node->getv( - "enableFl", enableFl, + "activeFl", activeFl, "label", userLabel, "device", devName, "framesPerCycle", framesPerCycle, @@ -1631,7 +1631,7 @@ namespace cw } // if the configuration is enabled - if( enableFl ) + if( activeFl ) { // locate the record assoc'd with devName if((ad = _audioDeviceNameToRecd(p,devName)) == nullptr ) @@ -1734,7 +1734,7 @@ namespace cw } // set the device group pointers - ad->enableFl = enableFl; + ad->activeFl = activeFl; ad->meterFl = meterFl; ad->label = userLabel; ad->userId = userId; @@ -1753,7 +1753,7 @@ namespace cw rc_t rc = kOkRC; for(unsigned i=0; iaudioDevN; ++i) - if( p->audioDevA[i].enableFl && p->audioDevA[i].meterFl ) + if( p->audioDevA[i].activeFl && p->audioDevA[i].meterFl ) if((rc = _audioDeviceEnableMeter(p, p->audioDevA[i].devIdx, kEnableFl | kInFl | kOutFl )) != kOkRC ) { cwLogError(rc,"Audio enable on device '%s' failed.",p->audioDevA[i].label); @@ -2613,12 +2613,12 @@ cw::rc_t cw::io::audioDeviceSetUserId( handle_t h, unsigned devIdx, unsigned us return kInvalidArgRC; } -bool cw::io::audioDeviceIsEnabled( handle_t h, unsigned devIdx ) +bool cw::io::audioDeviceIsActive( handle_t h, unsigned devIdx ) { io_t* p = _handleToPtr(h); audioDev_t* ad; if((ad = _audioDeviceIndexToRecd(p,devIdx)) != nullptr ) - return ad->enableFl; + return ad->activeFl; return false; } @@ -2646,6 +2646,17 @@ unsigned cw::io::audioDeviceUserId( handle_t h, unsigned devIdx ) return ad->userId; } +cw::rc_t cw::io::audioDeviceEnable( handle_t h, unsigned devIdx, bool inputFl, bool enableFl ) +{ + io_t* p = _handleToPtr(h); + return audio::device::enable(p->audioH, devIdx, inputFl, enableFl ); +} + +cw::rc_t cw::io::audioDeviceSeek( handle_t h, unsigned devIdx, bool inputFl, unsigned frameOffset ) +{ + io_t* p = _handleToPtr(h); + return audio::device::seek(p->audioH, devIdx, inputFl, frameOffset ); +} double cw::io::audioDeviceSampleRate( handle_t h, unsigned devIdx ) { diff --git a/cwIo.h b/cwIo.h index ed53fb5..204fb96 100644 --- a/cwIo.h +++ b/cwIo.h @@ -228,9 +228,11 @@ namespace cw unsigned audioDeviceLabelToIndex( handle_t h, const char* label ); const char* audioDeviceLabel( handle_t h, unsigned devIdx ); rc_t audioDeviceSetUserId( handle_t h, unsigned devIdx, unsigned userId ); - bool audioDeviceIsEnabled( handle_t h, unsigned devIdx ); + bool audioDeviceIsActive( handle_t h, unsigned devIdx ); const char* audioDeviceName( handle_t h, unsigned devIdx ); unsigned audioDeviceUserId( handle_t h, unsigned devIdx ); + rc_t audioDeviceEnable( handle_t h, unsigned devIdx, bool inputFl, bool enableFl ); + rc_t audioDeviceSeek( handle_t h, unsigned devIdx, bool inputFl, unsigned frameOffset ); double audioDeviceSampleRate( handle_t h, unsigned devIdx ); unsigned audioDeviceFramesPerCycle( handle_t h, unsigned devIdx ); unsigned audioDeviceChannelCount( handle_t h, unsigned devIdx, unsigned inOrOutFlag ); diff --git a/cwIoAudioPanel.cpp b/cwIoAudioPanel.cpp index 5c94638..27d5b06 100644 --- a/cwIoAudioPanel.cpp +++ b/cwIoAudioPanel.cpp @@ -274,7 +274,7 @@ cw::rc_t cw::io::audio_panel::create( handle_t& hRef, io::handle_t ioH, unsigne // create the audio panels for each audio device for(unsigned i=0; i