simplified and optimized samplebuffer

This commit is contained in:
itsmattkc
2022-05-09 14:55:51 -07:00
parent 58c4600d04
commit bb0fedabba
47 changed files with 214 additions and 252 deletions
+10 -10
View File
@@ -40,10 +40,10 @@ AudioVisualWaveform::AudioVisualWaveform() :
} }
} }
void AudioVisualWaveform::OverwriteSamplesFromBuffer(SampleBufferPtr samples, int sample_rate, const rational &start, double target_rate, Sample& data, int &start_index, int &samples_length) void AudioVisualWaveform::OverwriteSamplesFromBuffer(const SampleBuffer &samples, int sample_rate, const rational &start, double target_rate, Sample& data, int &start_index, int &samples_length)
{ {
start_index = time_to_samples(start, target_rate); start_index = time_to_samples(start, target_rate);
samples_length = time_to_samples(static_cast<double>(samples->sample_count()) / static_cast<double>(sample_rate), target_rate); samples_length = time_to_samples(static_cast<double>(samples.sample_count()) / static_cast<double>(sample_rate), target_rate);
int end_index = start_index + samples_length; int end_index = start_index + samples_length;
if (data.size() < end_index) { if (data.size() < end_index) {
@@ -54,7 +54,7 @@ void AudioVisualWaveform::OverwriteSamplesFromBuffer(SampleBufferPtr samples, in
for (int i=0; i<samples_length; i+=channels_) { for (int i=0; i<samples_length; i+=channels_) {
int src_start = qRound((double(i) * chunk_size)) / channels_; int src_start = qRound((double(i) * chunk_size)) / channels_;
int src_end = qMin(qRound((double(i + channels_) * chunk_size)) / channels_, samples->sample_count()); int src_end = qMin(qRound((double(i + channels_) * chunk_size)) / channels_, samples.sample_count());
Sample summary = SumSamples(samples, Sample summary = SumSamples(samples,
src_start, src_start,
@@ -91,7 +91,7 @@ void AudioVisualWaveform::OverwriteSamplesFromMipmap(const AudioVisualWaveform::
input_length = samples_length; input_length = samples_length;
} }
void AudioVisualWaveform::OverwriteSamples(SampleBufferPtr samples, int sample_rate, const rational &start) void AudioVisualWaveform::OverwriteSamples(const SampleBuffer &samples, int sample_rate, const rational &start)
{ {
if (!channels_) { if (!channels_) {
qWarning() << "Failed to write samples - channel count is zero"; qWarning() << "Failed to write samples - channel count is zero";
@@ -125,7 +125,7 @@ void AudioVisualWaveform::OverwriteSamples(SampleBufferPtr samples, int sample_r
current_mipmap->second); current_mipmap->second);
} }
rational sample_length(samples->sample_count(), sample_rate); rational sample_length(samples.sample_count(), sample_rate);
length_ = qMax(length_, start + sample_length); length_ = qMax(length_, start + sample_length);
} }
@@ -277,7 +277,7 @@ AudioVisualWaveform::Sample AudioVisualWaveform::GetSummaryFromTime(const ration
return AudioVisualWaveform::Sample(channel_count(), {0, 0}); return AudioVisualWaveform::Sample(channel_count(), {0, 0});
} }
void ExpandMinMaxChannel(float *a, int start, int length, float &min_val, float &max_val) void ExpandMinMaxChannel(const float *a, int start, int length, float &min_val, float &max_val)
{ {
#if defined(Q_PROCESSOR_X86) || defined(Q_PROCESSOR_ARM) #if defined(Q_PROCESSOR_X86) || defined(Q_PROCESSOR_ARM)
// SSE optimized // SSE optimized
@@ -321,13 +321,13 @@ void ExpandMinMaxChannel(float *a, int start, int length, float &min_val, float
#endif #endif
} }
AudioVisualWaveform::Sample AudioVisualWaveform::SumSamples(SampleBufferPtr samples, int start_index, int length) AudioVisualWaveform::Sample AudioVisualWaveform::SumSamples(const SampleBuffer &samples, int start_index, int length)
{ {
int channels = samples->audio_params().channel_count(); int channels = samples.audio_params().channel_count();
AudioVisualWaveform::Sample summed_samples(channels); AudioVisualWaveform::Sample summed_samples(channels);
for (int channel=0; channel<samples->audio_params().channel_count(); channel++) { for (int channel=0; channel<samples.audio_params().channel_count(); channel++) {
ExpandMinMaxChannel(samples->data(channel), start_index, length, summed_samples[channel].min, summed_samples[channel].max); ExpandMinMaxChannel(samples.data(channel), start_index, length, summed_samples[channel].min, summed_samples[channel].max);
} }
// for reference: this approximation is n x faster (and less accurate) for a n-tracks clip // for reference: this approximation is n x faster (and less accurate) for a n-tracks clip
+3 -3
View File
@@ -65,7 +65,7 @@ public:
* *
* Starting at `start`, writes samples over anything in the buffer, expanding it if necessary. * Starting at `start`, writes samples over anything in the buffer, expanding it if necessary.
*/ */
void OverwriteSamples(SampleBufferPtr samples, int sample_rate, const rational& start = 0); void OverwriteSamples(const SampleBuffer &samples, int sample_rate, const rational& start = 0);
/** /**
* @brief Replaces sums at a certain range in this visual waveform * @brief Replaces sums at a certain range in this visual waveform
@@ -98,7 +98,7 @@ public:
Sample GetSummaryFromTime(const rational& start, const rational& length) const; Sample GetSummaryFromTime(const rational& start, const rational& length) const;
static Sample SumSamples(SampleBufferPtr samples, int start_index, int length); static Sample SumSamples(const SampleBuffer &samples, int start_index, int length);
static Sample ReSumSamples(const SamplePerChannel *samples, int nb_samples, int nb_channels); static Sample ReSumSamples(const SamplePerChannel *samples, int nb_samples, int nb_channels);
@@ -111,7 +111,7 @@ public:
static const rational kMaximumSampleRate; static const rational kMaximumSampleRate;
private: private:
void OverwriteSamplesFromBuffer(SampleBufferPtr samples, int sample_rate, const rational& start, double target_rate, Sample &data, int &start_index, int &samples_length); void OverwriteSamplesFromBuffer(const SampleBuffer &samples, int sample_rate, const rational& start, double target_rate, Sample &data, int &start_index, int &samples_length);
void OverwriteSamplesFromMipmap(const Sample& input, double input_sample_rate, int &input_start, int &input_length, const rational& start, double output_rate, Sample &output_data); void OverwriteSamplesFromMipmap(const Sample& input, double input_sample_rate, int &input_start, int &input_length, const rational& start, double output_rate, Sample &output_data);
+6 -6
View File
@@ -109,7 +109,7 @@ FramePtr Decoder::RetrieveVideo(const rational &timecode, const RetrieveVideoPar
return RetrieveVideoInternal(timecode, divider, cancelled); return RetrieveVideoInternal(timecode, divider, cancelled);
} }
Decoder::RetrieveAudioStatus Decoder::RetrieveAudio(SampleBufferPtr dest, const TimeRange &range, const AudioParams &params, const QString& cache_path, Footage::LoopMode loop_mode, RenderMode::Mode mode) Decoder::RetrieveAudioStatus Decoder::RetrieveAudio(SampleBuffer &dest, const TimeRange &range, const AudioParams &params, const QString& cache_path, Footage::LoopMode loop_mode, RenderMode::Mode mode)
{ {
QMutexLocker locker(&mutex_); QMutexLocker locker(&mutex_);
@@ -272,14 +272,14 @@ bool Decoder::ConformAudioInternal(const QVector<QString> &filenames, const Audi
return false; return false;
} }
bool Decoder::RetrieveAudioFromConform(SampleBufferPtr sample_buffer, const QVector<QString> &conform_filenames, const TimeRange& range, Footage::LoopMode loop_mode, const AudioParams &input_params) bool Decoder::RetrieveAudioFromConform(SampleBuffer &sample_buffer, const QVector<QString> &conform_filenames, const TimeRange& range, Footage::LoopMode loop_mode, const AudioParams &input_params)
{ {
PlanarFileDevice input; PlanarFileDevice input;
if (input.open(conform_filenames, QFile::ReadOnly)) { if (input.open(conform_filenames, QFile::ReadOnly)) {
qint64 read_index = input_params.time_to_bytes(range.in()) / input_params.channel_count(); qint64 read_index = input_params.time_to_bytes(range.in()) / input_params.channel_count();
qint64 write_index = 0; qint64 write_index = 0;
const qint64 buffer_length_in_bytes = sample_buffer->sample_count() * input_params.bytes_per_sample_per_channel(); const qint64 buffer_length_in_bytes = sample_buffer.sample_count() * input_params.bytes_per_sample_per_channel();
while (write_index < buffer_length_in_bytes) { while (write_index < buffer_length_in_bytes) {
if (loop_mode == Footage::kLoopModeLoop) { if (loop_mode == Footage::kLoopModeLoop) {
@@ -297,15 +297,15 @@ bool Decoder::RetrieveAudioFromConform(SampleBufferPtr sample_buffer, const QVec
if (read_index < 0) { if (read_index < 0) {
// Reading before 0, write silence here until audio data would actually start // Reading before 0, write silence here until audio data would actually start
write_count = qMin(-read_index, buffer_length_in_bytes); write_count = qMin(-read_index, buffer_length_in_bytes);
sample_buffer->silence_bytes(write_index, write_index + write_count); sample_buffer.silence_bytes(write_index, write_index + write_count);
} else if (read_index >= input.size()) { } else if (read_index >= input.size()) {
// Reading after data length, write silence until the end of the buffer // Reading after data length, write silence until the end of the buffer
write_count = buffer_length_in_bytes - write_index; write_count = buffer_length_in_bytes - write_index;
sample_buffer->silence_bytes(write_index, write_index + write_count); sample_buffer.silence_bytes(write_index, write_index + write_count);
} else { } else {
write_count = qMin(input.size() - read_index, buffer_length_in_bytes - write_index); write_count = qMin(input.size() - read_index, buffer_length_in_bytes - write_index);
input.seek(read_index); input.seek(read_index);
input.read(reinterpret_cast<char**>(sample_buffer->to_raw_ptrs()), write_count, write_index); input.read(reinterpret_cast<char**>(sample_buffer.to_raw_ptrs().data()), write_count, write_index);
} }
read_index += write_count; read_index += write_count;
+2 -2
View File
@@ -201,7 +201,7 @@ public:
* *
* This function is thread safe and can only run while the decoder is open. \see Open() * This function is thread safe and can only run while the decoder is open. \see Open()
*/ */
RetrieveAudioStatus RetrieveAudio(SampleBufferPtr dest, const TimeRange& range, const AudioParams& params, const QString &cache_path, Footage::LoopMode loop_mode, RenderMode::Mode mode); RetrieveAudioStatus RetrieveAudio(SampleBuffer &dest, const TimeRange& range, const AudioParams& params, const QString &cache_path, Footage::LoopMode loop_mode, RenderMode::Mode mode);
/** /**
* @brief Determine the last time this decoder instance was used in any way * @brief Determine the last time this decoder instance was used in any way
@@ -307,7 +307,7 @@ signals:
private: private:
void UpdateLastAccessed(); void UpdateLastAccessed();
bool RetrieveAudioFromConform(SampleBufferPtr sample_buffer, const QVector<QString> &conform_filenames, const TimeRange &range, Footage::LoopMode loop_mode, const AudioParams &params); bool RetrieveAudioFromConform(SampleBuffer &sample_buffer, const QVector<QString> &conform_filenames, const TimeRange &range, Footage::LoopMode loop_mode, const AudioParams &params);
CodecStream stream_; CodecStream stream_;
+1 -1
View File
@@ -183,7 +183,7 @@ public slots:
virtual bool Open() = 0; virtual bool Open() = 0;
virtual bool WriteFrame(olive::FramePtr frame, olive::rational time) = 0; virtual bool WriteFrame(olive::FramePtr frame, olive::rational time) = 0;
virtual bool WriteAudio(olive::SampleBufferPtr audio) = 0; virtual bool WriteAudio(const olive::SampleBuffer &audio) = 0;
virtual bool WriteSubtitle(const SubtitleBlock *sub_block) = 0; virtual bool WriteSubtitle(const SubtitleBlock *sub_block) = 0;
virtual void Close() = 0; virtual void Close() = 0;
+2 -2
View File
@@ -515,7 +515,7 @@ bool FFmpegDecoder::ConformAudioInternal(const QVector<QString> &filenames, cons
// Resample audio to our destination parameters // Resample audio to our destination parameters
nb_samples = swr_convert(resampler, nb_samples = swr_convert(resampler,
reinterpret_cast<uint8_t**>(data.to_raw_ptrs()), reinterpret_cast<uint8_t**>(data.to_raw_ptrs().data()),
nb_samples, nb_samples,
const_cast<const uint8_t**>(frame->data), const_cast<const uint8_t**>(frame->data),
frame->nb_samples); frame->nb_samples);
@@ -526,7 +526,7 @@ bool FFmpegDecoder::ConformAudioInternal(const QVector<QString> &filenames, cons
nb_bytes_per_channel = params.samples_to_bytes(nb_samples) / nb_channels; nb_bytes_per_channel = params.samples_to_bytes(nb_samples) / nb_channels;
// Write to files // Write to files
wave_out.write(const_cast<const char**>(reinterpret_cast<char**>(data.to_raw_ptrs())), nb_bytes_per_channel); wave_out.write(const_cast<const char**>(reinterpret_cast<char**>(data.to_raw_ptrs().data())), nb_bytes_per_channel);
} }
// Free buffer // Free buffer
+9 -9
View File
@@ -266,26 +266,26 @@ fail:
return success; return success;
} }
bool FFmpegEncoder::WriteAudio(SampleBufferPtr audio) bool FFmpegEncoder::WriteAudio(const SampleBuffer &audio)
{ {
bool result = true; bool result = true;
// Create input buffer // Create input buffer
int input_sample_count = 0; int input_sample_count = 0;
uint8_t** input_data = nullptr; uint8_t** input_data = nullptr;
if (audio) { if (audio.is_allocated()) {
input_sample_count = audio->sample_count(); input_sample_count = audio.sample_count();
int input_linesize; int input_linesize;
av_samples_alloc_array_and_samples(&input_data, &input_linesize, audio->audio_params().channel_count(), av_samples_alloc_array_and_samples(&input_data, &input_linesize, audio.audio_params().channel_count(),
input_sample_count, FFmpegUtils::GetFFmpegSampleFormat(audio->audio_params().format()), 0); input_sample_count, FFmpegUtils::GetFFmpegSampleFormat(audio.audio_params().format()), 0);
for (int i=0; i<audio->audio_params().channel_count(); i++) { for (int i=0; i<audio.audio_params().channel_count(); i++) {
memcpy(input_data[i], audio->data(i), input_sample_count * audio->audio_params().bytes_per_sample_per_channel()); memcpy(input_data[i], audio.data(i), input_sample_count * audio.audio_params().bytes_per_sample_per_channel());
} }
} }
result = WriteAudioData(audio ? audio->audio_params() : params().audio_params(), const_cast<const uint8_t**>(input_data), input_sample_count); result = WriteAudioData(audio.audio_params().is_valid() ? audio.audio_params() : params().audio_params(), const_cast<const uint8_t**>(input_data), input_sample_count);
if (input_data) { if (input_data) {
av_freep(&input_data[0]); av_freep(&input_data[0]);
@@ -774,7 +774,7 @@ void FFmpegEncoder::FlushEncoders()
} }
if (audio_codec_ctx_) { if (audio_codec_ctx_) {
WriteAudio(nullptr); WriteAudio(SampleBuffer());
FlushCodecCtx(audio_codec_ctx_, audio_stream_); FlushCodecCtx(audio_codec_ctx_, audio_stream_);
} }
+1 -1
View File
@@ -47,7 +47,7 @@ public:
virtual bool WriteFrame(olive::FramePtr frame, olive::rational time) override; virtual bool WriteFrame(olive::FramePtr frame, olive::rational time) override;
virtual bool WriteAudio(olive::SampleBufferPtr audio) override; virtual bool WriteAudio(const olive::SampleBuffer &audio) override;
bool WriteAudioData(const AudioParams &audio_params, const uint8_t **data, int input_sample_count); bool WriteAudioData(const AudioParams &audio_params, const uint8_t **data, int input_sample_count);
+1 -1
View File
@@ -62,7 +62,7 @@ bool OIIOEncoder::WriteFrame(FramePtr frame, rational time)
return true; return true;
} }
bool OIIOEncoder::WriteAudio(SampleBufferPtr audio) bool OIIOEncoder::WriteAudio(const SampleBuffer &audio)
{ {
// Do nothing // Do nothing
return false; return false;
+1 -1
View File
@@ -35,7 +35,7 @@ public slots:
virtual bool Open() override; virtual bool Open() override;
virtual bool WriteFrame(olive::FramePtr frame, olive::rational time) override; virtual bool WriteFrame(olive::FramePtr frame, olive::rational time) override;
virtual bool WriteAudio(SampleBufferPtr audio) override; virtual bool WriteAudio(const SampleBuffer &audio) override;
virtual bool WriteSubtitle(const SubtitleBlock *sub_block) override; virtual bool WriteSubtitle(const SubtitleBlock *sub_block) override;
virtual void Close() override; virtual void Close() override;
+28 -33
View File
@@ -20,6 +20,8 @@
#include "samplebuffer.h" #include "samplebuffer.h"
#include "common/cpuoptimize.h"
namespace olive { namespace olive {
SampleBuffer::SampleBuffer() : SampleBuffer::SampleBuffer() :
@@ -27,25 +29,18 @@ SampleBuffer::SampleBuffer() :
{ {
} }
SampleBufferPtr SampleBuffer::Create() SampleBuffer::SampleBuffer(const AudioParams &audio_params, const rational &length) :
audio_params_(audio_params)
{ {
return std::make_shared<SampleBuffer>(); sample_count_per_channel_ = audio_params_.time_to_samples(length);
allocate();
} }
SampleBufferPtr SampleBuffer::CreateAllocated(const AudioParams &audio_params, const rational &length) SampleBuffer::SampleBuffer(const AudioParams &audio_params, int samples_per_channel) :
audio_params_(audio_params),
sample_count_per_channel_(samples_per_channel)
{ {
return CreateAllocated(audio_params, audio_params.time_to_samples(length)); allocate();
}
SampleBufferPtr SampleBuffer::CreateAllocated(const AudioParams &audio_params, int samples_per_channel)
{
SampleBufferPtr buffer = Create();
buffer->set_audio_params(audio_params);
buffer->set_sample_count(samples_per_channel);
buffer->allocate();
return buffer;
} }
const AudioParams &SampleBuffer::audio_params() const const AudioParams &SampleBuffer::audio_params() const
@@ -104,14 +99,11 @@ void SampleBuffer::allocate()
for (int i=0; i<audio_params_.channel_count(); i++) { for (int i=0; i<audio_params_.channel_count(); i++) {
data_[i].resize(sample_count_per_channel_); data_[i].resize(sample_count_per_channel_);
} }
update_raw();
} }
void SampleBuffer::destroy() void SampleBuffer::destroy()
{ {
data_.clear(); data_.clear();
raw_ptrs_.clear();
} }
void SampleBuffer::reverse() void SampleBuffer::reverse()
@@ -157,29 +149,40 @@ void SampleBuffer::speed(double speed)
} }
data_ = output_data; data_ = output_data;
update_raw();
} }
void SampleBuffer::transform_volume(float f) void SampleBuffer::transform_volume(float f)
{ {
for (int i=0;i<audio_params().channel_count();i++) { for (int i=0;i<audio_params().channel_count();i++) {
for (int j=0;j<sample_count_per_channel_;j++) { transform_volume_for_channel(i, f);
data_[i][j] *= f;
}
} }
} }
void SampleBuffer::transform_volume_for_channel(int channel, float volume) void SampleBuffer::transform_volume_for_channel(int channel, float volume)
{ {
for (int i=0;i<sample_count_per_channel_;i++) { float *cdat = data_[channel].data();
data_[channel][i] *= volume; int unopt_start = 0;
#if defined(Q_PROCESSOR_X86) || defined(Q_PROCESSOR_ARM)
__m128 mult = _mm_load1_ps(&volume);
unopt_start = (sample_count_per_channel_ / 4) * 4;
for (int j=0; j<unopt_start; j+=4) {
float *here = cdat + j;
__m128 samples = _mm_loadu_ps(here);
__m128 multiplied = _mm_mul_ps(samples, mult);
_mm_storeu_ps(here, multiplied);
}
#endif
for (int j=unopt_start; j<sample_count_per_channel_; j++) {
cdat[j] *= volume;
} }
} }
void SampleBuffer::transform_volume_for_sample(int sample_index, float volume) void SampleBuffer::transform_volume_for_sample(int sample_index, float volume)
{ {
for (int i=0;i<audio_params().channel_count();i++) { for (int i=0;i<audio_params().channel_count();i++) {
data_[i][sample_index] *= volume; transform_volume_for_sample_on_channel(sample_index, i, volume);
} }
} }
@@ -220,12 +223,4 @@ void SampleBuffer::set(int channel, const float *data, int sample_offset, int sa
memcpy(&data_[channel].data()[sample_offset], data, sizeof(float) * sample_length); memcpy(&data_[channel].data()[sample_offset], data, sizeof(float) * sample_length);
} }
void SampleBuffer::update_raw()
{
raw_ptrs_.resize(data_.size());
for (int i=0; i<raw_ptrs_.size(); i++) {
raw_ptrs_[i] = data_[i].data();
}
}
} }
+9 -15
View File
@@ -27,9 +27,6 @@
namespace olive { namespace olive {
class SampleBuffer;
using SampleBufferPtr = std::shared_ptr<SampleBuffer>;
/** /**
* @brief A buffer of audio samples * @brief A buffer of audio samples
* *
@@ -42,12 +39,8 @@ class SampleBuffer
{ {
public: public:
SampleBuffer(); SampleBuffer();
SampleBuffer(const AudioParams& audio_params, const rational& length);
static SampleBufferPtr Create(); SampleBuffer(const AudioParams& audio_params, int samples_per_channel);
static SampleBufferPtr CreateAllocated(const AudioParams& audio_params, const rational& length);
static SampleBufferPtr CreateAllocated(const AudioParams& audio_params, int samples_per_channel);
DISABLE_COPY_MOVE(SampleBuffer)
const AudioParams& audio_params() const; const AudioParams& audio_params() const;
void set_audio_params(const AudioParams& params); void set_audio_params(const AudioParams& params);
@@ -69,9 +62,13 @@ public:
return data_.at(channel).constData(); return data_.at(channel).constData();
} }
float **to_raw_ptrs() QVector<float *> to_raw_ptrs()
{ {
return raw_ptrs_.data(); QVector<float *> r(data_.size());
for (int i=0; i<r.size(); i++) {
r[i] = data_[i].data();
}
return r;
} }
bool is_allocated() const; bool is_allocated() const;
@@ -96,19 +93,16 @@ public:
} }
private: private:
void update_raw();
AudioParams audio_params_; AudioParams audio_params_;
int sample_count_per_channel_; int sample_count_per_channel_;
QVector< QVector<float> > data_; QVector< QVector<float> > data_;
QVector<float*> raw_ptrs_;
}; };
} }
Q_DECLARE_METATYPE(olive::SampleBufferPtr) Q_DECLARE_METATYPE(olive::SampleBuffer)
#endif // SAMPLEBUFFER_H #endif // SAMPLEBUFFER_H
+1 -1
View File
@@ -108,7 +108,7 @@ void Core::DeclareTypesForQt()
qRegisterMetaType<NodeValueTable>(); qRegisterMetaType<NodeValueTable>();
qRegisterMetaType<NodeValueDatabase>(); qRegisterMetaType<NodeValueDatabase>();
qRegisterMetaType<FramePtr>(); qRegisterMetaType<FramePtr>();
qRegisterMetaType<SampleBufferPtr>(); qRegisterMetaType<SampleBuffer>();
qRegisterMetaType<AudioParams>(); qRegisterMetaType<AudioParams>();
qRegisterMetaType<NodeKeyframe::Type>(); qRegisterMetaType<NodeKeyframe::Type>();
qRegisterMetaType<Decoder::RetrieveState>(); qRegisterMetaType<Decoder::RetrieveState>();
+18 -15
View File
@@ -67,45 +67,48 @@ void PanNode::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeV
Q_UNUSED(globals) Q_UNUSED(globals)
// Create a sample job // Create a sample job
SampleJob job(kSamplesInput, value); SampleBuffer samples = value[kSamplesInput].toSamples();
if (samples.is_allocated()) {
if (job.HasSamples()) { bool pushed_job = false;
bool push_job = false;
// This node is only compatible with stereo audio // This node is only compatible with stereo audio
if (job.samples()->audio_params().channel_count() == 2) { if (samples.audio_params().channel_count() == 2) {
// If the input is static, we can just do it now which will be faster // If the input is static, we can just do it now which will be faster
if (IsInputStatic(kPanningInput)) { if (IsInputStatic(kPanningInput)) {
float pan_volume = job.GetValue(kPanningInput).toDouble(); float pan_volume = value[kPanningInput].toDouble();
if (!qIsNull(pan_volume)) { if (!qIsNull(pan_volume)) {
if (pan_volume > 0) { if (pan_volume > 0) {
job.samples()->transform_volume_for_channel(0, 1.0f - pan_volume); samples.transform_volume_for_channel(0, 1.0f - pan_volume);
} else { } else {
job.samples()->transform_volume_for_channel(1, 1.0f + pan_volume); samples.transform_volume_for_channel(1, 1.0f + pan_volume);
} }
} }
} else { } else {
// Requires job // Requires job
push_job = true;
pushed_job = true;
table->Push(NodeValue::kSamples, SampleJob(kSamplesInput, value), this);
} }
} }
table->Push(NodeValue::kSamples, push_job ? QVariant::fromValue(job) : QVariant::fromValue(job.samples()), this); if (!pushed_job) {
table->Push(value[kSamplesInput]);
}
} }
} }
void PanNode::ProcessSamples(const NodeValueRow &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const void PanNode::ProcessSamples(const NodeValueRow &values, const SampleBuffer &input, SampleBuffer &output, int index) const
{ {
float pan_val = values[kPanningInput].toDouble(); float pan_val = values[kPanningInput].toDouble();
for (int i=0;i<input->audio_params().channel_count();i++) { for (int i=0;i<input.audio_params().channel_count();i++) {
output->data(i)[index] = input->data(i)[index]; output.data(i)[index] = input.data(i)[index];
} }
if (pan_val > 0) { if (pan_val > 0) {
output->data(0)[index] *= (1.0F - pan_val); output.data(0)[index] *= (1.0F - pan_val);
} else if (pan_val < 0) { } else if (pan_val < 0) {
output->data(1)[index] *= (1.0F - qAbs(pan_val)); output.data(1)[index] *= (1.0F - qAbs(pan_val));
} }
} }
+1 -1
View File
@@ -40,7 +40,7 @@ public:
virtual void Value(const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; virtual void Value(const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
virtual void ProcessSamples(const NodeValueRow &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const override; virtual void ProcessSamples(const NodeValueRow &values, const SampleBuffer &input, SampleBuffer &output, int index) const override;
virtual void Retranslate() override; virtual void Retranslate() override;
+1 -1
View File
@@ -73,7 +73,7 @@ void VolumeNode::Value(const NodeValueRow &value, const NodeGlobals &globals, No
table); table);
} }
void VolumeNode::ProcessSamples(const NodeValueRow &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const void VolumeNode::ProcessSamples(const NodeValueRow &values, const SampleBuffer &input, SampleBuffer &output, int index) const
{ {
return ProcessSamplesInternal(values, kOpMultiply, kSamplesInput, kVolumeInput, input, output, index); return ProcessSamplesInternal(values, kOpMultiply, kSamplesInput, kVolumeInput, input, output, index);
} }
+1 -1
View File
@@ -40,7 +40,7 @@ public:
virtual void Value(const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; virtual void Value(const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
virtual void ProcessSamples(const NodeValueRow &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const override; virtual void ProcessSamples(const NodeValueRow &values, const SampleBuffer &input, SampleBuffer &output, int index) const override;
virtual void Retranslate() override; virtual void Retranslate() override;
@@ -60,27 +60,27 @@ void CrossDissolveTransition::ShaderJobEvent(const NodeValueRow &value, ShaderJo
job.SetAlphaChannelRequired(GenerateJob::kAlphaForceOn); job.SetAlphaChannelRequired(GenerateJob::kAlphaForceOn);
} }
void CrossDissolveTransition::SampleJobEvent(SampleBufferPtr from_samples, SampleBufferPtr to_samples, SampleBufferPtr out_samples, double time_in) const void CrossDissolveTransition::SampleJobEvent(const SampleBuffer &from_samples, const SampleBuffer &to_samples, SampleBuffer &out_samples, double time_in) const
{ {
for (int i=0; i<out_samples->sample_count(); i++) { for (int i=0; i<out_samples.sample_count(); i++) {
double this_sample_time = out_samples->audio_params().samples_to_time(i).toDouble() + time_in; double this_sample_time = out_samples.audio_params().samples_to_time(i).toDouble() + time_in;
double progress = GetTotalProgress(this_sample_time); double progress = GetTotalProgress(this_sample_time);
for (int j=0; j<out_samples->audio_params().channel_count(); j++) { for (int j=0; j<out_samples.audio_params().channel_count(); j++) {
out_samples->data(j)[i] = 0; out_samples.data(j)[i] = 0;
if (from_samples) { if (from_samples.is_allocated()) {
if (i < from_samples->sample_count()) { if (i < from_samples.sample_count()) {
out_samples->data(j)[i] += from_samples->data(j)[i] * TransformCurve(1.0 - progress); out_samples.data(j)[i] += from_samples.data(j)[i] * TransformCurve(1.0 - progress);
} }
} }
if (to_samples) { if (to_samples.is_allocated()) {
// Offset input samples from the end // Offset input samples from the end
int in_index = i - (out_samples->sample_count() - to_samples->sample_count()); int in_index = i - (out_samples.sample_count() - to_samples.sample_count());
if (in_index >= 0) { if (in_index >= 0) {
out_samples->data(j)[i] += to_samples->data(j)[in_index] * TransformCurve(progress); out_samples.data(j)[i] += to_samples.data(j)[in_index] * TransformCurve(progress);
} }
} }
} }
@@ -45,7 +45,7 @@ public:
protected: protected:
virtual void ShaderJobEvent(const NodeValueRow &value, ShaderJob& job) const override; virtual void ShaderJobEvent(const NodeValueRow &value, ShaderJob& job) const override;
virtual void SampleJobEvent(SampleBufferPtr from_samples, SampleBufferPtr to_samples, SampleBufferPtr out_samples, double time_in) const override; virtual void SampleJobEvent(const SampleBuffer &from_samples, const SampleBuffer &to_samples, SampleBuffer &out_samples, double time_in) const override;
}; };
+6 -23
View File
@@ -206,25 +206,22 @@ void TransitionBlock::Value(const NodeValueRow &value, const NodeGlobals &global
push_job = QVariant::fromValue(job); push_job = QVariant::fromValue(job);
} else if (data_type == NodeValue::kSamples) { } else if (data_type == NodeValue::kSamples) {
// This must be an audio transition // This must be an audio transition
SampleBufferPtr from_samples = out_buffer.toSamples(); SampleBuffer from_samples = out_buffer.toSamples();
SampleBufferPtr to_samples = in_buffer.toSamples(); SampleBuffer to_samples = in_buffer.toSamples();
if (from_samples || to_samples) { if (from_samples.is_allocated() || to_samples.is_allocated()) {
double time_in = globals.time().in().toDouble(); double time_in = globals.time().in().toDouble();
double time_out = globals.time().out().toDouble(); double time_out = globals.time().out().toDouble();
const AudioParams& params = (from_samples) ? from_samples->audio_params() : to_samples->audio_params(); const AudioParams& params = (from_samples.is_allocated()) ? from_samples.audio_params() : to_samples.audio_params();
SampleBufferPtr out_samples; SampleBuffer out_samples;
if (params.is_valid()) { if (params.is_valid()) {
int nb_samples = params.time_to_samples(time_out - time_in); int nb_samples = params.time_to_samples(time_out - time_in);
out_samples = SampleBuffer::CreateAllocated(params, nb_samples); out_samples = SampleBuffer(params, nb_samples);
SampleJobEvent(from_samples, to_samples, out_samples, time_in); SampleJobEvent(from_samples, to_samples, out_samples, time_in);
} else {
// Create dummy sample buffer
out_samples = SampleBuffer::Create();
} }
job_type = NodeValue::kSamples; job_type = NodeValue::kSamples;
@@ -251,20 +248,6 @@ void TransitionBlock::InvalidateCache(const TimeRange &range, const QString &fro
super::InvalidateCache(r, from, element, options); super::InvalidateCache(r, from, element, options);
} }
void TransitionBlock::ShaderJobEvent(const NodeValueRow &value, ShaderJob &job) const
{
Q_UNUSED(value)
Q_UNUSED(job)
}
void TransitionBlock::SampleJobEvent(SampleBufferPtr from_samples, SampleBufferPtr to_samples, SampleBufferPtr out_samples, double time_in) const
{
Q_UNUSED(from_samples)
Q_UNUSED(to_samples)
Q_UNUSED(out_samples)
Q_UNUSED(time_in)
}
double TransitionBlock::TransformCurve(double linear) const double TransitionBlock::TransformCurve(double linear) const
{ {
switch (static_cast<CurveType>(GetStandardValue(kCurveInput).toInt())) { switch (static_cast<CurveType>(GetStandardValue(kCurveInput).toInt())) {
+2 -2
View File
@@ -73,9 +73,9 @@ public:
static const QString kCenterInput; static const QString kCenterInput;
protected: protected:
virtual void ShaderJobEvent(const NodeValueRow &value, ShaderJob& job) const; virtual void ShaderJobEvent(const NodeValueRow &value, ShaderJob& job) const {}
virtual void SampleJobEvent(SampleBufferPtr from_samples, SampleBufferPtr to_samples, SampleBufferPtr out_samples, double time_in) const; virtual void SampleJobEvent(const SampleBuffer &from_samples, const SampleBuffer &to_samples, SampleBuffer &out_samples, double time_in) const {}
double TransformCurve(double linear) const; double TransformCurve(double linear) const;
+2 -12
View File
@@ -72,14 +72,8 @@ void HashTraverser::ProcessVideoFootage(TexturePtr destination, const FootageJob
texture_ids_.insert(destination.get(), hash_.result()); texture_ids_.insert(destination.get(), hash_.result());
} }
void HashTraverser::ProcessAudioFootage(SampleBufferPtr destination, const FootageJob &stream, const TimeRange &input_time) void HashTraverser::ProcessAudioFootage(SampleBuffer &destination, const FootageJob &stream, const TimeRange &input_time)
{ {
Hash(FileFunctions::GetUniqueFileIdentifier(stream.filename()));
Hash(stream.loop_mode());
Hash(stream.audio_params().stream_index());
Hash(input_time);
texture_ids_.insert(destination.get(), hash_.result());
} }
void HashTraverser::ProcessShader(TexturePtr destination, const Node *node, const TimeRange &range, const ShaderJob &job) void HashTraverser::ProcessShader(TexturePtr destination, const Node *node, const TimeRange &range, const ShaderJob &job)
@@ -104,9 +98,8 @@ void HashTraverser::ProcessColorTransform(TexturePtr destination, const Node *no
texture_ids_.insert(destination.get(), hash_.result()); texture_ids_.insert(destination.get(), hash_.result());
} }
void HashTraverser::ProcessSamples(SampleBufferPtr destination, const Node *node, const TimeRange &range, const SampleJob &job) void HashTraverser::ProcessSamples(SampleBuffer &destination, const Node *node, const TimeRange &range, const SampleJob &job)
{ {
texture_ids_.insert(destination.get(), hash_.result());
} }
void HashTraverser::ProcessFrameGeneration(TexturePtr destination, const Node *node, const GenerateJob &job) void HashTraverser::ProcessFrameGeneration(TexturePtr destination, const Node *node, const GenerateJob &job)
@@ -146,9 +139,6 @@ void HashTraverser::HashNodeValue(const NodeValue &value)
if (value_type == NodeValue::kTexture) { if (value_type == NodeValue::kTexture) {
TexturePtr texture = value.toTexture(); TexturePtr texture = value.toTexture();
id_for_buffer = texture_ids_.value(texture.get()); id_for_buffer = texture_ids_.value(texture.get());
} else {
SampleBufferPtr samples = value.toSamples();
id_for_buffer = texture_ids_.value(samples.get());
} }
if (!id_for_buffer.isEmpty()) { if (!id_for_buffer.isEmpty()) {
+2 -2
View File
@@ -35,13 +35,13 @@ public:
protected: protected:
virtual void ProcessVideoFootage(TexturePtr destination, const FootageJob &stream, const rational &input_time) override; virtual void ProcessVideoFootage(TexturePtr destination, const FootageJob &stream, const rational &input_time) override;
virtual void ProcessAudioFootage(SampleBufferPtr destination, const FootageJob &stream, const TimeRange &input_time) override; virtual void ProcessAudioFootage(SampleBuffer &destination, const FootageJob &stream, const TimeRange &input_time) override;
virtual void ProcessShader(TexturePtr destination, const Node *node, const TimeRange &range, const ShaderJob& job) override; virtual void ProcessShader(TexturePtr destination, const Node *node, const TimeRange &range, const ShaderJob& job) override;
virtual void ProcessColorTransform(TexturePtr destination, const Node *node, const ColorTransformJob& job) override; virtual void ProcessColorTransform(TexturePtr destination, const Node *node, const ColorTransformJob& job) override;
virtual void ProcessSamples(SampleBufferPtr destination, const Node *node, const TimeRange &range, const SampleJob &job) override; virtual void ProcessSamples(SampleBuffer &destination, const Node *node, const TimeRange &range, const SampleJob &job) override;
virtual void ProcessFrameGeneration(TexturePtr destination, const Node *node, const GenerateJob& job) override; virtual void ProcessFrameGeneration(TexturePtr destination, const Node *node, const GenerateJob& job) override;
+1 -1
View File
@@ -109,7 +109,7 @@ void MathNode::Value(const NodeValueRow &value, const NodeGlobals &globals, Node
table); table);
} }
void MathNode::ProcessSamples(const NodeValueRow &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const void MathNode::ProcessSamples(const NodeValueRow &values, const SampleBuffer &input, SampleBuffer &output, int index) const
{ {
return ProcessSamplesInternal(values, GetOperation(), kParamAIn, kParamBIn, input, output, index); return ProcessSamplesInternal(values, GetOperation(), kParamAIn, kParamBIn, input, output, index);
} }
+1 -1
View File
@@ -54,7 +54,7 @@ public:
virtual void Value(const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; virtual void Value(const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
virtual void ProcessSamples(const NodeValueRow &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const override; virtual void ProcessSamples(const NodeValueRow &values, const SampleBuffer &input, SampleBuffer &output, int index) const override;
static const QString kMethodIn; static const QString kMethodIn;
static const QString kParamAIn; static const QString kParamAIn;
+22 -21
View File
@@ -298,18 +298,18 @@ void MathNodeBase::ValueInternal(Operation operation, Pairing pairing, const QSt
case kPairSampleSample: case kPairSampleSample:
{ {
SampleBufferPtr samples_a = val_a.toSamples(); SampleBuffer samples_a = val_a.toSamples();
SampleBufferPtr samples_b = val_b.toSamples(); SampleBuffer samples_b = val_b.toSamples();
int max_samples = qMax(samples_a->sample_count(), samples_b->sample_count()); int max_samples = qMax(samples_a.sample_count(), samples_b.sample_count());
int min_samples = qMin(samples_a->sample_count(), samples_b->sample_count()); int min_samples = qMin(samples_a.sample_count(), samples_b.sample_count());
SampleBufferPtr mixed_samples = SampleBuffer::CreateAllocated(samples_a->audio_params(), max_samples); SampleBuffer mixed_samples = SampleBuffer(samples_a.audio_params(), max_samples);
for (int i=0;i<mixed_samples->audio_params().channel_count();i++) { for (int i=0;i<mixed_samples.audio_params().channel_count();i++) {
// Mix samples that are in both buffers // Mix samples that are in both buffers
for (int j=0;j<min_samples;j++) { for (int j=0;j<min_samples;j++) {
mixed_samples->data(i)[j] = PerformAll<float, float>(operation, samples_a->data(i)[j], samples_b->data(i)[j]); mixed_samples.data(i)[j] = PerformAll<float, float>(operation, samples_a.data(i)[j], samples_b.data(i)[j]);
} }
} }
@@ -317,11 +317,11 @@ void MathNodeBase::ValueInternal(Operation operation, Pairing pairing, const QSt
// Fill in remainder space with 0s // Fill in remainder space with 0s
int remainder = max_samples - min_samples; int remainder = max_samples - min_samples;
SampleBufferPtr larger_buffer = (max_samples == samples_a->sample_count()) ? samples_a : samples_b; const SampleBuffer &larger_buffer = (max_samples == samples_a.sample_count()) ? samples_a : samples_b;
for (int i=0;i<mixed_samples->audio_params().channel_count();i++) { for (int i=0;i<mixed_samples.audio_params().channel_count();i++) {
memcpy(&mixed_samples->data(i)[min_samples], memcpy(&mixed_samples.data(i)[min_samples],
&larger_buffer->data(i)[min_samples], &larger_buffer.data(i)[min_samples],
remainder * sizeof(float)); remainder * sizeof(float));
} }
} }
@@ -396,24 +396,25 @@ void MathNodeBase::ValueInternal(Operation operation, Pairing pairing, const QSt
float number = RetrieveNumber(number_val); float number = RetrieveNumber(number_val);
SampleJob job(val_a.type() == NodeValue::kSamples ? val_a : val_b); SampleBuffer buffer = val_a.type() == NodeValue::kSamples ? val_a.toSamples() : val_b.toSamples();
job.InsertValue(number_param, NodeValue(NodeValue::kFloat, number, this));
if (job.HasSamples()) { if (buffer.is_allocated()) {
if (IsInputStatic(number_param)) { if (IsInputStatic(number_param)) {
if (!NumberIsNoOp(operation, number)) { if (!NumberIsNoOp(operation, number)) {
for (int i=0;i<job.samples()->audio_params().channel_count();i++) { for (int i=0;i<buffer.audio_params().channel_count();i++) {
#if defined(Q_PROCESSOR_X86) || defined(Q_PROCESSOR_ARM) #if defined(Q_PROCESSOR_X86) || defined(Q_PROCESSOR_ARM)
// Use SSE instructions for optimization // Use SSE instructions for optimization
PerformAllOnFloatBufferSSE(operation, job.samples()->data(i), number, 0, job.samples()->sample_count()); PerformAllOnFloatBufferSSE(operation, buffer.data(i), number, 0, buffer.sample_count());
#else #else
PerformAllOnFloatBuffer(operation, job.samples()->data(i), number, 0, job.samples()->sample_count()); PerformAllOnFloatBuffer(operation, buffer.data(i), number, 0, buffer.sample_count());
#endif #endif
} }
} }
output->Push(NodeValue::kSamples, QVariant::fromValue(job.samples()), this); output->Push(NodeValue::kSamples, QVariant::fromValue(buffer), this);
} else { } else {
SampleJob job(val_a.type() == NodeValue::kSamples ? val_a : val_b);
job.InsertValue(number_param, NodeValue(NodeValue::kFloat, number, this));
output->Push(NodeValue::kSamples, QVariant::fromValue(job), this); output->Push(NodeValue::kSamples, QVariant::fromValue(job), this);
} }
} }
@@ -426,7 +427,7 @@ void MathNodeBase::ValueInternal(Operation operation, Pairing pairing, const QSt
} }
} }
void MathNodeBase::ProcessSamplesInternal(const NodeValueRow &values, MathNodeBase::Operation operation, const QString &param_a_in, const QString &param_b_in, const SampleBufferPtr input, SampleBufferPtr output, int index) const void MathNodeBase::ProcessSamplesInternal(const NodeValueRow &values, MathNodeBase::Operation operation, const QString &param_a_in, const QString &param_b_in, const olive::SampleBuffer &input, olive::SampleBuffer &output, int index) const
{ {
// This function is only used for sample+number pairing // This function is only used for sample+number pairing
NodeValue number_val = values[param_a_in]; NodeValue number_val = values[param_a_in];
@@ -441,8 +442,8 @@ void MathNodeBase::ProcessSamplesInternal(const NodeValueRow &values, MathNodeBa
float number_flt = RetrieveNumber(number_val); float number_flt = RetrieveNumber(number_val);
for (int i=0;i<output->audio_params().channel_count();i++) { for (int i=0;i<output.audio_params().channel_count();i++) {
output->data(i)[index] = PerformAll<float, float>(operation, input->data(i)[index], number_flt); output.data(i)[index] = PerformAll<float, float>(operation, input.data(i)[index], number_flt);
} }
} }
+1 -1
View File
@@ -121,7 +121,7 @@ protected:
void ValueInternal(Operation operation, Pairing pairing, const QString& param_a_in, const NodeValue &val_a, const QString& param_b_in, const NodeValue& val_b, const NodeGlobals &globals, NodeValueTable *output) const; void ValueInternal(Operation operation, Pairing pairing, const QString& param_a_in, const NodeValue &val_a, const QString& param_b_in, const NodeValue& val_b, const NodeGlobals &globals, NodeValueTable *output) const;
void ProcessSamplesInternal(const NodeValueRow &values, Operation operation, const QString& param_a_in, const QString& param_b_in, const SampleBufferPtr input, SampleBufferPtr output, int index) const; void ProcessSamplesInternal(const NodeValueRow &values, Operation operation, const QString& param_a_in, const QString& param_b_in, const SampleBuffer &input, SampleBuffer &output, int index) const;
}; };
+1 -1
View File
@@ -1525,7 +1525,7 @@ ShaderCode Node::GetShaderCode(const ShaderRequest &request) const
return ShaderCode(QString(), QString()); return ShaderCode(QString(), QString());
} }
void Node::ProcessSamples(const NodeValueRow &, const SampleBufferPtr, SampleBufferPtr, int) const void Node::ProcessSamples(const NodeValueRow &, const SampleBuffer &, SampleBuffer &, int) const
{ {
} }
+1 -1
View File
@@ -691,7 +691,7 @@ public:
/** /**
* @brief If Value() pushes a ShaderJob, this is the function that will process them. * @brief If Value() pushes a ShaderJob, this is the function that will process them.
*/ */
virtual void ProcessSamples(const NodeValueRow &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const; virtual void ProcessSamples(const NodeValueRow &values, const SampleBuffer &input, SampleBuffer &output, int index) const;
/** /**
* @brief If Value() pushes a GenerateJob, override this function for the image to create * @brief If Value() pushes a GenerateJob, override this function for the image to create
+2 -2
View File
@@ -400,7 +400,7 @@ void NodeTraverser::ResolveJobs(NodeValue &val, const TimeRange &range)
} else if (job.type() == Track::kAudio) { } else if (job.type() == Track::kAudio) {
SampleBufferPtr buffer = CreateSampleBuffer(GetCacheAudioParams(), range.length()); SampleBuffer buffer = CreateSampleBuffer(GetCacheAudioParams(), range.length());
ProcessAudioFootage(buffer, job, range); ProcessAudioFootage(buffer, job, range);
val.set_value(buffer); val.set_value(buffer);
@@ -409,7 +409,7 @@ void NodeTraverser::ResolveJobs(NodeValue &val, const TimeRange &range)
} else if (val.canConvert<SampleJob>()) { } else if (val.canConvert<SampleJob>()) {
SampleJob job = val.value<SampleJob>(); SampleJob job = val.value<SampleJob>();
SampleBufferPtr output_buffer = CreateSampleBuffer(job.samples()->audio_params(), job.samples()->sample_count()); SampleBuffer output_buffer = CreateSampleBuffer(job.samples().audio_params(), job.samples().sample_count());
ProcessSamples(output_buffer, val.source(), range, job); ProcessSamples(output_buffer, val.source(), range, job);
val.set_value(QVariant::fromValue(output_buffer)); val.set_value(QVariant::fromValue(output_buffer));
+6 -6
View File
@@ -85,13 +85,13 @@ protected:
virtual void ProcessVideoFootage(TexturePtr destination, const FootageJob &stream, const rational &input_time){} virtual void ProcessVideoFootage(TexturePtr destination, const FootageJob &stream, const rational &input_time){}
virtual void ProcessAudioFootage(SampleBufferPtr destination, const FootageJob &stream, const TimeRange &input_time){} virtual void ProcessAudioFootage(SampleBuffer &destination, const FootageJob &stream, const TimeRange &input_time){}
virtual void ProcessShader(TexturePtr destination, const Node *node, const TimeRange &range, const ShaderJob& job){} virtual void ProcessShader(TexturePtr destination, const Node *node, const TimeRange &range, const ShaderJob& job){}
virtual void ProcessColorTransform(TexturePtr destination, const Node *node, const ColorTransformJob& job){} virtual void ProcessColorTransform(TexturePtr destination, const Node *node, const ColorTransformJob& job){}
virtual void ProcessSamples(SampleBufferPtr destination, const Node *node, const TimeRange &range, const SampleJob &job){} virtual void ProcessSamples(SampleBuffer &destination, const Node *node, const TimeRange &range, const SampleJob &job){}
virtual void ProcessFrameGeneration(TexturePtr destination, const Node *node, const GenerateJob& job){} virtual void ProcessFrameGeneration(TexturePtr destination, const Node *node, const GenerateJob& job){}
@@ -102,18 +102,18 @@ protected:
return CreateDummyTexture(p); return CreateDummyTexture(p);
} }
virtual SampleBufferPtr CreateSampleBuffer(const AudioParams &params, int sample_count) virtual SampleBuffer CreateSampleBuffer(const AudioParams &params, int sample_count)
{ {
// Return dummy by default // Return dummy by default
return SampleBuffer::Create(); return SampleBuffer();
} }
SampleBufferPtr CreateSampleBuffer(const AudioParams &params, const rational &length) SampleBuffer CreateSampleBuffer(const AudioParams &params, const rational &length)
{ {
if (params.is_valid()) { if (params.is_valid()) {
return CreateSampleBuffer(params, params.time_to_samples(length)); return CreateSampleBuffer(params, params.time_to_samples(length));
} else { } else {
return SampleBuffer::Create(); return SampleBuffer();
} }
} }
+1 -1
View File
@@ -307,7 +307,7 @@ public:
static void ValidateVectorString(QStringList* list, int count); static void ValidateVectorString(QStringList* list, int count);
TexturePtr toTexture() const { return value<TexturePtr>(); } TexturePtr toTexture() const { return value<TexturePtr>(); }
SampleBufferPtr toSamples() const { return value<SampleBufferPtr>(); } SampleBuffer toSamples() const { return value<SampleBuffer>(); }
bool toBool() const { return value<bool>(); } bool toBool() const { return value<bool>(); }
double toDouble() const { return value<double>(); } double toDouble() const { return value<double>(); }
int64_t toInt() const { return value<int64_t>(); } int64_t toInt() const { return value<int64_t>(); }
+4 -4
View File
@@ -58,7 +58,7 @@ void AudioPlaybackCache::SetParameters(const AudioParams &params)
emit ParametersChanged(); emit ParametersChanged();
} }
void AudioPlaybackCache::WritePCM(const TimeRange &range, const TimeRangeList &valid_ranges, SampleBufferPtr samples) void AudioPlaybackCache::WritePCM(const TimeRange &range, const TimeRangeList &valid_ranges, const SampleBuffer &samples)
{ {
// Ensure if we have enough segments to write this data, creating more if not // Ensure if we have enough segments to write this data, creating more if not
qint64 length_diff = params_.time_to_bytes_per_channel(range.out()) - playlist_.GetLength(); qint64 length_diff = params_.time_to_bytes_per_channel(range.out()) - playlist_.GetLength();
@@ -72,7 +72,7 @@ void AudioPlaybackCache::WritePCM(const TimeRange &range, const TimeRangeList &v
TimeRangeList ranges_we_validated; TimeRangeList ranges_we_validated;
// Calculate buffer size per channel // Calculate buffer size per channel
qint64 buffer_size_per_channel = samples ? samples->sample_count() * params_.bytes_per_sample_per_channel() : 0; qint64 buffer_size_per_channel = samples.sample_count() * params_.bytes_per_sample_per_channel();
// Write each valid range to the segments // Write each valid range to the segments
foreach (const TimeRange& r, valid_ranges) { foreach (const TimeRange& r, valid_ranges) {
@@ -114,7 +114,7 @@ void AudioPlaybackCache::WritePCM(const TimeRange &range, const TimeRangeList &v
if (possible_write_length > 0) { if (possible_write_length > 0) {
// Assume `samples` is valid if we're here, or else `buffer_size_per_channel` and // Assume `samples` is valid if we're here, or else `buffer_size_per_channel` and
// therefore `possible_write_length` will be 0. // therefore `possible_write_length` will be 0.
seg_file.write(reinterpret_cast<const char*>(samples->data(i)) + src_offset, possible_write_length); seg_file.write(reinterpret_cast<const char*>(samples.data(i)) + src_offset, possible_write_length);
} }
if (possible_write_length < total_write_length) { if (possible_write_length < total_write_length) {
@@ -167,7 +167,7 @@ void AudioPlaybackCache::WriteSilence(const TimeRange &range)
{ {
// WritePCM will automatically fill non-existent bytes with silence, so we just have to send // WritePCM will automatically fill non-existent bytes with silence, so we just have to send
// it an empty sample buffer // it an empty sample buffer
WritePCM(range, {range}, nullptr); WritePCM(range, {range}, SampleBuffer());
} }
void AudioPlaybackCache::ShiftEvent(const rational &from_in_time, const rational &to_in_time) void AudioPlaybackCache::ShiftEvent(const rational &from_in_time, const rational &to_in_time)
+1 -1
View File
@@ -66,7 +66,7 @@ public:
void SetParameters(const AudioParams& params); void SetParameters(const AudioParams& params);
void WritePCM(const TimeRange &range, const TimeRangeList &valid_ranges, SampleBufferPtr samples); void WritePCM(const TimeRange &range, const TimeRangeList &valid_ranges, const SampleBuffer &samples);
void WriteWaveform(const TimeRange &range, const TimeRangeList &valid_ranges, const AudioVisualWaveform *waveform); void WriteWaveform(const TimeRange &range, const TimeRangeList &valid_ranges, const AudioVisualWaveform *waveform);
+3 -4
View File
@@ -30,7 +30,6 @@ class SampleJob : public AcceleratedJob {
public: public:
SampleJob() SampleJob()
{ {
samples_ = nullptr;
} }
SampleJob(const NodeValue& value) SampleJob(const NodeValue& value)
@@ -43,18 +42,18 @@ public:
samples_ = row[from].toSamples(); samples_ = row[from].toSamples();
} }
SampleBufferPtr samples() const const SampleBuffer &samples() const
{ {
return samples_; return samples_;
} }
bool HasSamples() const bool HasSamples() const
{ {
return samples_ && samples_->is_allocated(); return samples_.is_allocated();
} }
private: private:
SampleBufferPtr samples_; SampleBuffer samples_;
}; };
+1 -1
View File
@@ -207,7 +207,7 @@ void PreviewAutoCacher::AudioRendered()
// WritePCM is tolerant to its buffer being null, it will just write silence instead // WritePCM is tolerant to its buffer being null, it will just write silence instead
viewer_node_->audio_playback_cache()->WritePCM(range, viewer_node_->audio_playback_cache()->WritePCM(range,
valid_ranges, valid_ranges,
watcher->Get().value<SampleBufferPtr>()); watcher->Get().value<SampleBuffer>());
} }
viewer_node_->audio_playback_cache()->WriteWaveform(range, valid_ranges, &waveform); viewer_node_->audio_playback_cache()->WriteWaveform(range, valid_ranges, &waveform);
+24 -28
View File
@@ -200,11 +200,11 @@ void RenderProcessor::Run()
ResolveJobs(sample_val, time); ResolveJobs(sample_val, time);
SampleBufferPtr samples = sample_val.toSamples(); SampleBuffer samples = sample_val.toSamples();
if (samples && ticket_->property("enablewaveforms").toBool()) { if (samples.is_allocated() && ticket_->property("enablewaveforms").toBool()) {
AudioVisualWaveform vis; AudioVisualWaveform vis;
vis.set_channel_count(samples->audio_params().channel_count()); vis.set_channel_count(samples.audio_params().channel_count());
vis.OverwriteSamples(samples, samples->audio_params().sample_rate()); vis.OverwriteSamples(samples, samples.audio_params().sample_rate());
ticket_->setProperty("waveform", QVariant::fromValue(vis)); ticket_->setProperty("waveform", QVariant::fromValue(vis));
} }
@@ -275,9 +275,8 @@ NodeValueTable RenderProcessor::GenerateBlockTable(const Track *track, const Tim
QVector<Block*> active_blocks = track->BlocksAtTimeRange(range); QVector<Block*> active_blocks = track->BlocksAtTimeRange(range);
// All these blocks will need to output to a buffer so we create one here // All these blocks will need to output to a buffer so we create one here
SampleBufferPtr block_range_buffer = SampleBuffer::CreateAllocated(audio_params, SampleBuffer block_range_buffer(audio_params, range.length());
audio_params.time_to_samples(range.length())); block_range_buffer.silence();
block_range_buffer->silence();
NodeValueTable merged_table; NodeValueTable merged_table;
@@ -292,10 +291,10 @@ NodeValueTable RenderProcessor::GenerateBlockTable(const Track *track, const Tim
// Destination buffer // Destination buffer
NodeValueTable table = GenerateTable(b, track->GetValueHintForInput(Track::kBlockInput, track->GetArrayIndexFromBlock(b)),Track::TransformRangeForBlock(b, range_for_block)); NodeValueTable table = GenerateTable(b, track->GetValueHintForInput(Track::kBlockInput, track->GetArrayIndexFromBlock(b)),Track::TransformRangeForBlock(b, range_for_block));
SampleBufferPtr samples_from_this_block = table.Take(NodeValue::kSamples).toSamples(); SampleBuffer samples_from_this_block = table.Take(NodeValue::kSamples).toSamples();
ClipBlock *clip_cast = dynamic_cast<ClipBlock*>(b); ClipBlock *clip_cast = dynamic_cast<ClipBlock*>(b);
if (samples_from_this_block) { if (samples_from_this_block.is_allocated()) {
// If this is a clip, we might have extra speed/reverse information // If this is a clip, we might have extra speed/reverse information
if (clip_cast) { if (clip_cast) {
double speed_value = clip_cast->speed(); double speed_value = clip_cast->speed();
@@ -303,12 +302,12 @@ NodeValueTable RenderProcessor::GenerateBlockTable(const Track *track, const Tim
if (qIsNull(speed_value)) { if (qIsNull(speed_value)) {
// Just silence, don't think there's any other practical application of 0 speed audio // Just silence, don't think there's any other practical application of 0 speed audio
samples_from_this_block->silence(); samples_from_this_block.silence();
} else if (!qFuzzyCompare(speed_value, 1.0)) { } else if (!qFuzzyCompare(speed_value, 1.0)) {
if (clip_cast->maintain_audio_pitch()) { if (clip_cast->maintain_audio_pitch()) {
AudioProcessor processor; AudioProcessor processor;
if (processor.Open(samples_from_this_block->audio_params(), samples_from_this_block->audio_params(), speed_value)) { if (processor.Open(samples_from_this_block.audio_params(), samples_from_this_block.audio_params(), speed_value)) {
AudioProcessor::Buffer out; AudioProcessor::Buffer out;
// FIXME: This is not the best way to do this, the TempoProcessor works best // FIXME: This is not the best way to do this, the TempoProcessor works best
@@ -317,7 +316,7 @@ NodeValueTable RenderProcessor::GenerateBlockTable(const Track *track, const Tim
// well on export (assuming audio is all generated at once on export), but // well on export (assuming audio is all generated at once on export), but
// users may hear clicks and pops in the audio during preview due to this // users may hear clicks and pops in the audio during preview due to this
// approach. // approach.
int r = processor.Convert(samples_from_this_block->to_raw_ptrs(), samples_from_this_block->sample_count(), nullptr); int r = processor.Convert(samples_from_this_block.to_raw_ptrs().data(), samples_from_this_block.sample_count(), nullptr);
if (r < 0) { if (r < 0) {
qCritical() << "Failed to change tempo of audio:" << r; qCritical() << "Failed to change tempo of audio:" << r;
@@ -327,16 +326,13 @@ NodeValueTable RenderProcessor::GenerateBlockTable(const Track *track, const Tim
processor.Convert(nullptr, 0, &out); processor.Convert(nullptr, 0, &out);
if (!out.empty()) { if (!out.empty()) {
int nb_samples = out.front().size() * samples_from_this_block->audio_params().bytes_per_sample_per_channel(); int nb_samples = out.front().size() * samples_from_this_block.audio_params().bytes_per_sample_per_channel();
if (nb_samples) { if (nb_samples) {
SampleBufferPtr new_samples = SampleBuffer::Create(); SampleBuffer new_samples(samples_from_this_block.audio_params(), nb_samples);
new_samples->set_audio_params(samples_from_this_block->audio_params());
new_samples->set_sample_count(nb_samples);
new_samples->allocate();
for (int i=0; i<out.size(); i++) { for (int i=0; i<out.size(); i++) {
memcpy(new_samples->data(i), out[i].data(), out[i].size()); memcpy(new_samples.data(i), out[i].data(), out[i].size());
} }
samples_from_this_block = new_samples; samples_from_this_block = new_samples;
@@ -346,20 +342,20 @@ NodeValueTable RenderProcessor::GenerateBlockTable(const Track *track, const Tim
} }
} else { } else {
// Multiply time // Multiply time
samples_from_this_block->speed(speed_value); samples_from_this_block.speed(speed_value);
} }
} }
if (reversed) { if (reversed) {
samples_from_this_block->reverse(); samples_from_this_block.reverse();
} }
} }
int copy_length = qMin(max_dest_sz, samples_from_this_block->sample_count()); int copy_length = qMin(max_dest_sz, samples_from_this_block.sample_count());
// Copy samples into destination buffer // Copy samples into destination buffer
for (int i=0; i<samples_from_this_block->audio_params().channel_count(); i++) { for (int i=0; i<samples_from_this_block.audio_params().channel_count(); i++) {
block_range_buffer->set(i, samples_from_this_block->data(i), destination_offset, copy_length); block_range_buffer.set(i, samples_from_this_block.data(i), destination_offset, copy_length);
} }
NodeValueTable::Merge({merged_table, table}); NodeValueTable::Merge({merged_table, table});
@@ -372,7 +368,7 @@ NodeValueTable RenderProcessor::GenerateBlockTable(const Track *track, const Tim
waveform_info.block = clip_cast; waveform_info.block = clip_cast;
waveform_info.range = range_for_block - b->in(); waveform_info.range = range_for_block - b->in();
if (!(waveform_info.silence = !samples_from_this_block.get())) { if (!(waveform_info.silence = !samples_from_this_block.is_allocated())) {
// Generate a visual waveform from the samples acquired from this block // Generate a visual waveform from the samples acquired from this block
AudioVisualWaveform visual_waveform; AudioVisualWaveform visual_waveform;
visual_waveform.set_channel_count(audio_params.channel_count()); visual_waveform.set_channel_count(audio_params.channel_count());
@@ -483,7 +479,7 @@ void RenderProcessor::ProcessVideoFootage(TexturePtr destination, const FootageJ
} }
} }
void RenderProcessor::ProcessAudioFootage(SampleBufferPtr destination, const FootageJob &stream, const TimeRange &input_time) void RenderProcessor::ProcessAudioFootage(SampleBuffer &destination, const FootageJob &stream, const TimeRange &input_time)
{ {
DecoderPtr decoder = ResolveDecoderFromInput(stream.decoder(), Decoder::CodecStream(stream.filename(), stream.audio_params().stream_index())); DecoderPtr decoder = ResolveDecoderFromInput(stream.decoder(), Decoder::CodecStream(stream.filename(), stream.audio_params().stream_index()));
@@ -526,9 +522,9 @@ void RenderProcessor::ProcessShader(TexturePtr destination, const Node *node, co
render_ctx_->BlitToTexture(shader, job, destination.get()); render_ctx_->BlitToTexture(shader, job, destination.get());
} }
void RenderProcessor::ProcessSamples(SampleBufferPtr destination, const Node *node, const TimeRange &range, const SampleJob &job) void RenderProcessor::ProcessSamples(SampleBuffer &destination, const Node *node, const TimeRange &range, const SampleJob &job)
{ {
if (!job.samples() || !job.samples()->is_allocated()) { if (!job.samples().is_allocated()) {
return; return;
} }
@@ -536,7 +532,7 @@ void RenderProcessor::ProcessSamples(SampleBufferPtr destination, const Node *no
const AudioParams& audio_params = GetCacheAudioParams(); const AudioParams& audio_params = GetCacheAudioParams();
for (int i=0;i<job.samples()->sample_count();i++) { for (int i=0;i<job.samples().sample_count();i++) {
// Calculate the exact rational time at this sample // Calculate the exact rational time at this sample
double sample_to_second = static_cast<double>(i) / static_cast<double>(audio_params.sample_rate()); double sample_to_second = static_cast<double>(i) / static_cast<double>(audio_params.sample_rate());
+4 -4
View File
@@ -46,11 +46,11 @@ protected:
virtual void ProcessVideoFootage(TexturePtr destination, const FootageJob &stream, const rational &input_time) override; virtual void ProcessVideoFootage(TexturePtr destination, const FootageJob &stream, const rational &input_time) override;
virtual void ProcessAudioFootage(SampleBufferPtr destination, const FootageJob &stream, const TimeRange &input_time) override; virtual void ProcessAudioFootage(SampleBuffer &destination, const FootageJob &stream, const TimeRange &input_time) override;
virtual void ProcessShader(TexturePtr destination, const Node *node, const TimeRange &range, const ShaderJob& job) override; virtual void ProcessShader(TexturePtr destination, const Node *node, const TimeRange &range, const ShaderJob& job) override;
virtual void ProcessSamples(SampleBufferPtr destination, const Node *node, const TimeRange &range, const SampleJob &job) override; virtual void ProcessSamples(SampleBuffer &destination, const Node *node, const TimeRange &range, const SampleJob &job) override;
virtual void ProcessColorTransform(TexturePtr destination, const Node *node, const ColorTransformJob& job) override; virtual void ProcessColorTransform(TexturePtr destination, const Node *node, const ColorTransformJob& job) override;
@@ -63,9 +63,9 @@ protected:
return render_ctx_->CreateTexture(p); return render_ctx_->CreateTexture(p);
} }
virtual SampleBufferPtr CreateSampleBuffer(const AudioParams &params, int sample_count) override virtual SampleBuffer CreateSampleBuffer(const AudioParams &params, int sample_count) override
{ {
return SampleBuffer::CreateAllocated(params, sample_count); return SampleBuffer(params, sample_count);
} }
virtual void ConvertToReferenceSpace(TexturePtr destination, TexturePtr source, const QString &input_cs) override; virtual void ConvertToReferenceSpace(TexturePtr destination, TexturePtr source, const QString &input_cs) override;
+3 -3
View File
@@ -192,7 +192,7 @@ bool ExportTask::FrameDownloaded(FramePtr f, const QByteArray &hash, const QVect
return true; return true;
} }
bool ExportTask::AudioDownloaded(const TimeRange &range, SampleBufferPtr samples) bool ExportTask::AudioDownloaded(const TimeRange &range, const SampleBuffer &samples)
{ {
TimeRange adjusted_range = range; TimeRange adjusted_range = range;
@@ -221,7 +221,7 @@ bool ExportTask::EncodeSubtitle(const SubtitleBlock *sub)
} }
} }
bool ExportTask::WriteAudioLoop(const TimeRange& time, SampleBufferPtr samples) bool ExportTask::WriteAudioLoop(const TimeRange& time, const SampleBuffer &samples)
{ {
if (!encoder_->WriteAudio(samples)) { if (!encoder_->WriteAudio(samples)) {
SetError(encoder_->GetError()); SetError(encoder_->GetError());
@@ -232,7 +232,7 @@ bool ExportTask::WriteAudioLoop(const TimeRange& time, SampleBufferPtr samples)
for (auto it=audio_map_.begin(); it!=audio_map_.end(); it++) { for (auto it=audio_map_.begin(); it!=audio_map_.end(); it++) {
TimeRange t = it.key(); TimeRange t = it.key();
SampleBufferPtr s = it.value(); SampleBuffer s = it.value();
if (t.in() == audio_time_) { if (t.in() == audio_time_) {
// Erase from audio map since we're just about to write it // Erase from audio map since we're just about to write it
+3 -3
View File
@@ -40,7 +40,7 @@ protected:
virtual bool FrameDownloaded(FramePtr frame, const QByteArray& hash, const QVector<rational>& times) override; virtual bool FrameDownloaded(FramePtr frame, const QByteArray& hash, const QVector<rational>& times) override;
virtual bool AudioDownloaded(const TimeRange& range, SampleBufferPtr samples) override; virtual bool AudioDownloaded(const TimeRange& range, const SampleBuffer &samples) override;
virtual bool EncodeSubtitle(const SubtitleBlock *sub) override; virtual bool EncodeSubtitle(const SubtitleBlock *sub) override;
@@ -50,11 +50,11 @@ protected:
} }
private: private:
bool WriteAudioLoop(const TimeRange &time, SampleBufferPtr samples); bool WriteAudioLoop(const TimeRange &time, const SampleBuffer &samples);
QHash<rational, FramePtr> time_map_; QHash<rational, FramePtr> time_map_;
QHash<TimeRange, SampleBufferPtr> audio_map_; QHash<TimeRange, SampleBuffer> audio_map_;
ColorManager* color_manager_; ColorManager* color_manager_;
+1 -1
View File
@@ -97,7 +97,7 @@ bool PreCacheTask::FrameDownloaded(FramePtr frame, const QByteArray &hash, const
return true; return true;
} }
bool PreCacheTask::AudioDownloaded(const TimeRange &range, SampleBufferPtr samples) bool PreCacheTask::AudioDownloaded(const TimeRange &range, const SampleBuffer &samples)
{ {
// Pre-cache doesn't cache any audio // Pre-cache doesn't cache any audio
+1 -1
View File
@@ -40,7 +40,7 @@ protected:
virtual bool FrameDownloaded(FramePtr frame, const QByteArray& hash, const QVector<rational>& times) override; virtual bool FrameDownloaded(FramePtr frame, const QByteArray& hash, const QVector<rational>& times) override;
virtual bool AudioDownloaded(const TimeRange& range, SampleBufferPtr samples) override; virtual bool AudioDownloaded(const TimeRange& range, const SampleBuffer &samples) override;
private: private:
Project* project_; Project* project_;
+1 -1
View File
@@ -195,7 +195,7 @@ bool RenderTask::Render(ColorManager* manager,
TimeRange range = watcher->property("range").value<TimeRange>(); TimeRange range = watcher->property("range").value<TimeRange>();
if (!AudioDownloaded(range, watcher->Get().value<SampleBufferPtr>())) { if (!AudioDownloaded(range, watcher->Get().value<SampleBuffer>())) {
result = false; result = false;
} }
+1 -1
View File
@@ -53,7 +53,7 @@ protected:
virtual bool FrameDownloaded(FramePtr frame, const QByteArray& hash, const QVector<rational>& times) = 0; virtual bool FrameDownloaded(FramePtr frame, const QByteArray& hash, const QVector<rational>& times) = 0;
virtual bool AudioDownloaded(const TimeRange& range, SampleBufferPtr samples) = 0; virtual bool AudioDownloaded(const TimeRange& range, const SampleBuffer &samples) = 0;
virtual bool EncodeSubtitle(const SubtitleBlock *subtitle); virtual bool EncodeSubtitle(const SubtitleBlock *subtitle);
+2 -2
View File
@@ -75,7 +75,7 @@ void AudioMonitor::Stop()
// loop will stop itself since file_ and waveform_ are null. // loop will stop itself since file_ and waveform_ are null.
} }
void AudioMonitor::PushSampleBuffer(SampleBufferPtr d) void AudioMonitor::PushSampleBuffer(const SampleBuffer &d)
{ {
if (!params_.channel_count()) { if (!params_.channel_count()) {
return; return;
@@ -83,7 +83,7 @@ void AudioMonitor::PushSampleBuffer(SampleBufferPtr d)
QVector<double> v(params_.channel_count(), 0); QVector<double> v(params_.channel_count(), 0);
AudioVisualWaveform::Sample summed = AudioVisualWaveform::SumSamples(d, 0, d->sample_count()); AudioVisualWaveform::Sample summed = AudioVisualWaveform::SumSamples(d, 0, d.sample_count());
AudioVisualWaveformSampleToInternalValues(summed, v); AudioVisualWaveformSampleToInternalValues(summed, v);
+2 -2
View File
@@ -59,7 +59,7 @@ public:
} }
} }
static void PushSampleBufferOnAll(SampleBufferPtr d) static void PushSampleBufferOnAll(const SampleBuffer &d)
{ {
foreach (AudioMonitor *m, instances_) { foreach (AudioMonitor *m, instances_) {
m->PushSampleBuffer(d); m->PushSampleBuffer(d);
@@ -71,7 +71,7 @@ public slots:
void Stop(); void Stop();
void PushSampleBuffer(SampleBufferPtr samples); void PushSampleBuffer(const SampleBuffer &samples);
void StartWaveform(const AudioVisualWaveform *waveform, const rational& start, int playback_speed); void StartWaveform(const AudioVisualWaveform *waveform, const rational& start, int playback_speed);
+8 -7
View File
@@ -511,16 +511,16 @@ void ViewerWidget::ReceivedAudioBufferForPlayback()
audio_playback_queue_.pop_front(); audio_playback_queue_.pop_front();
if (watcher->HasResult()) { if (watcher->HasResult()) {
SampleBufferPtr samples = watcher->Get().value<SampleBufferPtr>(); SampleBuffer samples = watcher->Get().value<SampleBuffer>();
if (samples) { if (samples.is_allocated()) {
// If the samples must be reversed, reverse them now // If the samples must be reversed, reverse them now
if (playback_speed_ < 0) { if (playback_speed_ < 0) {
samples->reverse(); samples.reverse();
} }
// Convert to packed data for audio output // Convert to packed data for audio output
AudioProcessor::Buffer buf; AudioProcessor::Buffer buf;
int r = audio_processor_.Convert(samples->to_raw_ptrs(), samples->sample_count(), &buf); int r = audio_processor_.Convert(samples.to_raw_ptrs().data(), samples.sample_count(), &buf);
// TempoProcessor may have emptied the array // TempoProcessor may have emptied the array
if (r >= 0) { if (r >= 0) {
@@ -556,8 +556,9 @@ void ViewerWidget::ReceivedAudioBufferForScrubbing()
RenderTicketWatcher *watcher = static_cast<RenderTicketWatcher *>(sender()); RenderTicketWatcher *watcher = static_cast<RenderTicketWatcher *>(sender());
if (watcher->HasResult()) { if (watcher->HasResult()) {
if (SampleBufferPtr samples = watcher->Get().value<SampleBufferPtr>()) { SampleBuffer samples = watcher->Get().value<SampleBuffer>();
if (samples->audio_params().channel_count() > 0) { if (samples.is_allocated()) {
if (samples.audio_params().channel_count() > 0) {
/* Fade code /* Fade code
const int kFadeSz = qMin(200, samples->sample_count()/4); const int kFadeSz = qMin(200, samples->sample_count()/4);
for (int i=0; i<kFadeSz; i++) { for (int i=0; i<kFadeSz; i++) {
@@ -567,7 +568,7 @@ void ViewerWidget::ReceivedAudioBufferForScrubbing()
}*/ }*/
AudioProcessor::Buffer buf; AudioProcessor::Buffer buf;
int r = audio_processor_.Convert(samples->to_raw_ptrs(), samples->sample_count(), &buf); int r = audio_processor_.Convert(samples.to_raw_ptrs().data(), samples.sample_count(), &buf);
if (r >= 0) { if (r >= 0) {
if (!buf.empty()) { if (!buf.empty()) {