From 365bdb755c23145dd3f4ea4dfe9912498abd05e3 Mon Sep 17 00:00:00 2001 From: Ralf Ramsauer Date: Sun, 11 Oct 2015 19:06:05 +0200 Subject: [PATCH] Added new Class for playing WAVE files from memory Signed-off-by: Ralf Ramsauer --- doorlockd/client/wave.cpp | 86 +++++++++++++++++++++++++++++++++++++++ doorlockd/client/wave.h | 35 ++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 doorlockd/client/wave.cpp create mode 100644 doorlockd/client/wave.h diff --git a/doorlockd/client/wave.cpp b/doorlockd/client/wave.cpp new file mode 100644 index 0000000..d7cfbe0 --- /dev/null +++ b/doorlockd/client/wave.cpp @@ -0,0 +1,86 @@ +#include +#include +#include + +#include + +#include "wave.h" + +Wave::Wave(int bits, + int channels, + int rate, + Raw data) : + _format(new ao_sample_format), + _data(data) +{ + _format->bits = bits; + _format->rate = rate; + _format->channels = channels; + _format->byte_format = AO_FMT_LITTLE; + _format->matrix = nullptr; + + int default_driver; + default_driver = ao_default_driver_id(); + _device = ao_open_live(default_driver, + _format.get(), + nullptr); +} + +Wave::~Wave() +{ + if (_device != nullptr) + ao_close(_device); +} + +Wave Wave::fromFile(const std::string &filename) +{ + SF_INFO sfinfo; + SNDFILE *file = sf_open(filename.c_str(), SFM_READ, &sfinfo); + if (file == nullptr) + throw std::runtime_error("Unable to open soundfile " + filename); + + size_t rawSize = sfinfo.channels * sfinfo.frames * sizeof(short); + Raw data; + data.resize(rawSize); + + sf_read_raw(file, &data.front(), data.size()); + sf_close(file); + + int bits; + switch (sfinfo.format & SF_FORMAT_SUBMASK) { + case SF_FORMAT_PCM_16: + bits = 16; + break; + case SF_FORMAT_PCM_24: + bits = 24; + break; + case SF_FORMAT_PCM_32: + bits = 32; + break; + case SF_FORMAT_PCM_S8: + bits = 8; + break; + case SF_FORMAT_PCM_U8: + bits = 8; + break; + default: + bits = 16; + break; + } + + return Wave(bits, + sfinfo.channels, + sfinfo.samplerate, + data); +} + +void Wave::play() const +{ + if (_device == nullptr) { + return; + } + + ao_play(_device, + (char*)&_data.front(), + _data.size()); +} diff --git a/doorlockd/client/wave.h b/doorlockd/client/wave.h new file mode 100644 index 0000000..b60560c --- /dev/null +++ b/doorlockd/client/wave.h @@ -0,0 +1,35 @@ +#ifndef WAVE_H +#define WAVE_H + +#include +#include +#include + +#include + +class Wave { +public: + + using Raw = std::vector; + + static Wave fromFile(const std::string &filename); + Wave(int bits, + int channels, + int rate, + Raw data); + Wave(const Wave &rhs); + ~Wave(); + + Wave &operator=(const Wave &rhs); + + void play() const; + +private: + + std::unique_ptr _format; + ao_device* _device = { nullptr }; + + const Raw _data; +}; + +#endif