aboutsummaryrefslogtreecommitdiffstats
path: root/alc/backends/wave.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'alc/backends/wave.cpp')
-rw-r--r--alc/backends/wave.cpp117
1 files changed, 57 insertions, 60 deletions
diff --git a/alc/backends/wave.cpp b/alc/backends/wave.cpp
index 794d5cb8..985bb539 100644
--- a/alc/backends/wave.cpp
+++ b/alc/backends/wave.cpp
@@ -55,38 +55,44 @@ using std::chrono::nanoseconds;
using ubyte = unsigned char;
using ushort = unsigned short;
+struct FileDeleter {
+ void operator()(gsl::owner<FILE*> f) { fclose(f); }
+};
+using FilePtr = std::unique_ptr<FILE,FileDeleter>;
+
+/* NOLINTNEXTLINE(*-avoid-c-arrays) */
constexpr char waveDevice[] = "Wave File Writer";
-constexpr ubyte SUBTYPE_PCM[]{
+constexpr std::array<ubyte,16> SUBTYPE_PCM{{
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa,
0x00, 0x38, 0x9b, 0x71
-};
-constexpr ubyte SUBTYPE_FLOAT[]{
+}};
+constexpr std::array<ubyte,16> SUBTYPE_FLOAT{{
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa,
0x00, 0x38, 0x9b, 0x71
-};
+}};
-constexpr ubyte SUBTYPE_BFORMAT_PCM[]{
+constexpr std::array<ubyte,16> SUBTYPE_BFORMAT_PCM{{
0x01, 0x00, 0x00, 0x00, 0x21, 0x07, 0xd3, 0x11, 0x86, 0x44, 0xc8, 0xc1,
0xca, 0x00, 0x00, 0x00
-};
+}};
-constexpr ubyte SUBTYPE_BFORMAT_FLOAT[]{
+constexpr std::array<ubyte,16> SUBTYPE_BFORMAT_FLOAT{{
0x03, 0x00, 0x00, 0x00, 0x21, 0x07, 0xd3, 0x11, 0x86, 0x44, 0xc8, 0xc1,
0xca, 0x00, 0x00, 0x00
-};
+}};
void fwrite16le(ushort val, FILE *f)
{
- ubyte data[2]{ static_cast<ubyte>(val&0xff), static_cast<ubyte>((val>>8)&0xff) };
- fwrite(data, 1, 2, f);
+ std::array data{static_cast<ubyte>(val&0xff), static_cast<ubyte>((val>>8)&0xff)};
+ fwrite(data.data(), 1, data.size(), f);
}
void fwrite32le(uint val, FILE *f)
{
- ubyte data[4]{ static_cast<ubyte>(val&0xff), static_cast<ubyte>((val>>8)&0xff),
- static_cast<ubyte>((val>>16)&0xff), static_cast<ubyte>((val>>24)&0xff) };
- fwrite(data, 1, 4, f);
+ std::array data{static_cast<ubyte>(val&0xff), static_cast<ubyte>((val>>8)&0xff),
+ static_cast<ubyte>((val>>16)&0xff), static_cast<ubyte>((val>>24)&0xff)};
+ fwrite(data.data(), 1, data.size(), f);
}
@@ -101,23 +107,16 @@ struct WaveBackend final : public BackendBase {
void start() override;
void stop() override;
- FILE *mFile{nullptr};
+ FilePtr mFile{nullptr};
long mDataStart{-1};
std::vector<std::byte> mBuffer;
std::atomic<bool> mKillNow{true};
std::thread mThread;
-
- DEF_NEWDEL(WaveBackend)
};
-WaveBackend::~WaveBackend()
-{
- if(mFile)
- fclose(mFile);
- mFile = nullptr;
-}
+WaveBackend::~WaveBackend() = default;
int WaveBackend::mixerProc()
{
@@ -169,8 +168,8 @@ int WaveBackend::mixerProc()
}
}
- const size_t fs{fwrite(mBuffer.data(), frameSize, mDevice->UpdateSize, mFile)};
- if(fs < mDevice->UpdateSize || ferror(mFile))
+ const size_t fs{fwrite(mBuffer.data(), frameSize, mDevice->UpdateSize, mFile.get())};
+ if(fs < mDevice->UpdateSize || ferror(mFile.get()))
{
ERR("Error writing to file\n");
mDevice->handleDisconnect("Failed to write playback samples");
@@ -196,7 +195,7 @@ int WaveBackend::mixerProc()
void WaveBackend::open(std::string_view name)
{
- auto fname = ConfigValueStr(nullptr, "wave", "file");
+ auto fname = ConfigValueStr({}, "wave", "file");
if(!fname) throw al::backend_exception{al::backend_error::NoDevice,
"No wave output filename"};
@@ -212,10 +211,10 @@ void WaveBackend::open(std::string_view name)
#ifdef _WIN32
{
std::wstring wname{utf8_to_wstr(fname.value())};
- mFile = _wfopen(wname.c_str(), L"wb");
+ mFile = FilePtr{_wfopen(wname.c_str(), L"wb")};
}
#else
- mFile = fopen(fname->c_str(), "wb");
+ mFile = FilePtr{fopen(fname->c_str(), "wb")};
#endif
if(!mFile)
throw al::backend_exception{al::backend_error::DeviceError, "Could not open file '%s': %s",
@@ -228,12 +227,11 @@ bool WaveBackend::reset()
{
uint channels{0}, bytes{0}, chanmask{0};
bool isbformat{false};
- size_t val;
- fseek(mFile, 0, SEEK_SET);
- clearerr(mFile);
+ fseek(mFile.get(), 0, SEEK_SET);
+ clearerr(mFile.get());
- if(GetConfigValueBool(nullptr, "wave", "bformat", false))
+ if(GetConfigValueBool({}, "wave", "bformat", false))
{
mDevice->FmtChans = DevFmtAmbi3D;
mDevice->mAmbiOrder = 1;
@@ -282,49 +280,48 @@ bool WaveBackend::reset()
bytes = mDevice->bytesFromFmt();
channels = mDevice->channelsFromFmt();
- rewind(mFile);
+ rewind(mFile.get());
- fputs("RIFF", mFile);
- fwrite32le(0xFFFFFFFF, mFile); // 'RIFF' header len; filled in at close
+ fputs("RIFF", mFile.get());
+ fwrite32le(0xFFFFFFFF, mFile.get()); // 'RIFF' header len; filled in at close
- fputs("WAVE", mFile);
+ fputs("WAVE", mFile.get());
- fputs("fmt ", mFile);
- fwrite32le(40, mFile); // 'fmt ' header len; 40 bytes for EXTENSIBLE
+ fputs("fmt ", mFile.get());
+ fwrite32le(40, mFile.get()); // 'fmt ' header len; 40 bytes for EXTENSIBLE
// 16-bit val, format type id (extensible: 0xFFFE)
- fwrite16le(0xFFFE, mFile);
+ fwrite16le(0xFFFE, mFile.get());
// 16-bit val, channel count
- fwrite16le(static_cast<ushort>(channels), mFile);
+ fwrite16le(static_cast<ushort>(channels), mFile.get());
// 32-bit val, frequency
- fwrite32le(mDevice->Frequency, mFile);
+ fwrite32le(mDevice->Frequency, mFile.get());
// 32-bit val, bytes per second
- fwrite32le(mDevice->Frequency * channels * bytes, mFile);
+ fwrite32le(mDevice->Frequency * channels * bytes, mFile.get());
// 16-bit val, frame size
- fwrite16le(static_cast<ushort>(channels * bytes), mFile);
+ fwrite16le(static_cast<ushort>(channels * bytes), mFile.get());
// 16-bit val, bits per sample
- fwrite16le(static_cast<ushort>(bytes * 8), mFile);
+ fwrite16le(static_cast<ushort>(bytes * 8), mFile.get());
// 16-bit val, extra byte count
- fwrite16le(22, mFile);
+ fwrite16le(22, mFile.get());
// 16-bit val, valid bits per sample
- fwrite16le(static_cast<ushort>(bytes * 8), mFile);
+ fwrite16le(static_cast<ushort>(bytes * 8), mFile.get());
// 32-bit val, channel mask
- fwrite32le(chanmask, mFile);
+ fwrite32le(chanmask, mFile.get());
// 16 byte GUID, sub-type format
- val = fwrite((mDevice->FmtType == DevFmtFloat) ?
- (isbformat ? SUBTYPE_BFORMAT_FLOAT : SUBTYPE_FLOAT) :
- (isbformat ? SUBTYPE_BFORMAT_PCM : SUBTYPE_PCM), 1, 16, mFile);
- (void)val;
+ std::ignore = fwrite((mDevice->FmtType == DevFmtFloat) ?
+ (isbformat ? SUBTYPE_BFORMAT_FLOAT.data() : SUBTYPE_FLOAT.data()) :
+ (isbformat ? SUBTYPE_BFORMAT_PCM.data() : SUBTYPE_PCM.data()), 1, 16, mFile.get());
- fputs("data", mFile);
- fwrite32le(0xFFFFFFFF, mFile); // 'data' header len; filled in at close
+ fputs("data", mFile.get());
+ fwrite32le(0xFFFFFFFF, mFile.get()); // 'data' header len; filled in at close
- if(ferror(mFile))
+ if(ferror(mFile.get()))
{
ERR("Error writing header: %s\n", strerror(errno));
return false;
}
- mDataStart = ftell(mFile);
+ mDataStart = ftell(mFile.get());
setDefaultWFXChannelOrder();
@@ -336,7 +333,7 @@ bool WaveBackend::reset()
void WaveBackend::start()
{
- if(mDataStart > 0 && fseek(mFile, 0, SEEK_END) != 0)
+ if(mDataStart > 0 && fseek(mFile.get(), 0, SEEK_END) != 0)
WARN("Failed to seek on output file\n");
try {
mKillNow.store(false, std::memory_order_release);
@@ -356,14 +353,14 @@ void WaveBackend::stop()
if(mDataStart > 0)
{
- long size{ftell(mFile)};
+ long size{ftell(mFile.get())};
if(size > 0)
{
long dataLen{size - mDataStart};
- if(fseek(mFile, 4, SEEK_SET) == 0)
- fwrite32le(static_cast<uint>(size-8), mFile); // 'WAVE' header len
- if(fseek(mFile, mDataStart-4, SEEK_SET) == 0)
- fwrite32le(static_cast<uint>(dataLen), mFile); // 'data' header len
+ if(fseek(mFile.get(), 4, SEEK_SET) == 0)
+ fwrite32le(static_cast<uint>(size-8), mFile.get()); // 'WAVE' header len
+ if(fseek(mFile.get(), mDataStart-4, SEEK_SET) == 0)
+ fwrite32le(static_cast<uint>(dataLen), mFile.get()); // 'data' header len
}
}
}