aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniil Cherednik <dan.cherednik@gmail.com>2019-12-30 00:13:23 +0300
committerDaniil Cherednik <dan.cherednik@gmail.com>2020-01-01 22:29:50 +0300
commit3d69df17657c40030fb486a86ef179a42b3873ca (patch)
tree56002a11e97322d6b6360b1479330ba83e87d731
parentb58f4dd8353121094acdb41ad96fbdec4a580d79 (diff)
downloadatracdenc-3d69df17657c40030fb486a86ef179a42b3873ca.tar.gz
Initiall support of stdin reading for windows
Expected au(snd) format, 44100hz, 16bit, stereo or mono
-rw-r--r--src/CMakeLists.txt9
-rw-r--r--src/lib/endian.h60
-rw-r--r--src/oma/liboma/src/liboma.c14
-rw-r--r--src/platform/win/pcm_io/mf/pcm_io_mf.cpp (renamed from src/platform/win/pcm_io_mf/pcm_io_mf.cpp)32
-rw-r--r--src/platform/win/pcm_io/mf/pcm_io_mf.h26
-rw-r--r--src/platform/win/pcm_io/pcm_io.cpp64
-rw-r--r--src/platform/win/pcm_io/pcm_io_impl.h26
-rw-r--r--src/platform/win/pcm_io/win32/pcm_io_win32.cpp172
-rw-r--r--src/platform/win/pcm_io/win32/pcm_io_win32.h23
9 files changed, 393 insertions, 33 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 019acf3..0838942 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -30,7 +30,9 @@ if (WIN32)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
include_directories("platform/win/getopt")
set(SOURCE_PCM_IO_LIB
- platform/win/pcm_io_mf/pcm_io_mf.cpp
+ platform/win/pcm_io/mf/pcm_io_mf.cpp
+ platform/win/pcm_io/win32/pcm_io_win32.cpp
+ platform/win/pcm_io/pcm_io.cpp
)
else()
INCLUDE(FindLibSndFile)
@@ -46,7 +48,10 @@ if (${BIGENDIAN})
add_compile_definitions(BIGENDIAN_ORDER)
endif()
-include_directories("oma/liboma/include")
+include_directories(
+ "lib"
+ "oma/liboma/include"
+)
set(SOURCE_FFT_LIB fft/kissfft_impl/kiss_fft.c)
set_source_files_properties(fft/kissfft_impl/kiss_fft.c PROPERTIES COMPILE_FLAGS -Dkiss_fft_scalar=double)
diff --git a/src/lib/endian.h b/src/lib/endian.h
new file mode 100644
index 0000000..519cca1
--- /dev/null
+++ b/src/lib/endian.h
@@ -0,0 +1,60 @@
+/*
+ * This file is part of AtracDEnc.
+ *
+ * AtracDEnc is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * AtracDEnc is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with AtracDEnc; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LIB_ENDIAN_H
+#define LIB_ENDIAN_H
+
+#include <stdint.h>
+
+static inline uint32_t swapbyte32_on_le(uint32_t in) {
+#ifdef BIGENDIAN_ORDER
+ return in;
+#else
+ return ((in & 0xff) << 24) | ((in & 0xff00) << 8) | ((in & 0xff0000) >> 8) | ((in & 0xff000000) >> 24);
+#endif
+}
+
+static inline uint16_t swapbyte16_on_le(uint16_t in) {
+#ifdef BIGENDIAN_ORDER
+ return in;
+#else
+ return ((in & 0xff) << 8) | ((in & 0xff00) >> 8);
+#endif
+}
+
+#ifdef __cplusplus
+
+static inline int16_t conv_ntoh(int16_t in) {
+ return (int16_t)swapbyte16_on_le((uint16_t)in);
+}
+
+static inline uint16_t conv_ntoh(uint16_t in) {
+ return swapbyte16_on_le(in);
+}
+
+static inline int32_t conv_ntoh(int32_t in) {
+ return (int32_t)swapbyte32_on_le((uint32_t)in);
+}
+
+static inline uint32_t conv_ntoh(uint32_t in) {
+ return swapbyte32_on_le(in);
+}
+
+#endif
+
+#endif \ No newline at end of file
diff --git a/src/oma/liboma/src/liboma.c b/src/oma/liboma/src/liboma.c
index d44b490..13d3a40 100644
--- a/src/oma/liboma/src/liboma.c
+++ b/src/oma/liboma/src/liboma.c
@@ -19,6 +19,8 @@
#include "../include/oma.h"
#include "oma_internal.h"
+#include <endian.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
@@ -42,14 +44,6 @@ enum {
OMAERR_EOF = -6
};
-static uint32_t swapbyte32(uint32_t in) {
-#ifdef BIGENDIAN_ORDER
- return in;
-#else
- return ((in & 0xff) << 24 ) | ((in & 0xff00) << 8) | ((in & 0xff0000) >> 8) | ((in & 0xff000000) >> 24);
-#endif
-}
-
#ifdef _MSC_VER
__declspec(thread) int err;
#else
@@ -127,7 +121,7 @@ static int oma_write_atrac3_header(uint32_t *params, oma_info_t *info) {
fprintf(stderr, "framesize: %d\n", framesz);
if (framesz > 0x3FF)
return -1;
- *params = swapbyte32((OMAC_ID_ATRAC3 << 24) | (js << 17) | ((uint32_t)samplerate_idx << 13) | framesz);
+ *params = swapbyte32_on_le((OMAC_ID_ATRAC3 << 24) | (js << 17) | ((uint32_t)samplerate_idx << 13) | framesz);
return 0;
}
@@ -163,7 +157,7 @@ static int oma_write_atrac3p_header(uint32_t *params, oma_info_t *info) {
if (ch_id < 0)
return -1;
- *params = swapbyte32((OMAC_ID_ATRAC3PLUS << 24) | ((int32_t)samplerate_idx << 13) | ((ch_id + 1) << 10) | framesz);
+ *params = swapbyte32_on_le((OMAC_ID_ATRAC3PLUS << 24) | ((int32_t)samplerate_idx << 13) | ((ch_id + 1) << 10) | framesz);
return 0;
}
diff --git a/src/platform/win/pcm_io_mf/pcm_io_mf.cpp b/src/platform/win/pcm_io/mf/pcm_io_mf.cpp
index b8ddd98..3f9ff3a 100644
--- a/src/platform/win/pcm_io_mf/pcm_io_mf.cpp
+++ b/src/platform/win/pcm_io/mf/pcm_io_mf.cpp
@@ -19,6 +19,9 @@
#include "../../../wav.h"
#include "../../../env.h"
+#include "pcm_io_mf.h"
+#include "../pcm_io_impl.h"
+
#include <comdef.h>
#include <initguid.h>
@@ -213,7 +216,7 @@ public:
hr = MFCreateSourceReaderFromURL(wpath.c_str(), NULL, &Reader_);
if (FAILED(hr)) {
- throw THException(hr, "unable to open input file");
+ throw THException(hr, "qqq unable to open input file");
}
hr = ConfigureAudioStream(Reader_, &MediaType_);
@@ -282,7 +285,7 @@ public:
if (OutFile == INVALID_HANDLE_VALUE) {
hr = HRESULT_FROM_WIN32(GetLastError());
- throw THException(hr, "unable to open output file");
+ throw THException(hr, "qqq2 unable to open output file");
}
hr = WriteToFile(OutFile, header, sizeof(header));
@@ -347,19 +350,6 @@ public:
return static_cast<size_t>(totalSamples);
}
- void ConvertToPcmBuffer(const BYTE* audioData, TPCMBuffer<TFloat>& buf, size_t sz, size_t shift) {
- if (ChannelsNum_ == 1) {
- for (size_t i = 0; i < sz; i++) {
- *(buf[i + shift] + 0) = (*(int16_t*)(audioData + i * 2 + 0)) / (TFloat)32768.0;
- }
- } else {
- for (size_t i = 0; i < sz; i++) {
- *(buf[i + shift] + 0) = (*(int16_t*)(audioData + i * 4 + 0)) / (TFloat)32768.0;
- *(buf[i + shift] + 1) = (*(int16_t*)(audioData + i * 4 + 2)) / (TFloat)32768.0;
- }
- }
- }
-
size_t Read(TPCMBuffer<TFloat>& buf, size_t sz) override {
HRESULT hr = S_OK;
@@ -374,11 +364,11 @@ public:
abort();
}
curPos = (Buf_.size() - ConsummerPos_) / BytesPerSample_;
- ConvertToPcmBuffer(Buf_.data() + ConsummerPos_, buf, curPos, 0);
+ ConvertToPcmBufferFromLE(Buf_.data() + ConsummerPos_, buf, curPos, 0, ChannelsNum_);
ConsummerPos_ = 0;
} else {
// We have all data in our buffer, just convert it and shift consumer position
- ConvertToPcmBuffer(Buf_.data() + ConsummerPos_, buf, sz, 0);
+ ConvertToPcmBufferFromLE(Buf_.data() + ConsummerPos_, buf, sz, 0, ChannelsNum_);
ConsummerPos_ += sizeBytes;
return sz;
}
@@ -430,10 +420,10 @@ public:
if (sizeBytes > (readyToRead + (curPos * BytesPerSample_))) {
const size_t ready = readyToRead / BytesPerSample_;
- ConvertToPcmBuffer(audioData, buf, ready, curPos);
+ ConvertToPcmBufferFromLE(audioData, buf, ready, curPos, ChannelsNum_);
curPos += ready;
} else {
- ConvertToPcmBuffer(audioData, buf, sz - curPos, curPos);
+ ConvertToPcmBufferFromLE(audioData, buf, sz - curPos, curPos, ChannelsNum_);
size_t leftBytes = readyToRead - (sz - curPos) * BytesPerSample_;
Buf_.resize(leftBytes);
std::memcpy(Buf_.data(), audioData + (sz - curPos) * BytesPerSample_, leftBytes);
@@ -484,10 +474,10 @@ private:
HANDLE OutFile = NULL;
};
-IPCMProviderImpl* CreatePCMIOReadImpl(const std::string& path) {
+IPCMProviderImpl* CreatePCMIOMFReadImpl(const std::string& path) {
return new TPCMIOMediaFoundationFile(path);
}
-IPCMProviderImpl* CreatePCMIOWriteImpl(const std::string& path, int channels, int sampleRate) {
+IPCMProviderImpl* CreatePCMIOMFWriteImpl(const std::string& path, int channels, int sampleRate) {
return new TPCMIOMediaFoundationFile(path, channels, sampleRate);
} \ No newline at end of file
diff --git a/src/platform/win/pcm_io/mf/pcm_io_mf.h b/src/platform/win/pcm_io/mf/pcm_io_mf.h
new file mode 100644
index 0000000..71b18d1
--- /dev/null
+++ b/src/platform/win/pcm_io/mf/pcm_io_mf.h
@@ -0,0 +1,26 @@
+/*
+ * This file is part of AtracDEnc.
+ *
+ * AtracDEnc is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * AtracDEnc is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with AtracDEnc; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+
+#include <string>
+
+class IPCMProviderImpl;
+
+IPCMProviderImpl* CreatePCMIOMFReadImpl(const std::string& path);
+IPCMProviderImpl* CreatePCMIOMFWriteImpl(const std::string& path, int channels, int sampleRate); \ No newline at end of file
diff --git a/src/platform/win/pcm_io/pcm_io.cpp b/src/platform/win/pcm_io/pcm_io.cpp
new file mode 100644
index 0000000..fb44cc0
--- /dev/null
+++ b/src/platform/win/pcm_io/pcm_io.cpp
@@ -0,0 +1,64 @@
+/*
+ * This file is part of AtracDEnc.
+ *
+ * AtracDEnc is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * AtracDEnc is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with AtracDEnc; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "pcm_io_impl.h"
+#include "mf/pcm_io_mf.h"
+#include "win32/pcm_io_win32.h"
+
+#include <endian.h>
+
+#include <iostream>
+#include <windows.h>
+
+
+void ConvertToPcmBufferFromLE(const BYTE* audioData, TPCMBuffer<TFloat>& buf, size_t sz, size_t shift, size_t channelsNum) {
+ if (channelsNum == 1) {
+ for (size_t i = 0; i < sz; i++) {
+ *(buf[i + shift] + 0) = (*(int16_t*)(audioData + i * 2 + 0)) / (TFloat)32768.0;
+ }
+ } else {
+ for (size_t i = 0; i < sz; i++) {
+ *(buf[i + shift] + 0) = (*(int16_t*)(audioData + i * 4 + 0)) / (TFloat)32768.0;
+ *(buf[i + shift] + 1) = (*(int16_t*)(audioData + i * 4 + 2)) / (TFloat)32768.0;
+ }
+ }
+}
+
+void ConvertToPcmBufferFromBE(const BYTE* audioData, TPCMBuffer<TFloat>& buf, size_t sz, size_t shift, size_t channelsNum) {
+ if (channelsNum == 1) {
+ for (size_t i = 0; i < sz; i++) {
+ *(buf[i + shift] + 0) = conv_ntoh((*(int16_t*)(audioData + i * 2 + 0))) / (TFloat)32768.0;
+ }
+ } else {
+ for (size_t i = 0; i < sz; i++) {
+ *(buf[i + shift] + 0) = conv_ntoh((*(int16_t*)(audioData + i * 4 + 0))) / (TFloat)32768.0;
+ *(buf[i + shift] + 1) = conv_ntoh((*(int16_t*)(audioData + i * 4 + 2))) / (TFloat)32768.0;
+ }
+ }
+}
+
+IPCMProviderImpl* CreatePCMIOReadImpl(const std::string& path) {
+ if (path == "-") {
+ return CreatePCMIOStreamWin32ReadImpl();
+ }
+ return CreatePCMIOMFReadImpl(path);
+}
+
+IPCMProviderImpl* CreatePCMIOWriteImpl(const std::string& path, int channels, int sampleRate) {
+ return CreatePCMIOMFWriteImpl(path, channels, sampleRate);
+} \ No newline at end of file
diff --git a/src/platform/win/pcm_io/pcm_io_impl.h b/src/platform/win/pcm_io/pcm_io_impl.h
new file mode 100644
index 0000000..117ebe0
--- /dev/null
+++ b/src/platform/win/pcm_io/pcm_io_impl.h
@@ -0,0 +1,26 @@
+/*
+ * This file is part of AtracDEnc.
+ *
+ * AtracDEnc is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * AtracDEnc is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with AtracDEnc; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+
+#include "../../../wav.h"
+
+#include <windows.h>
+
+void ConvertToPcmBufferFromLE(const BYTE* audioData, TPCMBuffer<TFloat>& buf, size_t sz, size_t shift, size_t channelsNum);
+void ConvertToPcmBufferFromBE(const BYTE* audioData, TPCMBuffer<TFloat>& buf, size_t sz, size_t shift, size_t channelsNum); \ No newline at end of file
diff --git a/src/platform/win/pcm_io/win32/pcm_io_win32.cpp b/src/platform/win/pcm_io/win32/pcm_io_win32.cpp
new file mode 100644
index 0000000..3454bb6
--- /dev/null
+++ b/src/platform/win/pcm_io/win32/pcm_io_win32.cpp
@@ -0,0 +1,172 @@
+/*
+ * This file is part of AtracDEnc.
+ *
+ * AtracDEnc is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * AtracDEnc is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with AtracDEnc; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "../../../wav.h"
+#include "../../../env.h"
+
+#include <endian.h>
+
+#include "pcm_io_win32.h"
+#include "../pcm_io_impl.h"
+
+#include<windows.h>
+
+static std::string GetLastErrorAsString()
+{
+ DWORD errorMessageID = ::GetLastError();
+ if (errorMessageID == 0)
+ return std::string();
+
+ LPSTR messageBuffer = nullptr;
+ size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
+
+ std::string message(messageBuffer, size);
+
+ LocalFree(messageBuffer);
+
+ return message;
+}
+
+class TPCMIOStreamWin32 : public IPCMProviderImpl {
+public:
+ TPCMIOStreamWin32() {
+ ReadHandle_ = GetStdHandle(STD_INPUT_HANDLE);
+ if (ReadHandle_ == INVALID_HANDLE_VALUE) {
+ const std::string msg = "Unable to open input stream " + GetLastErrorAsString();
+ throw std::exception(msg.data());
+ }
+
+ static const DWORD headerSz = 24;
+ Buf_.resize(headerSz);
+
+ DWORD read;
+ if (ReadFile(ReadHandle_, Buf_.data(), headerSz, &read, NULL)) {
+ if (read != headerSz) {
+ throw std::exception("Not enough data to determinate format.");
+ }
+
+ const uint32_t offset = ParseHeader();
+ if (offset < headerSz) {
+ throw std::exception("incorrect data offset");
+ }
+
+ uint32_t toSkip = offset - headerSz;
+ while (toSkip) {
+ char c;
+ bool success;
+ success = ReadFile(ReadHandle_, &c, 1, &read, NULL);
+ if (!success || !read) {
+ throw std::exception("Unable to seek to data position");
+ }
+ toSkip--;
+ }
+ } else {
+ const std::string msg = "Unable to read header from pipe " + GetLastErrorAsString();
+ throw std::exception(msg.data());
+ }
+ }
+
+ size_t Read(TPCMBuffer<TFloat>& buf, size_t sz) override {
+ if (Finished_)
+ return 0;
+
+ DWORD bytesToRead = sz * 2 * ChannelsNum_; // 16 bit per sampple
+ Buf_.resize(bytesToRead);
+
+ DWORD pos = 0;
+
+ while (pos < bytesToRead) {
+ DWORD read;
+ bool success;
+ success = ReadFile(ReadHandle_, Buf_.data() + pos, bytesToRead - pos, &read, NULL);
+ if (!success || !read) {
+ Finished_ = true;
+ break;
+ }
+ pos += read;
+ }
+
+ size_t toConvert = pos / 2 / ChannelsNum_;
+ ConvertToPcmBufferFromBE(Buf_.data(), buf, toConvert, 0, ChannelsNum_);
+
+ return toConvert;
+ }
+
+ size_t Write(const TPCMBuffer<TFloat>& buf, size_t sz) override {
+ abort();
+ return 0;
+ }
+
+ size_t GetChannelsNum() const override {
+ return ChannelsNum_;
+ }
+
+ size_t GetSampleRate() const override {
+ return SampleRate_;
+ }
+
+ size_t GetTotalSamples() const override {
+ return (size_t)-1;
+ }
+
+private:
+ static uint32_t ExtractValue(BYTE* buf) {
+ uint32_t tmp;
+ memcpy(&tmp, buf, 4);
+ return conv_ntoh(tmp);
+ }
+
+ uint32_t ParseHeader() {
+ static const std::vector<BYTE> magic = { '.', 's', 'n', 'd' };
+ if (!std::equal(Buf_.begin(), Buf_.begin() + magic.size(), magic.begin())) {
+ throw std::exception("Input stream must have AU(SND) format");
+ }
+
+ uint32_t dataOffset = ExtractValue(&Buf_[4]);
+ //uint32_t dataSize = ExtractValue(&Buf_[8]);
+
+ uint32_t encoding = ExtractValue(&Buf_[12]);
+ if (encoding != 3) {
+ throw std::exception("Expected PCM 16 bit format");
+ }
+
+ uint32_t sampleRate = ExtractValue(&Buf_[16]);
+ if (sampleRate != 44100) {
+ throw std::exception("Expected 44100Hz sampe rate");
+ }
+
+ ChannelsNum_ = ExtractValue(&Buf_[20]);
+ if (ChannelsNum_ != 1 && ChannelsNum_ != 2) {
+ throw std::exception("Expected 1 or 2 channels");
+ }
+
+ return dataOffset;
+ }
+
+ HANDLE ReadHandle_;
+ uint32_t ChannelsNum_ = 2;
+ const uint32_t SampleRate_ = 44100;
+
+ std::vector<BYTE> Buf_;
+ bool Finished_ = false;
+};
+
+IPCMProviderImpl* CreatePCMIOStreamWin32ReadImpl() {
+ return new TPCMIOStreamWin32();
+} \ No newline at end of file
diff --git a/src/platform/win/pcm_io/win32/pcm_io_win32.h b/src/platform/win/pcm_io/win32/pcm_io_win32.h
new file mode 100644
index 0000000..52b0c1c
--- /dev/null
+++ b/src/platform/win/pcm_io/win32/pcm_io_win32.h
@@ -0,0 +1,23 @@
+/*
+ * This file is part of AtracDEnc.
+ *
+ * AtracDEnc is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * AtracDEnc is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with AtracDEnc; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+
+class IPCMProviderImpl;
+
+IPCMProviderImpl* CreatePCMIOStreamWin32ReadImpl(); \ No newline at end of file