aboutsummaryrefslogtreecommitdiffstats
path: root/src/platform/win
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 /src/platform/win
parentb58f4dd8353121094acdb41ad96fbdec4a580d79 (diff)
downloadatracdenc-3d69df17657c40030fb486a86ef179a42b3873ca.tar.gz
Initiall support of stdin reading for windows
Expected au(snd) format, 44100hz, 16bit, stereo or mono
Diffstat (limited to 'src/platform/win')
-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
6 files changed, 322 insertions, 21 deletions
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