Skip to content

Commit 2abf948

Browse files
committed
Fixed auto zoom option when piping audio to stdin
See #176
1 parent 0f01573 commit 2abf948

13 files changed

+479
-80
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ include_directories("${PROJECT_BINARY_DIR}")
230230

231231
set(MODULES
232232
src/AudioFileReader.cpp
233+
src/AudioLoader.cpp
233234
src/AudioProcessor.cpp
234235
src/BStdFile.cpp
235236
src/DurationCalculator.cpp
@@ -246,6 +247,7 @@ set(MODULES
246247
src/Rgba.cpp
247248
src/SndFileAudioFileReader.cpp
248249
src/TimeUtil.cpp
250+
src/VectorAudioFileReader.cpp
249251
src/WaveformBuffer.cpp
250252
src/WaveformColors.cpp
251253
src/WaveformGenerator.cpp

src/AudioLoader.cpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
//------------------------------------------------------------------------------
2+
//
3+
// Copyright 2022 BBC Research and Development
4+
//
5+
// Author: Chris Needham
6+
//
7+
// This file is part of Audio Waveform Image Generator.
8+
//
9+
// Audio Waveform Image Generator is free software: you can redistribute it
10+
// and/or modify it under the terms of the GNU General Public License as
11+
// published by the Free Software Foundation, either version 3 of the License,
12+
// or (at your option) any later version.
13+
//
14+
// Audio Waveform Image Generator is distributed in the hope that it will be
15+
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17+
// Public License for more details.
18+
//
19+
// You should have received a copy of the GNU General Public License along with
20+
// Audio Waveform Image Generator. If not, see <http://www.gnu.org/licenses/>.
21+
//
22+
//------------------------------------------------------------------------------
23+
24+
#include "AudioLoader.h"
25+
26+
#include "Log.h"
27+
28+
#include <ostream>
29+
30+
//------------------------------------------------------------------------------
31+
32+
AudioLoader::AudioLoader() :
33+
sample_rate_(0),
34+
channels_(0)
35+
{
36+
}
37+
38+
//------------------------------------------------------------------------------
39+
40+
bool AudioLoader::init(int sample_rate, int channels, long /* frame_count */, int /* buffer_size */)
41+
{
42+
sample_rate_ = sample_rate;
43+
channels_ = channels;
44+
45+
return true;
46+
}
47+
48+
//------------------------------------------------------------------------------
49+
50+
bool AudioLoader::shouldContinue() const
51+
{
52+
return true;
53+
}
54+
55+
//------------------------------------------------------------------------------
56+
57+
bool AudioLoader::process(const short* input_buffer, int input_frame_count)
58+
{
59+
for (int i = 0; i < input_frame_count * channels_; i++) {
60+
audio_samples_.push_back(input_buffer[i]);
61+
}
62+
63+
return true;
64+
}
65+
66+
//------------------------------------------------------------------------------
67+
68+
void AudioLoader::done()
69+
{
70+
}
71+
72+
//------------------------------------------------------------------------------
73+
74+
double AudioLoader::getDuration() const
75+
{
76+
const size_t frame_count = audio_samples_.size() / channels_;
77+
78+
return static_cast<double>(frame_count) / static_cast<double>(sample_rate_);
79+
}
80+
81+
//------------------------------------------------------------------------------

src/AudioLoader.h

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
//------------------------------------------------------------------------------
2+
//
3+
// Copyright 2022 BBC Research and Development
4+
//
5+
// Author: Chris Needham
6+
//
7+
// This file is part of Audio Waveform Image Generator.
8+
//
9+
// Audio Waveform Image Generator is free software: you can redistribute it
10+
// and/or modify it under the terms of the GNU General Public License as
11+
// published by the Free Software Foundation, either version 3 of the License,
12+
// or (at your option) any later version.
13+
//
14+
// Audio Waveform Image Generator is distributed in the hope that it will be
15+
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17+
// Public License for more details.
18+
//
19+
// You should have received a copy of the GNU General Public License along with
20+
// Audio Waveform Image Generator. If not, see <http://www.gnu.org/licenses/>.
21+
//
22+
//------------------------------------------------------------------------------
23+
24+
#if !defined(INC_AUDIO_LOADER_H)
25+
#define INC_AUDIO_LOADER_H
26+
27+
//------------------------------------------------------------------------------
28+
29+
#include "AudioProcessor.h"
30+
31+
#include <vector>
32+
33+
//------------------------------------------------------------------------------
34+
35+
class AudioLoader : public AudioProcessor
36+
{
37+
public:
38+
AudioLoader();
39+
40+
virtual bool init(
41+
int sample_rate,
42+
int channels,
43+
long frame_count,
44+
int buffer_size
45+
);
46+
47+
virtual bool shouldContinue() const;
48+
49+
virtual bool process(
50+
const short* input_buffer,
51+
int input_frame_count
52+
);
53+
54+
virtual void done();
55+
56+
double getDuration() const;
57+
58+
const std::vector<short>& getData() const { return audio_samples_; }
59+
int getSampleRate() const { return sample_rate_; }
60+
int getChannels() const { return channels_; }
61+
62+
private:
63+
int sample_rate_;
64+
int channels_;
65+
std::vector<short> audio_samples_;
66+
};
67+
68+
//------------------------------------------------------------------------------
69+
70+
#endif // #if !defined(INC_AUDIO_LOADER_H)
71+
72+
//------------------------------------------------------------------------------

src/Mp3AudioFileReader.cpp

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//------------------------------------------------------------------------------
22
//
3-
// Copyright 2013-2021 BBC Research and Development
3+
// Copyright 2013-2022 BBC Research and Development
44
//
55
// Author: Chris Needham
66
//
@@ -327,7 +327,9 @@ Mp3AudioFileReader::Mp3AudioFileReader() :
327327
show_info_(true),
328328
file_(nullptr),
329329
close_(true),
330-
file_size_(0)
330+
file_size_(0),
331+
sample_rate_(0),
332+
frames_(0)
331333
{
332334
}
333335

@@ -408,7 +410,7 @@ static constexpr unsigned long fourCC(char a, char b, char c, char d)
408410
return (static_cast<unsigned long>(a) << 24) |
409411
(static_cast<unsigned long>(b) << 16) |
410412
(static_cast<unsigned long>(c) << 8) |
411-
static_cast<unsigned long>(d);
413+
static_cast<unsigned long>(d);
412414
}
413415

414416
//------------------------------------------------------------------------------
@@ -717,7 +719,10 @@ bool Mp3AudioFileReader::run(AudioProcessor& processor)
717719
break;
718720
}
719721

720-
progress_reporter.update(0, file_size_);
722+
frames_ = 0;
723+
sample_rate_ = sample_rate;
724+
725+
progress_reporter.update(0.0, 0, file_size_);
721726

722727
started = true;
723728
}
@@ -767,10 +772,14 @@ bool Mp3AudioFileReader::run(AudioProcessor& processor)
767772
if (output_ptr == output_buffer_end) {
768773
long pos = ftell(file_);
769774

770-
progress_reporter.update(pos, file_size_);
771-
772775
const int frames = OUTPUT_BUFFER_SIZE / channels;
773776

777+
frames_ += frames;
778+
779+
const double seconds = static_cast<double>(frames_) / static_cast<double>(sample_rate_);
780+
781+
progress_reporter.update(seconds, pos, file_size_);
782+
774783
if (!processor.process(output_buffer, frames)) {
775784
status = STATUS_PROCESS_ERROR;
776785
break;
@@ -787,7 +796,10 @@ bool Mp3AudioFileReader::run(AudioProcessor& processor)
787796
if (output_ptr != output_buffer && status != STATUS_PROCESS_ERROR) {
788797
int buffer_size = static_cast<int>(output_ptr - output_buffer);
789798

790-
if (!processor.process(output_buffer, buffer_size / channels)) {
799+
const int frames = buffer_size / channels;
800+
frames_ += frames;
801+
802+
if (!processor.process(output_buffer, frames)) {
791803
status = STATUS_PROCESS_ERROR;
792804
}
793805
}
@@ -796,7 +808,10 @@ bool Mp3AudioFileReader::run(AudioProcessor& processor)
796808

797809
if (status == STATUS_OK) {
798810
// Report 100% done.
799-
progress_reporter.update(file_size_, file_size_);
811+
812+
const double seconds = static_cast<double>(frames_) / static_cast<double>(sample_rate_);
813+
814+
progress_reporter.update(seconds, file_size_, file_size_);
800815

801816
char buffer[80];
802817

src/Mp3AudioFileReader.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ class Mp3AudioFileReader : public AudioFileReader
5656
FILE* file_;
5757
bool close_;
5858
long file_size_;
59+
int sample_rate_;
60+
int frames_;
5961
};
6062

6163
//------------------------------------------------------------------------------

src/OptionHandler.cpp

Lines changed: 56 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "OptionHandler.h"
2525
#include "Config.h"
2626

27+
#include "AudioLoader.h"
2728
#include "DurationCalculator.h"
2829
#include "Error.h"
2930
#include "FileFormat.h"
@@ -34,6 +35,7 @@
3435
#include "Options.h"
3536
#include "SndFileAudioFileReader.h"
3637
#include "Streams.h"
38+
#include "VectorAudioFileReader.h"
3739
#include "WaveformBuffer.h"
3840
#include "WaveformColors.h"
3941
#include "WaveformGenerator.h"
@@ -386,37 +388,73 @@ bool OptionHandler::renderWaveformImage(
386388
);
387389
}
388390
else {
389-
if (calculate_duration) {
390-
auto result = getDuration(input_filename, input_format, !options.getQuiet());
391+
if (FileUtil::isStdioFilename(input_filename.c_str()) &&
392+
FileUtil::isStdinFifo() &&
393+
calculate_duration) {
394+
std::unique_ptr<AudioFileReader> audio_file_reader(
395+
createAudioFileReader(input_filename, input_format)
396+
);
391397

392-
if (!result.first) {
393-
// log(Error) << "Failed to get audio duration\n";
398+
if (!audio_file_reader->open(input_filename.string().c_str())) {
394399
return false;
395400
}
396401

397-
double duration = result.second;
402+
AudioLoader loader;
403+
404+
if (!audio_file_reader->run(loader)) {
405+
return false;
406+
}
398407

399408
scale_factor.reset(
400-
new DurationScaleFactor(0.0, duration, options.getImageWidth())
409+
new DurationScaleFactor(0.0, loader.getDuration(), options.getImageWidth())
401410
);
402-
}
403411

404-
std::unique_ptr<AudioFileReader> audio_file_reader(
405-
createAudioFileReader(input_filename, input_format)
406-
);
412+
const bool split_channels = options.getSplitChannels();
407413

408-
if (!audio_file_reader->open(input_filename.string().c_str(), !calculate_duration)) {
409-
return false;
410-
}
414+
WaveformGenerator processor(input_buffer, split_channels, *scale_factor);
411415

412-
const bool split_channels = options.getSplitChannels();
413-
WaveformGenerator processor(input_buffer, split_channels, *scale_factor);
416+
VectorAudioFileReader reader(loader.getData(), loader.getSampleRate(), loader.getChannels());
417+
418+
if (!reader.run(processor)) {
419+
return false;
420+
}
421+
422+
output_samples_per_pixel = input_buffer.getSamplesPerPixel();
414423

415-
if (!audio_file_reader->run(processor)) {
416-
return false;
417424
}
425+
else {
426+
if (calculate_duration) {
427+
auto result = getDuration(input_filename, input_format, !options.getQuiet());
418428

419-
output_samples_per_pixel = input_buffer.getSamplesPerPixel();
429+
if (!result.first) {
430+
return false;
431+
}
432+
433+
double duration = result.second;
434+
435+
scale_factor.reset(
436+
new DurationScaleFactor(0.0, duration, options.getImageWidth())
437+
);
438+
}
439+
440+
std::unique_ptr<AudioFileReader> audio_file_reader(
441+
createAudioFileReader(input_filename, input_format)
442+
);
443+
444+
if (!audio_file_reader->open(input_filename.string().c_str(), !calculate_duration)) {
445+
return false;
446+
}
447+
448+
const bool split_channels = options.getSplitChannels();
449+
450+
WaveformGenerator processor(input_buffer, split_channels, *scale_factor);
451+
452+
if (!audio_file_reader->run(processor)) {
453+
return false;
454+
}
455+
456+
output_samples_per_pixel = input_buffer.getSamplesPerPixel();
457+
}
420458
}
421459

422460
WaveformBuffer output_buffer;

0 commit comments

Comments
 (0)