Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: Ability to have much less samples #104

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/DurationCalculator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,9 @@ double DurationCalculator::getDuration() const
}

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

long DurationCalculator::getFrameCount() const {
return frame_count_;
}

//------------------------------------------------------------------------------
2 changes: 2 additions & 0 deletions src/DurationCalculator.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ class DurationCalculator : public AudioProcessor

double getDuration() const;

long getFrameCount() const;

private:
int sample_rate_;
long frame_count_;
Expand Down
70 changes: 65 additions & 5 deletions src/OptionHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,16 +114,65 @@ static std::unique_ptr<AudioFileReader> createAudioFileReader(

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

static std::unique_ptr<ScaleFactor> createScaleFactor(const Options& options)
// Returns the frame count of a given audio. Frame is block of samples, one for each channel.

static std::pair<bool, long> getFrameCount(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have a getDuration function that does the same job, only returning duration in seconds, rather than frames. I'd prefer not to duplicate code where possible.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So what you suggest?

  1. Remove getFrameCount
  2. Replace usage of "FrameCount" with duration*sample_rate?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking to modify getDuration to return frames instead of seconds, then divide by sample rate where we need seconds

const boost::filesystem::path& input_filename,
const FileFormat::FileFormat input_format)
{
std::unique_ptr<AudioFileReader> audio_file_reader(
createAudioFileReader(input_filename, input_format)
);

if (!audio_file_reader->open(input_filename.string().c_str())) {
return std::make_pair(false, 0);
}

error_stream << "Calculating audio frame count...\n";

DurationCalculator duration_calculator;

if (!audio_file_reader->run(duration_calculator)) {
return std::make_pair(false, 0);
}

const long frame_count = duration_calculator.getFrameCount();

error_stream << "Frame count: " << frame_count << '\n';

if (FileUtil::isStdioFilename(input_filename.string().c_str())) {
if (fseek(stdin, 0, SEEK_SET) != 0) {
return std::make_pair(false, 0);
}
}

return std::make_pair(true, frame_count);
}


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

static std::unique_ptr<ScaleFactor>
createScaleFactor(const Options &options, const boost::filesystem::path &input_filename,
const FileFormat::FileFormat input_format)
{
std::unique_ptr<ScaleFactor> scale_factor;

if ((options.hasSamplesPerPixel() || options.hasPixelsPerSecond()) &&
if ((options.hasSamplesPerPixel() || options.hasPixelsPerSecond() || options.hasPixelsCount()) &&
options.hasEndTime()) {
throwError("Specify either end time or zoom level, but not both");
}
else if (options.hasSamplesPerPixel() && options.hasPixelsPerSecond() && options.hasPixelsCount()) {
throwError("Specify either zoom or pixels per second or pixels count, but not all of them");
}
else if (options.hasSamplesPerPixel() && options.hasPixelsPerSecond()) {
throwError("Specify either zoom or pixels per second, but not both");
throwError("Specify either zoom or pixels per second or pixels count, but not both");
}
else if (options.hasPixelsPerSecond() && options.hasPixelsCount()) {
throwError("Specify either pixels per second or pixels count, but not both");
}
else if (options.hasSamplesPerPixel() && options.hasPixelsCount()) {
throwError("Specify either zoom or pixels count, but not both");
}
else if (options.hasEndTime()) {
scale_factor.reset(new DurationScaleFactor(
Expand All @@ -137,6 +186,17 @@ static std::unique_ptr<ScaleFactor> createScaleFactor(const Options& options)
new PixelsPerSecondScaleFactor(options.getPixelsPerSecond())
);
}
else if (options.hasPixelsCount()) {
const auto frames = getFrameCount(input_filename, input_format);

if (!frames.first) {
throwError("Unable to get frame count from file");
}

scale_factor.reset(
new PixelScaleFactor(options.getPixelsCount(), frames.second)
);
}
else {
scale_factor.reset(
new SamplesPerPixelScaleFactor(options.getSamplesPerPixel())
Expand Down Expand Up @@ -224,7 +284,7 @@ bool OptionHandler::generateWaveformData(
const FileFormat::FileFormat output_format,
const Options& options)
{
const std::unique_ptr<ScaleFactor> scale_factor = createScaleFactor(options);
const std::unique_ptr<ScaleFactor> scale_factor = createScaleFactor(options, input_filename, input_format);

const boost::filesystem::path output_file_ext = output_filename.extension();

Expand Down Expand Up @@ -336,7 +396,7 @@ bool OptionHandler::renderWaveformImage(
const bool calculate_duration = options.isAutoSamplesPerPixel();

if (!calculate_duration) {
scale_factor = createScaleFactor(options);
scale_factor = createScaleFactor(options, input_filename, input_format);
}

const WaveformColors colors = createWaveformColors(options);
Expand Down
7 changes: 7 additions & 0 deletions src/Options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ Options::Options() :
has_samples_per_pixel_(false),
pixels_per_second_(0),
has_pixels_per_second_(false),
pixels_count_(0),
has_pixels_count_(false),
image_width_(0),
image_height_(0),
bits_(16),
Expand Down Expand Up @@ -117,6 +119,10 @@ bool Options::parseCommandLine(int argc, const char* const* argv)
"pixels-per-second",
po::value<int>(&pixels_per_second_)->default_value(100),
"zoom level (pixels per second)"
)(
"pixels-count",
po::value<int>(&pixels_count_)->default_value(10000),
"zoom level (pixels count)"
)(
"bits,b",
po::value<int>(&bits_)->default_value(16),
Expand Down Expand Up @@ -195,6 +201,7 @@ bool Options::parseCommandLine(int argc, const char* const* argv)

has_samples_per_pixel_ = !variables_map["zoom"].defaulted();
has_pixels_per_second_ = !variables_map["pixels-per-second"].defaulted();
has_pixels_count_ = !variables_map["pixels-count"].defaulted();

has_bits_ = !variables_map["bits"].defaulted();

Expand Down
6 changes: 6 additions & 0 deletions src/Options.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ class Options
int getPixelsPerSecond() const { return pixels_per_second_; }
bool hasPixelsPerSecond() const { return has_pixels_per_second_; }

int getPixelsCount() const { return pixels_count_; }
bool hasPixelsCount() const { return has_pixels_count_; }

int getBits() const { return bits_; }
bool hasBits() const { return has_bits_; }
int getImageWidth() const { return image_width_; }
Expand Down Expand Up @@ -150,6 +153,9 @@ class Options
int pixels_per_second_;
bool has_pixels_per_second_;

int pixels_count_;
bool has_pixels_count_;

int image_width_;
int image_height_;
int bits_;
Expand Down
23 changes: 23 additions & 0 deletions src/WaveformGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,29 @@ int PixelsPerSecondScaleFactor::getSamplesPerPixel(int sample_rate) const

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

PixelScaleFactor::PixelScaleFactor(int pixels_count, long frames_count) :
pixels_count_(pixels_count),
frames_count_(frames_count)
{
if (pixels_count_ <= 0) {
throwError("Invalid pixels count: must be greater than zero");
}

if (frames_count_ <= 0) {
throwError("Invalid frames count: must be greater than zero");
}
}

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

int PixelScaleFactor::getSamplesPerPixel(int /*sample_rate*/) const
{
return static_cast<int>(frames_count_ / pixels_count_ +
((frames_count_ % pixels_count_) > 0 ? 1 : 0));
}

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

const int MAX_SAMPLE = std::numeric_limits<short>::max();
const int MIN_SAMPLE = std::numeric_limits<short>::min();

Expand Down
14 changes: 14 additions & 0 deletions src/WaveformGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,20 @@ class DurationScaleFactor : public ScaleFactor

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

class PixelScaleFactor : public ScaleFactor
{
public:
PixelScaleFactor(int pixels_count, long frames_count);

public:
virtual int getSamplesPerPixel(int sample_rate) const;

private:
int pixels_count_;
long frames_count_;
};

//------------------------------------------------------------------------------
class WaveformGenerator : public AudioProcessor
{
public:
Expand Down