Commit b97b7c42 authored by Stefan Westerfeld's avatar Stefan Westerfeld

Provide basic stream read_frames/write_frames error handling.

Signed-off-by: Stefan Westerfeld's avatarStefan Westerfeld <stefan@space.twc.de>
parent 9061a6ed
......@@ -2,6 +2,7 @@
#define AUDIOWMARK_AUDIO_STREAM_HH
#include <vector>
#include "utils.hh"
class AudioStream
{
......@@ -15,13 +16,13 @@ public:
class AudioInputStream : public AudioStream
{
virtual std::vector<float> read_frames (size_t count) = 0;
virtual Error read_frames (std::vector<float>& samples, size_t count) = 0;
};
class AudioOutputStream : public AudioStream
{
public:
virtual bool write_frames (const std::vector<float>& frames) = 0;
virtual Error write_frames (const std::vector<float>& frames) = 0;
};
#endif /* AUDIOWMARK_AUDIO_STREAM_HH */
......@@ -1126,7 +1126,14 @@ add_watermark (const string& infile, const string& outfile, const string& bits)
size_t total_output_frames = 0;
while (true)
{
samples = in_stream->read_frames (Params::frame_size);
Error err = Error::Code::NONE;
err = in_stream->read_frames (samples, Params::frame_size);
if (err)
{
error ("audiowmark: input stream read failed: %s\n", err.message());
return 1;
}
total_input_frames += samples.size() / n_channels;
if (samples.size() < Params::frame_size * n_channels)
......@@ -1149,7 +1156,13 @@ add_watermark (const string& infile, const string& outfile, const string& bits)
size_t max_write_frames = total_input_frames - total_output_frames;
if (samples.size() > max_write_frames * n_channels)
samples.resize (max_write_frames * n_channels);
out_stream->write_frames (samples);
err = out_stream->write_frames (samples);
if (err)
{
error ("audiowmark output write failed: %s\n", err.message());
return 1;
}
total_output_frames += samples.size() / n_channels;
}
#if 0
......
......@@ -79,14 +79,17 @@ SFInputStream::bit_depth() const
return m_bit_depth;
}
vector<float>
SFInputStream::read_frames (size_t count)
Error
SFInputStream::read_frames (vector<float>& samples, size_t count)
{
assert (m_state == State::OPEN);
vector<int> isamples (count * m_n_channels);
sf_count_t r_count = sf_readf_int (m_sndfile, &isamples[0], count);
if (sf_error (m_sndfile))
return Error (sf_strerror (m_sndfile));
/* reading a wav file and saving it again with the libsndfile float API will
* change some values due to normalization issues:
* http://www.mega-nerd.com/libsndfile/FAQ.html#Q010
......@@ -95,12 +98,12 @@ SFInputStream::read_frames (size_t count)
* and float manually - the important part is that the normalization factors
* used during read and write are identical
*/
vector<float> result (r_count * m_n_channels);;
samples.resize (r_count * m_n_channels);
const double norm = 1.0 / 0x80000000LL;
for (size_t i = 0; i < result.size(); i++)
result[i] = isamples[i] * norm;
for (size_t i = 0; i < samples.size(); i++)
samples[i] = isamples[i] * norm;
return result;
return Error::Code::NONE;
}
void
......
......@@ -27,7 +27,7 @@ public:
~SFInputStream();
bool open (const std::string& filename);
std::vector<float> read_frames (size_t count);
Error read_frames (std::vector<float>& samples, size_t count);
void close();
int
......
......@@ -62,7 +62,7 @@ SFOutputStream::close()
}
}
bool
Error
SFOutputStream::write_frames (const vector<float>& samples)
{
vector<int> isamples (samples.size());
......@@ -78,20 +78,13 @@ SFOutputStream::write_frames (const vector<float>& samples)
sf_count_t frames = samples.size() / m_n_channels;
sf_count_t count = sf_writef_int (m_sndfile, &isamples[0], frames);
int error = sf_error (m_sndfile);
if (error)
{
m_error_blurb = sf_strerror (m_sndfile);
return false;
}
if (sf_error (m_sndfile))
return Error (sf_strerror (m_sndfile));
if (count != frames)
{
m_error_blurb = "writing sample data failed: short write";
return false;
}
return Error ("writing sample data failed: short write");
return true;
return Error::Code::NONE;
}
int
......
......@@ -27,7 +27,7 @@ public:
~SFOutputStream();
bool open (const std::string& filename, int n_channels, int sample_rate, int bit_depth, size_t n_frames);
bool write_frames (const std::vector<float>& frames) override;
Error write_frames (const std::vector<float>& frames) override;
void close();
int bit_depth() const override;
int sample_rate() const override;
......
......@@ -118,7 +118,7 @@ convert_frames (const vector<float>& samples, vector<unsigned char>& output_byte
}
}
bool
Error
StdoutWavOutputStream::write_frames (const vector<float>& samples)
{
vector<unsigned char> output_bytes (samples.size() * (m_bit_depth / 8));
......@@ -137,7 +137,7 @@ StdoutWavOutputStream::write_frames (const vector<float>& samples)
}
fwrite (&output_bytes[0], 1, output_bytes.size(), stdout);
return true;
return Error::Code::NONE;
}
void
......
......@@ -24,7 +24,7 @@ public:
~StdoutWavOutputStream();
bool open (int n_channels, int sample_rate, int bit_depth, size_t n_frames);
bool write_frames (const std::vector<float>& frames) override;
Error write_frames (const std::vector<float>& frames) override;
void close();
int sample_rate() const override;
int bit_depth() const override;
......
......@@ -31,7 +31,7 @@ main (int argc, char **argv)
vector<float> samples;
do
{
samples = in.read_frames (1024);
in.read_frames (samples, 1024);
out.write_frames (samples);
}
while (samples.size());
......
......@@ -37,4 +37,49 @@ void warning (const char *format, ...) AUDIOWMARK_PRINTF (1, 2);
void info (const char *format, ...) AUDIOWMARK_PRINTF (1, 2);
void debug (const char *format, ...) AUDIOWMARK_PRINTF (1, 2);
class Error
{
public:
enum class Code {
NONE,
STR
};
Error (Code code) :
m_code (code)
{
switch (code)
{
case Code::NONE:
m_message = "OK";
break;
default:
m_message = "Unknown error";
}
}
explicit
Error (const std::string& message) :
m_code (Code::STR),
m_message (message)
{
}
Code
code()
{
return m_code;
}
const char *
message()
{
return m_message.c_str();
}
operator bool()
{
return m_code != Code::NONE;
}
private:
Code m_code;
std::string m_message;
};
#endif /* AUDIOWMARK_UTILS_HH */
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