mirror of
https://github.com/cookiengineer/audacity
synced 2025-11-18 07:04:07 +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:
@@ -3843,11 +3843,10 @@ bool AudioIoCallback::FillOutputBuffers(
|
||||
return true;
|
||||
}
|
||||
|
||||
// ------ MEMORY ALLOCATION ----------------------
|
||||
//Real time process section
|
||||
{
|
||||
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();
|
||||
|
||||
bool selected = false;
|
||||
@@ -3855,8 +3854,7 @@ bool AudioIoCallback::FillOutputBuffers(
|
||||
int chanCnt = 0;
|
||||
|
||||
// Choose a common size to take from all ring buffers
|
||||
const auto toGet =
|
||||
std::min<size_t>(framesPerBuffer, GetCommonlyReadyPlayback());
|
||||
const auto toGet = std::min<size_t>(framesPerBuffer, GetCommonlyReadyPlayback());
|
||||
|
||||
// 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.
|
||||
@@ -3873,9 +3871,8 @@ bool AudioIoCallback::FillOutputBuffers(
|
||||
|
||||
bool drop = false; // Track should become silent.
|
||||
bool dropQuickly = false; // Track has already been faded to silence.
|
||||
for (unsigned t = 0; t < numPlaybackTracks; t++)
|
||||
{
|
||||
WaveTrack *vt = mPlaybackTracks[t].get();
|
||||
for (unsigned t = 0; t < numPlaybackTracks; t++) {
|
||||
WaveTrack* vt = mPlaybackTracks[t].get();
|
||||
bufHelper.get()->chans[chanCnt] = vt;
|
||||
|
||||
// TODO: more-than-two-channels
|
||||
@@ -3889,31 +3886,27 @@ bool AudioIoCallback::FillOutputBuffers(
|
||||
bool firstChannel = vt->IsLeader();
|
||||
bool lastChannel = !nextTrack || nextTrack->IsLeader();
|
||||
|
||||
if ( firstChannel )
|
||||
{
|
||||
if (firstChannel) {
|
||||
selected = vt->GetSelected();
|
||||
// IF mono THEN clear 'the other' channel.
|
||||
if ( lastChannel && (numPlaybackChannels>1)) {
|
||||
if (lastChannel && (numPlaybackChannels > 1)) {
|
||||
// TODO: more-than-two-channels
|
||||
memset(bufHelper.get()->tempBufs[1], 0, framesPerBuffer * sizeof(float));
|
||||
}
|
||||
drop = TrackShouldBeSilent( *vt );
|
||||
drop = TrackShouldBeSilent(*vt);
|
||||
dropQuickly = drop;
|
||||
}
|
||||
|
||||
if( mbMicroFades )
|
||||
dropQuickly = dropQuickly && TrackHasBeenFadedOut( *vt );
|
||||
if (mbMicroFades)
|
||||
dropQuickly = dropQuickly && TrackHasBeenFadedOut(*vt);
|
||||
|
||||
decltype(framesPerBuffer) len = 0;
|
||||
|
||||
if (dropQuickly)
|
||||
{
|
||||
if (dropQuickly) {
|
||||
len = mPlaybackBuffers[t]->Discard(toGet);
|
||||
// keep going here.
|
||||
// we may still need to issue a paComplete.
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
len = mPlaybackBuffers[t]->Get((samplePtr)bufHelper.get()->tempBufs[chanCnt],
|
||||
floatSample,
|
||||
toGet);
|
||||
@@ -3939,13 +3932,13 @@ bool AudioIoCallback::FillOutputBuffers(
|
||||
// available, so maxLen ought to increase from 0 only once
|
||||
mMaxFramesOutput = std::max(mMaxFramesOutput, len);
|
||||
|
||||
if ( !lastChannel )
|
||||
if (!lastChannel)
|
||||
continue;
|
||||
|
||||
// Last channel of a track seen now
|
||||
len = mMaxFramesOutput;
|
||||
|
||||
if( !dropQuickly && selected )
|
||||
if (!dropQuickly && selected)
|
||||
len = em.RealtimeProcess(group, chanCnt, bufHelper.get()->tempBufs, len);
|
||||
group++;
|
||||
|
||||
@@ -3963,20 +3956,20 @@ bool AudioIoCallback::FillOutputBuffers(
|
||||
//
|
||||
// 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.
|
||||
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];
|
||||
|
||||
if (vt->GetChannelIgnoringPan() == Track::LeftChannel || vt->GetChannelIgnoringPan() == Track::MonoChannel )
|
||||
AddToOutputChannel( 0, outputMeterFloats, outputFloats, bufHelper.get()->tempBufs[c], drop, len, vt);
|
||||
if (vt->GetChannelIgnoringPan() == Track::LeftChannel || vt->GetChannelIgnoringPan() == Track::MonoChannel)
|
||||
AddToOutputChannel(0, outputMeterFloats, outputFloats, bufHelper.get()->tempBufs[c], drop, len, vt);
|
||||
|
||||
if (vt->GetChannelIgnoringPan() == Track::RightChannel || vt->GetChannelIgnoringPan() == Track::MonoChannel )
|
||||
AddToOutputChannel( 1, outputMeterFloats, outputFloats, bufHelper.get()->tempBufs[c], drop, len, vt);
|
||||
if (vt->GetChannelIgnoringPan() == Track::RightChannel || vt->GetChannelIgnoringPan() == Track::MonoChannel)
|
||||
AddToOutputChannel(1, outputMeterFloats, outputFloats, bufHelper.get()->tempBufs[c], drop, len, vt);
|
||||
}
|
||||
|
||||
chanCnt = 0;
|
||||
}
|
||||
|
||||
|
||||
// Poke: If there are no playback tracks, then the earlier check
|
||||
// about the time indicator being past the end won't happen;
|
||||
// do it here instead (but not if looping or scrubbing)
|
||||
@@ -3986,6 +3979,8 @@ bool AudioIoCallback::FillOutputBuffers(
|
||||
// wxASSERT( maxLen == toGet );
|
||||
|
||||
em.RealtimeProcessEnd();
|
||||
delete bufHelper.release();
|
||||
}
|
||||
mLastPlaybackTimeMillis = ::wxGetUTCTimeMillis();
|
||||
|
||||
ClampBuffer( outputFloats, framesPerBuffer*numPlaybackChannels );
|
||||
|
||||
@@ -23,19 +23,24 @@ class AudioIOBufferHelper
|
||||
this->chans = safenew WaveTrack * [numPlaybackChannels];
|
||||
this->tempBufs = safenew float* [numPlaybackChannels];
|
||||
|
||||
for (unsigned int c = 0; c < numPlaybackChannels; c++) {
|
||||
tempBufs[c] = safenew float[framesPerBuffer];
|
||||
tempBufs[0] = safenew float[(size_t)numPlaybackChannels * framesPerBuffer];
|
||||
|
||||
for (unsigned int c = 1; c < numPlaybackChannels; c++) {
|
||||
tempBufs[c] = tempBufs[c - 1] + framesPerBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
~AudioIOBufferHelper() {
|
||||
for (unsigned int c = 0; c < numPlaybackChannels; c++) {
|
||||
delete[] tempBufs[c];
|
||||
}
|
||||
|
||||
delete[] tempBufs[0];
|
||||
|
||||
delete[] tempBufs;
|
||||
|
||||
tempBufs = nullptr;
|
||||
|
||||
delete[] chans;
|
||||
|
||||
chans = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user