-
Notifications
You must be signed in to change notification settings - Fork 244
Optimize bDelayPan and divisions #3706
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -982,7 +982,7 @@ void CServer::MixEncodeTransmitData ( const int iChanCnt, const int iNumClients | |
| // stereo: apply stereo-to-mono attenuation | ||
| for ( i = 0, k = 0; i < iServerFrameSizeSamples; i++, k += 2 ) | ||
| { | ||
| vecfIntermProcBuf[i] += ( static_cast<float> ( vecsData[k] ) + vecsData[k + 1] ) / 2; | ||
| vecfIntermProcBuf[i] += ( static_cast<float> ( vecsData[k] ) + vecsData[k + 1] ) * 0.5f; | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -1001,7 +1001,7 @@ void CServer::MixEncodeTransmitData ( const int iChanCnt, const int iNumClients | |
| // stereo: apply stereo-to-mono attenuation | ||
| for ( i = 0, k = 0; i < iServerFrameSizeSamples; i++, k += 2 ) | ||
| { | ||
| vecfIntermProcBuf[i] += fGain * ( static_cast<float> ( vecsData[k] ) + vecsData[k + 1] ) / 2; | ||
| vecfIntermProcBuf[i] += fGain * ( static_cast<float> ( vecsData[k] ) + vecsData[k + 1] ) * 0.5f; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know if we do this right. Shouldn't we normalize the floats to
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought the way the signal summation work was progressive:
etc. Clipping should never happen. However, that's ignoring panning, of course. If you multiple L 1.0f by 1.1f and divide R 1.0f by 1.1f, you will get clipping. I guess - as panning is on the client GUI as is level - this is seen as something the client user has under their control: drop the channel level to allow for panning. As with all the audio code -- I could easily be wrong. I can't follow it.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Floats are internally normalised anyway, having the max available precision in the mantissa, and then scaling with the exponent. This all happens internally within the floating-point engine.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Which proves that it must be refactored...
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I think normalization in the float representation only means to have only one non-zero digit in front of the mantissa and therefore scaling the exponent. I think we still miss out on precision because we convert big numbers to float while float has the most precision up to values of
I couldn't find anything which takes the number of clients into account, i.e. there is no scaling happening. We just keep adding and adding... |
||
| } | ||
| } | ||
| } | ||
|
|
@@ -1020,7 +1020,7 @@ void CServer::MixEncodeTransmitData ( const int iChanCnt, const int iNumClients | |
| const int maxPanDelay = MAX_DELAY_PANNING_SAMPLES; | ||
|
|
||
| int iPanDelL = 0, iPanDelR = 0, iPanDel; | ||
| int iLpan, iRpan, iPan; | ||
| int iLpan, iRpan; | ||
|
|
||
| for ( j = 0; j < iNumClients; j++ ) | ||
| { | ||
|
|
@@ -1036,21 +1036,20 @@ void CServer::MixEncodeTransmitData ( const int iChanCnt, const int iNumClients | |
| const float fGainL = MathUtils::GetLeftPan ( fPan, false ) * fGain; | ||
| const float fGainR = MathUtils::GetRightPan ( fPan, false ) * fGain; | ||
|
|
||
| const bool isMono = vecNumAudioChannels[j] == 1; | ||
|
|
||
| if ( bDelayPan ) | ||
| { | ||
| iPanDel = lround ( (float) ( 2 * maxPanDelay - 2 ) * ( vecvecfPannings[iChanCnt][j] - 0.5f ) ); | ||
| iPanDelL = ( iPanDel > 0 ) ? iPanDel : 0; | ||
| iPanDelR = ( iPanDel < 0 ) ? -iPanDel : 0; | ||
| } | ||
|
|
||
| if ( vecNumAudioChannels[j] == 1 ) | ||
| { | ||
| // mono: copy same mono data in both out stereo audio channels | ||
| for ( i = 0, k = 0; i < iServerFrameSizeSamples; i++, k += 2 ) | ||
| if ( isMono ) | ||
| { | ||
| // left/right channel | ||
| if ( bDelayPan ) | ||
| // mono: copy same mono data in both out stereo audio channels | ||
| for ( i = 0, k = 0; i < iServerFrameSizeSamples; i++, k += 2 ) | ||
| { | ||
| // left/right channel | ||
| // pan address shift | ||
|
|
||
| // left channel | ||
|
|
@@ -1079,54 +1078,60 @@ void CServer::MixEncodeTransmitData ( const int iChanCnt, const int iNumClients | |
| vecfIntermProcBuf[k + 1] += vecsData[iRpan] * fGainR; | ||
| } | ||
| } | ||
| else | ||
| { | ||
| vecfIntermProcBuf[k] += vecsData[i] * fGainL; | ||
| vecfIntermProcBuf[k + 1] += vecsData[i] * fGainR; | ||
| } | ||
| } | ||
| } | ||
| else | ||
| { | ||
| // stereo | ||
| for ( i = 0; i < ( 2 * iServerFrameSizeSamples ); i++ ) | ||
| else | ||
| { | ||
| // left/right channel | ||
| if ( bDelayPan ) | ||
| // stereo | ||
| for ( i = 0; i < ( 2 * iServerFrameSizeSamples ); i += 2 ) | ||
| { | ||
| // pan address shift | ||
| if ( ( i & 1 ) == 0 ) | ||
|
|
||
| iLpan = i - 2 * iPanDelL; // left channel | ||
| iRpan = ( i + 1 ) - 2 * iPanDelR; // right channel | ||
|
|
||
| // interleaved channels | ||
| if ( iLpan < 0 ) | ||
| { | ||
| iPan = i - 2 * iPanDelL; // if even : left channel | ||
| // get from second | ||
| iLpan = iLpan + 2 * iServerFrameSizeSamples; | ||
| vecfIntermProcBuf[i] += vecsData2[iLpan] * fGain; | ||
| } | ||
| else | ||
| { | ||
| iPan = i - 2 * iPanDelR; // if odd : right channel | ||
| vecfIntermProcBuf[i] += vecsData[iLpan] * fGain; | ||
| } | ||
| // interleaved channels | ||
| if ( iPan < 0 ) | ||
|
|
||
| if ( iRpan < 0 ) | ||
| { | ||
| // get from second | ||
| iPan = iPan + 2 * iServerFrameSizeSamples; | ||
| vecfIntermProcBuf[i] += vecsData2[iPan] * fGain; | ||
| iRpan = iRpan + 2 * iServerFrameSizeSamples; | ||
| vecfIntermProcBuf[i + 1] += vecsData2[iRpan] * fGain; | ||
| } | ||
| else | ||
| { | ||
| vecfIntermProcBuf[i] += vecsData[iPan] * fGain; | ||
| vecfIntermProcBuf[i + 1] += vecsData[iRpan] * fGain; | ||
| } | ||
| } | ||
| else | ||
| } | ||
| } | ||
| else | ||
| { | ||
| if ( isMono ) | ||
| { | ||
| // mono: copy same mono data in both out stereo audio channels | ||
| for ( i = 0, k = 0; i < iServerFrameSizeSamples; i++, k += 2 ) | ||
| { | ||
| if ( ( i & 1 ) == 0 ) | ||
| { | ||
| // if even : left channel | ||
| vecfIntermProcBuf[i] += vecsData[i] * fGainL; | ||
| } | ||
| else | ||
| { | ||
| // if odd : right channel | ||
| vecfIntermProcBuf[i] += vecsData[i] * fGainR; | ||
| } | ||
|
Comment on lines
-1120
to
-1129
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Got rid of modulo computation |
||
| vecfIntermProcBuf[k] += vecsData[i] * fGainL; | ||
| vecfIntermProcBuf[k + 1] += vecsData[i] * fGainR; | ||
| } | ||
| } | ||
| else | ||
| { | ||
| for ( i = 0; i < ( 2 * iServerFrameSizeSamples ); i += 2 ) | ||
| { | ||
| // left/right channel | ||
| vecfIntermProcBuf[i] += vecsData[i] * fGainL; | ||
| vecfIntermProcBuf[i + 1] += vecsData[i + 1] * fGainR; | ||
| } | ||
| } | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't we just right shift the short to halve it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not with a
float. Doing so with anintbefore conversion would reduce the resolution by 1 bit.Doing
* 0.5for/ 2.0fwith a float preserves the full resolution in the mantissa and just changes the exponent. I wouldn't be surprised if the compiler produces exactly the same code in both cases.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/ 2.0ffeels more intuitive, somehow. If there's no execution speed difference, I'd rather keep it.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's unlikely to be different - however this may depend on the compiler. 0.5f is easier for the compiler to optimise than / 2, I'd argue.