From 70a78fa42632a6d5e3739b35e0ff17cd80a06878 Mon Sep 17 00:00:00 2001 From: Volker Fischer Date: Sat, 2 May 2020 17:15:18 +0200 Subject: [PATCH] backup checkin, WIP --- mac/sound.cpp | 242 +++++++++++++++++++++++++++++++++----------------- mac/sound.h | 18 +++- 2 files changed, 177 insertions(+), 83 deletions(-) diff --git a/mac/sound.cpp b/mac/sound.cpp index 6a125b97..4a21be11 100755 --- a/mac/sound.cpp +++ b/mac/sound.cpp @@ -264,40 +264,49 @@ int CSound::CountChannels ( AudioDeviceID devID, UInt32 propSize; int result = 0; - // check for the case the we have interleaved format, in that case we assume - // that only the very first buffer contains all our channels - if ( iNumChanPerFrame > 1 ) + if ( isInput ) { - result = iNumChanPerFrame; + vecNumInBufChan.Init ( 0 ); } else { - // it seems we have multiple buffers where each buffer has only one channel, - // in that case we assume that each input channel has its own buffer - AudioObjectPropertyScope theScope = isInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; + vecNumOutBufChan.Init ( 0 ); + } - AudioObjectPropertyAddress theAddress = { kAudioDevicePropertyStreamConfiguration, - theScope, - 0 }; + // it seems we have multiple buffers where each buffer has only one channel, + // in that case we assume that each input channel has its own buffer + AudioObjectPropertyScope theScope = isInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; - AudioObjectGetPropertyDataSize ( devID, &theAddress, 0, NULL, &propSize ); + AudioObjectPropertyAddress theAddress = { kAudioDevicePropertyStreamConfiguration, + theScope, + 0 }; - AudioBufferList *buflist = (AudioBufferList*) malloc ( propSize ); + AudioObjectGetPropertyDataSize ( devID, &theAddress, 0, NULL, &propSize ); - err = AudioObjectGetPropertyData ( devID, &theAddress, 0, NULL, &propSize, buflist ); + AudioBufferList *buflist = (AudioBufferList*) malloc ( propSize ); - if ( !err ) + err = AudioObjectGetPropertyData ( devID, &theAddress, 0, NULL, &propSize, buflist ); + + if ( !err ) + { + for ( UInt32 i = 0; i < buflist->mNumberBuffers; ++i ) { - for ( UInt32 i = 0; i < buflist->mNumberBuffers; ++i ) + // The correct value mNumberChannels for an AudioBuffer can be derived from the mChannelsPerFrame + // and the interleaved flag. For non interleaved formats, mNumberChannels is always 1. + // For interleaved formats, mNumberChannels is equal to mChannelsPerFrame. + result += buflist->mBuffers[i].mNumberChannels; + + if ( isInput ) { - // The correct value mNumberChannels for an AudioBuffer can be derived from the mChannelsPerFrame - // and the interleaved flag. For non interleaved formats, mNumberChannels is always 1. - // For interleaved formats, mNumberChannels is equal to mChannelsPerFrame. - result += buflist->mBuffers[i].mNumberChannels; + vecNumInBufChan.Add ( buflist->mBuffers[i].mNumberChannels ); + } + else + { + vecNumOutBufChan.Add ( buflist->mBuffers[i].mNumberChannels ); } } - free ( buflist ); } + free ( buflist ); return result; } @@ -317,10 +326,10 @@ QString CSound::LoadAndInitializeDriver ( int iDriverIdx, bool ) // the device has changed, per definition we reset the channel // mapping to the defaults (first two available channels) - iSelInputLeftChannel = 0; - iSelInputRightChannel = min ( iNumInChan - 1, 1 ); - iSelOutputLeftChannel = 0; - iSelOutputRightChannel = min ( iNumOutChan - 1, 1 ); + SetLeftInputChannel ( 0 ); + SetRightInputChannel ( 1 ); + SetLeftOutputChannel ( 0 ); + SetRightOutputChannel ( 1 ); } return strStat; @@ -599,12 +608,85 @@ QString CSound::CheckDeviceCapabilities ( const int iDriverIdx ) return ""; } +void CSound::UpdateChSelection() +{ + // calculate the selected input/output buffer and the selected interleaved + // channel index in the buffer, note that each buffer can have a different + // number of interleaved channels + int iChCnt; + int iSelCHLeft, iSelAddCHLeft; + int iSelCHRight, iSelAddCHRight; + iSelAddInBufferLeft = -1; // initialize with invalid value + iSelAddInInterlChLeft = -1; // initialize with invalid value + iSelAddInBufferRight = -1; // initialize with invalid value + iSelAddInInterlChRight = -1; // initialize with invalid value + + // input + GetSelCHAndAddCH ( iSelInputLeftChannel, iNumInChan, iSelCHLeft, iSelAddCHLeft ); + GetSelCHAndAddCH ( iSelInputRightChannel, iNumInChan, iSelCHRight, iSelAddCHRight ); + + iChCnt = 0; + + for ( int iBuf = 0; iBuf < vecNumInBufChan.Size(); iBuf++ ) + { + iChCnt += vecNumInBufChan[iBuf]; + + if ( iChCnt > iSelCHLeft ) + { + iSelInBufferLeft = iBuf; + iSelInInterlChLeft = iSelCHLeft - iChCnt + vecNumInBufChan[iBuf]; + } + + if ( iChCnt > iSelCHRight ) + { + iSelInBufferRight = iBuf; + iSelInInterlChRight = iSelCHRight - iChCnt + vecNumInBufChan[iBuf]; + } + + if ( ( iSelAddCHLeft >= 0 ) && ( iChCnt > iSelAddCHLeft ) ) + { + iSelAddInBufferLeft = iBuf; + iSelAddInInterlChLeft = iSelAddCHLeft - iChCnt + vecNumInBufChan[iBuf]; + } + + if ( ( iSelAddCHRight >= 0 ) && ( iChCnt > iSelAddCHRight ) ) + { + iSelAddInBufferRight = iBuf; + iSelAddInInterlChRight = iSelAddCHRight - iChCnt + vecNumInBufChan[iBuf]; + } + } + + // output + GetSelCHAndAddCH ( iSelOutputLeftChannel, iNumOutChan, iSelCHLeft, iSelAddCHLeft ); + GetSelCHAndAddCH ( iSelOutputRightChannel, iNumOutChan, iSelCHRight, iSelAddCHRight ); + + iChCnt = 0; + + for ( int iBuf = 0; iBuf < vecNumOutBufChan.Size(); iBuf++ ) + { + iChCnt += vecNumOutBufChan[iBuf]; + + if ( iChCnt > iSelCHLeft ) + { + iSelOutBufferLeft = iBuf; + iSelOutInterlChLeft = iSelCHLeft - iChCnt + vecNumOutBufChan[iBuf]; + } + + if ( iChCnt > iSelCHRight ) + { + iSelOutBufferRight = iBuf; + iSelOutInterlChRight = iSelCHRight - iChCnt + vecNumOutBufChan[iBuf]; + } + } +} + void CSound::SetLeftInputChannel ( const int iNewChan ) { // apply parameter after input parameter check if ( ( iNewChan >= 0 ) && ( iNewChan < iNumInChanPlusAddChan ) ) { iSelInputLeftChannel = iNewChan; + UpdateChSelection(); } } @@ -614,6 +696,7 @@ void CSound::SetRightInputChannel ( const int iNewChan ) if ( ( iNewChan >= 0 ) && ( iNewChan < iNumInChanPlusAddChan ) ) { iSelInputRightChannel = iNewChan; + UpdateChSelection(); } } @@ -623,6 +706,7 @@ void CSound::SetLeftOutputChannel ( const int iNewChan ) if ( ( iNewChan >= 0 ) && ( iNewChan < iNumOutChan ) ) { iSelOutputLeftChannel = iNewChan; + UpdateChSelection(); } } @@ -632,6 +716,7 @@ void CSound::SetRightOutputChannel ( const int iNewChan ) if ( ( iNewChan >= 0 ) && ( iNewChan < iNumOutChan ) ) { iSelOutputRightChannel = iNewChan; + UpdateChSelection(); } } @@ -854,90 +939,62 @@ OSStatus CSound::callbackIO ( AudioDeviceID inDevice, const int iCoreAudioBufferSizeMono = pSound->iCoreAudioBufferSizeMono; const int iNumInChan = pSound->iNumInChan; const int iNumOutChan = pSound->iNumOutChan; - const int iSelInputLeftChannel = pSound->iSelInputLeftChannel; - const int iSelInputRightChannel = pSound->iSelInputRightChannel; - const int iSelOutputLeftChannel = pSound->iSelOutputLeftChannel; - const int iSelOutputRightChannel = pSound->iSelOutputRightChannel; + const int iSelInBufferLeft = pSound->iSelInBufferLeft; + const int iSelInBufferRight = pSound->iSelInBufferRight; + const int iSelInInterlChLeft = pSound->iSelInInterlChLeft; + const int iSelInInterlChRight = pSound->iSelInInterlChRight; + const int iSelAddInBufferLeft = pSound->iSelAddInBufferLeft; + const int iSelAddInBufferRight = pSound->iSelAddInBufferRight; + const int iSelAddInInterlChLeft = pSound->iSelAddInInterlChLeft; + const int iSelAddInInterlChRight = pSound->iSelAddInInterlChRight; + const int iSelOutBufferLeft = pSound->iSelOutBufferLeft; + const int iSelOutBufferRight = pSound->iSelOutBufferRight; + const int iSelOutInterlChLeft = pSound->iSelOutInterlChLeft; + const int iSelOutInterlChRight = pSound->iSelOutInterlChRight; if ( ( inDevice == pSound->CurrentAudioInputDeviceID ) && inInputData ) { - int iSelCHLeft, iSelAddCHLeft; - int iSelCHRight, iSelAddCHRight; - - // get selected input channels plus optional additional channel - GetSelCHAndAddCH ( iSelInputLeftChannel, iNumInChan, iSelCHLeft, iSelAddCHLeft ); - GetSelCHAndAddCH ( iSelInputRightChannel, iNumInChan, iSelCHRight, iSelAddCHRight ); - // check size (float32 has four bytes) - if ( inInputData->mBuffers[0].mDataByteSize == - static_cast ( iCoreAudioBufferSizeMono * iNumInChan * 4 ) ) +// TODO check... + if ( inInputData->mBuffers[iSelInBufferLeft].mDataByteSize == ... +inInputData->mBuffers[0].mDataByteSize * inInputData->mNumberBuffers == +(UInt32) iNumInChan * static_cast ( iCoreAudioBufferSizeMono * 4 ) ) { - // one buffer with all the channels in interleaved format: - // get a pointer to the input data of the correct type - Float32* pInData = static_cast ( inInputData->mBuffers[0].mData ); + Float32* pLeftData = static_cast ( inInputData->mBuffers[iSelInBufferLeft].mData ); + Float32* pRightData = static_cast ( inInputData->mBuffers[iSelInBufferRight].mData ); + int iNumChanPerFrameLeft = pSound->vecNumInBufChan[iSelInBufferLeft]; + int iNumChanPerFrameRight = pSound->vecNumInBufChan[iSelInBufferRight]; // copy input data for ( int i = 0; i < iCoreAudioBufferSizeMono; i++ ) { // copy left and right channels separately - pSound->vecsTmpAudioSndCrdStereo[2 * i] = (short) ( pInData[iNumInChan * i + iSelCHLeft] * _MAXSHORT ); - pSound->vecsTmpAudioSndCrdStereo[2 * i + 1] = (short) ( pInData[iNumInChan * i + iSelCHRight] * _MAXSHORT ); + pSound->vecsTmpAudioSndCrdStereo[2 * i] = (short) ( pLeftData[iNumChanPerFrameLeft * i + iSelInInterlChLeft] * _MAXSHORT ); + pSound->vecsTmpAudioSndCrdStereo[2 * i + 1] = (short) ( pRightData[iNumChanPerFrameRight * i + iSelInInterlChRight] * _MAXSHORT ); } // add an additional optional channel - if ( iSelAddCHLeft >= 0 ) + if ( iSelAddInBufferLeft >= 0 ) { - for ( int i = 0; i < iCoreAudioBufferSizeMono; i++ ) - { - pSound->vecsTmpAudioSndCrdStereo[2 * i] = Double2Short ( - pSound->vecsTmpAudioSndCrdStereo[2 * i] + pInData[iNumInChan * i + iSelAddCHLeft] * _MAXSHORT ); - } - } - - if ( iSelAddCHRight >= 0 ) - { - for ( int i = 0; i < iCoreAudioBufferSizeMono; i++ ) - { - pSound->vecsTmpAudioSndCrdStereo[2 * i + 1] = Double2Short ( - pSound->vecsTmpAudioSndCrdStereo[2 * i + 1] + pInData[iNumInChan * i + iSelAddCHRight] * _MAXSHORT ); - } - } - } - else if ( inInputData->mNumberBuffers == (UInt32) iNumInChan && // we should have a matching number of buffers to channels - inInputData->mBuffers[0].mDataByteSize == static_cast ( iCoreAudioBufferSizeMono * 4 ) ) - { - // one buffer per channel mode: - Float32* pLeftData = static_cast ( inInputData->mBuffers[iSelCHLeft].mData ); - Float32* pRightData = static_cast ( inInputData->mBuffers[iSelCHRight].mData ); - - // copy input data - for ( int i = 0; i < iCoreAudioBufferSizeMono; i++ ) - { - // copy left and right channels separately - pSound->vecsTmpAudioSndCrdStereo[2 * i] = (short) ( pLeftData[i] * _MAXSHORT ); - pSound->vecsTmpAudioSndCrdStereo[2 * i + 1] = (short) ( pRightData[i] * _MAXSHORT ); - } - - // add an additional optional channel - if ( iSelAddCHLeft >= 0 ) - { - pLeftData = static_cast ( inInputData->mBuffers[iSelAddCHLeft].mData ); + pLeftData = static_cast ( inInputData->mBuffers[iSelAddInBufferLeft].mData ); + iNumChanPerFrameLeft = pSound->vecNumInBufChan[iSelAddInBufferLeft]; for ( int i = 0; i < iCoreAudioBufferSizeMono; i++ ) { pSound->vecsTmpAudioSndCrdStereo[2 * i] = Double2Short ( - pSound->vecsTmpAudioSndCrdStereo[2 * i] + pLeftData[i] * _MAXSHORT ); + pSound->vecsTmpAudioSndCrdStereo[2 * i] + pLeftData[iNumChanPerFrameLeft * i + iSelAddInInterlChLeft] * _MAXSHORT ); } } - if ( iSelAddCHRight >= 0 ) + if ( iSelAddInBufferRight >= 0 ) { - pRightData = static_cast ( inInputData->mBuffers[iSelAddCHRight].mData ); + pRightData = static_cast ( inInputData->mBuffers[iSelAddInBufferRight].mData ); + iNumChanPerFrameRight = pSound->vecNumInBufChan[iSelAddInBufferRight]; for ( int i = 0; i < iCoreAudioBufferSizeMono; i++ ) { pSound->vecsTmpAudioSndCrdStereo[2 * i + 1] = Double2Short ( - pSound->vecsTmpAudioSndCrdStereo[2 * i + 1] + pRightData[i] * _MAXSHORT ); + pSound->vecsTmpAudioSndCrdStereo[2 * i + 1] + pRightData[iNumChanPerFrameRight * i + iSelAddInInterlChRight] * _MAXSHORT ); } } } @@ -954,6 +1011,27 @@ OSStatus CSound::callbackIO ( AudioDeviceID inDevice, if ( ( inDevice == pSound->CurrentAudioOutputDeviceID ) && outOutputData ) { // check size (float32 has four bytes) +// if ( outOutputData->mBuffers[0].mDataByteSize * outOutputData->mNumberBuffers == +// (UInt32) iNumOutChan * static_cast ( iCoreAudioBufferSizeMono * 4 ) ) +// { +// const int iNumChanPerFrame = iNumOutChan / outOutputData->mNumberBuffers; +// const int iSelBufferLeft = iSelOutputLeftChannel / iNumChanPerFrame; +// const int iSelBufferRight = iSelOutputRightChannel / iNumChanPerFrame; +// const int iSelInterlChLeft = iSelOutputLeftChannel % iNumChanPerFrame; +// const int iSelInterlChRight = iSelOutputRightChannel % iNumChanPerFrame; +// +// Float32* pLeftData = static_cast ( outOutputData->mBuffers[iSelBufferLeft].mData ); +// Float32* pRightData = static_cast ( outOutputData->mBuffers[iSelBufferRight].mData ); +// +// // copy output data +// for ( int i = 0; i < iCoreAudioBufferSizeMono; i++ ) +// { +// // copy left and right channels separately +// pLeftData[iNumChanPerFrame * i + iSelInterlChLeft] = (Float32) pSound->vecsTmpAudioSndCrdStereo[2 * i] / _MAXSHORT; +// pRightData[iNumChanPerFrame * i + iSelInterlChRight] = (Float32) pSound->vecsTmpAudioSndCrdStereo[2 * i] / _MAXSHORT; +// } +// } +// else if ( outOutputData->mBuffers[0].mDataByteSize == static_cast ( iCoreAudioBufferSizeMono * iNumOutChan * 4 ) ) { diff --git a/mac/sound.h b/mac/sound.h index a4f267f8..ce905d35 100755 --- a/mac/sound.h +++ b/mac/sound.h @@ -75,11 +75,27 @@ public: int iSelInputRightChannel; int iSelOutputLeftChannel; int iSelOutputRightChannel; + int iSelInBufferLeft; + int iSelInBufferRight; + int iSelInInterlChLeft; + int iSelInInterlChRight; + int iSelAddInBufferLeft; + int iSelAddInBufferRight; + int iSelAddInInterlChLeft; + int iSelAddInInterlChRight; + int iSelOutBufferLeft; + int iSelOutBufferRight; + int iSelOutInterlChLeft; + int iSelOutInterlChRight; + CVector vecNumInBufChan; + CVector vecNumOutBufChan; protected: virtual QString LoadAndInitializeDriver ( int iIdx, bool ); - QString CheckDeviceCapabilities ( const int iDriverIdx ); + QString CheckDeviceCapabilities ( const int iDriverIdx ); + void UpdateChSelection(); + int CountChannels ( AudioDeviceID devID, const int iNumChanPerFrame, bool isInput );