aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniil Cherednik <dan.cherednik@gmail.com>2019-05-15 01:14:42 +0300
committerDaniil Cherednik <dan.cherednik@gmail.com>2019-05-15 01:14:42 +0300
commited9629395ce9696164c1d617d573a47982e82169 (patch)
tree5dbe92165b9fa3750740331b7af165d0aaab88c3
parent218e2163453deac6f7a74765a21258b5c566a8cc (diff)
downloadatracdenc-ed9629395ce9696164c1d617d573a47982e82169.tar.gz
Support for MS Windows platform
- VS build (2017 tested) - Media Foundation Framework support to read/write pcm data (instead of libsndfile)
-rw-r--r--CMakeLists.txt6
-rw-r--r--src/CMakeLists.txt32
-rw-r--r--src/aea.cpp7
-rw-r--r--src/aea.h2
-rw-r--r--src/atrac/atrac1.cpp2
-rw-r--r--src/atrac/atrac1.h3
-rw-r--r--src/atrac/atrac1_bitalloc.cpp9
-rw-r--r--src/atrac/atrac1_bitalloc.h10
-rw-r--r--src/atrac/atrac1_dequantiser.cpp2
-rw-r--r--src/atrac/atrac1_dequantiser.h2
-rw-r--r--src/atrac/atrac1_qmf.h2
-rw-r--r--src/atrac/atrac3.cpp2
-rw-r--r--src/atrac/atrac3.h3
-rw-r--r--src/atrac/atrac3_bitstream.cpp6
-rw-r--r--src/atrac/atrac3_bitstream.h6
-rw-r--r--src/atrac/atrac3_qmf.h2
-rw-r--r--src/atrac/atrac_psy_common.cpp2
-rw-r--r--src/atrac/atrac_psy_common.h2
-rw-r--r--src/atrac/atrac_scale.cpp2
-rw-r--r--src/atrac/atrac_scale.h2
-rw-r--r--src/atrac1denc.cpp2
-rw-r--r--src/atrac1denc.h3
-rw-r--r--src/atrac3denc.cpp2
-rw-r--r--src/atrac3denc.h7
-rw-r--r--src/atrac3denc_ut.cpp2
-rw-r--r--src/atracdenc_ut.cpp2
-rw-r--r--src/bitstream/bitstream.cpp4
-rw-r--r--src/bitstream/bitstream.h2
-rw-r--r--src/bitstream/bitstream_ut.cpp2
-rw-r--r--src/compressed_io.h8
-rw-r--r--src/config.h4
-rw-r--r--src/delay_buffer.h2
-rw-r--r--src/env.cpp31
-rw-r--r--src/env.h (renamed from src/atrac_encode_settings.h)8
-rw-r--r--src/gain_processor.h2
-rw-r--r--src/main.cpp59
-rw-r--r--src/mdct/common.h2
-rw-r--r--src/mdct/mdct.cpp2
-rw-r--r--src/mdct/mdct.h2
-rw-r--r--src/mdct/mdct_ut.cpp2
-rw-r--r--src/oma.cpp2
-rw-r--r--src/oma.h2
-rw-r--r--src/oma/liboma/include/oma.h2
-rw-r--r--src/oma/liboma/src/liboma.c25
-rw-r--r--src/oma/liboma/src/oma_internal.h2
-rw-r--r--src/oma/liboma/src/tools/omacp.c2
-rw-r--r--src/oma/liboma/src/tools/omainfo.c2
-rw-r--r--src/pcm_io_sndfile.cpp81
-rw-r--r--src/pcmengin.h11
-rw-r--r--src/platform/win/getopt/getopt.h655
-rw-r--r--src/platform/win/pcm_io_mf/pcm_io_mf.cpp493
-rw-r--r--src/qmf/qmf.cpp2
-rw-r--r--src/qmf/qmf.h2
-rw-r--r--src/transient_detector.cpp2
-rw-r--r--src/transient_detector.h2
-rw-r--r--src/transient_detector_ut.cpp2
-rw-r--r--src/util.h2
-rw-r--r--src/util_ut.cpp2
-rw-r--r--src/wav.cpp61
-rw-r--r--src/wav.h27
-rw-r--r--test/CMakeLists.txt2
61 files changed, 1491 insertions, 142 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a1f680e..fe996e5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,7 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
-add_subdirectory(3rd/gtest-1.7.0)
+if (UNIX)
+ add_subdirectory(3rd/gtest-1.7.0)
+ add_subdirectory(test)
+endif()
add_subdirectory(src)
-add_subdirectory(test)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index d0395ab..146b670 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,4 +1,4 @@
-CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
macro(use_11)
if (CMAKE_VERSION VERSION_LESS "3.1")
@@ -17,14 +17,34 @@ use_11()
#add_definitions( "-Wall -O2 -g -Rpass-analysis=loop-vectorize" )
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fsanitize=address -fno-omit-frame-pointer")
-add_definitions( "-Wall -O2 -g" )
+if (UNIX)
+ add_definitions( "-Wall -O2 -g" )
+endif()
project(atracdenc)
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/modules")
-INCLUDE(FindLibSndFile)
-include_directories(${LIBSNDFILE_INCLUDE_DIR})
+if (WIN32)
+ add_compile_definitions(PLATFORM_WINDOWS)
+ include_directories("platform/win/getopt")
+ set(SOURCE_PCM_IO_LIB
+ platform/win/pcm_io_mf/pcm_io_mf.cpp
+ )
+else()
+ INCLUDE(FindLibSndFile)
+ include_directories(${LIBSNDFILE_INCLUDE_DIR})
+ set(SOURCE_PCM_IO_LIB
+ pcm_io_sndfile.cpp
+ )
+endif()
+
+include (TestBigEndian)
+TEST_BIG_ENDIAN(BIGENDIAN_ORDER)
+if (${BIGENDIAN})
+ add_compile_definitions(BIGENDIAN_ORDER)
+endif()
+
include_directories("oma/liboma/include")
set(SOURCE_FFT_LIB fft/kissfft_impl/kiss_fft.c)
@@ -34,6 +54,7 @@ set(SOURCE_EXE
main.cpp
wav.cpp
aea.cpp
+ env.cpp
transient_detector.cpp
atrac1denc.cpp
bitstream/bitstream.cpp
@@ -50,7 +71,8 @@ set(SOURCE_EXE
)
add_library(fft_impl STATIC ${SOURCE_FFT_LIB})
+add_library(pcm_io STATIC ${SOURCE_PCM_IO_LIB})
add_library(oma STATIC ${SOURCE_OMA_LIB})
add_executable(atracdenc ${SOURCE_EXE})
-target_link_libraries(atracdenc fft_impl oma ${SNDFILE_LIBRARIES})
+target_link_libraries(atracdenc fft_impl pcm_io oma ${SNDFILE_LIBRARIES})
diff --git a/src/aea.cpp b/src/aea.cpp
index 4603aea..4387825 100644
--- a/src/aea.cpp
+++ b/src/aea.cpp
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -24,9 +24,8 @@
using std::string;
-
TAea::TMeta TAea::ReadMeta(const string& filename) {
- FILE* fp = fopen(filename.c_str(), "r");
+ FILE* fp = fopen(filename.c_str(), "rb");
if (!fp)
throw TAeaIOError("Can't open file to read", errno);
std::array<char, AeaMetaSize> buf;
@@ -44,7 +43,7 @@ TAea::TMeta TAea::ReadMeta(const string& filename) {
}
TAea::TMeta TAea::CreateMeta(const string& filename, const string& title, int channelNum, uint32_t numFrames) {
- FILE* fp = fopen(filename.c_str(), "w");
+ FILE* fp = fopen(filename.c_str(), "wb");
if (!fp)
throw TAeaIOError("Can't open file to write", errno);
std::array<char, AeaMetaSize> buf;
diff --git a/src/aea.h b/src/aea.h
index 6b8c334..a1d99bc 100644
--- a/src/aea.h
+++ b/src/aea.h
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/atrac/atrac1.cpp b/src/atrac/atrac1.cpp
index b96fa30..f7e6c61 100644
--- a/src/atrac/atrac1.cpp
+++ b/src/atrac/atrac1.cpp
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/atrac/atrac1.h b/src/atrac/atrac1.h
index 460c86d..45d1bdf 100644
--- a/src/atrac/atrac1.h
+++ b/src/atrac/atrac1.h
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -22,6 +22,7 @@
#include <map>
#include <math.h>
#include "../bitstream/bitstream.h"
+#include "../config.h"
namespace NAtracDEnc {
namespace NAtrac1 {
diff --git a/src/atrac/atrac1_bitalloc.cpp b/src/atrac/atrac1_bitalloc.cpp
index 1a7b155..ae6ad2f 100644
--- a/src/atrac/atrac1_bitalloc.cpp
+++ b/src/atrac/atrac1_bitalloc.cpp
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -23,6 +23,7 @@
#include <math.h>
#include <cassert>
#include "../bitstream/bitstream.h"
+#include "../env.h"
namespace NAtracDEnc {
namespace NAtrac1 {
@@ -217,6 +218,12 @@ uint32_t TAtrac1SimpleBitAlloc::Write(const std::vector<TScaledBlock>& scaledBlo
return BfuAmountTab[bfuIdx];
}
+TAtrac1BitStreamWriter::TAtrac1BitStreamWriter(TAea* container)
+ : Container(container)
+{
+ NEnv::SetRoundFloat();
+};
+
void TAtrac1BitStreamWriter::WriteBitStream(const vector<uint32_t>& bitsPerEachBlock,
const std::vector<TScaledBlock>& scaledBlocks,
uint32_t bfuAmountIdx,
diff --git a/src/atrac/atrac1_bitalloc.h b/src/atrac/atrac1_bitalloc.h
index 695defc..2478ddb 100644
--- a/src/atrac/atrac1_bitalloc.h
+++ b/src/atrac/atrac1_bitalloc.h
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -24,7 +24,6 @@
#include <vector>
#include <map>
#include <cstdint>
-#include <cfenv>
namespace NAtracDEnc {
namespace NAtrac1 {
@@ -50,11 +49,8 @@ public:
class TAtrac1BitStreamWriter : public virtual TAtrac1Data {
TAea* Container;
public:
- explicit TAtrac1BitStreamWriter(TAea* container)
- : Container(container)
- {
- fesetround(FE_TONEAREST);
- };
+ explicit TAtrac1BitStreamWriter(TAea* container);
+
void WriteBitStream(const std::vector<uint32_t>& bitsPerEachBlock, const std::vector<TScaledBlock>& scaledBlocks,
uint32_t bfuAmountIdx, const TBlockSize& blockSize);
};
diff --git a/src/atrac/atrac1_dequantiser.cpp b/src/atrac/atrac1_dequantiser.cpp
index 9cc0666..a259f42 100644
--- a/src/atrac/atrac1_dequantiser.cpp
+++ b/src/atrac/atrac1_dequantiser.cpp
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/atrac/atrac1_dequantiser.h b/src/atrac/atrac1_dequantiser.h
index 80e1e9c..d3c25bd 100644
--- a/src/atrac/atrac1_dequantiser.h
+++ b/src/atrac/atrac1_dequantiser.h
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/atrac/atrac1_qmf.h b/src/atrac/atrac1_qmf.h
index efcf2c1..8b3e5e4 100644
--- a/src/atrac/atrac1_qmf.h
+++ b/src/atrac/atrac1_qmf.h
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/atrac/atrac3.cpp b/src/atrac/atrac3.cpp
index 8236a92..82fb34b 100644
--- a/src/atrac/atrac3.cpp
+++ b/src/atrac/atrac3.cpp
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/atrac/atrac3.h b/src/atrac/atrac3.h
index b6594e5..eb97808 100644
--- a/src/atrac/atrac3.h
+++ b/src/atrac/atrac3.h
@@ -12,11 +12,12 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * 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 "../config.h"
#include <math.h>
#include <cstdint>
#include <vector>
diff --git a/src/atrac/atrac3_bitstream.cpp b/src/atrac/atrac3_bitstream.cpp
index 8a391db..d39faa2 100644
--- a/src/atrac/atrac3_bitstream.cpp
+++ b/src/atrac/atrac3_bitstream.cpp
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -196,7 +196,7 @@ void TAtrac3BitStreamWriter::EncodeSpecs(const TSingleChannelElement& sce, NBitS
int mt[MaxSpecs];
const vector<TScaledBlock>& scaledBlocks = sce.ScaledBlocks;
- auto allocation = CreateAllocation(sce, bitsUsed, mt);
+ const auto& allocation = CreateAllocation(sce, bitsUsed, mt);
const vector<uint32_t>& precisionPerEachBlocks = allocation.second;
EncodeTonalComponents(sce, precisionPerEachBlocks, bitStream);
const uint32_t numBlocks = precisionPerEachBlocks.size(); //number of blocks to save
@@ -471,7 +471,7 @@ void TAtrac3BitStreamWriter::WriteSoundUnit(const vector<TSingleChannelElement>&
assert(s < 8);
}
}
- const uint16_t bitsUsedByGainInfoAndHeader = bitStream->GetSizeInBits();
+ const uint16_t bitsUsedByGainInfoAndHeader = (uint16_t)bitStream->GetSizeInBits();
usedBits[channel] = bitsUsedByGainInfoAndHeader;
assert(bitStream->GetSizeInBits() == usedBits[channel]);
}
diff --git a/src/atrac/atrac3_bitstream.h b/src/atrac/atrac3_bitstream.h
index b65e212..24c2ca7 100644
--- a/src/atrac/atrac3_bitstream.h
+++ b/src/atrac/atrac3_bitstream.h
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -25,7 +25,7 @@
#include "atrac_scale.h"
#include <vector>
#include <utility>
-#include <cfenv>
+#include "../env.h"
namespace NAtracDEnc {
namespace NAtrac3 {
@@ -89,7 +89,7 @@ public:
, Params(params)
, BfuIdxConst(bfuIdxConst)
{
- fesetround(FE_TONEAREST);
+ NEnv::SetRoundFloat();
}
void WriteSoundUnit(const std::vector<TSingleChannelElement>& singleChannelElements);
diff --git a/src/atrac/atrac3_qmf.h b/src/atrac/atrac3_qmf.h
index 49f9dcd..6f26d54 100644
--- a/src/atrac/atrac3_qmf.h
+++ b/src/atrac/atrac3_qmf.h
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/atrac/atrac_psy_common.cpp b/src/atrac/atrac_psy_common.cpp
index 8ff86a1..257b8f3 100644
--- a/src/atrac/atrac_psy_common.cpp
+++ b/src/atrac/atrac_psy_common.cpp
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/atrac/atrac_psy_common.h b/src/atrac/atrac_psy_common.h
index 45a0706..dc1e65e 100644
--- a/src/atrac/atrac_psy_common.h
+++ b/src/atrac/atrac_psy_common.h
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/atrac/atrac_scale.cpp b/src/atrac/atrac_scale.cpp
index a8a6fda..f24f7b0 100644
--- a/src/atrac/atrac_scale.cpp
+++ b/src/atrac/atrac_scale.cpp
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/atrac/atrac_scale.h b/src/atrac/atrac_scale.h
index c992c03..eadb6bd 100644
--- a/src/atrac/atrac_scale.h
+++ b/src/atrac/atrac_scale.h
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/atrac1denc.cpp b/src/atrac1denc.cpp
index 49ee644..e15680b 100644
--- a/src/atrac1denc.cpp
+++ b/src/atrac1denc.cpp
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/atrac1denc.h b/src/atrac1denc.h
index 821591a..33bbc76 100644
--- a/src/atrac1denc.h
+++ b/src/atrac1denc.h
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -20,7 +20,6 @@
#include "pcmengin.h"
#include "aea.h"
#include "oma.h"
-#include "atrac_encode_settings.h"
#include "transient_detector.h"
#include "atrac/atrac1.h"
#include "atrac/atrac1_qmf.h"
diff --git a/src/atrac3denc.cpp b/src/atrac3denc.cpp
index 519cd9b..9bb7eb2 100644
--- a/src/atrac3denc.cpp
+++ b/src/atrac3denc.cpp
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/atrac3denc.h b/src/atrac3denc.h
index a07f717..adf6df6 100644
--- a/src/atrac3denc.h
+++ b/src/atrac3denc.h
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -32,6 +32,7 @@
#include "mdct/mdct.h"
#include "gain_processor.h"
+#include <algorithm>
#include <functional>
#include <array>
#include <cmath>
@@ -41,10 +42,10 @@ namespace NAtracDEnc {
inline uint16_t RelationToIdx(TFloat x) {
if (x <= 0.5) {
- x = 1.0 / std::max(x, 0.00048828125);
+ x = 1.0 / std::max(x, (TFloat)0.00048828125);
return 4 + GetFirstSetBit(std::trunc(x));
} else {
- x = std::min(x, 16.0);
+ x = std::min(x, (TFloat)16.0);
return 4 - GetFirstSetBit(std::trunc(x));
}
}
diff --git a/src/atrac3denc_ut.cpp b/src/atrac3denc_ut.cpp
index 7813210..f52af02 100644
--- a/src/atrac3denc_ut.cpp
+++ b/src/atrac3denc_ut.cpp
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/atracdenc_ut.cpp b/src/atracdenc_ut.cpp
index 7e81716..9b7b331 100644
--- a/src/atracdenc_ut.cpp
+++ b/src/atracdenc_ut.cpp
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/bitstream/bitstream.cpp b/src/bitstream/bitstream.cpp
index 733fb15..ddcd288 100644
--- a/src/bitstream/bitstream.cpp
+++ b/src/bitstream/bitstream.cpp
@@ -12,13 +12,13 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "bitstream.h"
-#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#ifndef BIGENDIAN_ORDER
#define NBITSTREAM__LITTLE_ENDIAN_CPU
#endif
diff --git a/src/bitstream/bitstream.h b/src/bitstream/bitstream.h
index 08eb74f..cfba790 100644
--- a/src/bitstream/bitstream.h
+++ b/src/bitstream/bitstream.h
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/bitstream/bitstream_ut.cpp b/src/bitstream/bitstream_ut.cpp
index d339b06..853b969 100644
--- a/src/bitstream/bitstream_ut.cpp
+++ b/src/bitstream/bitstream_ut.cpp
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/compressed_io.h b/src/compressed_io.h
index c325ce9..7fca4f1 100644
--- a/src/compressed_io.h
+++ b/src/compressed_io.h
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -25,12 +25,12 @@
class ICompressedIO {
public:
class TFrame {
- uint64_t Sz;
+ size_t Sz;
char* Data;
TFrame(const TFrame& src) = delete;
TFrame() = delete;
public:
- TFrame(uint64_t sz)
+ TFrame(size_t sz)
: Sz(sz)
{
Data = new char[Sz];
@@ -38,7 +38,7 @@ public:
~TFrame() {
delete[] Data;
}
- uint64_t Size() const { return Sz; }
+ size_t Size() const { return Sz; }
char* Get() { return Data; }
};
virtual void WriteFrame(std::vector<char> data) = 0;
diff --git a/src/config.h b/src/config.h
index 8d9461d..0e2fd8d 100644
--- a/src/config.h
+++ b/src/config.h
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -20,6 +20,8 @@
#define CONFIG_DOUBLE
+#define NOMINMAX
+
#ifdef CONFIG_DOUBLE
# define kiss_fft_scalar double
typedef double TFloat;
diff --git a/src/delay_buffer.h b/src/delay_buffer.h
index 9e0cfb1..14555fa 100644
--- a/src/delay_buffer.h
+++ b/src/delay_buffer.h
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/env.cpp b/src/env.cpp
new file mode 100644
index 0000000..b5d2a5b
--- /dev/null
+++ b/src/env.cpp
@@ -0,0 +1,31 @@
+/*
+ * 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 "env.h"
+
+#include <fenv.h>
+
+#pragma STDC FENV_ACCESS on
+
+namespace NEnv {
+
+void SetRoundFloat() {
+ fesetround(FE_TONEAREST);
+}
+
+} // namespace NEnv \ No newline at end of file
diff --git a/src/atrac_encode_settings.h b/src/env.h
index 897b6ae..66a21dc 100644
--- a/src/atrac_encode_settings.h
+++ b/src/env.h
@@ -12,12 +12,14 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * 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
-namespace NAtracDEnc {
+namespace NEnv {
-}
+void SetRoundFloat();
+
+} // namespace NEnv \ No newline at end of file
diff --git a/src/gain_processor.h b/src/gain_processor.h
index 66d6b1c..f43531f 100644
--- a/src/gain_processor.h
+++ b/src/gain_processor.h
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/main.cpp b/src/main.cpp
index a1f2867..4fb1ee9 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -29,6 +29,11 @@
#include "atrac1denc.h"
#include "atrac3denc.h"
+#ifdef PLATFORM_WINDOWS
+#include <windows.h>
+#include <shellapi.h>
+#endif
+
using std::cout;
using std::cerr;
using std::endl;
@@ -104,8 +109,8 @@ enum EOptions
static void CheckInputFormat(const TWav* p)
{
- if (p->IsFormatSupported() == false)
- throw std::runtime_error("unsupported format of input file");
+// if (p->IsFormatSupported() == false)
+// throw std::runtime_error("unsupported format of input file");
if (p->GetSampleRate() != 44100)
throw std::runtime_error("unsupported sample rate");
@@ -199,7 +204,7 @@ static void PrepareAtrac3Encoder(const string& inFile,
atracProcessor->reset(new TAtrac3Processor(std::move(omaIO), std::move(encoderSettings)));
}
-int main(int argc, char* const* argv)
+int main_(int argc, char* const* argv)
{
const char* myName = argv[0];
static struct option longopts[] = {
@@ -364,17 +369,57 @@ int main(int argc, char* const* argv)
while (totalSamples > (processed = pcmEngine->ApplyProcess(pcmFrameSz, atracLambda)))
{
if (!noStdOut)
- printProgress(processed*100/totalSamples);
+ printProgress(static_cast<int>(processed*100/totalSamples));
}
if (!noStdOut)
cout << "\nDone" << endl;
}
catch (TAeaIOError err) {
cerr << "Aea IO fatal error: " << err.what() << endl;
- exit(1);
+ return 1;
}
catch (TWavIOError err) {
cerr << "Wav IO fatal error: " << err.what() << endl;
- exit(1);
+ return 1;
}
+ catch (const std::exception& ex) {
+ cerr << "Encode/Decode error: " << ex.what() << endl;
+ return 1;
+ }
+ return 0;
+}
+
+int main(int argc, char* const* argv) {
+#ifndef PLATFORM_WINDOWS
+ return main_(argc, argv);
+# else
+ LPWSTR* argvW = CommandLineToArgvW(GetCommandLineW(), &argc);
+
+ std::vector<char*> newArgv(argc);
+
+ for (int i = 0; i < argc; i++) {
+ const size_t sz = wcslen(argvW[i]);
+ const size_t maxUtf8Len = sz * 4;
+ // 0 termination in any case
+ std::vector<char> buf(maxUtf8Len + 1);
+
+ if (!WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, argvW[i], -1, buf.data(), maxUtf8Len, NULL, NULL)) {
+ DWORD lastError = GetLastError();
+ std::cerr << "Unable to convert argument to uft8, " << std::hex << lastError << std::endl;
+ }
+ const size_t utf8Len = strlen(buf.data());
+ newArgv[i] = new char[utf8Len + 1];
+ strcpy(newArgv[i], buf.data());
+ }
+
+
+ int rv = main_(argc, newArgv.data());
+
+ for (auto& a : newArgv) {
+ delete[] a;
+ }
+
+ LocalFree(argvW);
+ return rv;
+#endif
}
diff --git a/src/mdct/common.h b/src/mdct/common.h
index 1dd2afd..9b3c893 100644
--- a/src/mdct/common.h
+++ b/src/mdct/common.h
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/mdct/mdct.cpp b/src/mdct/mdct.cpp
index eb77fde..6acd8d3 100644
--- a/src/mdct/mdct.cpp
+++ b/src/mdct/mdct.cpp
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/mdct/mdct.h b/src/mdct/mdct.h
index 6af27b0..97d5437 100644
--- a/src/mdct/mdct.h
+++ b/src/mdct/mdct.h
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/mdct/mdct_ut.cpp b/src/mdct/mdct_ut.cpp
index fcfd4ff..f9fb688 100644
--- a/src/mdct/mdct_ut.cpp
+++ b/src/mdct/mdct_ut.cpp
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/oma.cpp b/src/oma.cpp
index 3de7f8b..ceeaf69 100644
--- a/src/oma.cpp
+++ b/src/oma.cpp
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/oma.h b/src/oma.h
index fdf0ec2..d706d51 100644
--- a/src/oma.h
+++ b/src/oma.h
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/oma/liboma/include/oma.h b/src/oma/liboma/include/oma.h
index 232f8e5..89fbbaa 100644
--- a/src/oma/liboma/include/oma.h
+++ b/src/oma/liboma/include/oma.h
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/oma/liboma/src/liboma.c b/src/oma/liboma/src/liboma.c
index d8a4358..d44b490 100644
--- a/src/oma/liboma/src/liboma.c
+++ b/src/oma/liboma/src/liboma.c
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -25,11 +25,9 @@
#include <string.h>
#include <assert.h>
-//to use htonl
-//TODO: rewrite
-#include <arpa/inet.h>
-static const int OMA_HEADER_SIZE = 96;
+#define OMA_HEADER_SIZE 96
+
static const int liboma_samplerates[8] = { 32000, 44100, 48000, 88200, 96000, 0 };
static const char* codec_name[6] = { "ATRAC3", "ATRAC3PLUS", "MPEG1LAYER3", "LPCM", "", "OMAC_ID_WMA" };
static char ea3_str[] = {'E', 'A', '3'};
@@ -44,7 +42,20 @@ 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
static __thread int err;
+#endif
+
int oma_get_last_err() {
return err;
}
@@ -116,7 +127,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 = htonl((OMAC_ID_ATRAC3 << 24) | (js << 17) | ((uint32_t)samplerate_idx << 13) | framesz);
+ *params = swapbyte32((OMAC_ID_ATRAC3 << 24) | (js << 17) | ((uint32_t)samplerate_idx << 13) | framesz);
return 0;
}
@@ -152,7 +163,7 @@ static int oma_write_atrac3p_header(uint32_t *params, oma_info_t *info) {
if (ch_id < 0)
return -1;
- *params = htonl((OMAC_ID_ATRAC3PLUS << 24) | ((int32_t)samplerate_idx << 13) | ((ch_id + 1) << 10) | framesz);
+ *params = swapbyte32((OMAC_ID_ATRAC3PLUS << 24) | ((int32_t)samplerate_idx << 13) | ((ch_id + 1) << 10) | framesz);
return 0;
}
diff --git a/src/oma/liboma/src/oma_internal.h b/src/oma/liboma/src/oma_internal.h
index f6e2e2e..1334080 100644
--- a/src/oma/liboma/src/oma_internal.h
+++ b/src/oma/liboma/src/oma_internal.h
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/oma/liboma/src/tools/omacp.c b/src/oma/liboma/src/tools/omacp.c
index 77e1325..b938f04 100644
--- a/src/oma/liboma/src/tools/omacp.c
+++ b/src/oma/liboma/src/tools/omacp.c
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/oma/liboma/src/tools/omainfo.c b/src/oma/liboma/src/tools/omainfo.c
index d9f31aa..1edee98 100644
--- a/src/oma/liboma/src/tools/omainfo.c
+++ b/src/oma/liboma/src/tools/omainfo.c
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/pcm_io_sndfile.cpp b/src/pcm_io_sndfile.cpp
new file mode 100644
index 0000000..52737c0
--- /dev/null
+++ b/src/pcm_io_sndfile.cpp
@@ -0,0 +1,81 @@
+/*
+ * 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 <sndfile.hh>
+#include <algorithm>
+
+static int fileext_to_libsndfmt(const std::string& filename) {
+ int fmt = SF_FORMAT_WAV; //default fmt
+ if (filename == "-")
+ return SF_FORMAT_AU;
+ size_t pos = filename.find_last_of(".");
+ if (pos == std::string::npos || pos == filename.size() - 1) //no dot or filename.
+ return fmt;
+ std::string ext = filename.substr(pos+1);
+ std::transform(ext.begin(), ext.end(), ext.begin(), ::toupper);
+ if (ext == "AU") {
+ fmt = SF_FORMAT_AU;
+ } else if (ext == "AIFF") {
+ fmt = SF_FORMAT_AIFF;
+ } else if (ext == "PCM" || ext == "RAW") {
+ fmt = SF_FORMAT_RAW;
+ }
+ return fmt;
+}
+
+class TPCMIOSndFile : public IPCMProviderImpl {
+public:
+ TPCMIOSndFile(const std::string& filename)
+ : File(SndfileHandle(filename))
+ {
+ File.command(SFC_SET_NORM_DOUBLE /*| SFC_SET_NORM_FLOAT*/, nullptr, SF_TRUE);
+ }
+ TPCMIOSndFile(const std::string& filename, int channels, int sampleRate)
+ : File(SndfileHandle(filename, SFM_WRITE, fileext_to_libsndfmt(filename) | SF_FORMAT_PCM_16, channels, sampleRate))
+ {
+ File.command(SFC_SET_NORM_DOUBLE /*| SFC_SET_NORM_FLOAT*/, nullptr, SF_TRUE);
+ }
+public:
+ size_t GetChannelsNum() const override {
+ return File.channels();
+ }
+ size_t GetSampleRate() const override {
+ return File.samplerate();
+ }
+ size_t GetTotalSamples() const override {
+ return File.frames();
+ }
+ size_t Read(TPCMBuffer<TFloat>& buf, size_t sz) override {
+ return File.readf(buf[0], sz);
+ }
+ size_t Write(const TPCMBuffer<TFloat>& buf, size_t sz) override {
+ return File.writef(buf[0], sz);
+ }
+private:
+ mutable SndfileHandle File;
+};
+
+IPCMProviderImpl* CreatePCMIOReadImpl(const std::string& path) {
+ return new TPCMIOSndFile(path);
+}
+
+IPCMProviderImpl* CreatePCMIOWriteImpl(const std::string& path, int channels, int sampleRate) {
+ return new TPCMIOSndFile(path, channels, sampleRate);
+}
diff --git a/src/pcmengin.h b/src/pcmengin.h
index 629f98b..915fc7c 100644
--- a/src/pcmengin.h
+++ b/src/pcmengin.h
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -23,6 +23,7 @@
#include <exception>
#include <functional>
#include <cstdlib>
+#include <iostream>
#include <assert.h>
#include <string.h>
@@ -61,14 +62,18 @@ public:
}
T* operator[](size_t pos) {
size_t rpos = pos * NumChannels;
- if (rpos >= Buf_.size())
+ if (rpos >= Buf_.size()) {
+ std::cerr << "attempt to access out of buffer pos: " << pos << std::endl;
std::abort();
+ }
return &Buf_[rpos];
}
const T* operator[](size_t pos) const {
size_t rpos = pos * NumChannels;
- if (rpos >= Buf_.size())
+ if (rpos >= Buf_.size()) {
+ std::cerr << "attempt to access out of buffer pos: " << pos << std::endl;
std::abort();
+ }
return &Buf_[rpos];
}
uint16_t Channels() const {
diff --git a/src/platform/win/getopt/getopt.h b/src/platform/win/getopt/getopt.h
new file mode 100644
index 0000000..bfa86b3
--- /dev/null
+++ b/src/platform/win/getopt/getopt.h
@@ -0,0 +1,655 @@
+#ifndef __GETOPT_H__
+/**
+ * DISCLAIMER
+ * This file is part of the mingw-w64 runtime package.
+ *
+ * The mingw-w64 runtime package and its code is distributed in the hope that it
+ * will be useful but WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESSED OR
+ * IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to
+ * warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+ /*
+ * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dieter Baron and Thomas Klausner.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma warning(disable:4996);
+
+#define __GETOPT_H__
+
+#define NOMINMAX
+
+/* All the headers include this file. */
+#include <crtdefs.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <windows.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */
+
+#ifdef REPLACE_GETOPT
+int opterr = 1; /* if error message should be printed */
+int optind = 1; /* index into parent argv vector */
+int optopt = '?'; /* character checked for validity */
+#undef optreset /* see getopt.h */
+#define optreset __mingw_optreset
+int optreset; /* reset getopt */
+char *optarg; /* argument associated with option */
+#endif
+
+//extern int optind; /* index of first non-option in argv */
+//extern int optopt; /* single option character, as parsed */
+//extern int opterr; /* flag to enable built-in diagnostics... */
+// /* (user may set to zero, to suppress) */
+//
+//extern char *optarg; /* pointer to argument of current option */
+
+#define PRINT_ERROR ((opterr) && (*options != ':'))
+
+#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
+#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
+#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
+
+/* return values */
+#define BADCH (int)'?'
+#define BADARG ((*options == ':') ? (int)':' : (int)'?')
+#define INORDER (int)1
+
+#ifndef __CYGWIN__
+#define __progname __argv[0]
+#else
+extern char __declspec(dllimport) *__progname;
+#endif
+
+#ifdef __CYGWIN__
+static char EMSG[] = "";
+#else
+#define EMSG ""
+#endif
+
+static int getopt_internal(int, char * const *, const char *,
+ const struct option *, int *, int);
+static int parse_long_options(char * const *, const char *,
+ const struct option *, int *, int);
+static int gcd(int, int);
+static void permute_args(int, int, int, char * const *);
+
+static char *place = EMSG; /* option letter processing */
+
+/* XXX: set optreset to 1 rather than these two */
+static int nonopt_start = -1; /* first non option argument (for permute) */
+static int nonopt_end = -1; /* first option after non options (for permute) */
+
+/* Error messages */
+static const char recargchar[] = "option requires an argument -- %c";
+static const char recargstring[] = "option requires an argument -- %s";
+static const char ambig[] = "ambiguous option -- %.*s";
+static const char noarg[] = "option doesn't take an argument -- %.*s";
+static const char illoptchar[] = "unknown option -- %c";
+static const char illoptstring[] = "unknown option -- %s";
+
+static void
+_vwarnx(const char *fmt,va_list ap)
+{
+ (void)fprintf(stderr,"%s: ",__progname);
+ if (fmt != NULL)
+ (void)vfprintf(stderr,fmt,ap);
+ (void)fprintf(stderr,"\n");
+}
+
+static void
+warnx(const char *fmt,...)
+{
+ va_list ap;
+ va_start(ap,fmt);
+ _vwarnx(fmt,ap);
+ va_end(ap);
+}
+
+/*
+ * Compute the greatest common divisor of a and b.
+ */
+static int
+gcd(int a, int b)
+{
+ int c;
+
+ c = a % b;
+ while (c != 0) {
+ a = b;
+ b = c;
+ c = a % b;
+ }
+
+ return (b);
+}
+
+/*
+ * Exchange the block from nonopt_start to nonopt_end with the block
+ * from nonopt_end to opt_end (keeping the same order of arguments
+ * in each block).
+ */
+static void
+permute_args(int panonopt_start, int panonopt_end, int opt_end,
+ char * const *nargv)
+{
+ int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
+ char *swap;
+
+ /*
+ * compute lengths of blocks and number and size of cycles
+ */
+ nnonopts = panonopt_end - panonopt_start;
+ nopts = opt_end - panonopt_end;
+ ncycle = gcd(nnonopts, nopts);
+ cyclelen = (opt_end - panonopt_start) / ncycle;
+
+ for (i = 0; i < ncycle; i++) {
+ cstart = panonopt_end+i;
+ pos = cstart;
+ for (j = 0; j < cyclelen; j++) {
+ if (pos >= panonopt_end)
+ pos -= nnonopts;
+ else
+ pos += nopts;
+ swap = nargv[pos];
+ /* LINTED const cast */
+ ((char **) nargv)[pos] = nargv[cstart];
+ /* LINTED const cast */
+ ((char **)nargv)[cstart] = swap;
+ }
+ }
+}
+
+#ifdef REPLACE_GETOPT
+/*
+ * getopt --
+ * Parse argc/argv argument vector.
+ *
+ * [eventually this will replace the BSD getopt]
+ */
+int
+getopt(int nargc, char * const *nargv, const char *options)
+{
+
+ /*
+ * We don't pass FLAG_PERMUTE to getopt_internal() since
+ * the BSD getopt(3) (unlike GNU) has never done this.
+ *
+ * Furthermore, since many privileged programs call getopt()
+ * before dropping privileges it makes sense to keep things
+ * as simple (and bug-free) as possible.
+ */
+ return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
+}
+#endif /* REPLACE_GETOPT */
+
+//extern int getopt(int nargc, char * const *nargv, const char *options);
+
+#ifdef _BSD_SOURCE
+/*
+ * BSD adds the non-standard `optreset' feature, for reinitialisation
+ * of `getopt' parsing. We support this feature, for applications which
+ * proclaim their BSD heritage, before including this header; however,
+ * to maintain portability, developers are advised to avoid it.
+ */
+# define optreset __mingw_optreset
+extern int optreset;
+#endif
+#ifdef __cplusplus
+}
+#endif
+/*
+ * POSIX requires the `getopt' API to be specified in `unistd.h';
+ * thus, `unistd.h' includes this header. However, we do not want
+ * to expose the `getopt_long' or `getopt_long_only' APIs, when
+ * included in this manner. Thus, close the standard __GETOPT_H__
+ * declarations block, and open an additional __GETOPT_LONG_H__
+ * specific block, only when *not* __UNISTD_H_SOURCED__, in which
+ * to declare the extended API.
+ */
+#endif /* !defined(__GETOPT_H__) */
+
+#if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__)
+#define __GETOPT_LONG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct option /* specification for a long form option... */
+{
+ const char *name; /* option name, without leading hyphens */
+ int has_arg; /* does it take an argument? */
+ int *flag; /* where to save its status, or NULL */
+ int val; /* its associated status value */
+};
+
+enum /* permitted values for its `has_arg' field... */
+{
+ no_argument = 0, /* option never takes an argument */
+ required_argument, /* option always requires an argument */
+ optional_argument /* option may take an argument */
+};
+
+/*
+ * parse_long_options --
+ * Parse long options in argc/argv argument vector.
+ * Returns -1 if short_too is set and the option does not match long_options.
+ */
+static int
+parse_long_options(char * const *nargv, const char *options,
+ const struct option *long_options, int *idx, int short_too)
+{
+ char *current_argv, *has_equal;
+ size_t current_argv_len;
+ int i, ambiguous, match;
+
+#define IDENTICAL_INTERPRETATION(_x, _y) \
+ (long_options[(_x)].has_arg == long_options[(_y)].has_arg && \
+ long_options[(_x)].flag == long_options[(_y)].flag && \
+ long_options[(_x)].val == long_options[(_y)].val)
+
+ current_argv = place;
+ match = -1;
+ ambiguous = 0;
+
+ optind++;
+
+ if ((has_equal = strchr(current_argv, '=')) != NULL) {
+ /* argument found (--option=arg) */
+ current_argv_len = has_equal - current_argv;
+ has_equal++;
+ } else
+ current_argv_len = strlen(current_argv);
+
+ for (i = 0; long_options[i].name; i++) {
+ /* find matching long option */
+ if (strncmp(current_argv, long_options[i].name,
+ current_argv_len))
+ continue;
+
+ if (strlen(long_options[i].name) == current_argv_len) {
+ /* exact match */
+ match = i;
+ ambiguous = 0;
+ break;
+ }
+ /*
+ * If this is a known short option, don't allow
+ * a partial match of a single character.
+ */
+ if (short_too && current_argv_len == 1)
+ continue;
+
+ if (match == -1) /* partial match */
+ match = i;
+ else if (!IDENTICAL_INTERPRETATION(i, match))
+ ambiguous = 1;
+ }
+ if (ambiguous) {
+ /* ambiguous abbreviation */
+ if (PRINT_ERROR)
+ warnx(ambig, (int)current_argv_len,
+ current_argv);
+ optopt = 0;
+ return (BADCH);
+ }
+ if (match != -1) { /* option found */
+ if (long_options[match].has_arg == no_argument
+ && has_equal) {
+ if (PRINT_ERROR)
+ warnx(noarg, (int)current_argv_len,
+ current_argv);
+ /*
+ * XXX: GNU sets optopt to val regardless of flag
+ */
+ if (long_options[match].flag == NULL)
+ optopt = long_options[match].val;
+ else
+ optopt = 0;
+ return (BADARG);
+ }
+ if (long_options[match].has_arg == required_argument ||
+ long_options[match].has_arg == optional_argument) {
+ if (has_equal)
+ optarg = has_equal;
+ else if (long_options[match].has_arg ==
+ required_argument) {
+ /*
+ * optional argument doesn't use next nargv
+ */
+ optarg = nargv[optind++];
+ }
+ }
+ if ((long_options[match].has_arg == required_argument)
+ && (optarg == NULL)) {
+ /*
+ * Missing argument; leading ':' indicates no error
+ * should be generated.
+ */
+ if (PRINT_ERROR)
+ warnx(recargstring,
+ current_argv);
+ /*
+ * XXX: GNU sets optopt to val regardless of flag
+ */
+ if (long_options[match].flag == NULL)
+ optopt = long_options[match].val;
+ else
+ optopt = 0;
+ --optind;
+ return (BADARG);
+ }
+ } else { /* unknown option */
+ if (short_too) {
+ --optind;
+ return (-1);
+ }
+ if (PRINT_ERROR)
+ warnx(illoptstring, current_argv);
+ optopt = 0;
+ return (BADCH);
+ }
+ if (idx)
+ *idx = match;
+ if (long_options[match].flag) {
+ *long_options[match].flag = long_options[match].val;
+ return (0);
+ } else
+ return (long_options[match].val);
+#undef IDENTICAL_INTERPRETATION
+}
+
+/*
+ * getopt_internal --
+ * Parse argc/argv argument vector. Called by user level routines.
+ */
+static int
+getopt_internal(int nargc, char * const *nargv, const char *options,
+ const struct option *long_options, int *idx, int flags)
+{
+ char *oli; /* option letter list index */
+ int optchar, short_too;
+ static int posixly_correct = -1;
+
+ if (options == NULL)
+ return (-1);
+
+ /*
+ * XXX Some GNU programs (like cvs) set optind to 0 instead of
+ * XXX using optreset. Work around this braindamage.
+ */
+ if (optind == 0)
+ optind = optreset = 1;
+
+ /*
+ * Disable GNU extensions if POSIXLY_CORRECT is set or options
+ * string begins with a '+'.
+ *
+ * CV, 2009-12-14: Check POSIXLY_CORRECT anew if optind == 0 or
+ * optreset != 0 for GNU compatibility.
+ */
+ if (posixly_correct == -1 || optreset != 0)
+ posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
+ if (*options == '-')
+ flags |= FLAG_ALLARGS;
+ else if (posixly_correct || *options == '+')
+ flags &= ~FLAG_PERMUTE;
+ if (*options == '+' || *options == '-')
+ options++;
+
+ optarg = NULL;
+ if (optreset)
+ nonopt_start = nonopt_end = -1;
+start:
+ if (optreset || !*place) { /* update scanning pointer */
+ optreset = 0;
+ if (optind >= nargc) { /* end of argument vector */
+ place = EMSG;
+ if (nonopt_end != -1) {
+ /* do permutation, if we have to */
+ permute_args(nonopt_start, nonopt_end,
+ optind, nargv);
+ optind -= nonopt_end - nonopt_start;
+ }
+ else if (nonopt_start != -1) {
+ /*
+ * If we skipped non-options, set optind
+ * to the first of them.
+ */
+ optind = nonopt_start;
+ }
+ nonopt_start = nonopt_end = -1;
+ return (-1);
+ }
+ if (*(place = nargv[optind]) != '-' ||
+ (place[1] == '\0' && strchr(options, '-') == NULL)) {
+ place = EMSG; /* found non-option */
+ if (flags & FLAG_ALLARGS) {
+ /*
+ * GNU extension:
+ * return non-option as argument to option 1
+ */
+ optarg = nargv[optind++];
+ return (INORDER);
+ }
+ if (!(flags & FLAG_PERMUTE)) {
+ /*
+ * If no permutation wanted, stop parsing
+ * at first non-option.
+ */
+ return (-1);
+ }
+ /* do permutation */
+ if (nonopt_start == -1)
+ nonopt_start = optind;
+ else if (nonopt_end != -1) {
+ permute_args(nonopt_start, nonopt_end,
+ optind, nargv);
+ nonopt_start = optind -
+ (nonopt_end - nonopt_start);
+ nonopt_end = -1;
+ }
+ optind++;
+ /* process next argument */
+ goto start;
+ }
+ if (nonopt_start != -1 && nonopt_end == -1)
+ nonopt_end = optind;
+
+ /*
+ * If we have "-" do nothing, if "--" we are done.
+ */
+ if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
+ optind++;
+ place = EMSG;
+ /*
+ * We found an option (--), so if we skipped
+ * non-options, we have to permute.
+ */
+ if (nonopt_end != -1) {
+ permute_args(nonopt_start, nonopt_end,
+ optind, nargv);
+ optind -= nonopt_end - nonopt_start;
+ }
+ nonopt_start = nonopt_end = -1;
+ return (-1);
+ }
+ }
+
+ /*
+ * Check long options if:
+ * 1) we were passed some
+ * 2) the arg is not just "-"
+ * 3) either the arg starts with -- we are getopt_long_only()
+ */
+ if (long_options != NULL && place != nargv[optind] &&
+ (*place == '-' || (flags & FLAG_LONGONLY))) {
+ short_too = 0;
+ if (*place == '-')
+ place++; /* --foo long option */
+ else if (*place != ':' && strchr(options, *place) != NULL)
+ short_too = 1; /* could be short option too */
+
+ optchar = parse_long_options(nargv, options, long_options,
+ idx, short_too);
+ if (optchar != -1) {
+ place = EMSG;
+ return (optchar);
+ }
+ }
+
+ if ((optchar = (int)*place++) == (int)':' ||
+ (optchar == (int)'-' && *place != '\0') ||
+ (oli = (char*)strchr(options, optchar)) == NULL) {
+ /*
+ * If the user specified "-" and '-' isn't listed in
+ * options, return -1 (non-option) as per POSIX.
+ * Otherwise, it is an unknown option character (or ':').
+ */
+ if (optchar == (int)'-' && *place == '\0')
+ return (-1);
+ if (!*place)
+ ++optind;
+ if (PRINT_ERROR)
+ warnx(illoptchar, optchar);
+ optopt = optchar;
+ return (BADCH);
+ }
+ if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
+ /* -W long-option */
+ if (*place) /* no space */
+ /* NOTHING */;
+ else if (++optind >= nargc) { /* no arg */
+ place = EMSG;
+ if (PRINT_ERROR)
+ warnx(recargchar, optchar);
+ optopt = optchar;
+ return (BADARG);
+ } else /* white space */
+ place = nargv[optind];
+ optchar = parse_long_options(nargv, options, long_options,
+ idx, 0);
+ place = EMSG;
+ return (optchar);
+ }
+ if (*++oli != ':') { /* doesn't take argument */
+ if (!*place)
+ ++optind;
+ } else { /* takes (optional) argument */
+ optarg = NULL;
+ if (*place) /* no white space */
+ optarg = place;
+ else if (oli[1] != ':') { /* arg not optional */
+ if (++optind >= nargc) { /* no arg */
+ place = EMSG;
+ if (PRINT_ERROR)
+ warnx(recargchar, optchar);
+ optopt = optchar;
+ return (BADARG);
+ } else
+ optarg = nargv[optind];
+ }
+ place = EMSG;
+ ++optind;
+ }
+ /* dump back option letter */
+ return (optchar);
+}
+
+/*
+ * getopt_long --
+ * Parse argc/argv argument vector.
+ */
+int
+getopt_long(int nargc, char * const *nargv, const char *options,
+ const struct option *long_options, int *idx)
+{
+
+ return (getopt_internal(nargc, nargv, options, long_options, idx,
+ FLAG_PERMUTE));
+}
+
+/*
+ * getopt_long_only --
+ * Parse argc/argv argument vector.
+ */
+int
+getopt_long_only(int nargc, char * const *nargv, const char *options,
+ const struct option *long_options, int *idx)
+{
+
+ return (getopt_internal(nargc, nargv, options, long_options, idx,
+ FLAG_PERMUTE|FLAG_LONGONLY));
+}
+
+//extern int getopt_long(int nargc, char * const *nargv, const char *options,
+// const struct option *long_options, int *idx);
+//extern int getopt_long_only(int nargc, char * const *nargv, const char *options,
+// const struct option *long_options, int *idx);
+/*
+ * Previous MinGW implementation had...
+ */
+#ifndef HAVE_DECL_GETOPT
+/*
+ * ...for the long form API only; keep this for compatibility.
+ */
+# define HAVE_DECL_GETOPT 1
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */
diff --git a/src/platform/win/pcm_io_mf/pcm_io_mf.cpp b/src/platform/win/pcm_io_mf/pcm_io_mf.cpp
new file mode 100644
index 0000000..b8ddd98
--- /dev/null
+++ b/src/platform/win/pcm_io_mf/pcm_io_mf.cpp
@@ -0,0 +1,493 @@
+/*
+ * 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 <comdef.h>
+
+#include <initguid.h>
+#include <cguid.h>
+#include <atlbase.h>
+#include <windows.h>
+#include <mfapi.h>
+#include <mfidl.h>
+#include <mfreadwrite.h>
+#include <stdio.h>
+#include <mferror.h>
+
+#include <propvarutil.h>
+
+#include <algorithm>
+#include <iostream>
+#include <sstream>
+
+#include <string>
+
+#pragma comment(lib, "Mfplat.lib")
+#pragma comment(lib, "Mfreadwrite.lib")
+#pragma comment(lib, "Propsys.lib")
+
+class THException : public std::exception {
+ static std::string hrToText(HRESULT hr) {
+ _com_error err(hr);
+ return err.ErrorMessage();
+ }
+public:
+ THException(HRESULT hr, const std::string& msg)
+ : std::exception((msg + ", " + hrToText(hr)).c_str())
+ {}
+};
+
+static std::wstring Utf8ToMultiByte(const std::string& in) {
+ std::vector<wchar_t> buf;
+ int len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, in.data(), in.size(), buf.data(), 0);
+ if (!len) {
+ throw std::exception("unable to convert utf8 to multiByte");
+ }
+ buf.resize((size_t)len);
+ MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, in.data(), in.size(), buf.data(), buf.size());
+ return std::wstring(buf.data(), buf.size());
+}
+
+// TODO: add dither, noise shape?
+static inline int16_t FloatToInt16(TFloat in) {
+ return std::min((int)INT16_MAX, std::max((int)INT16_MIN, (int)lrint(in * (TFloat)INT16_MAX)));
+}
+
+static HRESULT WriteToFile(HANDLE hFile, void* p, DWORD cb) {
+ DWORD cbWritten = 0;
+ HRESULT hr = S_OK;
+
+ BOOL bResult = WriteFile(hFile, p, cb, &cbWritten, NULL);
+ if (!bResult) {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ }
+ return hr;
+}
+
+static HRESULT ConfigureAudioStream(IMFSourceReader *pReader, IMFMediaType **ppPCMAudio) {
+ CComPtr<IMFMediaType> pUncompressedAudioType;
+ CComPtr<IMFMediaType> pPartialType;
+
+ // Select the first audio stream, and deselect all other streams.
+ HRESULT hr = pReader->SetStreamSelection(
+ (DWORD)MF_SOURCE_READER_ALL_STREAMS, FALSE);
+
+ if (SUCCEEDED(hr)) {
+ hr = pReader->SetStreamSelection(
+ (DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, TRUE);
+ }
+
+ // Create a partial media type that specifies uncompressed PCM audio.
+ hr = MFCreateMediaType(&pPartialType);
+
+ if (SUCCEEDED(hr)) {
+ hr = pPartialType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio);
+ }
+
+ if (SUCCEEDED(hr)) {
+ hr = pPartialType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM);
+ }
+
+ // Set this type on the source reader. The source reader will
+ // load the necessary decoder.
+ if (SUCCEEDED(hr)) {
+ hr = pReader->SetCurrentMediaType(
+ (DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM,
+ NULL, pPartialType);
+ }
+
+ // Get the complete uncompressed format.
+ if (SUCCEEDED(hr)) {
+ hr = pReader->GetCurrentMediaType(
+ (DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM,
+ &pUncompressedAudioType);
+ }
+
+ // Ensure the stream is selected.
+ if (SUCCEEDED(hr)) {
+ hr = pReader->SetStreamSelection(
+ (DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM,
+ TRUE);
+ }
+
+ // Return the PCM format to the caller.
+ if (SUCCEEDED(hr)) {
+ *ppPCMAudio = pUncompressedAudioType;
+ (*ppPCMAudio)->AddRef();
+ }
+
+ return hr;
+}
+
+static HRESULT CreatePCMAudioType(UINT32 sampleRate, UINT32 bitsPerSample, UINT32 cChannels, IMFMediaType **ppType) {
+ HRESULT hr = S_OK;
+
+ CComPtr<IMFMediaType> pType;
+
+ // Calculate derived values.
+ UINT32 blockAlign = cChannels * (bitsPerSample / 8);
+ UINT32 bytesPerSecond = blockAlign * sampleRate;
+
+ // Create the empty media type.
+ hr = MFCreateMediaType(&pType);
+
+ // Set attributes on the type.
+ if (SUCCEEDED(hr)) {
+ hr = pType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio);
+ }
+
+ if (SUCCEEDED(hr)) {
+ hr = pType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM);
+ }
+
+ if (SUCCEEDED(hr)) {
+ hr = pType->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, cChannels);
+ }
+
+ if (SUCCEEDED(hr)) {
+ hr = pType->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, sampleRate);
+ }
+
+ if (SUCCEEDED(hr)) {
+ hr = pType->SetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, blockAlign);
+ }
+
+ if (SUCCEEDED(hr)) {
+ hr = pType->SetUINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, bytesPerSecond);
+ }
+
+ if (SUCCEEDED(hr)) {
+ hr = pType->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, bitsPerSample);
+ }
+
+ if (SUCCEEDED(hr)) {
+ hr = pType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
+ }
+
+ if (SUCCEEDED(hr)) {
+ // Return the type to the caller.
+ *ppType = pType;
+ (*ppType)->AddRef();
+ }
+
+ return hr;
+}
+
+class TPCMIOMediaFoundationFile : public IPCMProviderImpl {
+public:
+ TPCMIOMediaFoundationFile(const std::string& path) {
+
+ HRESULT hr = S_OK;
+
+ hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
+
+ if (!SUCCEEDED(hr)) {
+ throw THException(hr, "unable to initialize COM library");
+ }
+
+ hr = MFStartup(MF_VERSION);
+
+ if (!SUCCEEDED(hr)) {
+ throw THException(hr, "unable to initialize Media Foundation platform");
+ }
+
+ std::wstring wpath = Utf8ToMultiByte(path);
+
+ hr = MFCreateSourceReaderFromURL(wpath.c_str(), NULL, &Reader_);
+
+ if (FAILED(hr)) {
+ throw THException(hr, "unable to open input file");
+ }
+
+ hr = ConfigureAudioStream(Reader_, &MediaType_);
+
+ if (FAILED(hr)) {
+ throw THException(hr, "unable to get media type");
+ }
+
+ if (FAILED(MediaType_->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &ChannelsNum_))) {
+ throw THException(hr, "unable to get channels number");
+ }
+
+ if (FAILED(MediaType_->GetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, &SampleRate_))) {
+ throw THException(hr, "unable to get sample rate");
+ }
+
+ if (FAILED(MediaType_->GetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, &BytesPerSample_))) {
+ throw THException(hr, "unable to get sample size");
+ }
+
+ if (!(ChannelsNum_ == 1 && BytesPerSample_ == 2 || ChannelsNum_ == 2 && BytesPerSample_ == 4)) {
+ throw THException(hr, "unsupported samaple format");
+ }
+
+ NEnv::SetRoundFloat();
+ }
+
+ TPCMIOMediaFoundationFile(const std::string& path, int channels, int sampleRate) {
+
+ HRESULT hr = S_OK;
+ ChannelsNum_ = channels;
+ SampleRate_ = sampleRate;
+
+ hr = CreatePCMAudioType(sampleRate, 16, channels, &MediaType_);
+
+ if (FAILED(hr)) {
+ throw THException(hr, "unable to create PCM audio type");
+ }
+
+ UINT32 format = 0;
+
+ WAVEFORMATEX *wav = NULL;
+
+ hr = MFCreateWaveFormatExFromMFMediaType(MediaType_, &wav, &format);
+
+ if (FAILED(hr)) {
+ throw THException(hr, "unable to create wave format");
+ }
+
+ DWORD header[] = {
+ // RIFF header
+ FCC('RIFF'),
+ 0,
+ FCC('WAVE'),
+ // Start of 'fmt ' chunk
+ FCC('fmt '),
+ format
+ };
+
+ DWORD dataHeader[] = { FCC('data'), 0 };
+
+ std::wstring wpath = Utf8ToMultiByte(path);
+
+ OutFile = CreateFileW(wpath.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL,
+ CREATE_ALWAYS, 0, NULL);
+
+ if (OutFile == INVALID_HANDLE_VALUE) {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ throw THException(hr, "unable to open output file");
+ }
+
+ hr = WriteToFile(OutFile, header, sizeof(header));
+
+ // Write the WAVEFORMATEX structure.
+ if (SUCCEEDED(hr)) {
+ hr = WriteToFile(OutFile, wav, format);
+ }
+
+ // Write the start of the 'data' chunk
+
+ if (SUCCEEDED(hr)) {
+ hr = WriteToFile(OutFile, dataHeader, sizeof(dataHeader));
+ }
+
+ if (FAILED(hr)) {
+ throw THException(hr, "unable to write headers");
+ }
+
+ NEnv::SetRoundFloat();
+ }
+
+ ~TPCMIOMediaFoundationFile() {
+ if (OutFile) {
+ if (!CloseHandle(OutFile)) {
+ std::cerr << "unable to close handle" << std::endl;
+ }
+ }
+ }
+
+public:
+ size_t GetChannelsNum() const override {
+ return ChannelsNum_;
+ }
+
+ size_t GetSampleRate() const override {
+ return SampleRate_;
+ }
+
+ size_t GetTotalSamples() const override {
+ PROPVARIANT var;
+ LONGLONG duration; // duration in 100 nanosecond units
+ HRESULT hr = Reader_->GetPresentationAttribute(MF_SOURCE_READER_MEDIASOURCE, MF_PD_DURATION, &var);
+ if (SUCCEEDED(hr)) {
+ hr = PropVariantToInt64(var, &duration);
+ PropVariantClear(&var);
+ }
+ if (!SUCCEEDED(hr)) {
+ throw THException(hr, "unable to extract duration from source");
+ }
+
+ const UINT32 bytesPerSecond = MFGetAttributeUINT32(MediaType_, MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 0);
+ const UINT32 blockSize = MFGetAttributeUINT32(MediaType_, MF_MT_AUDIO_BLOCK_ALIGNMENT, 0);
+
+ if (!blockSize) {
+ throw THException(hr, "got zero block size");
+ }
+
+ const LONGLONG samplesPerSecond = bytesPerSecond / blockSize;
+ const LONGLONG totalSamples = samplesPerSecond * duration / 10000000;
+
+ 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;
+
+ const size_t sizeBytes = sz * BytesPerSample_;
+
+ size_t curPos = 0; // position in outpuf buffer (TPCMBuffer)
+
+ if (!Buf_.empty()) {
+ if (sizeBytes > (Buf_.size() - ConsummerPos_)) {
+ if (Buf_.size() & 0x3) {
+ std::cerr << "buffer misconfiguration" << std::endl;
+ abort();
+ }
+ curPos = (Buf_.size() - ConsummerPos_) / BytesPerSample_;
+ ConvertToPcmBuffer(Buf_.data() + ConsummerPos_, buf, curPos, 0);
+ ConsummerPos_ = 0;
+ } else {
+ // We have all data in our buffer, just convert it and shift consumer position
+ ConvertToPcmBuffer(Buf_.data() + ConsummerPos_, buf, sz, 0);
+ ConsummerPos_ += sizeBytes;
+ return sz;
+ }
+ }
+
+ bool cont = true;
+ while (cont) {
+ DWORD flags = 0;
+ DWORD readyToRead = 0;
+ CComPtr<IMFSample> sample;
+
+ hr = Reader_->ReadSample((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM,
+ 0, NULL, &flags, NULL, &sample);
+
+ if (FAILED(hr)) {
+ break;
+ }
+
+ if (flags & MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED) {
+ std::cerr << "Type change - not supported by WAVE file format.\n" << std::endl;
+ break;
+ }
+
+ if (flags & MF_SOURCE_READERF_ENDOFSTREAM) {
+ std::cerr << "End of input file.\n" << std::endl;
+ break;
+ }
+
+ if (sample == NULL) {
+ continue;
+ }
+ LONGLONG duration;
+ sample->GetSampleDuration(&duration);
+
+ CComPtr<IMFMediaBuffer> buffer;
+ BYTE *audioData = NULL;
+
+ hr = sample->ConvertToContiguousBuffer(&buffer);
+
+ if (FAILED(hr)) {
+ break;
+ }
+
+ hr = buffer->Lock(&audioData, NULL, &readyToRead);
+
+ if (FAILED(hr)) {
+ break;
+ }
+
+ if (sizeBytes > (readyToRead + (curPos * BytesPerSample_))) {
+ const size_t ready = readyToRead / BytesPerSample_;
+ ConvertToPcmBuffer(audioData, buf, ready, curPos);
+ curPos += ready;
+ } else {
+ ConvertToPcmBuffer(audioData, buf, sz - curPos, curPos);
+ size_t leftBytes = readyToRead - (sz - curPos) * BytesPerSample_;
+ Buf_.resize(leftBytes);
+ std::memcpy(Buf_.data(), audioData + (sz - curPos) * BytesPerSample_, leftBytes);
+ // out buffer writen completely
+ curPos = sz;
+ cont = false;
+ }
+
+ hr = buffer->Unlock();
+ audioData = NULL;
+
+ if (FAILED(hr)) {
+ break;
+ }
+ }
+
+ if (FAILED(hr)) {
+ throw THException(hr, "unable to read from PCM stream");
+ }
+
+ return curPos;
+ }
+
+ size_t Write(const TPCMBuffer<TFloat>& buf, size_t sz) override {
+ const size_t samples = ChannelsNum_ * sz;
+ Buf_.resize(samples * 2);
+ for (size_t i = 0; i < samples; i++) {
+ *(int16_t*)(Buf_.data() + i * 2) = FloatToInt16(*(buf[0] + i));
+ }
+ if (FAILED(WriteToFile(OutFile, Buf_.data(), Buf_.size()))) {
+ throw std::exception("unable to write PCM buffer to file");
+ }
+ return sz;
+ }
+
+private:
+ CComPtr<IMFSourceReader> Reader_;
+ CComPtr<IMFMediaType> MediaType_;
+
+ uint32_t ChannelsNum_;
+ uint32_t SampleRate_;
+ uint32_t BytesPerSample_;
+
+ // Temporial buffer and consumer position
+ std::vector<BYTE> Buf_;
+ size_t ConsummerPos_ = 0;
+
+ HANDLE OutFile = NULL;
+};
+
+IPCMProviderImpl* CreatePCMIOReadImpl(const std::string& path) {
+ return new TPCMIOMediaFoundationFile(path);
+}
+
+IPCMProviderImpl* CreatePCMIOWriteImpl(const std::string& path, int channels, int sampleRate) {
+ return new TPCMIOMediaFoundationFile(path, channels, sampleRate);
+} \ No newline at end of file
diff --git a/src/qmf/qmf.cpp b/src/qmf/qmf.cpp
index 09e6f16..24d2400 100644
--- a/src/qmf/qmf.cpp
+++ b/src/qmf/qmf.cpp
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/qmf/qmf.h b/src/qmf/qmf.h
index c00c1d3..67bbef2 100644
--- a/src/qmf/qmf.h
+++ b/src/qmf/qmf.h
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/transient_detector.cpp b/src/transient_detector.cpp
index 660b776..692c3a7 100644
--- a/src/transient_detector.cpp
+++ b/src/transient_detector.cpp
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/transient_detector.h b/src/transient_detector.h
index 392bc8e..0bd0ca0 100644
--- a/src/transient_detector.h
+++ b/src/transient_detector.h
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/transient_detector_ut.cpp b/src/transient_detector_ut.cpp
index 65055fd..e41d4ac 100644
--- a/src/transient_detector_ut.cpp
+++ b/src/transient_detector_ut.cpp
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/util.h b/src/util.h
index e0994f6..a6c7b20 100644
--- a/src/util.h
+++ b/src/util.h
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/util_ut.cpp b/src/util_ut.cpp
index adef6ba..d4626a8 100644
--- a/src/util_ut.cpp
+++ b/src/util_ut.cpp
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
diff --git a/src/wav.cpp b/src/wav.cpp
index b5827b3..649189b 100644
--- a/src/wav.cpp
+++ b/src/wav.cpp
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -28,56 +28,39 @@
#include "wav.h"
#include "pcmengin.h"
-static int fileext_to_libsndfmt(const std::string& filename) {
- int fmt = SF_FORMAT_WAV; //default fmt
- if (filename == "-")
- return SF_FORMAT_AU;
- size_t pos = filename.find_last_of(".");
- if (pos == std::string::npos || pos == filename.size() - 1) //no dot or filename.
- return fmt;
- std::string ext = filename.substr(pos+1);
- std::transform(ext.begin(), ext.end(), ext.begin(), ::toupper);
- if (ext == "AU") {
- fmt = SF_FORMAT_AU;
- } else if (ext == "AIFF") {
- fmt = SF_FORMAT_AIFF;
- } else if (ext == "PCM" || ext == "RAW") {
- fmt = SF_FORMAT_RAW;
- }
- return fmt;
-}
+IPCMProviderImpl* CreatePCMIOReadImpl(const std::string& path);
-TWav::TWav(const std::string& filename)
- : File(SndfileHandle(filename)) {
- File.command(SFC_SET_NORM_DOUBLE /*| SFC_SET_NORM_FLOAT*/, nullptr, SF_TRUE);
-}
+IPCMProviderImpl* CreatePCMIOWriteImpl(const std::string& path, int channels, int sampleRate);
-TWav::TWav(const std::string& filename, int channels, int sampleRate)
- : File(SndfileHandle(filename, SFM_WRITE, fileext_to_libsndfmt(filename) | SF_FORMAT_PCM_16, channels, sampleRate)) {
- File.command(SFC_SET_NORM_DOUBLE /*| SFC_SET_NORM_FLOAT*/, nullptr, SF_TRUE);
-}
+TWav::TWav(const std::string& path)
+ : Impl(CreatePCMIOReadImpl(path))
+{ }
+
+TWav::TWav(const std::string& path, int channels, int sampleRate)
+ : Impl(CreatePCMIOWriteImpl(path, channels, sampleRate))
+{ }
TWav::~TWav() {
}
uint64_t TWav::GetTotalSamples() const {
- return File.frames();
+ return Impl->GetTotalSamples();
}
uint32_t TWav::GetChannelNum() const {
- return File.channels();
+ return Impl->GetChannelsNum();
}
uint32_t TWav::GetSampleRate() const {
- return File.samplerate();
+ return Impl->GetSampleRate();
}
-bool TWav::IsFormatSupported() const {
- switch (File.format() & SF_FORMAT_TYPEMASK) {
- case SF_FORMAT_WAV:
- case SF_FORMAT_AIFF:
- return true;
- default:
- return false;
- }
-}
+//bool TWav::IsFormatSupported() const {
+// switch (File.format() & SF_FORMAT_TYPEMASK) {
+// case SF_FORMAT_WAV:
+// case SF_FORMAT_AIFF:
+// return true;
+// default:
+// return false;
+// }
+//}
diff --git a/src/wav.h b/src/wav.h
index a76a30b..7fbb7ad 100644
--- a/src/wav.h
+++ b/src/wav.h
@@ -12,7 +12,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with AtracDEnc; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -21,7 +21,7 @@
#include <memory>
#include <string>
-#include <sndfile.hh>
+#include "config.h"
#include "pcmengin.h"
@@ -70,8 +70,19 @@ public:
}
};
+class IPCMProviderImpl {
+public:
+ virtual ~IPCMProviderImpl() = default;
+ virtual size_t GetChannelsNum() const = 0;
+ virtual size_t GetSampleRate() const = 0;
+ virtual size_t GetTotalSamples() const = 0;
+ virtual size_t Read(TPCMBuffer<TFloat>& buf, size_t sz) = 0;
+ virtual size_t Write(const TPCMBuffer<TFloat>& buf, size_t sz) = 0;
+};
+
+//TODO: split for reader/writer
class TWav {
- mutable SndfileHandle File;
+ mutable std::unique_ptr<IPCMProviderImpl> Impl;
public:
enum Mode {
E_READ,
@@ -83,7 +94,7 @@ public:
uint32_t GetChannelNum() const;
uint32_t GetSampleRate() const;
uint64_t GetTotalSamples() const;
- bool IsFormatSupported() const;
+
template<class T>
IPCMReader<T>* GetPCMReader() const;
@@ -96,9 +107,9 @@ typedef std::unique_ptr<TWav> TWavPtr;
template<class T>
IPCMReader<T>* TWav::GetPCMReader() const {
return new TWavPcmReader<T>([this](TPCMBuffer<T>& data, const uint32_t size) {
- if (data.Channels() != (size_t)File.channels())
+ if (data.Channels() != Impl->GetChannelsNum())
throw TWrongReadBuffer();
- if (size_t read = File.readf(data[0], size) != size) {
+ if (size_t read = Impl->Read(data, size) != size) {
assert(read < size);
//fprintf(stderr, "to zero: %d\n", size-read);
data.Zero(read, size - read);
@@ -109,9 +120,9 @@ IPCMReader<T>* TWav::GetPCMReader() const {
template<class T>
IPCMWriter<T>* TWav::GetPCMWriter() {
return new TWavPcmWriter<T>([this](const TPCMBuffer<T>& data, const uint32_t size) {
- if (data.Channels() != (size_t)File.channels())
+ if (data.Channels() != Impl->GetChannelsNum())
throw TWrongReadBuffer();
- if (File.writef(data[0], size) != size) {
+ if (Impl->Write(data, size) != size) {
fprintf(stderr, "can't write block\n");
}
});
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index fdd974f..0425f7a 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -39,6 +39,7 @@ add_executable(bitstream_test ${bitstream_test_sources})
target_link_libraries(bitstream_test gtest_main)
set(atrac1mdct_test_sources
+ ../src/env.cpp
../src/atrac1denc.cpp
../src/transient_detector.cpp
../src/bitstream/bitstream.cpp
@@ -56,6 +57,7 @@ add_executable(atrac1mdct_test ${atrac1mdct_test_sources})
target_link_libraries(atrac1mdct_test fft_impl gtest_main)
set(atrac3mdct_test_sources
+ ../src/env.cpp
../src/atrac3denc.cpp
../src/transient_detector.cpp
../src/bitstream/bitstream.cpp