fixed 32-bit integer overflow on long audio
This commit is contained in:
@@ -33,9 +33,5 @@ set(OLIVE_SOURCES
|
||||
codec/frame.h
|
||||
codec/samplebuffer.cpp
|
||||
codec/samplebuffer.h
|
||||
codec/waveinput.cpp
|
||||
codec/waveinput.h
|
||||
codec/waveoutput.cpp
|
||||
codec/waveoutput.h
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
@@ -57,19 +57,13 @@ ConformManager::Conform ConformManager::GetConformState(const QString &decoder_i
|
||||
|
||||
QString ConformManager::GetConformedFilename(const QString &cache_path, const Decoder::CodecStream &stream, const AudioParams ¶ms)
|
||||
{
|
||||
QString index_fn = QStringLiteral("%1.%2:%3").arg(FileFunctions::GetUniqueFileIdentifier(stream.filename()),
|
||||
QString::number(stream.stream()));
|
||||
QString index_fn = QStringLiteral("%1-%2.%3.%4.%5.pcm").arg(FileFunctions::GetUniqueFileIdentifier(stream.filename()),
|
||||
QString::number(stream.stream()),
|
||||
QString::number(params.sample_rate()),
|
||||
QString::number(params.format()),
|
||||
QString::number(params.channel_layout()));
|
||||
|
||||
index_fn = QDir(cache_path).filePath(index_fn);
|
||||
|
||||
index_fn.append('.');
|
||||
index_fn.append(QString::number(params.sample_rate()));
|
||||
index_fn.append('.');
|
||||
index_fn.append(QString::number(params.format()));
|
||||
index_fn.append('.');
|
||||
index_fn.append(QString::number(params.channel_layout()));
|
||||
|
||||
return index_fn;
|
||||
return QDir(cache_path).filePath(index_fn);
|
||||
}
|
||||
|
||||
void ConformManager::ConformTaskFinished(Task *task, bool succeeded)
|
||||
|
||||
+11
-14
@@ -25,8 +25,6 @@
|
||||
|
||||
#include "codec/ffmpeg/ffmpegdecoder.h"
|
||||
#include "codec/oiio/oiiodecoder.h"
|
||||
#include "codec/waveinput.h"
|
||||
#include "codec/waveoutput.h"
|
||||
#include "common/ffmpegutils.h"
|
||||
#include "common/filefunctions.h"
|
||||
#include "common/timecodefunctions.h"
|
||||
@@ -129,7 +127,7 @@ Decoder::RetrieveAudioData Decoder::RetrieveAudio(const TimeRange &range, const
|
||||
}
|
||||
|
||||
// See if we got the conform
|
||||
SampleBufferPtr out_buffer = RetrieveAudioFromConform(conform.filename, range, loop_mode);
|
||||
SampleBufferPtr out_buffer = RetrieveAudioFromConform(conform.filename, range, loop_mode, params);
|
||||
|
||||
return {kOK, out_buffer, nullptr};
|
||||
}
|
||||
@@ -265,13 +263,11 @@ bool Decoder::ConformAudioInternal(const QString& filename, const AudioParams &p
|
||||
return false;
|
||||
}
|
||||
|
||||
SampleBufferPtr Decoder::RetrieveAudioFromConform(const QString &conform_filename, const TimeRange& range, Footage::LoopMode loop_mode)
|
||||
SampleBufferPtr Decoder::RetrieveAudioFromConform(const QString &conform_filename, const TimeRange& range, Footage::LoopMode loop_mode, const AudioParams &input_params)
|
||||
{
|
||||
WaveInput input(conform_filename);
|
||||
|
||||
if (input.open()) {
|
||||
const AudioParams& input_params = input.params();
|
||||
QFile input(conform_filename);
|
||||
|
||||
if (input.open(QFile::ReadOnly)) {
|
||||
QByteArray packed_data(input_params.time_to_bytes(range.length()), Qt::Uninitialized);
|
||||
|
||||
qint64 read_index = input_params.time_to_bytes(range.in());
|
||||
@@ -279,12 +275,12 @@ SampleBufferPtr Decoder::RetrieveAudioFromConform(const QString &conform_filenam
|
||||
|
||||
while (write_index < packed_data.size()) {
|
||||
if (loop_mode == Footage::kLoopModeLoop) {
|
||||
while (read_index >= input.data_length()) {
|
||||
read_index -= input.data_length();
|
||||
while (read_index >= input.size()) {
|
||||
read_index -= input.size();
|
||||
}
|
||||
|
||||
while (read_index < 0) {
|
||||
read_index += input.data_length();
|
||||
read_index += input.size();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,13 +290,14 @@ SampleBufferPtr Decoder::RetrieveAudioFromConform(const QString &conform_filenam
|
||||
// Reading before 0, write silence here until audio data would actually start
|
||||
write_count = qMin(-read_index, qint64(packed_data.size()));
|
||||
memset(packed_data.data() + write_index, 0, write_count);
|
||||
} else if (read_index >= input.data_length()) {
|
||||
} else if (read_index >= input.size()) {
|
||||
// Reading after data length, write silence until the end of the buffer
|
||||
write_count = packed_data.size() - write_index;
|
||||
memset(packed_data.data() + write_index, 0, write_count);
|
||||
} else {
|
||||
write_count = qMin(input.data_length() - read_index, packed_data.size() - write_index);
|
||||
input.read(read_index, packed_data.data() + write_index, write_count);
|
||||
write_count = qMin(input.size() - read_index, packed_data.size() - write_index);
|
||||
input.seek(read_index);
|
||||
input.read(packed_data.data() + write_index, write_count);
|
||||
}
|
||||
|
||||
read_index += write_count;
|
||||
|
||||
+1
-2
@@ -33,7 +33,6 @@ extern "C" {
|
||||
|
||||
#include "codec/frame.h"
|
||||
#include "codec/samplebuffer.h"
|
||||
#include "codec/waveoutput.h"
|
||||
#include "common/rational.h"
|
||||
#include "node/project/footage/footage.h"
|
||||
#include "node/project/footage/footagedescription.h"
|
||||
@@ -313,7 +312,7 @@ signals:
|
||||
private:
|
||||
void UpdateLastAccessed();
|
||||
|
||||
SampleBufferPtr RetrieveAudioFromConform(const QString& conform_filename, const TimeRange &range, Footage::LoopMode loop_mode);
|
||||
SampleBufferPtr RetrieveAudioFromConform(const QString& conform_filename, const TimeRange &range, Footage::LoopMode loop_mode, const AudioParams ¶ms);
|
||||
|
||||
CodecStream stream_;
|
||||
|
||||
|
||||
@@ -38,7 +38,6 @@ extern "C" {
|
||||
#include <QThread>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
|
||||
#include "codec/waveinput.h"
|
||||
#include "common/define.h"
|
||||
#include "common/ffmpegutils.h"
|
||||
#include "common/filefunctions.h"
|
||||
@@ -465,7 +464,7 @@ bool FFmpegDecoder::ConformAudioInternal(const QString &filename, const AudioPar
|
||||
|
||||
swr_init(resampler);
|
||||
|
||||
WaveOutput wave_out(filename, params);
|
||||
QFile wave_out(filename);
|
||||
|
||||
AVPacket* pkt = av_packet_alloc();
|
||||
AVFrame* frame = av_frame_alloc();
|
||||
@@ -473,7 +472,7 @@ bool FFmpegDecoder::ConformAudioInternal(const QString &filename, const AudioPar
|
||||
|
||||
bool success = false;
|
||||
|
||||
if (wave_out.open()) {
|
||||
if (wave_out.open(QFile::WriteOnly)) {
|
||||
while (true) {
|
||||
// Check if we have a `cancelled` ptr and its value
|
||||
if (cancelled && *cancelled) {
|
||||
|
||||
@@ -37,7 +37,6 @@ extern "C" {
|
||||
#include <QWaitCondition>
|
||||
|
||||
#include "codec/decoder.h"
|
||||
#include "codec/waveoutput.h"
|
||||
#include "ffmpegframepool.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
@@ -1,244 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2021 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "waveinput.h"
|
||||
|
||||
extern "C" {
|
||||
#include <libavcodec/avcodec.h>
|
||||
}
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QtMath>
|
||||
|
||||
namespace olive {
|
||||
|
||||
WaveInput::WaveInput(const QString &f) :
|
||||
file_(f)
|
||||
{
|
||||
}
|
||||
|
||||
WaveInput::~WaveInput()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
bool WaveInput::open()
|
||||
{
|
||||
if (!file_.open(QFile::ReadOnly)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (file_.read(4) != "RIFF") {
|
||||
close();
|
||||
qCritical() << "No RIFF found";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip filesize bytes
|
||||
file_.seek(file_.pos() + 4);
|
||||
|
||||
if (file_.read(4) != "WAVE") {
|
||||
close();
|
||||
qCritical() << "No WAVE found";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find fmt_ section
|
||||
if (!find_str(&file_, "fmt ")) {
|
||||
close();
|
||||
qCritical() << "No fmt found";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip fmt_ section size
|
||||
file_.seek(file_.pos()+4);
|
||||
|
||||
// Create data stream for reading bytes into types
|
||||
QDataStream data_stream(&file_);
|
||||
data_stream.setByteOrder(QDataStream::LittleEndian);
|
||||
|
||||
// Read data type
|
||||
uint16_t data_type;
|
||||
data_stream >> data_type;
|
||||
|
||||
bool data_is_float;
|
||||
switch (data_type) {
|
||||
case 1: // PCM Integer
|
||||
data_is_float = false;
|
||||
break;
|
||||
case 3:
|
||||
data_is_float = true;
|
||||
break;
|
||||
default:
|
||||
// If it's neither float nor int, we can't work with this file
|
||||
close();
|
||||
qCritical() << "Invalid WAV type" << data_type;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read number of channels
|
||||
uint16_t channel_count;
|
||||
data_stream >> channel_count;
|
||||
|
||||
uint64_t channel_layout = static_cast<uint64_t>(av_get_default_channel_layout(channel_count));
|
||||
|
||||
int32_t sample_rate;
|
||||
data_stream >> sample_rate;
|
||||
|
||||
// Skip bytes per second value and bytes per sample value
|
||||
file_.seek(file_.pos() + 6);
|
||||
|
||||
uint16_t bits_per_sample;
|
||||
data_stream >> bits_per_sample;
|
||||
|
||||
AudioParams::Format format;
|
||||
|
||||
switch (bits_per_sample) {
|
||||
case 8:
|
||||
format = AudioParams::kFormatUnsigned8;
|
||||
break;
|
||||
case 16:
|
||||
format = AudioParams::kFormatSigned16;
|
||||
break;
|
||||
case 32:
|
||||
if (data_is_float) {
|
||||
format = AudioParams::kFormatFloat32;
|
||||
} else {
|
||||
format = AudioParams::kFormatSigned32;
|
||||
}
|
||||
break;
|
||||
case 64:
|
||||
if (data_is_float) {
|
||||
format = AudioParams::kFormatFloat64;
|
||||
} else {
|
||||
format = AudioParams::kFormatSigned64;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// We don't know this format...
|
||||
close();
|
||||
qCritical() << "Invalid format found" << bits_per_sample;
|
||||
return false;
|
||||
}
|
||||
|
||||
// We're good to go!
|
||||
params_ = AudioParams(sample_rate, channel_layout, format);
|
||||
|
||||
if (!find_str(&file_, "data")) {
|
||||
close();
|
||||
qCritical() << "No data tag found";
|
||||
return false;
|
||||
}
|
||||
|
||||
data_stream >> data_size_;
|
||||
data_position_ = file_.pos();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WaveInput::is_open() const
|
||||
{
|
||||
return file_.isOpen();
|
||||
}
|
||||
|
||||
QByteArray WaveInput::read(qint64 length)
|
||||
{
|
||||
if (!is_open()) {
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
return file_.read(qMin(calculate_max_read(), length));
|
||||
}
|
||||
|
||||
QByteArray WaveInput::read(qint64 offset, qint64 length)
|
||||
{
|
||||
if (!is_open()) {
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
seek(offset);
|
||||
return file_.read(qMin(calculate_max_read(), length));
|
||||
}
|
||||
|
||||
qint64 WaveInput::read(qint64 offset, char *buffer, qint64 length)
|
||||
{
|
||||
if (!is_open()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Q_ASSERT(length > 0);
|
||||
|
||||
seek(offset);
|
||||
return file_.read(buffer, qMin(calculate_max_read(), length));
|
||||
}
|
||||
|
||||
bool WaveInput::seek(qint64 pos)
|
||||
{
|
||||
return file_.seek(data_position_ + qMin(pos, qint64(data_size_)));
|
||||
}
|
||||
|
||||
bool WaveInput::at_end() const
|
||||
{
|
||||
return file_.pos() == (data_position_ + data_size_);
|
||||
}
|
||||
|
||||
const AudioParams &WaveInput::params() const
|
||||
{
|
||||
return params_;
|
||||
}
|
||||
|
||||
void WaveInput::close()
|
||||
{
|
||||
if (file_.isOpen()) {
|
||||
file_.close();
|
||||
}
|
||||
}
|
||||
|
||||
const quint32 &WaveInput::data_length() const
|
||||
{
|
||||
return data_size_;
|
||||
}
|
||||
|
||||
int WaveInput::sample_count() const
|
||||
{
|
||||
return params_.bytes_to_samples(data_size_);
|
||||
}
|
||||
|
||||
bool WaveInput::find_str(QFile *f, const char *str)
|
||||
{
|
||||
qint64 pos = f->pos();
|
||||
while (f->read(4) != str) {
|
||||
if (f->atEnd()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pos++;
|
||||
f->seek(pos);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
qint64 WaveInput::calculate_max_read() const
|
||||
{
|
||||
return data_size_ - (file_.pos() - data_position_ );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2021 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef WAVEINPUT_H
|
||||
#define WAVEINPUT_H
|
||||
|
||||
#include <QFile>
|
||||
|
||||
#include "render/audioparams.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class WaveInput
|
||||
{
|
||||
public:
|
||||
WaveInput(const QString& f);
|
||||
|
||||
~WaveInput();
|
||||
|
||||
DISABLE_COPY_MOVE(WaveInput)
|
||||
|
||||
bool open();
|
||||
|
||||
bool is_open() const;
|
||||
|
||||
QByteArray read(qint64 length);
|
||||
QByteArray read(qint64 offset, qint64 length);
|
||||
qint64 read(qint64 offset, char *buffer, qint64 length);
|
||||
|
||||
bool seek(qint64 pos);
|
||||
|
||||
bool at_end() const;
|
||||
|
||||
const AudioParams& params() const;
|
||||
|
||||
void close();
|
||||
|
||||
const quint32& data_length() const;
|
||||
|
||||
int sample_count() const;
|
||||
|
||||
private:
|
||||
bool find_str(QFile* f, const char* str);
|
||||
|
||||
qint64 calculate_max_read() const;
|
||||
|
||||
AudioParams params_;
|
||||
|
||||
QFile file_;
|
||||
|
||||
qint64 data_position_;
|
||||
|
||||
quint32 data_size_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // WAVEINPUT_H
|
||||
@@ -1,180 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2021 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "waveoutput.h"
|
||||
|
||||
#include "render/audioparams.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
const int16_t kWAVIntegerFormat = 1;
|
||||
const int16_t kWAVFloatFormat = 3;
|
||||
|
||||
WaveOutput::WaveOutput(const QString &f,
|
||||
const AudioParams& params) :
|
||||
file_(f),
|
||||
params_(params)
|
||||
{
|
||||
Q_ASSERT(params_.is_valid());
|
||||
}
|
||||
|
||||
WaveOutput::~WaveOutput()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
bool WaveOutput::open()
|
||||
{
|
||||
data_length_ = 0;
|
||||
|
||||
if (file_.open(QFile::WriteOnly)) {
|
||||
// RIFF header
|
||||
file_.write("RIFF");
|
||||
|
||||
// Total file size minus RIFF and this integer (minus 8 bytes, filled in later)
|
||||
write_int<int32_t>(&file_, 0);
|
||||
|
||||
// File type header
|
||||
file_.write("WAVE");
|
||||
|
||||
// Begin format descriptor chunk
|
||||
file_.write("fmt ");
|
||||
|
||||
// Format chunk size
|
||||
write_int<int32_t>(&file_, 16);
|
||||
|
||||
// Type of format
|
||||
switch (params_.format()) {
|
||||
case AudioParams::kFormatUnsigned8:
|
||||
case AudioParams::kFormatSigned16:
|
||||
case AudioParams::kFormatSigned32:
|
||||
case AudioParams::kFormatSigned64:
|
||||
write_int<int16_t>(&file_, kWAVIntegerFormat);
|
||||
break;
|
||||
case AudioParams::kFormatFloat32:
|
||||
case AudioParams::kFormatFloat64:
|
||||
write_int<int16_t>(&file_, kWAVFloatFormat);
|
||||
break;
|
||||
case AudioParams::kFormatInvalid:
|
||||
case AudioParams::kFormatCount:
|
||||
qWarning() << "Invalid sample format for WAVE audio";
|
||||
file_.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Number of channels
|
||||
write_int<int16_t>(&file_, static_cast<int16_t>(params_.channel_count()));
|
||||
|
||||
// Sample rate
|
||||
write_int<int32_t>(&file_, params_.sample_rate());
|
||||
|
||||
// Bytes per second
|
||||
write_int<int32_t>(&file_, params_.samples_to_bytes(params_.sample_rate()));
|
||||
|
||||
// Bytes per sample
|
||||
write_int<int16_t>(&file_, static_cast<int16_t>(params_.samples_to_bytes(1)));
|
||||
|
||||
// Bits per sample per channel
|
||||
write_int<int16_t>(&file_, static_cast<int16_t>(params_.bits_per_sample()));
|
||||
|
||||
// Data chunk header
|
||||
file_.write("data");
|
||||
|
||||
// Size of data chunk (filled in later)
|
||||
write_int<int32_t>(&file_, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void WaveOutput::write(const QByteArray &bytes)
|
||||
{
|
||||
if (file_.isOpen()) {
|
||||
file_.write(bytes);
|
||||
|
||||
data_length_ += bytes.size();
|
||||
}
|
||||
}
|
||||
|
||||
void WaveOutput::write(const char *bytes, int length)
|
||||
{
|
||||
if (file_.isOpen()) {
|
||||
file_.write(bytes, length);
|
||||
|
||||
data_length_ += length;
|
||||
}
|
||||
}
|
||||
|
||||
void WaveOutput::close()
|
||||
{
|
||||
if (file_.isOpen()) {
|
||||
|
||||
// Write file sizes
|
||||
file_.seek(4);
|
||||
write_int<int32_t>(&file_, data_length_ + 36);
|
||||
|
||||
file_.seek(40);
|
||||
write_int<int32_t>(&file_, data_length_);
|
||||
|
||||
file_.close();
|
||||
}
|
||||
}
|
||||
|
||||
const int& WaveOutput::data_length() const
|
||||
{
|
||||
return data_length_;
|
||||
}
|
||||
|
||||
const AudioParams &WaveOutput::params() const
|
||||
{
|
||||
return params_;
|
||||
}
|
||||
|
||||
void WaveOutput::switch_endianness(QByteArray& array)
|
||||
{
|
||||
int half_sz = array.size()/2;
|
||||
|
||||
for (int i=0;i<half_sz;i++) {
|
||||
int oppose_index = array.size() - i - 1;
|
||||
|
||||
char temp = array[i];
|
||||
array[i] = array[oppose_index];
|
||||
array[oppose_index] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void WaveOutput::write_int(QFile *file, T integer)
|
||||
{
|
||||
QByteArray bytes;
|
||||
bytes.resize(sizeof(T));
|
||||
memcpy(bytes.data(), &integer, static_cast<size_t>(bytes.size()));
|
||||
|
||||
// WAV expects little-endian, so if the integer is big endian we need to switch
|
||||
if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
|
||||
switch_endianness(bytes);
|
||||
}
|
||||
|
||||
file->write(bytes);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2021 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef WAVEAUDIO_H
|
||||
#define WAVEAUDIO_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QFile>
|
||||
|
||||
#include "render/audioparams.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class WaveOutput
|
||||
{
|
||||
public:
|
||||
WaveOutput(const QString& f,
|
||||
const AudioParams& params);
|
||||
|
||||
~WaveOutput();
|
||||
|
||||
DISABLE_COPY_MOVE(WaveOutput)
|
||||
|
||||
bool open();
|
||||
|
||||
void write(const QByteArray& bytes);
|
||||
void write(const char* bytes, int length);
|
||||
|
||||
void close();
|
||||
|
||||
const int& data_length() const;
|
||||
|
||||
const AudioParams& params() const;
|
||||
|
||||
private:
|
||||
template<typename T>
|
||||
void write_int(QFile* file, T integer);
|
||||
|
||||
void switch_endianness(QByteArray &array);
|
||||
|
||||
QFile file_;
|
||||
|
||||
AudioParams params_;
|
||||
|
||||
int data_length_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // WAVEAUDIO_H
|
||||
Reference in New Issue
Block a user