aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
authorDaniil Cherednik <dan.cherednik@gmail.com>2024-06-17 20:12:45 +0000
committerDaniil Cherednik <dan.cherednik@gmail.com>2024-06-17 22:21:52 +0200
commit23a4e5f1dd7ce24f65a2af0598d1f92af4b5c424 (patch)
tree8a259ca8363c5b15fd3605b760518cb37e6ac63c /src/lib
parent73dbd1609445a0142e1e138b6b44ec6d1925cbb8 (diff)
downloadatracdenc-23a4e5f1dd7ce24f65a2af0598d1f92af4b5c424.tar.gz
[refactoring] move some libraries in to library directory
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/bitstream/bitstream.cpp88
-rw-r--r--src/lib/bitstream/bitstream.h47
-rw-r--r--src/lib/bitstream/bitstream_ut.cpp134
-rw-r--r--src/lib/liboma/include/oma.h78
-rw-r--r--src/lib/liboma/src/liboma.c321
-rw-r--r--src/lib/liboma/src/tools/omacp.c56
-rw-r--r--src/lib/liboma/src/tools/omainfo.c43
-rw-r--r--src/lib/mdct/common.h47
-rw-r--r--src/lib/mdct/dct.h31
-rw-r--r--src/lib/mdct/mdct.cpp82
-rw-r--r--src/lib/mdct/mdct.h182
-rw-r--r--src/lib/mdct/mdct_ut.cpp200
12 files changed, 1309 insertions, 0 deletions
diff --git a/src/lib/bitstream/bitstream.cpp b/src/lib/bitstream/bitstream.cpp
new file mode 100644
index 0000000..ddff907
--- /dev/null
+++ b/src/lib/bitstream/bitstream.cpp
@@ -0,0 +1,88 @@
+/*
+ * 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 <cstdint>
+#include "bitstream.h"
+
+#ifndef BIGENDIAN_ORDER
+#define NBITSTREAM__LITTLE_ENDIAN_CPU
+#endif
+
+namespace NBitStream {
+
+union UBytes {
+ uint32_t ui = 0;
+ uint8_t bytes[4];
+};
+
+TBitStream::TBitStream(const char* buf, int size)
+ : Buf(buf, buf+size)
+{}
+
+TBitStream::TBitStream()
+{}
+
+void TBitStream::Write(uint32_t val, int n) {
+ if (n > 23 || n < 0)
+ abort();
+ const int bitsLeft = Buf.size() * 8 - BitsUsed;
+ const int bitsReq = n - bitsLeft;
+ const int bytesPos = BitsUsed / 8;
+ const int overlap = BitsUsed % 8;
+
+ if (overlap || bitsReq >= 0) {
+ Buf.resize(Buf.size() + (bitsReq / 8 + (overlap ? 2 : 1 )), 0);
+ }
+ UBytes t;
+ t.ui = (val << (32 - n) >> overlap);
+
+ for (int i = 0; i < n/8 + (overlap ? 2 : 1); ++i) {
+#ifdef NBITSTREAM__LITTLE_ENDIAN_CPU
+ Buf[bytesPos+i] |= t.bytes[3-i];
+#else
+ Buf[bytesPos + i] |= t.bytes[i];
+#endif
+ }
+
+ BitsUsed += n;
+}
+
+uint32_t TBitStream::Read(int n) {
+ if (n >23 || n < 0)
+ abort();
+ const int bytesPos = ReadPos / 8;
+ const int overlap = ReadPos % 8;
+
+ UBytes t;
+ for (int i = 0; i < n/8 + (overlap ? 2 : 1); ++i) {
+#ifdef NBITSTREAM__LITTLE_ENDIAN_CPU
+ t.bytes[3-i] = (uint8_t)Buf[bytesPos+i];
+#else
+ t.bytes[i] = (uint8_t)Buf[bytesPos+i];
+#endif
+ }
+
+ t.ui = (t.ui << overlap >> (32 - n));
+ ReadPos += n;
+ return t.ui;
+}
+
+unsigned long long TBitStream::GetSizeInBits() const {
+ return BitsUsed;
+}
+
+}
diff --git a/src/lib/bitstream/bitstream.h b/src/lib/bitstream/bitstream.h
new file mode 100644
index 0000000..cfba790
--- /dev/null
+++ b/src/lib/bitstream/bitstream.h
@@ -0,0 +1,47 @@
+/*
+ * 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 <vector>
+
+#include <iostream>
+
+namespace NBitStream {
+
+static inline int MakeSign(int val, unsigned bits) {
+ unsigned shift = 8 * sizeof(int) - bits;
+ union { unsigned u; int s; } v = { (unsigned) val << shift };
+ return v.s >> shift;
+}
+
+class TBitStream {
+ std::vector<char> Buf;
+ int BitsUsed = 0;
+ int ReadPos = 0;
+ public:
+ TBitStream(const char* buf, int size);
+ TBitStream();
+ void Write(uint32_t val, int n);
+ uint32_t Read(int n);
+ unsigned long long GetSizeInBits() const;
+ uint32_t GetBufSize() const { return Buf.size(); };
+ const std::vector<char>& GetBytes() const {
+ return Buf;
+ }
+};
+} //NBitStream
diff --git a/src/lib/bitstream/bitstream_ut.cpp b/src/lib/bitstream/bitstream_ut.cpp
new file mode 100644
index 0000000..a426e7c
--- /dev/null
+++ b/src/lib/bitstream/bitstream_ut.cpp
@@ -0,0 +1,134 @@
+/*
+ * 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 "bitstream.h"
+#include <gtest/gtest.h>
+
+using namespace NBitStream;
+
+TEST(TBitStream, DefaultConstructor) {
+ TBitStream bs;
+ EXPECT_EQ(0u, bs.GetSizeInBits());
+}
+
+TEST(TBitStream, SimpleWriteRead) {
+ TBitStream bs;
+ bs.Write(5, 3);
+ bs.Write(true, 1);
+ EXPECT_EQ(4, bs.GetSizeInBits());
+ EXPECT_EQ(5, bs.Read(3));
+ EXPECT_EQ(true, bs.Read(1));
+}
+
+TEST(TBitStream, OverlapWriteRead) {
+ TBitStream bs;
+ bs.Write(101, 22);
+ EXPECT_EQ(22, bs.GetSizeInBits());
+
+ bs.Write(212, 22);
+ EXPECT_EQ(44, bs.GetSizeInBits());
+
+ bs.Write(323, 22);
+ EXPECT_EQ(66, bs.GetSizeInBits());
+
+ EXPECT_EQ(101, bs.Read(22));
+ EXPECT_EQ(212, bs.Read(22));
+ EXPECT_EQ(323, bs.Read(22));
+}
+
+TEST(TBitStream, OverlapWriteRead2) {
+ TBitStream bs;
+ bs.Write(2, 2);
+ bs.Write(7, 4);
+ bs.Write(10003, 16);
+
+ EXPECT_EQ(2, bs.Read(2));
+ EXPECT_EQ(7, bs.Read(4));
+ EXPECT_EQ(10003, bs.Read(16));
+}
+
+TEST(TBitStream, OverlapWriteRead3) {
+ TBitStream bs;
+ bs.Write(40, 6);
+ bs.Write(3, 2);
+ bs.Write(0, 3);
+ bs.Write(0, 3);
+ bs.Write(0, 3);
+ bs.Write(0, 3);
+
+ bs.Write(3, 5);
+ bs.Write(1, 2);
+ bs.Write(1, 1);
+ bs.Write(1, 1);
+ bs.Write(1, 1);
+ bs.Write(1, 1);
+
+ bs.Write(0, 3);
+ bs.Write(4, 3);
+ bs.Write(35, 6);
+ bs.Write(25, 6);
+ bs.Write(3, 3);
+ bs.Write(32, 6);
+ bs.Write(29, 6);
+ bs.Write(3, 3);
+ bs.Write(36, 6);
+ bs.Write(49, 6);
+
+
+
+
+ EXPECT_EQ(40, bs.Read(6));
+ EXPECT_EQ(3, bs.Read(2));
+ EXPECT_EQ(0, bs.Read(3));
+ EXPECT_EQ(0, bs.Read(3));
+ EXPECT_EQ(0, bs.Read(3));
+ EXPECT_EQ(0, bs.Read(3));
+ EXPECT_EQ(3, bs.Read(5));
+
+ EXPECT_EQ(1, bs.Read(2));
+ EXPECT_EQ(1, bs.Read(1));
+ EXPECT_EQ(1, bs.Read(1));
+ EXPECT_EQ(1, bs.Read(1));
+ EXPECT_EQ(1, bs.Read(1));
+
+ EXPECT_EQ(0, bs.Read(3));
+ EXPECT_EQ(4, bs.Read(3));
+ EXPECT_EQ(35, bs.Read(6));
+ EXPECT_EQ(25, bs.Read(6));
+ EXPECT_EQ(3, bs.Read(3));
+ EXPECT_EQ(32, bs.Read(6));
+ EXPECT_EQ(29, bs.Read(6));
+ EXPECT_EQ(3, bs.Read(3));
+ EXPECT_EQ(36, bs.Read(6));
+ EXPECT_EQ(49, bs.Read(6));
+
+}
+
+
+TEST(TBitStream, SignWriteRead) {
+ TBitStream bs;
+ bs.Write(MakeSign(-2, 3), 3);
+ bs.Write(MakeSign(-1, 3), 3);
+ bs.Write(MakeSign(1, 2), 2);
+ bs.Write(MakeSign(-7, 4), 4);
+ EXPECT_EQ(-2, MakeSign(bs.Read(3), 3));
+ EXPECT_EQ(-1, MakeSign(bs.Read(3), 3));
+ EXPECT_EQ(1, MakeSign(bs.Read(2), 2));
+ EXPECT_EQ(-7, MakeSign(bs.Read(4), 4));
+}
+
diff --git a/src/lib/liboma/include/oma.h b/src/lib/liboma/include/oma.h
new file mode 100644
index 0000000..857b0a7
--- /dev/null
+++ b/src/lib/liboma/include/oma.h
@@ -0,0 +1,78 @@
+/*
+ * This file is part of AtracDEnc.
+ *
+ * AtracDEnc is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * AtracDEnc is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with AtracDEnc; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#ifndef OMA_H
+#define OMA_H
+
+typedef struct omafile_ctx OMAFILE;
+
+struct oma_info {
+ int codec;
+ int framesize;
+ int samplerate;
+ int channel_format;
+};
+
+enum {
+ OMAM_R = 0x1,
+ OMAM_W = 0x2,
+};
+
+enum {
+ OMAC_ID_ATRAC3 = 0,
+ OMAC_ID_ATRAC3PLUS = 1,
+ OMAC_ID_MP3 = 2,
+ OMAC_ID_LPCM = 3,
+ OMAC_ID_WMA = 5
+};
+
+enum {
+ OMA_MONO = 0,
+ OMA_STEREO = 1,
+ OMA_STEREO_JS = 2,
+ OMA_3 = 3,
+ OMA_4 = 4,
+ OMA_6 = 5,
+ OMA_7 = 6,
+ OMA_8 = 7
+
+};
+
+typedef struct oma_info oma_info_t;
+typedef int block_count_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+int oma_get_last_err();
+
+OMAFILE* oma_open(const char *path, int mode, oma_info_t *info);
+int oma_close(OMAFILE* oma_file);
+
+block_count_t oma_read(OMAFILE *oma_file, void *ptr, block_count_t blocks);
+block_count_t oma_write(OMAFILE *oma_file, const void *ptr, block_count_t blocks);
+
+oma_info_t* oma_get_info(OMAFILE *oma_file);
+int oma_get_bitrate(oma_info_t *info);
+const char *oma_get_codecname(oma_info_t *info);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OMA_H */
diff --git a/src/lib/liboma/src/liboma.c b/src/lib/liboma/src/liboma.c
new file mode 100644
index 0000000..e957bd4
--- /dev/null
+++ b/src/lib/liboma/src/liboma.c
@@ -0,0 +1,321 @@
+/*
+ * 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 "../include/oma.h"
+
+#include <endian_tools.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+
+
+#define OMA_HEADER_SIZE 96
+
+struct omafile_ctx {
+ FILE* file;
+ oma_info_t info;
+};
+
+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'};
+static int channel_id_to_format_tab[7] = { OMA_MONO, OMA_STEREO, OMA_3, OMA_4, OMA_6, OMA_7, OMA_8 };
+enum {
+ OMAERR_OK = 0,
+ OMAERR_IO = -1,
+ OMAERR_PERM = -2,
+ OMAERR_FMT = -3,
+ OMAERR_ENCRYPT = -4,
+ OMAERR_VAL = -5,
+ OMAERR_EOF = -6
+};
+
+#ifdef _MSC_VER
+__declspec(thread) int err;
+#else
+static __thread int err;
+#endif
+
+int oma_get_last_err() {
+ return err;
+}
+
+static void save_err(int e) {
+ err = e;
+}
+
+static int oma_check_header(const char* buf) {
+ if (memcmp(buf, &ea3_str[0], 3) || buf[4] != 0 || buf[5] != OMA_HEADER_SIZE) {
+ return OMAERR_FMT;
+ }
+ return OMAERR_OK;
+}
+
+static int oma_check_encryption(const char* buf) {
+ if (buf[6] == -1 && buf[7] == -1)
+ return OMAERR_OK;
+ return OMAERR_ENCRYPT;
+}
+
+static int oma_get_samplerate_idx(int samplerate) {
+ if (samplerate <= 0) {
+ fprintf(stderr, "wrong samplerate\n");
+ return -1;
+ }
+ for (int i = 0; ; i++) {
+ if (liboma_samplerates[i] == samplerate)
+ return i;
+ if (liboma_samplerates[i] == 0)
+ return -1;
+ }
+ return -1;
+}
+
+static int oma_get_channel_idx(int channel_format) {
+ for (int i = 0; i < 7; i++) {
+ if (channel_id_to_format_tab[i] == channel_format)
+ return i;
+ }
+ return -1;
+}
+
+static int oma_read_atrac3_header(uint32_t params, oma_info_t* info) {
+ const int js = (params >> 17) & 0x1;
+ const int samplerate = liboma_samplerates[(params >> 13) & 0x7];
+ if (samplerate == 0) {
+ fprintf(stderr, "liboma: wrong samplerate params, can't read header\n");
+ return -1;
+ }
+ info->codec = OMAC_ID_ATRAC3;
+ info->framesize = (params & 0x3FF) * 8;
+ info->samplerate = samplerate;
+ info->channel_format = js ? OMA_STEREO_JS : OMA_STEREO;
+ return 0;
+}
+
+static int oma_write_atrac3_header(uint32_t *params, oma_info_t *info) {
+ const int channel_format = info->channel_format;
+ if (channel_format != OMA_STEREO_JS && channel_format != OMA_STEREO) {
+ fprintf(stderr, "wrong channel format\n");
+ return -1;
+ }
+ const uint32_t js = channel_format == OMA_STEREO_JS;
+ const int samplerate_idx = oma_get_samplerate_idx(info->samplerate);
+ if (samplerate_idx == -1)
+ return -1;
+ const uint32_t framesz = info->framesize / 8;
+ if (framesz > 0x3FF)
+ return -1;
+ *params = swapbyte32_on_le((OMAC_ID_ATRAC3 << 24) | (js << 17) | ((uint32_t)samplerate_idx << 13) | framesz);
+ return 0;
+}
+
+static int oma_read_atrac3p_header(uint32_t params, oma_info_t* info) {
+ const int channel_id = (params >> 10) & 7;
+ if (channel_id == 0) {
+ return -1;
+ }
+ const int samplerate = liboma_samplerates[(params >> 13) & 0x7];
+ if (samplerate == 0) {
+ fprintf(stderr, "liboma: wrong samplerate params, can't read header\n");
+ return -1;
+ }
+ info->codec = OMAC_ID_ATRAC3PLUS;
+ info->framesize = ((params & 0x3FF) * 8) + 8;
+ info->samplerate = samplerate;
+ uint32_t ch_id = (params >> 10) & 7;
+ info->channel_format = channel_id_to_format_tab[ch_id - 1];
+ return 0;
+}
+
+static int oma_write_atrac3p_header(uint32_t *params, oma_info_t *info) {
+
+ const int samplerate_idx = oma_get_samplerate_idx(info->samplerate);
+ if (samplerate_idx == -1)
+ return -1;
+
+ const uint32_t framesz = (info->framesize - 8) / 8;
+ if (framesz > 0x3FF)
+ return -1;
+
+ const int32_t ch_id = oma_get_channel_idx(info->channel_format);
+ if (ch_id < 0)
+ return -1;
+
+ *params = swapbyte32_on_le((OMAC_ID_ATRAC3PLUS << 24) | ((int32_t)samplerate_idx << 13) | ((ch_id + 1) << 10) | framesz);
+ return 0;
+}
+
+static int oma_write_header(OMAFILE* ctx, oma_info_t *omainfo) {
+ if (ctx == NULL || omainfo == NULL)
+ return -1;
+ char *headerbuf = (char*)calloc(OMA_HEADER_SIZE, 1);
+ memcpy(headerbuf, &ea3_str[0], 3);
+ headerbuf[3] = 1; //???
+ headerbuf[5] = OMA_HEADER_SIZE;
+ headerbuf[6] = 0xFF;
+ headerbuf[7] = 0xFF;
+ uint32_t *params = (uint32_t*)(headerbuf+32);
+ switch (omainfo->codec) {
+ case OMAC_ID_ATRAC3:
+ oma_write_atrac3_header(params, omainfo);
+ break;
+ case OMAC_ID_ATRAC3PLUS:
+ oma_write_atrac3p_header(params, omainfo);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ int rv = fwrite(headerbuf, sizeof(char), OMA_HEADER_SIZE, ctx->file);
+ if (rv != OMA_HEADER_SIZE) {
+ fprintf(stderr, "can't write header\n");
+ rv = -1;
+ }
+ free(headerbuf);
+ return rv;
+}
+
+static int oma_parse_header(OMAFILE* file) {
+ char buf[OMA_HEADER_SIZE];
+ int read = fread(&buf[0], sizeof(char), OMA_HEADER_SIZE, file->file);
+ int err = 0;
+ uint32_t params = 0;
+ if (OMA_HEADER_SIZE != read)
+ return feof(file->file) ? OMAERR_FMT : OMAERR_IO;
+
+ err = oma_check_header(&buf[0]);
+ if (OMAERR_OK != err)
+ return err;
+
+ err = oma_check_encryption(&buf[0]);
+ if (OMAERR_OK != err)
+ return err;
+
+ //detect codecs
+ params = ((uint8_t)buf[33]) << 16 | ((uint8_t)buf[34]) << 8 | ((uint8_t)buf[35]);
+ switch (buf[32]) {
+ case OMAC_ID_ATRAC3:
+ oma_read_atrac3_header(params, &file->info);
+ break;
+ case OMAC_ID_ATRAC3PLUS:
+ oma_read_atrac3p_header(params, &file->info);
+ break;
+
+ default:
+ fprintf(stderr, "got unsupported format: %d\n", buf[32]);
+ return OMAERR_FMT;
+ }
+
+ return OMAERR_OK;
+}
+
+OMAFILE* oma_open(const char *path, int mode, oma_info_t *info) {
+ const static char* modes[3] = {"", "rb", "wb"};
+ FILE* file = fopen(path, modes[mode]);
+ int err = 0;
+ if (NULL == file) {
+ return NULL;
+ }
+
+ struct omafile_ctx *ctx = (struct omafile_ctx*)malloc(sizeof(struct omafile_ctx));
+ if (NULL == ctx) {
+ goto close_ret;
+ }
+
+ ctx->file = file;
+ if (mode == OMAM_R) {
+ err = oma_parse_header(ctx);
+ if (OMAERR_OK != err) {
+ goto free_close_ret;
+ }
+ } else {
+ if (!info) {
+ err = OMAERR_VAL;
+ goto free_close_ret;
+ }
+ memcpy(&ctx->info, info, sizeof(oma_info_t));
+ err = oma_write_header(ctx, info);
+ }
+
+ return ctx;
+
+free_close_ret:
+ free(ctx);
+
+close_ret:
+ save_err(err);
+ fclose(file);
+ return NULL;
+}
+
+int oma_close(OMAFILE *ctx) {
+ FILE* file = ctx->file;
+ free(ctx);
+ fclose(file);
+ return 0;
+}
+
+block_count_t oma_read(OMAFILE *oma_file, void *ptr, block_count_t blocks) {
+ size_t read = fread(ptr, oma_file->info.framesize, blocks, oma_file->file);
+ if (read == blocks)
+ return read;
+ if (feof(oma_file->file)) {
+ save_err(OMAERR_EOF);
+ return 0;
+ }
+ return -1;
+}
+
+block_count_t oma_write(OMAFILE *oma_file, const void *ptr, block_count_t blocks) {
+ size_t writen = fwrite(ptr, oma_file->info.framesize, blocks, oma_file->file);
+ if (writen == blocks)
+ return writen;
+ return -1;
+}
+
+oma_info_t* oma_get_info(OMAFILE *oma_file) {
+ if (oma_file == NULL)
+ return NULL;
+ return &oma_file->info;
+}
+int oma_get_bitrate(oma_info_t *info) {
+ switch (info->codec) {
+ case OMAC_ID_ATRAC3:
+ return info->samplerate * info->framesize * 8 / 1024;
+ break;
+ case OMAC_ID_ATRAC3PLUS:
+ return info->samplerate * info->framesize * 8 / 2048;
+ break;
+ default:
+ return -1;
+ }
+ return -1;
+}
+
+const char *oma_get_codecname(oma_info_t *info) {
+ if (info == NULL)
+ return "";
+ int id = info->codec;
+ if (id < 0 || id > 5)
+ return "";
+ return codec_name[id];
+}
diff --git a/src/lib/liboma/src/tools/omacp.c b/src/lib/liboma/src/tools/omacp.c
new file mode 100644
index 0000000..b938f04
--- /dev/null
+++ b/src/lib/liboma/src/tools/omacp.c
@@ -0,0 +1,56 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+
+#include "oma.h"
+
+int main(int argc, char* const* argv) {
+ if (3 != argc)
+ fprintf(stdout, "usage: \n\t omainfo [in] [out]\n");
+
+ OMAFILE* infile = oma_open(argv[1], OMAM_R, NULL);
+ if (NULL == infile)
+ fprintf(stderr, "Can't open %s to read, err: %d\n", argv[1], oma_get_last_err());
+
+ oma_info_t *info = oma_get_info(infile);
+ const char *codecname = oma_get_codecname(info);
+ const int bitrate = oma_get_bitrate(info);
+
+ fprintf(stdout, "codec: %s, bitrate: %d, channel format: %d\n", codecname, bitrate, info->channel_format);
+
+ OMAFILE* outfile = oma_open(argv[2], OMAM_W, info);
+ if (NULL == outfile)
+ fprintf(stderr, "Can't open %s to write, err: %d\n", argv[2], oma_get_last_err());
+
+ char* buf = (char*)malloc(info->framesize);
+ for (;;) {
+ block_count_t rcount = oma_read(infile, buf, 1);
+ if (rcount == 0)
+ break;
+ if (rcount == -1) {
+ fprintf(stderr, "read error\n");
+ break;
+ }
+ if (oma_write(outfile, buf, 1) == -1) {
+ fprintf(stderr, "write error\n");
+ break;
+ }
+ }
+}
diff --git a/src/lib/liboma/src/tools/omainfo.c b/src/lib/liboma/src/tools/omainfo.c
new file mode 100644
index 0000000..1edee98
--- /dev/null
+++ b/src/lib/liboma/src/tools/omainfo.c
@@ -0,0 +1,43 @@
+/*
+ * 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 <stdio.h>
+
+#include "oma.h"
+
+int main(int argc, char* const* argv) {
+ fprintf(stderr, "%d\n", argc);
+ if (2 > argc) {
+ fprintf(stdout, "usage: \n\t omainfo [filename]\n");
+ return 1;
+ }
+
+ for (int i = 1; i < argc; i++) {
+ OMAFILE* file = oma_open(argv[i], OMAM_R, NULL);
+ if (NULL == file)
+ fprintf(stderr, "Can't open %s\n", argv[i]);
+
+ oma_info_t *info = oma_get_info(file);
+ const char *codecname = oma_get_codecname(info);
+ const int bitrate = oma_get_bitrate(info);
+
+ fprintf(stdout, "%s codec: %s, bitrate: %d, channelformat: %d framesz: %d\n", argv[i], codecname, bitrate, info->channel_format, info->framesize);
+ oma_close(file);
+ }
+ return 0;
+}
diff --git a/src/lib/mdct/common.h b/src/lib/mdct/common.h
new file mode 100644
index 0000000..9b3c893
--- /dev/null
+++ b/src/lib/mdct/common.h
@@ -0,0 +1,47 @@
+/*
+ * 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 "../config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#ifdef CONFIG_DOUBLE
+typedef double FLOAT;
+#define FCONST(X) (X)
+#define AFT_COS cos
+#define AFT_SIN sin
+#define AFT_TAN tan
+#define AFT_LOG10 log10
+#define AFT_EXP exp
+#define AFT_FABS fabs
+#define AFT_SQRT sqrt
+#define AFT_EXP exp
+#else
+typedef float FLOAT;
+#define FCONST(X) (X##f)
+#define AFT_COS cosf
+#define AFT_SIN sinf
+#define AFT_TAN tanf
+#define AFT_LOG10 log10f
+#define AFT_FABS fabsf
+#define AFT_SQRT sqrtf
+#define AFT_EXP expf
+#endif
diff --git a/src/lib/mdct/dct.h b/src/lib/mdct/dct.h
new file mode 100644
index 0000000..55b81a9
--- /dev/null
+++ b/src/lib/mdct/dct.h
@@ -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
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct atde_dct_ctx *atde_dct_ctx_t;
+
+atde_dct_ctx_t atde_create_dct4_16(float scale);
+void atde_free_dct_ctx(atde_dct_ctx_t ctx);
+void atde_do_dct4_16(atde_dct_ctx_t ctx, const float* in, float* out);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/lib/mdct/mdct.cpp b/src/lib/mdct/mdct.cpp
new file mode 100644
index 0000000..74b6d91
--- /dev/null
+++ b/src/lib/mdct/mdct.cpp
@@ -0,0 +1,82 @@
+/*
+ * 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 "mdct.h"
+#include "dct.h"
+#include <iostream>
+
+namespace NMDCT {
+
+static std::vector<TFloat> CalcSinCos(size_t n, TFloat scale)
+{
+ std::vector<TFloat> tmp(n >> 1);
+ const TFloat alpha = 2.0 * M_PI / (8.0 * n);
+ const TFloat omiga = 2.0 * M_PI / n;
+ scale = sqrt(scale/n);
+ for (size_t i = 0; i < (n >> 2); ++i) {
+ tmp[2 * i + 0] = scale * cos(omiga * i + alpha);
+ tmp[2 * i + 1] = scale * sin(omiga * i + alpha);
+ }
+ return tmp;
+}
+
+TMDCTBase::TMDCTBase(size_t n, TFloat scale)
+ : N(n)
+ , SinCos(CalcSinCos(n, scale))
+{
+ FFTIn = (kiss_fft_cpx*) malloc(sizeof(kiss_fft_cpx) * N >> 2);
+ FFTOut = (kiss_fft_cpx*) malloc(sizeof(kiss_fft_cpx) * N >> 2);
+ FFTPlan = kiss_fft_alloc(N >> 2, false, nullptr, nullptr);
+}
+
+TMDCTBase::~TMDCTBase()
+{
+ kiss_fft_free(FFTPlan);
+ free(FFTOut);
+ free(FFTIn);
+}
+
+} // namespace NMDCT
+
+struct atde_dct_ctx {
+ atde_dct_ctx(float scale)
+ : mdct(scale)
+ {}
+ NMDCT::TMIDCT<32, float> mdct;
+};
+
+atde_dct_ctx_t atde_create_dct4_16(float scale)
+{
+ return new atde_dct_ctx(32.0 * scale);
+}
+
+void atde_free_dct_ctx(atde_dct_ctx_t ctx)
+{
+ delete ctx;
+}
+
+void atde_do_dct4_16(atde_dct_ctx_t ctx, const float* in, float* out)
+{
+ //TODO: rewrire more optimal
+ const auto& x = ctx->mdct(in);
+
+ for (int i = 0; i < 16; i++) {
+ out[i] = x[i + 8] * -1.0;
+ }
+}
+
diff --git a/src/lib/mdct/mdct.h b/src/lib/mdct/mdct.h
new file mode 100644
index 0000000..59b9af7
--- /dev/null
+++ b/src/lib/mdct/mdct.h
@@ -0,0 +1,182 @@
+/*
+ * 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 "config.h"
+#include "fft/kissfft_impl/kiss_fft.h"
+#include <vector>
+#include <type_traits>
+
+namespace NMDCT {
+
+static_assert(sizeof(kiss_fft_scalar) == sizeof(TFloat), "size of fft_scalar is not equal to size of TFloat");
+
+class TMDCTBase {
+protected:
+ const size_t N;
+ const std::vector<TFloat> SinCos;
+ kiss_fft_cpx* FFTIn;
+ kiss_fft_cpx* FFTOut;
+ kiss_fft_cfg FFTPlan;
+ TMDCTBase(size_t n, TFloat scale);
+ virtual ~TMDCTBase();
+};
+
+
+template<size_t TN, typename TIO = TFloat>
+class TMDCT : public TMDCTBase {
+ std::vector<TIO> Buf;
+public:
+ TMDCT(float scale = 1.0)
+ : TMDCTBase(TN, scale)
+ , Buf(TN/2)
+ {
+ }
+ const std::vector<TIO>& operator()(const TIO* in) {
+
+ const size_t n2 = N >> 1;
+ const size_t n4 = N >> 2;
+ const size_t n34 = 3 * n4;
+ const size_t n54 = 5 * n4;
+ const TFloat* cos = &SinCos[0];
+ const TFloat* sin = &SinCos[1];
+
+ TFloat *xr, *xi, r0, i0;
+ TFloat c, s;
+ size_t n;
+
+ xr = (TFloat*)FFTIn;
+ xi = (TFloat*)FFTIn + 1;
+ for (n = 0; n < n4; n += 2) {
+ r0 = in[n34 - 1 - n] + in[n34 + n];
+ i0 = in[n4 + n] - in[n4 - 1 - n];
+
+ c = cos[n];
+ s = sin[n];
+
+ xr[n] = r0 * c + i0 * s;
+ xi[n] = i0 * c - r0 * s;
+ }
+
+ for (; n < n2; n += 2) {
+ r0 = in[n34 - 1 - n] - in[n - n4];
+ i0 = in[n4 + n] + in[n54 - 1 - n];
+
+ c = cos[n];
+ s = sin[n];
+
+ xr[n] = r0 * c + i0 * s;
+ xi[n] = i0 * c - r0 * s;
+ }
+
+ kiss_fft(FFTPlan, FFTIn, FFTOut);
+
+ xr = (TFloat*)FFTOut;
+ xi = (TFloat*)FFTOut + 1;
+ for (n = 0; n < n2; n += 2) {
+ r0 = xr[n];
+ i0 = xi[n];
+
+ c = cos[n];
+ s = sin[n];
+
+ Buf[n] = - r0 * c - i0 * s;
+ Buf[n2 - 1 -n] = - r0 * s + i0 * c;
+ }
+
+ return Buf;
+ }
+};
+
+template<size_t TN, typename TIO = TFloat>
+class TMIDCT : public TMDCTBase {
+ std::vector<TIO> Buf;
+public:
+ TMIDCT(float scale = TN)
+ : TMDCTBase(TN, scale/2)
+ , Buf(TN)
+ {}
+ const std::vector<TIO>& operator()(const TIO* in) {
+
+ const size_t n2 = N >> 1;
+ const size_t n4 = N >> 2;
+ const size_t n34 = 3 * n4;
+ const size_t n54 = 5 * n4;
+ const TFloat* cos = &SinCos[0];
+ const TFloat* sin = &SinCos[1];
+
+ TFloat *xr, *xi, r0, i0, r1, i1;
+ TFloat c, s;
+ size_t n;
+
+ xr = (TFloat*)FFTIn;
+ xi = (TFloat*)FFTIn + 1;
+
+ for (n = 0; n < n2; n += 2) {
+ r0 = in[n];
+ i0 = in[n2 - 1 - n];
+
+ c = cos[n];
+ s = sin[n];
+
+ xr[n] = -2.0 * (i0 * s + r0 * c);
+ xi[n] = -2.0 * (i0 * c - r0 * s);
+ }
+
+ kiss_fft(FFTPlan, FFTIn, FFTOut);
+
+ xr = (TFloat*)FFTOut;
+ xi = (TFloat*)FFTOut + 1;
+
+ for (n = 0; n < n4; n += 2) {
+ r0 = xr[n];
+ i0 = xi[n];
+
+ c = cos[n];
+ s = sin[n];
+
+ r1 = r0 * c + i0 * s;
+ i1 = r0 * s - i0 * c;
+
+ Buf[n34 - 1 - n] = r1;
+ Buf[n34 + n] = r1;
+ Buf[n4 + n] = i1;
+ Buf[n4 - 1 - n] = -i1;
+ }
+
+ for (; n < n2; n += 2) {
+ r0 = xr[n];
+ i0 = xi[n];
+
+ c = cos[n];
+ s = sin[n];
+
+ r1 = r0 * c + i0 * s;
+ i1 = r0 * s - i0 * c;
+
+ Buf[n34 - 1 - n] = r1;
+ Buf[n - n4] = -r1;
+ Buf[n4 + n] = i1;
+ Buf[n54 - 1 - n] = i1;
+ }
+ return Buf;
+ }
+};
+
+} //namespace NMDCT
diff --git a/src/lib/mdct/mdct_ut.cpp b/src/lib/mdct/mdct_ut.cpp
new file mode 100644
index 0000000..31f6f81
--- /dev/null
+++ b/src/lib/mdct/mdct_ut.cpp
@@ -0,0 +1,200 @@
+/*
+ * 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 "mdct.h"
+#include <gtest/gtest.h>
+
+#include <vector>
+#include <cstdlib>
+
+using std::vector;
+using namespace NMDCT;
+
+static vector<TFloat> mdct(TFloat* x, int N) {
+ vector<TFloat> res;
+ for (int k = 0; k < N; k++) {
+ TFloat sum = 0;
+ for (int n = 0; n < 2 * N; n++)
+ sum += x[n]* cos((M_PI/N) * ((TFloat)n + 0.5 + N/2) * ((TFloat)k + 0.5));
+
+ res.push_back(sum);
+ }
+ return res;
+}
+
+static vector<TFloat> midct(TFloat* x, int N) {
+ vector<TFloat> res;
+ for (int n = 0; n < 2 * N; n++) {
+ TFloat sum = 0;
+ for (int k = 0; k < N; k++)
+ sum += (x[k] * cos((M_PI/N) * ((TFloat)n + 0.5 + N/2) * ((TFloat)k + 0.5)));
+
+ res.push_back(sum);
+ }
+ return res;
+}
+
+TEST(TMdctTest, MDCT32) {
+ const int N = 32;
+ TMDCT<N> transform(N);
+ vector<TFloat> src(N);
+ for (int i = 0; i < N; i++) {
+ src[i] = i;
+ }
+ const vector<TFloat> res1 = mdct(&src[0], N/2);
+ const vector<TFloat> res2 = transform(&src[0]);
+ EXPECT_EQ(res1.size(), res2.size());
+ for (int i = 0; i < res1.size(); i++) {
+ EXPECT_NEAR(res1[i], res2[i], 0.0000000001);
+ }
+}
+
+TEST(TMdctTest, MDCT64) {
+ const int N = 64;
+ TMDCT<N> transform(N);
+ vector<TFloat> src(N);
+ for (int i = 0; i < N; i++) {
+ src[i] = i;
+ }
+ const vector<TFloat> res1 = mdct(&src[0], N/2);
+ const vector<TFloat> res2 = transform(&src[0]);
+ EXPECT_EQ(res1.size(), res2.size());
+ for (int i = 0; i < res1.size(); i++) {
+ EXPECT_NEAR(res1[i], res2[i], 0.0000000001);
+ }
+}
+
+TEST(TMdctTest, MDCT128) {
+ const int N = 128;
+ TMDCT<N> transform(N);
+ vector<TFloat> src(N);
+ for (int i = 0; i < N; i++) {
+ src[i] = i;
+ }
+ const vector<TFloat> res1 = mdct(&src[0], N/2);
+ const vector<TFloat> res2 = transform(&src[0]);
+ EXPECT_EQ(res1.size(), res2.size());
+ for (int i = 0; i < res1.size(); i++) {
+ EXPECT_NEAR(res1[i], res2[i], 0.0000000001);
+ }
+}
+
+TEST(TMdctTest, MDCT256) {
+ const int N = 256;
+ TMDCT<N> transform(N);
+ vector<TFloat> src(N);
+ for (int i = 0; i < N; i++) {
+ src[i] = i;
+ }
+ const vector<TFloat> res1 = mdct(&src[0], N/2);
+ const vector<TFloat> res2 = transform(&src[0]);
+ EXPECT_EQ(res1.size(), res2.size());
+ for (int i = 0; i < res1.size(); i++) {
+ EXPECT_NEAR(res1[i], res2[i], 0.00000001);
+ }
+}
+
+TEST(TMdctTest, MDCT256_RAND) {
+ const int N = 256;
+ TMDCT<N> transform(N);
+ vector<TFloat> src(N);
+ for (int i = 0; i < N; i++) {
+ src[i] = rand();
+ }
+ const vector<TFloat> res1 = mdct(&src[0], N/2);
+ const vector<TFloat> res2 = transform(&src[0]);
+ EXPECT_EQ(res1.size(), res2.size());
+ for (int i = 0; i < res1.size(); i++) {
+ EXPECT_NEAR(res1[i], res2[i], 0.01);
+ }
+}
+
+TEST(TMdctTest, MIDCT32) {
+ const int N = 32;
+ TMIDCT<N> transform;
+ vector<TFloat> src(N);
+ for (int i = 0; i < N/2; i++) {
+ src[i] = i;
+ }
+ const vector<TFloat> res1 = midct(&src[0], N/2);
+ const vector<TFloat> res2 = transform(&src[0]);
+ EXPECT_EQ(res1.size(), res2.size());
+ for (int i = 0; i < N; i++) {
+ EXPECT_NEAR(res1[i], res2[i], 0.0000000001);
+ }
+}
+
+TEST(TMdctTest, MIDCT64) {
+ const int N = 64;
+ TMIDCT<N> transform;
+ vector<TFloat> src(N);
+ for (int i = 0; i < N/2; i++) {
+ src[i] = i;
+ }
+ const vector<TFloat> res1 = midct(&src[0], N/2);
+ const vector<TFloat> res2 = transform(&src[0]);
+ EXPECT_EQ(res1.size(), res2.size());
+ for (int i = 0; i < N; i++) {
+ EXPECT_NEAR(res1[i], res2[i], 0.0000000001);
+ }
+}
+
+TEST(TMdctTest, MIDCT128) {
+ const int N = 128;
+ TMIDCT<N> transform(N);
+ vector<TFloat> src(N);
+ for (int i = 0; i < N/2; i++) {
+ src[i] = i;
+ }
+ const vector<TFloat> res1 = midct(&src[0], N/2);
+ const vector<TFloat> res2 = transform(&src[0]);
+ EXPECT_EQ(res1.size(), res2.size());
+ for (int i = 0; i < N; i++) {
+ EXPECT_NEAR(res1[i], res2[i], 0.0000000001);
+ }
+}
+
+TEST(TMdctTest, MIDCT256) {
+ const int N = 256;
+ TMIDCT<N> transform(N);
+ vector<TFloat> src(N);
+ for (int i = 0; i < N/2; i++) {
+ src[i] = i;
+ }
+ const vector<TFloat> res1 = midct(&src[0], N/2);
+ const vector<TFloat> res2 = transform(&src[0]);
+ EXPECT_EQ(res1.size(), res2.size());
+ for (int i = 0; i < N; i++) {
+ EXPECT_NEAR(res1[i], res2[i], 0.000000001);
+ }
+}
+
+TEST(TMdctTest, MIDCT256_RAND) {
+ const int N = 256;
+ TMIDCT<N> transform(N);
+ vector<TFloat> src(N);
+ for (int i = 0; i < N/2; i++) {
+ src[i] = rand();
+ }
+ const vector<TFloat> res1 = midct(&src[0], N/2);
+ const vector<TFloat> res2 = transform(&src[0]);
+ EXPECT_EQ(res1.size(), res2.size());
+ for (int i = 0; i < N; i++) {
+ EXPECT_NEAR(res1[i], res2[i], 0.01);
+ }
+}