Commit aa7071b8 authored by Stefan Westerfeld's avatar Stefan Westerfeld

Implement basic RawOutputStream.

Signed-off-by: Stefan Westerfeld's avatarStefan Westerfeld <stefan@space.twc.de>
parent e3418d3e
......@@ -2,7 +2,8 @@ bin_PROGRAMS = audiowmark
COMMON_SRC = utils.hh utils.cc convcode.hh convcode.cc random.hh random.cc mp3.cc mp3.hh wavdata.cc wavdata.hh \
audiostream.cc audiostream.hh sfinputstream.cc sfinputstream.hh stdoutwavoutputstream.cc stdoutwavoutputstream.hh \
sfoutputstream.cc sfoutputstream.hh rawinputstream.cc rawinputstream.hh
sfoutputstream.cc sfoutputstream.hh rawinputstream.cc rawinputstream.hh rawoutputstream.cc rawoutputstream.hh \
rawconverter.cc rawconverter.hh
COMMON_LIBS = $(SNDFILE_LIBS) $(FFTW_LIBS) $(LIBGCRYPT_LIBS) $(LIBMPG123_LIBS)
audiowmark_SOURCES = audiowmark.cc fft.cc fft.hh $(COMMON_SRC)
......
......@@ -7,12 +7,8 @@
class AudioStream
{
public:
// for streams that do not know the number of frames in advance (i.e. raw input stream)
static constexpr size_t N_FRAMES_UNKNOWN = ~size_t (0);
virtual int bit_depth() const = 0;
virtual int sample_rate() const = 0;
virtual size_t n_frames() const = 0;
virtual int n_channels() const = 0;
virtual ~AudioStream();
......@@ -21,6 +17,10 @@ public:
class AudioInputStream : public AudioStream
{
public:
// for streams that do not know the number of frames in advance (i.e. raw input stream)
static constexpr size_t N_FRAMES_UNKNOWN = ~size_t (0);
virtual size_t n_frames() const = 0;
virtual Error read_frames (std::vector<float>& samples, size_t count) = 0;
};
......
......@@ -15,6 +15,7 @@
#include "sfoutputstream.hh"
#include "stdoutwavoutputstream.hh"
#include "rawinputstream.hh"
#include "rawoutputstream.hh"
#include <zita-resampler/resampler.h>
#include <zita-resampler/vresampler.h>
......@@ -1178,7 +1179,7 @@ add_watermark (const string& infile, const string& outfile, const string& bits)
return 1;
}
}
if (in_stream->n_frames() == AudioStream::N_FRAMES_UNKNOWN)
if (in_stream->n_frames() == AudioInputStream::N_FRAMES_UNKNOWN)
{
info ("Time: unknown\n");
}
......@@ -1192,7 +1193,18 @@ add_watermark (const string& infile, const string& outfile, const string& bits)
const int out_bit_depth = in_stream->bit_depth() > 16 ? 24 : 16;
std::unique_ptr<AudioOutputStream> out_stream;
if (outfile == "-")
if (Params::output_format == Format::RAW)
{
RawOutputStream *rostream = new RawOutputStream();
out_stream.reset (rostream);
Error err = rostream->open (outfile, Params::raw_output_format);
if (err)
{
fprintf (stderr, "audiowmark: error opening %s: %s\n", outfile.c_str(), err.message());
return 1;
}
}
else if (outfile == "-")
{
StdoutWavOutputStream *swstream = new StdoutWavOutputStream();
out_stream.reset (swstream);
......
#include "rawconverter.hh"
#include <math.h>
using std::vector;
class RawConverterImpl : public RawConverter
{
public:
void to_raw (const std::vector<float>& samples, std::vector<unsigned char>& bytes);
void
from_raw (const std::vector<unsigned char>& bytes, std::vector<float>& samples)
{
}
};
RawConverter *
RawConverter::create (const RawFormat& raw_format, Error& error)
{
error = Error::Code::NONE;
return new RawConverterImpl;
}
void
RawConverterImpl::to_raw (const vector<float>& samples, vector<unsigned char>& output_bytes)
{
output_bytes.resize (2 * samples.size());
for (size_t i = 0; i < samples.size(); i++)
{
const double norm = 0x80000000LL;
const double min_value = -0x80000000LL;
const double max_value = 0x7FFFFFFF;
const int sample = lrint (bound<double> (min_value, samples[i] * norm, max_value));
// write 16-bit little endian value
output_bytes[i * 2] = sample >> 16;
output_bytes[i * 2 + 1] = sample >> 24;
}
}
#ifndef AUDIOWMARK_RAW_CONVERTER_HH
#define AUDIOWMARK_RAW_CONVERTER_HH
#include "rawinputstream.hh"
class RawConverter
{
public:
static RawConverter *create (const RawFormat& raw_format, Error& error);
virtual void to_raw (const std::vector<float>& samples, std::vector<unsigned char>& bytes) = 0;
virtual void from_raw (const std::vector<unsigned char>& bytes, std::vector<float>& samples) = 0;
};
#endif /* AUDIOWMARK_RAW_CONVERTER_HH */
......@@ -51,4 +51,3 @@ public:
};
#endif /* AUDIOWMARK_RAW_INPUT_STREAM_HH */
#include "rawoutputstream.hh"
#include <assert.h>
using std::string;
using std::vector;
RawOutputStream::~RawOutputStream()
{
close();
}
Error
RawOutputStream::open (const string& filename, const RawFormat& format)
{
assert (m_state == State::NEW);
if (!format.n_channels())
return Error ("RawOutputStream: output format: missing number of channels");
if (!format.bit_depth())
return Error ("RawOutputStream: output format: missing bit depth");
if (!format.sample_rate())
return Error ("RawOutputStream: output format: missing sample rate");
Error err = Error::Code::NONE;
RawConverter *rc = RawConverter::create (format, err);
if (err)
return err;
assert (rc);
m_raw_converter.reset (rc);
if (filename == "-")
{
m_output_file = stdout;
m_close_file = false;
}
else
{
m_output_file = fopen (filename.c_str(), "w");
m_close_file = true;
}
m_format = format;
m_state = State::OPEN;
return Error::Code::NONE;
}
int
RawOutputStream::sample_rate() const
{
return m_format.sample_rate();
}
int
RawOutputStream::bit_depth() const
{
return m_format.bit_depth();
}
int
RawOutputStream::n_channels() const
{
return m_format.n_channels();
}
Error
RawOutputStream::write_frames (const vector<float>& samples)
{
assert (m_state == State::OPEN);
vector<unsigned char> bytes;
m_raw_converter->to_raw (samples, bytes);
fwrite (&bytes[0], 1, bytes.size(), m_output_file);
return Error::Code::NONE;
}
void
RawOutputStream::close()
{
if (m_state == State::OPEN)
{
if (m_close_file && m_output_file)
{
fclose (m_output_file);
m_output_file = nullptr;
m_close_file = false;
}
m_state = State::CLOSED;
}
}
#ifndef AUDIOWMARK_RAW_OUTPUT_STREAM_HH
#define AUDIOWMARK_RAW_OUTPUT_STREAM_HH
#include "rawinputstream.hh"
#include "rawconverter.hh"
#include <memory>
class RawOutputStream : public AudioOutputStream
{
enum class State {
NEW,
OPEN,
CLOSED
};
State m_state = State::NEW;
RawFormat m_format;
FILE *m_output_file = nullptr;
bool m_close_file = false;
std::unique_ptr<RawConverter> m_raw_converter;
public:
~RawOutputStream();
int bit_depth() const override;
int sample_rate() const override;
int n_channels() const override;
Error open (const std::string& filename, const RawFormat& format);
Error write_frames (const std::vector<float>& frames) override;
void close();
};
#endif /* AUDIOWMARK_RAW_OUTPUT_STREAM_HH */
......@@ -18,7 +18,6 @@ SFOutputStream::open (const string& filename, int n_channels, int sample_rate, i
assert (m_state == State::NEW);
m_sample_rate = sample_rate;
m_n_frames = n_frames;
m_n_channels = n_channels;
SF_INFO sfinfo = {0,};
......@@ -104,9 +103,3 @@ SFOutputStream::n_channels() const
{
return m_n_channels;
}
size_t
SFOutputStream::n_frames() const
{
return m_n_frames;
}
......@@ -13,7 +13,6 @@ class SFOutputStream : public AudioOutputStream
std::string m_error_blurb;
int m_bit_depth = 0;
int m_sample_rate = 0;
size_t m_n_frames = 0;
int m_n_channels = 0;
enum class State {
......@@ -32,7 +31,6 @@ public:
int bit_depth() const override;
int sample_rate() const override;
int n_channels() const override;
size_t n_frames() const override;
};
#endif /* AUDIOWMARK_SF_OUTPUT_STREAM_HH */
......@@ -62,7 +62,7 @@ StdoutWavOutputStream::open (int n_channels, int sample_rate, int bit_depth, siz
{
return Error ("StdoutWavOutputStream::open: unsupported bit depth");
}
if (n_frames == N_FRAMES_UNKNOWN)
if (n_frames == AudioInputStream::N_FRAMES_UNKNOWN)
{
return Error ("unable to write wav format to standard out without input length information");
}
......@@ -94,7 +94,6 @@ StdoutWavOutputStream::open (int n_channels, int sample_rate, int bit_depth, siz
fwrite (&header_bytes[0], 1, header_bytes.size(), stdout);
m_bit_depth = bit_depth;
m_n_frames = n_frames;
m_state = State::OPEN;
return Error::Code::NONE;
......
......@@ -11,7 +11,6 @@ class StdoutWavOutputStream : public AudioOutputStream
int m_bit_depth = 0;
int m_sample_rate = 0;
int m_n_channels = 0;
size_t m_n_frames = 0;
size_t m_close_padding = 0;
enum class State {
......@@ -30,10 +29,6 @@ public:
int sample_rate() const override;
int bit_depth() const override;
int n_channels() const override;
size_t n_frames() const override
{
return m_n_frames;
}
const char *error_blurb() const
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment