Commit 19147744 authored by Stefan Westerfeld's avatar Stefan Westerfeld

Add minimal raw input stream.

Signed-off-by: Stefan Westerfeld's avatarStefan Westerfeld <stefan@space.twc.de>
parent 94024db7
......@@ -2,7 +2,7 @@ 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
sfoutputstream.cc sfoutputstream.hh rawinputstream.cc rawinputstream.hh
COMMON_LIBS = $(SNDFILE_LIBS) $(FFTW_LIBS) $(LIBGCRYPT_LIBS) $(LIBMPG123_LIBS)
audiowmark_SOURCES = audiowmark.cc fft.cc fft.hh $(COMMON_SRC)
......
......@@ -7,6 +7,9 @@
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;
......
......@@ -14,6 +14,7 @@
#include "sfinputstream.hh"
#include "sfoutputstream.hh"
#include "stdoutwavoutputstream.hh"
#include "rawinputstream.hh"
#include <zita-resampler/resampler.h>
#include <zita-resampler/vresampler.h>
......@@ -28,6 +29,8 @@ using std::complex;
using std::min;
using std::max;
enum class Format { AUTO = 1, RAW = 2 };
namespace Params
{
static size_t frame_size = 1024;
......@@ -54,6 +57,9 @@ namespace Params
static int test_cut = 0; // for sync test
static bool test_no_sync = false; // disable sync
static int test_truncate = 0;
static Format input_format = Format::AUTO;
static Format output_format = Format::AUTO;
}
void
......@@ -128,6 +134,17 @@ check_arg (uint argc,
exit (1);
}
Format
parse_format (const string& str)
{
if (str == "raw")
return Format::RAW;
if (str == "auto")
return Format::AUTO;
error ("audiowmark: unsupported format '%s'\n", str.c_str());
exit (1);
}
void
parse_options (int *argc_p,
char **argv_p[])
......@@ -192,6 +209,18 @@ parse_options (int *argc_p,
{
Params::test_truncate = atoi (opt_arg);
}
else if (check_arg (argc, argv, &i, "--input-format", &opt_arg))
{
Params::input_format = parse_format (opt_arg);
}
else if (check_arg (argc, argv, &i, "--output-format", &opt_arg))
{
Params::output_format = parse_format (opt_arg);
}
else if (check_arg (argc, argv, &i, "--format", &opt_arg))
{
Params::input_format = Params::output_format = parse_format (opt_arg);
}
}
/* resort argc/argv */
......@@ -1096,18 +1125,37 @@ add_watermark (const string& infile, const string& outfile, const string& bits)
auto bitvec_b = randomize_bit_order (conv_encode (ConvBlockType::b, bitvec), /* encode */ true);
std::unique_ptr<AudioInputStream> in_stream; // FIXME: virtual constructor
{
SFInputStream *sistream = new SFInputStream ();
in_stream.reset (sistream);
Error err = sistream->open (infile);
if (err)
{
fprintf (stderr, "audiowmark: error opening %s: %s\n", infile.c_str(), err.message());
return 1;
}
}
int orig_seconds = in_stream->n_frames() / in_stream->sample_rate();
info ("Time: %d:%02d\n", orig_seconds / 60, orig_seconds % 60);
if (Params::input_format == Format::AUTO)
{
SFInputStream *sistream = new SFInputStream();
in_stream.reset (sistream);
Error err = sistream->open (infile);
if (err)
{
fprintf (stderr, "audiowmark: error opening %s: %s\n", infile.c_str(), err.message());
return 1;
}
}
else
{
RawInputStream *ristream = new RawInputStream();
in_stream.reset (ristream);
Error err = ristream->open (infile);
if (err)
{
fprintf (stderr, "audiowmark: error opening %s: %s\n", infile.c_str(), err.message());
return 1;
}
}
if (in_stream->n_frames() == AudioStream::N_FRAMES_UNKNOWN)
{
info ("Time: unknown\n");
}
else
{
int orig_seconds = in_stream->n_frames() / in_stream->sample_rate();
info ("Time: %d:%02d\n", orig_seconds / 60, orig_seconds % 60);
}
info ("Sample Rate: %d\n", in_stream->sample_rate());
info ("Channels: %d\n", in_stream->n_channels());
......
#include "rawinputstream.hh"
#include <assert.h>
using std::string;
using std::vector;
RawInputStream::~RawInputStream()
{
close();
}
Error
RawInputStream::open (const string& filename)
{
assert (m_state == State::NEW);
#if 0
SF_INFO sfinfo = { 0, };
m_sndfile = sf_open (filename.c_str(), SFM_READ, &sfinfo);
int error = sf_error (m_sndfile);
if (error)
{
Error err (sf_strerror (m_sndfile));
if (m_sndfile)
{
m_sndfile = nullptr;
sf_close (m_sndfile);
}
return err;
}
m_n_channels = sfinfo.channels;
m_n_values = sfinfo.frames * sfinfo.channels;
m_sample_rate = sfinfo.samplerate;
switch (sfinfo.format & SF_FORMAT_SUBMASK)
{
case SF_FORMAT_PCM_U8:
case SF_FORMAT_PCM_S8:
m_bit_depth = 8;
break;
case SF_FORMAT_PCM_16:
m_bit_depth = 16;
break;
case SF_FORMAT_PCM_24:
m_bit_depth = 24;
break;
case SF_FORMAT_FLOAT:
case SF_FORMAT_PCM_32:
m_bit_depth = 32;
break;
case SF_FORMAT_DOUBLE:
m_bit_depth = 64;
break;
default:
m_bit_depth = 32; /* unknown */
}
#endif
m_state = State::OPEN;
return Error::Code::NONE;
}
int
RawInputStream::sample_rate() const
{
return 44100;
}
int
RawInputStream::bit_depth() const
{
return 16;
}
size_t
RawInputStream::n_frames() const
{
return N_FRAMES_UNKNOWN;
}
int
RawInputStream::n_channels() const
{
return 2;
}
Error
RawInputStream::read_frames (vector<float>& samples, size_t count)
{
assert (m_state == State::OPEN);
vector<unsigned char> input_bytes (count * n_channels() * (bit_depth() / 8));
size_t r_count = fread (input_bytes.data(), n_channels() * (bit_depth() / 8), count, stdin);
unsigned char *ptr = reinterpret_cast<unsigned char *> (input_bytes.data());
samples.resize (r_count * n_channels());
const double norm = 1.0 / 0x80000000LL;
for (size_t i = 0; i < samples.size(); i++)
{
int s32 = (ptr[1] << 24) + (ptr[0] << 16);
samples[i] = s32 * norm;
ptr += 2;
}
return Error::Code::NONE;
}
void
RawInputStream::close()
{
if (m_state == State::OPEN)
{
#if 0
assert (m_sndfile);
sf_close (m_sndfile);
#endif
m_state = State::CLOSED;
}
}
#ifndef AUDIOWMARK_RAW_INPUT_STREAM_HH
#define AUDIOWMARK_RAW_INPUT_STREAM_HH
#include <string>
#include <sndfile.h>
#include "audiostream.hh"
class RawInputStream : public AudioInputStream
{
enum class State {
NEW,
OPEN,
CLOSED
};
State m_state = State::NEW;
public:
~RawInputStream();
Error open (const std::string& filename);
Error read_frames (std::vector<float>& samples, size_t count) override;
void close();
int bit_depth() const override;
int sample_rate() const override;
size_t n_frames() const override;
int n_channels() const override;
};
#endif /* AUDIOWMARK_RAW_INPUT_STREAM_HH */
......@@ -62,6 +62,10 @@ 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)
{
return Error ("unable to write wav format to standard out without input length information");
}
vector<unsigned char> header_bytes;
size_t data_size = n_frames * n_channels * ((bit_depth + 7) / 8);
......
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