1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-11-18 15:13:56 +01:00

Make AudioIOBufferHelper.h cache friendly.

Improves performance of project loading substantively.

Signed-off-by: Emily Mabrey <emabrey@tenacityaudio.org>
Helped-by: Alex Disibio <alexdisibio@gmail.com>
This commit is contained in:
Emily Mabrey
2021-07-31 16:51:24 -04:00
parent 8c4278cc64
commit 15c4f546f3
2 changed files with 145 additions and 145 deletions

View File

@@ -3843,11 +3843,10 @@ bool AudioIoCallback::FillOutputBuffers(
return true; return true;
} }
// ------ MEMORY ALLOCATION ---------------------- //Real time process section
{
std::unique_ptr<AudioIOBufferHelper> bufHelper = std::make_unique<AudioIOBufferHelper>(numPlaybackChannels, framesPerBuffer); std::unique_ptr<AudioIOBufferHelper> bufHelper = std::make_unique<AudioIOBufferHelper>(numPlaybackChannels, framesPerBuffer);
// ------ End of MEMORY ALLOCATION --------------- auto& em = RealtimeEffectManager::Get();
auto & em = RealtimeEffectManager::Get();
em.RealtimeProcessStart(); em.RealtimeProcessStart();
bool selected = false; bool selected = false;
@@ -3855,8 +3854,7 @@ bool AudioIoCallback::FillOutputBuffers(
int chanCnt = 0; int chanCnt = 0;
// Choose a common size to take from all ring buffers // Choose a common size to take from all ring buffers
const auto toGet = const auto toGet = std::min<size_t>(framesPerBuffer, GetCommonlyReadyPlayback());
std::min<size_t>(framesPerBuffer, GetCommonlyReadyPlayback());
// The drop and dropQuickly booleans are so named for historical reasons. // The drop and dropQuickly booleans are so named for historical reasons.
// JKC: The original code attempted to be faster by doing nothing on silenced audio. // JKC: The original code attempted to be faster by doing nothing on silenced audio.
@@ -3873,9 +3871,8 @@ bool AudioIoCallback::FillOutputBuffers(
bool drop = false; // Track should become silent. bool drop = false; // Track should become silent.
bool dropQuickly = false; // Track has already been faded to silence. bool dropQuickly = false; // Track has already been faded to silence.
for (unsigned t = 0; t < numPlaybackTracks; t++) for (unsigned t = 0; t < numPlaybackTracks; t++) {
{ WaveTrack* vt = mPlaybackTracks[t].get();
WaveTrack *vt = mPlaybackTracks[t].get();
bufHelper.get()->chans[chanCnt] = vt; bufHelper.get()->chans[chanCnt] = vt;
// TODO: more-than-two-channels // TODO: more-than-two-channels
@@ -3889,31 +3886,27 @@ bool AudioIoCallback::FillOutputBuffers(
bool firstChannel = vt->IsLeader(); bool firstChannel = vt->IsLeader();
bool lastChannel = !nextTrack || nextTrack->IsLeader(); bool lastChannel = !nextTrack || nextTrack->IsLeader();
if ( firstChannel ) if (firstChannel) {
{
selected = vt->GetSelected(); selected = vt->GetSelected();
// IF mono THEN clear 'the other' channel. // IF mono THEN clear 'the other' channel.
if ( lastChannel && (numPlaybackChannels>1)) { if (lastChannel && (numPlaybackChannels > 1)) {
// TODO: more-than-two-channels // TODO: more-than-two-channels
memset(bufHelper.get()->tempBufs[1], 0, framesPerBuffer * sizeof(float)); memset(bufHelper.get()->tempBufs[1], 0, framesPerBuffer * sizeof(float));
} }
drop = TrackShouldBeSilent( *vt ); drop = TrackShouldBeSilent(*vt);
dropQuickly = drop; dropQuickly = drop;
} }
if( mbMicroFades ) if (mbMicroFades)
dropQuickly = dropQuickly && TrackHasBeenFadedOut( *vt ); dropQuickly = dropQuickly && TrackHasBeenFadedOut(*vt);
decltype(framesPerBuffer) len = 0; decltype(framesPerBuffer) len = 0;
if (dropQuickly) if (dropQuickly) {
{
len = mPlaybackBuffers[t]->Discard(toGet); len = mPlaybackBuffers[t]->Discard(toGet);
// keep going here. // keep going here.
// we may still need to issue a paComplete. // we may still need to issue a paComplete.
} } else {
else
{
len = mPlaybackBuffers[t]->Get((samplePtr)bufHelper.get()->tempBufs[chanCnt], len = mPlaybackBuffers[t]->Get((samplePtr)bufHelper.get()->tempBufs[chanCnt],
floatSample, floatSample,
toGet); toGet);
@@ -3939,13 +3932,13 @@ bool AudioIoCallback::FillOutputBuffers(
// available, so maxLen ought to increase from 0 only once // available, so maxLen ought to increase from 0 only once
mMaxFramesOutput = std::max(mMaxFramesOutput, len); mMaxFramesOutput = std::max(mMaxFramesOutput, len);
if ( !lastChannel ) if (!lastChannel)
continue; continue;
// Last channel of a track seen now // Last channel of a track seen now
len = mMaxFramesOutput; len = mMaxFramesOutput;
if( !dropQuickly && selected ) if (!dropQuickly && selected)
len = em.RealtimeProcess(group, chanCnt, bufHelper.get()->tempBufs, len); len = em.RealtimeProcess(group, chanCnt, bufHelper.get()->tempBufs, len);
group++; group++;
@@ -3963,20 +3956,20 @@ bool AudioIoCallback::FillOutputBuffers(
// //
// Each channel in the tracks can output to more than one channel on the device. // Each channel in the tracks can output to more than one channel on the device.
// For example mono channels output to both left and right output channels. // For example mono channels output to both left and right output channels.
if (len > 0) for (int c = 0; c < chanCnt; c++) if (len > 0) for (int c = 0; c < chanCnt; c++) {
{
vt = bufHelper.get()->chans[c]; vt = bufHelper.get()->chans[c];
if (vt->GetChannelIgnoringPan() == Track::LeftChannel || vt->GetChannelIgnoringPan() == Track::MonoChannel ) if (vt->GetChannelIgnoringPan() == Track::LeftChannel || vt->GetChannelIgnoringPan() == Track::MonoChannel)
AddToOutputChannel( 0, outputMeterFloats, outputFloats, bufHelper.get()->tempBufs[c], drop, len, vt); AddToOutputChannel(0, outputMeterFloats, outputFloats, bufHelper.get()->tempBufs[c], drop, len, vt);
if (vt->GetChannelIgnoringPan() == Track::RightChannel || vt->GetChannelIgnoringPan() == Track::MonoChannel ) if (vt->GetChannelIgnoringPan() == Track::RightChannel || vt->GetChannelIgnoringPan() == Track::MonoChannel)
AddToOutputChannel( 1, outputMeterFloats, outputFloats, bufHelper.get()->tempBufs[c], drop, len, vt); AddToOutputChannel(1, outputMeterFloats, outputFloats, bufHelper.get()->tempBufs[c], drop, len, vt);
} }
chanCnt = 0; chanCnt = 0;
} }
// Poke: If there are no playback tracks, then the earlier check // Poke: If there are no playback tracks, then the earlier check
// about the time indicator being past the end won't happen; // about the time indicator being past the end won't happen;
// do it here instead (but not if looping or scrubbing) // do it here instead (but not if looping or scrubbing)
@@ -3986,6 +3979,8 @@ bool AudioIoCallback::FillOutputBuffers(
// wxASSERT( maxLen == toGet ); // wxASSERT( maxLen == toGet );
em.RealtimeProcessEnd(); em.RealtimeProcessEnd();
delete bufHelper.release();
}
mLastPlaybackTimeMillis = ::wxGetUTCTimeMillis(); mLastPlaybackTimeMillis = ::wxGetUTCTimeMillis();
ClampBuffer( outputFloats, framesPerBuffer*numPlaybackChannels ); ClampBuffer( outputFloats, framesPerBuffer*numPlaybackChannels );

View File

@@ -23,19 +23,24 @@ class AudioIOBufferHelper
this->chans = safenew WaveTrack * [numPlaybackChannels]; this->chans = safenew WaveTrack * [numPlaybackChannels];
this->tempBufs = safenew float* [numPlaybackChannels]; this->tempBufs = safenew float* [numPlaybackChannels];
for (unsigned int c = 0; c < numPlaybackChannels; c++) { tempBufs[0] = safenew float[(size_t)numPlaybackChannels * framesPerBuffer];
tempBufs[c] = safenew float[framesPerBuffer];
for (unsigned int c = 1; c < numPlaybackChannels; c++) {
tempBufs[c] = tempBufs[c - 1] + framesPerBuffer;
} }
} }
~AudioIOBufferHelper() { ~AudioIOBufferHelper() {
for (unsigned int c = 0; c < numPlaybackChannels; c++) {
delete[] tempBufs[c]; delete[] tempBufs[0];
}
delete[] tempBufs; delete[] tempBufs;
tempBufs = nullptr;
delete[] chans; delete[] chans;
chans = nullptr;
} }
}; };