Skip to content

Commit

Permalink
Fixed auto zoom option when piping audio to stdin
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisn committed Dec 10, 2022
1 parent 0f01573 commit 2abf948
Show file tree
Hide file tree
Showing 13 changed files with 479 additions and 80 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
81 changes: 81 additions & 0 deletions src/AudioLoader.cpp
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
//
//------------------------------------------------------------------------------

#include "AudioLoader.h"

#include "Log.h"

#include <ostream>

//------------------------------------------------------------------------------

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<double>(frame_count) / static_cast<double>(sample_rate_);
}

//------------------------------------------------------------------------------
72 changes: 72 additions & 0 deletions src/AudioLoader.h
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
//
//------------------------------------------------------------------------------

#if !defined(INC_AUDIO_LOADER_H)
#define INC_AUDIO_LOADER_H

//------------------------------------------------------------------------------

#include "AudioProcessor.h"

#include <vector>

//------------------------------------------------------------------------------

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<short>& getData() const { return audio_samples_; }
int getSampleRate() const { return sample_rate_; }
int getChannels() const { return channels_; }

private:
int sample_rate_;
int channels_;
std::vector<short> audio_samples_;
};

//------------------------------------------------------------------------------

#endif // #if !defined(INC_AUDIO_LOADER_H)

//------------------------------------------------------------------------------
31 changes: 23 additions & 8 deletions src/Mp3AudioFileReader.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//------------------------------------------------------------------------------
//
// Copyright 2013-2021 BBC Research and Development
// Copyright 2013-2022 BBC Research and Development
//
// Author: Chris Needham
//
Expand Down Expand Up @@ -327,7 +327,9 @@ Mp3AudioFileReader::Mp3AudioFileReader() :
show_info_(true),
file_(nullptr),
close_(true),
file_size_(0)
file_size_(0),
sample_rate_(0),
frames_(0)
{
}

Expand Down Expand Up @@ -408,7 +410,7 @@ static constexpr unsigned long fourCC(char a, char b, char c, char d)
return (static_cast<unsigned long>(a) << 24) |
(static_cast<unsigned long>(b) << 16) |
(static_cast<unsigned long>(c) << 8) |
static_cast<unsigned long>(d);
static_cast<unsigned long>(d);
}

//------------------------------------------------------------------------------
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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<double>(frames_) / static_cast<double>(sample_rate_);

progress_reporter.update(seconds, pos, file_size_);

if (!processor.process(output_buffer, frames)) {
status = STATUS_PROCESS_ERROR;
break;
Expand All @@ -787,7 +796,10 @@ bool Mp3AudioFileReader::run(AudioProcessor& processor)
if (output_ptr != output_buffer && status != STATUS_PROCESS_ERROR) {
int buffer_size = static_cast<int>(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;
}
}
Expand All @@ -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<double>(frames_) / static_cast<double>(sample_rate_);

progress_reporter.update(seconds, file_size_, file_size_);

char buffer[80];

Expand Down
2 changes: 2 additions & 0 deletions src/Mp3AudioFileReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ class Mp3AudioFileReader : public AudioFileReader
FILE* file_;
bool close_;
long file_size_;
int sample_rate_;
int frames_;
};

//------------------------------------------------------------------------------
Expand Down
74 changes: 56 additions & 18 deletions src/OptionHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "OptionHandler.h"
#include "Config.h"

#include "AudioLoader.h"
#include "DurationCalculator.h"
#include "Error.h"
#include "FileFormat.h"
Expand All @@ -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"
Expand Down Expand Up @@ -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<AudioFileReader> 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<AudioFileReader> 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<AudioFileReader> 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;
Expand Down
Loading

0 comments on commit 2abf948

Please sign in to comment.