diff --git a/CMakeLists.txt b/CMakeLists.txt index 4040557..f640167 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -230,6 +230,7 @@ include_directories("${PROJECT_BINARY_DIR}") set(MODULES src/AudioFileReader.cpp + src/AudioLoader.cpp src/AudioProcessor.cpp src/BStdFile.cpp src/DurationCalculator.cpp @@ -246,6 +247,7 @@ set(MODULES src/Rgba.cpp src/SndFileAudioFileReader.cpp src/TimeUtil.cpp + src/VectorAudioFileReader.cpp src/WaveformBuffer.cpp src/WaveformColors.cpp src/WaveformGenerator.cpp diff --git a/src/AudioLoader.cpp b/src/AudioLoader.cpp new file mode 100644 index 0000000..9dafeb0 --- /dev/null +++ b/src/AudioLoader.cpp @@ -0,0 +1,81 @@ +//------------------------------------------------------------------------------ +// +// Copyright 2022 BBC Research and Development +// +// Author: Chris Needham +// +// This file is part of Audio Waveform Image Generator. +// +// Audio Waveform Image Generator 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. +// +// Audio Waveform Image Generator 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 +// Audio Waveform Image Generator. If not, see . +// +//------------------------------------------------------------------------------ + +#include "AudioLoader.h" + +#include "Log.h" + +#include + +//------------------------------------------------------------------------------ + +AudioLoader::AudioLoader() : + sample_rate_(0), + channels_(0) +{ +} + +//------------------------------------------------------------------------------ + +bool AudioLoader::init(int sample_rate, int channels, long /* frame_count */, int /* buffer_size */) +{ + sample_rate_ = sample_rate; + channels_ = channels; + + return true; +} + +//------------------------------------------------------------------------------ + +bool AudioLoader::shouldContinue() const +{ + return true; +} + +//------------------------------------------------------------------------------ + +bool AudioLoader::process(const short* input_buffer, int input_frame_count) +{ + for (int i = 0; i < input_frame_count * channels_; i++) { + audio_samples_.push_back(input_buffer[i]); + } + + return true; +} + +//------------------------------------------------------------------------------ + +void AudioLoader::done() +{ +} + +//------------------------------------------------------------------------------ + +double AudioLoader::getDuration() const +{ + const size_t frame_count = audio_samples_.size() / channels_; + + return static_cast(frame_count) / static_cast(sample_rate_); +} + +//------------------------------------------------------------------------------ diff --git a/src/AudioLoader.h b/src/AudioLoader.h new file mode 100644 index 0000000..50dc2d2 --- /dev/null +++ b/src/AudioLoader.h @@ -0,0 +1,72 @@ +//------------------------------------------------------------------------------ +// +// Copyright 2022 BBC Research and Development +// +// Author: Chris Needham +// +// This file is part of Audio Waveform Image Generator. +// +// Audio Waveform Image Generator 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. +// +// Audio Waveform Image Generator 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 +// Audio Waveform Image Generator. If not, see . +// +//------------------------------------------------------------------------------ + +#if !defined(INC_AUDIO_LOADER_H) +#define INC_AUDIO_LOADER_H + +//------------------------------------------------------------------------------ + +#include "AudioProcessor.h" + +#include + +//------------------------------------------------------------------------------ + +class AudioLoader : public AudioProcessor +{ + public: + AudioLoader(); + + virtual bool init( + int sample_rate, + int channels, + long frame_count, + int buffer_size + ); + + virtual bool shouldContinue() const; + + virtual bool process( + const short* input_buffer, + int input_frame_count + ); + + virtual void done(); + + double getDuration() const; + + const std::vector& getData() const { return audio_samples_; } + int getSampleRate() const { return sample_rate_; } + int getChannels() const { return channels_; } + + private: + int sample_rate_; + int channels_; + std::vector audio_samples_; +}; + +//------------------------------------------------------------------------------ + +#endif // #if !defined(INC_AUDIO_LOADER_H) + +//------------------------------------------------------------------------------ diff --git a/src/Mp3AudioFileReader.cpp b/src/Mp3AudioFileReader.cpp index 3669c8d..dfcd88a 100644 --- a/src/Mp3AudioFileReader.cpp +++ b/src/Mp3AudioFileReader.cpp @@ -1,6 +1,6 @@ //------------------------------------------------------------------------------ // -// Copyright 2013-2021 BBC Research and Development +// Copyright 2013-2022 BBC Research and Development // // Author: Chris Needham // @@ -327,7 +327,9 @@ Mp3AudioFileReader::Mp3AudioFileReader() : show_info_(true), file_(nullptr), close_(true), - file_size_(0) + file_size_(0), + sample_rate_(0), + frames_(0) { } @@ -408,7 +410,7 @@ static constexpr unsigned long fourCC(char a, char b, char c, char d) return (static_cast(a) << 24) | (static_cast(b) << 16) | (static_cast(c) << 8) | - static_cast(d); + static_cast(d); } //------------------------------------------------------------------------------ @@ -717,7 +719,10 @@ bool Mp3AudioFileReader::run(AudioProcessor& processor) break; } - progress_reporter.update(0, file_size_); + frames_ = 0; + sample_rate_ = sample_rate; + + progress_reporter.update(0.0, 0, file_size_); started = true; } @@ -767,10 +772,14 @@ bool Mp3AudioFileReader::run(AudioProcessor& processor) if (output_ptr == output_buffer_end) { long pos = ftell(file_); - progress_reporter.update(pos, file_size_); - const int frames = OUTPUT_BUFFER_SIZE / channels; + frames_ += frames; + + const double seconds = static_cast(frames_) / static_cast(sample_rate_); + + progress_reporter.update(seconds, pos, file_size_); + if (!processor.process(output_buffer, frames)) { status = STATUS_PROCESS_ERROR; break; @@ -787,7 +796,10 @@ bool Mp3AudioFileReader::run(AudioProcessor& processor) if (output_ptr != output_buffer && status != STATUS_PROCESS_ERROR) { int buffer_size = static_cast(output_ptr - output_buffer); - if (!processor.process(output_buffer, buffer_size / channels)) { + const int frames = buffer_size / channels; + frames_ += frames; + + if (!processor.process(output_buffer, frames)) { status = STATUS_PROCESS_ERROR; } } @@ -796,7 +808,10 @@ bool Mp3AudioFileReader::run(AudioProcessor& processor) if (status == STATUS_OK) { // Report 100% done. - progress_reporter.update(file_size_, file_size_); + + const double seconds = static_cast(frames_) / static_cast(sample_rate_); + + progress_reporter.update(seconds, file_size_, file_size_); char buffer[80]; diff --git a/src/Mp3AudioFileReader.h b/src/Mp3AudioFileReader.h index 2f8b3ce..09e466c 100644 --- a/src/Mp3AudioFileReader.h +++ b/src/Mp3AudioFileReader.h @@ -56,6 +56,8 @@ class Mp3AudioFileReader : public AudioFileReader FILE* file_; bool close_; long file_size_; + int sample_rate_; + int frames_; }; //------------------------------------------------------------------------------ diff --git a/src/OptionHandler.cpp b/src/OptionHandler.cpp index bcb56bd..cbdbd91 100644 --- a/src/OptionHandler.cpp +++ b/src/OptionHandler.cpp @@ -24,6 +24,7 @@ #include "OptionHandler.h" #include "Config.h" +#include "AudioLoader.h" #include "DurationCalculator.h" #include "Error.h" #include "FileFormat.h" @@ -34,6 +35,7 @@ #include "Options.h" #include "SndFileAudioFileReader.h" #include "Streams.h" +#include "VectorAudioFileReader.h" #include "WaveformBuffer.h" #include "WaveformColors.h" #include "WaveformGenerator.h" @@ -386,37 +388,73 @@ bool OptionHandler::renderWaveformImage( ); } else { - if (calculate_duration) { - auto result = getDuration(input_filename, input_format, !options.getQuiet()); + if (FileUtil::isStdioFilename(input_filename.c_str()) && + FileUtil::isStdinFifo() && + calculate_duration) { + std::unique_ptr audio_file_reader( + createAudioFileReader(input_filename, input_format) + ); - if (!result.first) { - // log(Error) << "Failed to get audio duration\n"; + if (!audio_file_reader->open(input_filename.string().c_str())) { return false; } - double duration = result.second; + AudioLoader loader; + + if (!audio_file_reader->run(loader)) { + return false; + } scale_factor.reset( - new DurationScaleFactor(0.0, duration, options.getImageWidth()) + new DurationScaleFactor(0.0, loader.getDuration(), options.getImageWidth()) ); - } - std::unique_ptr audio_file_reader( - createAudioFileReader(input_filename, input_format) - ); + const bool split_channels = options.getSplitChannels(); - if (!audio_file_reader->open(input_filename.string().c_str(), !calculate_duration)) { - return false; - } + WaveformGenerator processor(input_buffer, split_channels, *scale_factor); - const bool split_channels = options.getSplitChannels(); - WaveformGenerator processor(input_buffer, split_channels, *scale_factor); + VectorAudioFileReader reader(loader.getData(), loader.getSampleRate(), loader.getChannels()); + + if (!reader.run(processor)) { + return false; + } + + output_samples_per_pixel = input_buffer.getSamplesPerPixel(); - if (!audio_file_reader->run(processor)) { - return false; } + else { + if (calculate_duration) { + auto result = getDuration(input_filename, input_format, !options.getQuiet()); - output_samples_per_pixel = input_buffer.getSamplesPerPixel(); + if (!result.first) { + return false; + } + + double duration = result.second; + + scale_factor.reset( + new DurationScaleFactor(0.0, duration, options.getImageWidth()) + ); + } + + std::unique_ptr audio_file_reader( + createAudioFileReader(input_filename, input_format) + ); + + if (!audio_file_reader->open(input_filename.string().c_str(), !calculate_duration)) { + return false; + } + + const bool split_channels = options.getSplitChannels(); + + WaveformGenerator processor(input_buffer, split_channels, *scale_factor); + + if (!audio_file_reader->run(processor)) { + return false; + } + + output_samples_per_pixel = input_buffer.getSamplesPerPixel(); + } } WaveformBuffer output_buffer; diff --git a/src/ProgressReporter.cpp b/src/ProgressReporter.cpp index 6f3c70d..d72933d 100644 --- a/src/ProgressReporter.cpp +++ b/src/ProgressReporter.cpp @@ -22,51 +22,59 @@ //------------------------------------------------------------------------------ #include "ProgressReporter.h" +#include "Array.h" #include "FileUtil.h" #include "Log.h" +#include "TimeUtil.h" #include #include //------------------------------------------------------------------------------ -// If we're reading from a pipe, we may not know what the total duration is, -// so don't report progress in this case. - ProgressReporter::ProgressReporter() : - show_progress_(!FileUtil::isStdinFifo()), - percent_(-1) // Force first update to display 0% + percent_(-1), // Force first update to display 0% + seconds_(-1) { } //------------------------------------------------------------------------------ -void ProgressReporter::update(long long done, long long total) +void ProgressReporter::update(double seconds, long long done, long long total) { - if (!show_progress_) { - return; - } - - int percent; + if (total != 0) { + int percent; - if (total > 0) { - percent = static_cast(done * 100 / total); + if (total > 0) { + percent = static_cast(done * 100 / total); - if (percent < 0) { + if (percent < 0) { + percent = 0; + } + else if (percent > 100) { + percent = 100; + } + } + else { percent = 0; } - else if (percent > 100) { - percent = 100; + + if (percent != percent_) { + percent_ = percent; + + log(Info) << "\rDone: " << percent << "%" << std::flush; } } else { - percent = 0; - } + if (static_cast(seconds) != seconds_) { + seconds_ = static_cast(seconds); - if (percent != percent_) { - percent_ = percent; + char time[100]; - log(Info) << "\rDone: " << percent << "%" << std::flush; + TimeUtil::secondsToString(time, ARRAY_LENGTH(time), seconds_); + + log(Info) << "\rDone: " << time << std::flush; + } } } diff --git a/src/ProgressReporter.h b/src/ProgressReporter.h index 1723fb7..c470288 100644 --- a/src/ProgressReporter.h +++ b/src/ProgressReporter.h @@ -1,6 +1,6 @@ //------------------------------------------------------------------------------ // -// Copyright 2019 BBC Research and Development +// Copyright 2013-2022 BBC Research and Development // // Author: Chris Needham // @@ -32,11 +32,11 @@ class ProgressReporter ProgressReporter(); public: - void update(long long done, long long total); + void update(double seconds, long long done, long long total); private: - bool show_progress_; int percent_; + int seconds_; }; //------------------------------------------------------------------------------ diff --git a/src/SndFileAudioFileReader.cpp b/src/SndFileAudioFileReader.cpp index 977fa0a..cdb120b 100644 --- a/src/SndFileAudioFileReader.cpp +++ b/src/SndFileAudioFileReader.cpp @@ -1,6 +1,6 @@ //------------------------------------------------------------------------------ // -// Copyright 2013-2019 BBC Research and Development +// Copyright 2013-2022 BBC Research and Development // // Author: Chris Needham // @@ -136,7 +136,7 @@ bool SndFileAudioFileReader::run(AudioProcessor& processor) bool success = processor.init(info_.samplerate, info_.channels, info_.frames, BUFFER_SIZE); if (success && processor.shouldContinue()) { - progress_reporter.update(0, info_.frames); + progress_reporter.update(0.0, 0, info_.frames); while (success && frames_read == frames_to_read) { if (is_floating_point) { @@ -172,7 +172,11 @@ bool SndFileAudioFileReader::run(AudioProcessor& processor) total_frames_read += frames_read; - progress_reporter.update(total_frames_read, info_.frames); + const double seconds = + static_cast(total_frames_read) / + static_cast(info_.samplerate); + + progress_reporter.update(seconds, total_frames_read, info_.frames); } log(Info) << "\nRead " << total_frames_read << " frames\n"; diff --git a/src/SndFileAudioFileReader.h b/src/SndFileAudioFileReader.h index fd4cfe9..83f94a4 100644 --- a/src/SndFileAudioFileReader.h +++ b/src/SndFileAudioFileReader.h @@ -1,6 +1,6 @@ //------------------------------------------------------------------------------ // -// Copyright 2013-2018 BBC Research and Development +// Copyright 2013-2022 BBC Research and Development // // Author: Chris Needham // @@ -28,8 +28,6 @@ #include "AudioFileReader.h" -#include - #include //------------------------------------------------------------------------------ diff --git a/src/VectorAudioFileReader.cpp b/src/VectorAudioFileReader.cpp new file mode 100644 index 0000000..b59d3f3 --- /dev/null +++ b/src/VectorAudioFileReader.cpp @@ -0,0 +1,108 @@ +//------------------------------------------------------------------------------ +// +// Copyright 2022 BBC Research and Development +// +// Author: Chris Needham +// +// This file is part of Audio Waveform Image Generator. +// +// Audio Waveform Image Generator 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. +// +// Audio Waveform Image Generator 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 +// Audio Waveform Image Generator. If not, see . +// +//------------------------------------------------------------------------------ + +#include "VectorAudioFileReader.h" +#include "AudioProcessor.h" +#include "Log.h" +#include "ProgressReporter.h" + +#include + +//------------------------------------------------------------------------------ + +VectorAudioFileReader::VectorAudioFileReader( + const std::vector& samples, + int sample_rate, + int channels) : + samples_(samples), + sample_rate_(sample_rate), + channels_(channels) +{ +} + +//------------------------------------------------------------------------------ + +VectorAudioFileReader::~VectorAudioFileReader() +{ +} + +//------------------------------------------------------------------------------ + +bool VectorAudioFileReader::open(const char* /* input_filename */, bool /* show_info */) +{ + return true; +} + +//------------------------------------------------------------------------------ + +void VectorAudioFileReader::close() +{ +} + +//------------------------------------------------------------------------------ + +bool VectorAudioFileReader::run(AudioProcessor& processor) +{ + ProgressReporter progress_reporter; + + const size_t BUFFER_SIZE = 16384; + + const size_t total_frames = samples_.size() / channels_; + size_t frames_to_read = total_frames; + size_t index = 0; + size_t total_frames_read = 0; + + bool success = processor.init(sample_rate_, channels_, total_frames, BUFFER_SIZE); + + if (success && processor.shouldContinue()) { + progress_reporter.update(0.0, 0, total_frames); + + while (success && frames_to_read > 0) { + size_t max_frames = BUFFER_SIZE / channels_; + size_t frames = frames_to_read > max_frames ? max_frames : frames_to_read; + + success = processor.process( + &samples_[index], + static_cast(frames) + ); + + total_frames_read += frames; + index += frames * channels_; + frames_to_read -= frames; + + double seconds = static_cast(total_frames_read) / static_cast(sample_rate_); + + progress_reporter.update(seconds, total_frames_read, total_frames); + } + + log(Info) << '\n'; + + processor.done(); + } + + close(); + + return success; +} + +//------------------------------------------------------------------------------ diff --git a/src/VectorAudioFileReader.h b/src/VectorAudioFileReader.h new file mode 100644 index 0000000..5de8f5e --- /dev/null +++ b/src/VectorAudioFileReader.h @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// Copyright 2022 BBC Research and Development +// +// Author: Chris Needham +// +// This file is part of Audio Waveform Image Generator. +// +// Audio Waveform Image Generator 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. +// +// Audio Waveform Image Generator 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 +// Audio Waveform Image Generator. If not, see . +// +//------------------------------------------------------------------------------ + +#if !defined(INC_VECTOR_AUDIO_FILE_READER_H) +#define INC_VECTOR_AUDIO_FILE_READER_H + +//------------------------------------------------------------------------------ + +#include "AudioFileReader.h" + +#include + +//------------------------------------------------------------------------------ + +class AudioProcessor; + +//------------------------------------------------------------------------------ + +class VectorAudioFileReader : public AudioFileReader +{ + public: + VectorAudioFileReader( + const std::vector& samples, + int sample_rate, + int channels + ); + + virtual ~VectorAudioFileReader(); + + VectorAudioFileReader(const VectorAudioFileReader&) = delete; + VectorAudioFileReader& operator=(const VectorAudioFileReader&) = delete; + + public: + virtual bool open(const char* input_filename, bool show_info = true); + + virtual bool run(AudioProcessor& processor); + + private: + void close(); + + private: + const std::vector& samples_; + int sample_rate_; + int channels_; +}; + +//------------------------------------------------------------------------------ + +#endif // #if !defined(INC_VECTOR_AUDIO_FILE_READER_H) + +//------------------------------------------------------------------------------ diff --git a/test/ProgressReporterTest.cpp b/test/ProgressReporterTest.cpp index d1449c4..96a9d66 100644 --- a/test/ProgressReporterTest.cpp +++ b/test/ProgressReporterTest.cpp @@ -1,6 +1,6 @@ //------------------------------------------------------------------------------ // -// Copyright 2013-2019 BBC Research and Development +// Copyright 2013-2022 BBC Research and Development // // Author: Chris Needham // @@ -56,7 +56,7 @@ class ProgressReporterTest : public Test TEST_F(ProgressReporterTest, shouldDisplayZeroPercentWhenFirstCalled) { - progress_reporter_.update(0, 100); + progress_reporter_.update(0.0, 0, 100); ASSERT_THAT(error.str(), StrEq("\rDone: 0%")); } @@ -65,9 +65,9 @@ TEST_F(ProgressReporterTest, shouldDisplayZeroPercentWhenFirstCalled) TEST_F(ProgressReporterTest, shouldUpdatePercentage) { - progress_reporter_.update(0, 100); - progress_reporter_.update(50, 100); - progress_reporter_.update(100, 100); + progress_reporter_.update(0.0, 0, 100); + progress_reporter_.update(2.0, 50, 100); + progress_reporter_.update(4.0, 100, 100); ASSERT_THAT(error.str(), StrEq("\rDone: 0%\rDone: 50%\rDone: 100%")); } @@ -76,10 +76,10 @@ TEST_F(ProgressReporterTest, shouldUpdatePercentage) TEST_F(ProgressReporterTest, shouldNotUpdatePercentageIfUnchanged) { - progress_reporter_.update(0, 100); - progress_reporter_.update(50, 100); - progress_reporter_.update(50, 100); - progress_reporter_.update(100, 100); + progress_reporter_.update(0.0, 0, 100); + progress_reporter_.update(2.0, 50, 100); + progress_reporter_.update(2.0, 50, 100); + progress_reporter_.update(4.0, 100, 100); ASSERT_TRUE(output.str().empty()); ASSERT_THAT(error.str(), StrEq("\rDone: 0%\rDone: 50%\rDone: 100%")); @@ -89,9 +89,9 @@ TEST_F(ProgressReporterTest, shouldNotUpdatePercentageIfUnchanged) TEST_F(ProgressReporterTest, shouldAllowPercentageToDecrease) { - progress_reporter_.update(0, 100); - progress_reporter_.update(50, 100); - progress_reporter_.update(25, 100); + progress_reporter_.update(0.0, 0, 100); + progress_reporter_.update(2.0, 50, 100); + progress_reporter_.update(1.0, 25, 100); ASSERT_THAT(error.str(), StrEq("\rDone: 0%\rDone: 50%\rDone: 25%")); } @@ -100,7 +100,7 @@ TEST_F(ProgressReporterTest, shouldAllowPercentageToDecrease) TEST_F(ProgressReporterTest, shouldLimitPercentageAt0) { - progress_reporter_.update(-100, 100); + progress_reporter_.update(-4.0, -100, 100); ASSERT_THAT(error.str(), StrEq("\rDone: 0%")); } @@ -109,7 +109,7 @@ TEST_F(ProgressReporterTest, shouldLimitPercentageAt0) TEST_F(ProgressReporterTest, shouldLimitPercentageAt100) { - progress_reporter_.update(200, 100); + progress_reporter_.update(8.0, 200, 100); ASSERT_THAT(error.str(), StrEq("\rDone: 100%")); } @@ -118,9 +118,9 @@ TEST_F(ProgressReporterTest, shouldLimitPercentageAt100) TEST_F(ProgressReporterTest, shouldNotAssumeTotalIs100) { - progress_reporter_.update(0, 1000); - progress_reporter_.update(50, 1000); - progress_reporter_.update(100, 1000); + progress_reporter_.update(0.0, 0, 1000); + progress_reporter_.update(2.0, 50, 1000); + progress_reporter_.update(4.0, 100, 1000); ASSERT_THAT(error.str(), StrEq("\rDone: 0%\rDone: 5%\rDone: 10%")); } @@ -129,27 +129,27 @@ TEST_F(ProgressReporterTest, shouldNotAssumeTotalIs100) TEST_F(ProgressReporterTest, shouldDisplayPercentageAsWholeNumber) { - progress_reporter_.update(50, 101); + progress_reporter_.update(2.0, 50, 101); ASSERT_THAT(error.str(), StrEq("\rDone: 49%")); } //------------------------------------------------------------------------------ -TEST_F(ProgressReporterTest, shouldDisplayZeroIfTotalIsZero) +TEST_F(ProgressReporterTest, shouldAllowLargeNumbers) { - progress_reporter_.update(50, 0); + progress_reporter_.update(2.0, 5000000000LL, 10000000000LL); - ASSERT_THAT(error.str(), StrEq("\rDone: 0%")); + ASSERT_THAT(error.str(), StrEq("\rDone: 50%")); } //------------------------------------------------------------------------------ -TEST_F(ProgressReporterTest, shouldAllowLargeNumbers) +TEST_F(ProgressReporterTest, shouldDisplaySecondsIfTotalIsZero) { - progress_reporter_.update(5000000000LL, 10000000000LL); + progress_reporter_.update(2.0, 50, 0); - ASSERT_THAT(error.str(), StrEq("\rDone: 50%")); + ASSERT_THAT(error.str(), StrEq("\rDone: 00:02")); } //------------------------------------------------------------------------------