1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-07-02 17:23:18 +02:00

When recording into region selection, stop it precisely

This commit is contained in:
Paul Licameli 2018-05-24 02:35:44 -04:00
parent 92d27c618b
commit 0887d6d01e
2 changed files with 54 additions and 14 deletions

View File

@ -1933,10 +1933,21 @@ int AudioIO::StartStream(const WaveTrackConstArray &playbackTracks,
mTimeTrack = options.timeTrack;
}
mListener = options.listener;
mRate = sampleRate;
mT0 = t0;
mT1 = t1;
mRecordingSchedule = {};
mRecordingSchedule.mLatencyCorrection =
(gPrefs->Read(wxT("/AudioIO/LatencyCorrection"),
DEFAULT_LATENCY_CORRECTION))
/ 1000.0;
mRecordingSchedule.mDuration = mT1 - mT0;
if (captureTracks.size() > 0 && playbackTracks.size() > 0)
// adjust mT1 so that we don't give paComplete too soon to fill up the
// desired length of recording
mT1 -= mRecordingSchedule.mLatencyCorrection;
mListener = options.listener;
mRate = sampleRate;
mTime = t0;
mSeek = 0;
mLastRecordingOffset = 0;
@ -2150,7 +2161,12 @@ int AudioIO::StartStream(const WaveTrackConstArray &playbackTracks,
// Don't throw for read errors, just play silence:
false,
warpOptions,
mT0, mT1, 1,
mT0,
// Pass t1 -- not mT1 as may have been adjusted for latency
// -- so that overdub recording stops playing back samples
// at the right time, though transport may continue to record
t1,
1,
playbackMixBufferSize, false,
mRate, floatSample, false);
mPlaybackMixers[i]->ApplyTrackGains(false);
@ -2724,11 +2740,10 @@ void AudioIO::StopStream()
// case that we do not apply latency correction when recording the
// first track in a project.
//
double latencyCorrection = DEFAULT_LATENCY_CORRECTION;
gPrefs->Read(wxT("/AudioIO/LatencyCorrection"), &latencyCorrection);
double recordingOffset =
mLastRecordingOffset + latencyCorrection / 1000.0;
mLastRecordingOffset +
mRecordingSchedule.mLatencyCorrection;
for (unsigned int i = 0; i < mCaptureTracks.size(); i++) {
// The calls to Flush, and (less likely) Clear and InsertSilence,
@ -4016,12 +4031,16 @@ void AudioIO::FillBuffers()
mCaptureTracks.size() > 0)
GuardedCall( [&] {
// start record buffering
auto commonlyAvail = GetCommonlyAvailCapture();
const auto avail = GetCommonlyAvailCapture(); // samples
const auto remainingTime =
std::max(0.0, mRecordingSchedule.Remaining());
// This may be a very big double number:
const auto remainingSamples = remainingTime * mRate;
//
// Determine how much this will add to captured tracks
//
double deltat = commonlyAvail / mRate;
double deltat = avail / mRate;
if (mAudioThreadShouldCallFillBuffersOnce ||
deltat >= mMinCaptureSecsToCopy)
@ -4033,7 +4052,6 @@ void AudioIO::FillBuffers()
for( i = 0; i < numChannels; i++ )
{
auto avail = commonlyAvail;
sampleFormat trackFormat = mCaptureTracks[i]->GetSampleFormat();
AutoSaveFile appendLog;
@ -4042,12 +4060,16 @@ void AudioIO::FillBuffers()
{
SampleBuffer temp(avail, trackFormat);
const auto got =
mCaptureBuffers[i]->Get(temp.ptr(), trackFormat, avail);
mCaptureBuffers[i]->Get(temp.ptr(), trackFormat, avail);
// wxASSERT(got == avail);
// but we can't assert in this thread
wxUnusedVar(got);
// see comment in second handler about guarantee
mCaptureTracks[i]-> Append(temp.ptr(), trackFormat, avail, 1,
size_t size = avail;
if (double(size) > remainingSamples)
size = floor(remainingSamples);
mCaptureTracks[i]-> Append(temp.ptr(), trackFormat,
size, 1,
&appendLog);
}
else
@ -4056,7 +4078,7 @@ void AudioIO::FillBuffers()
SampleBuffer temp1(avail, floatSample);
SampleBuffer temp2(size, floatSample);
const auto got =
mCaptureBuffers[i]->Get(temp1.ptr(), floatSample, avail);
mCaptureBuffers[i]->Get(temp1.ptr(), floatSample, avail);
// wxASSERT(got == avail);
// but we can't assert in this thread
wxUnusedVar(got);
@ -4070,7 +4092,10 @@ void AudioIO::FillBuffers()
!IsStreamActive(), (float *)temp2.ptr(), size);
size = results.second;
// see comment in second handler about guarantee
mCaptureTracks[i]-> Append(temp2.ptr(), floatSample, size, 1,
if (double(size) > remainingSamples)
size = floor(remainingSamples);
mCaptureTracks[i]-> Append(temp2.ptr(), floatSample,
size, 1,
&appendLog);
}
}
@ -4084,7 +4109,9 @@ void AudioIO::FillBuffers()
blockFileLog.WriteSubTree(appendLog);
blockFileLog.EndTag(wxT("recordingrecovery"));
}
}
} // end loop over capture channels
mRecordingSchedule.mPosition += avail / mRate;
if (mListener && !blockFileLog.IsEmpty())
mListener->OnAudioIONewBlockFiles(blockFileLog);

View File

@ -814,6 +814,19 @@ public:
// Whether to check the error code passed to audacityAudioCallback to
// detect more dropouts
bool mDetectUpstreamDropouts{ true };
private:
struct RecordingSchedule {
double mLatencyCorrection{};
double mDuration{};
// This is initialized to 0 by the main thread, then updated
// only by the thread calling FillBuffers:
double mPosition{};
double Remaining() const
{ return mDuration - mLatencyCorrection - mPosition; }
} mRecordingSchedule{};
};
#endif