diff options
author | Daniil Cherednik <dan.cherednik@gmail.com> | 2019-12-30 00:13:23 +0300 |
---|---|---|
committer | Daniil Cherednik <dan.cherednik@gmail.com> | 2020-01-01 22:29:50 +0300 |
commit | 3d69df17657c40030fb486a86ef179a42b3873ca (patch) | |
tree | 56002a11e97322d6b6360b1479330ba83e87d731 /src/platform/win | |
parent | b58f4dd8353121094acdb41ad96fbdec4a580d79 (diff) | |
download | atracdenc-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.h | 26 | ||||
-rw-r--r-- | src/platform/win/pcm_io/pcm_io.cpp | 64 | ||||
-rw-r--r-- | src/platform/win/pcm_io/pcm_io_impl.h | 26 | ||||
-rw-r--r-- | src/platform/win/pcm_io/win32/pcm_io_win32.cpp | 172 | ||||
-rw-r--r-- | src/platform/win/pcm_io/win32/pcm_io_win32.h | 23 |
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 |