aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniil Cherednik <dan.cherednik@gmail.com>2019-05-21 01:01:29 +0300
committerDaniil Cherednik <dan.cherednik@gmail.com>2019-08-23 16:58:34 +0300
commit8b0e9c515ec0872bd24ea4563a733ca743fe7d1f (patch)
treefc37e469237bf1b5dc828657ad79ed75abaa3093
parent72c3f6ec998e8acfade1e1b40abf32af21eb282b (diff)
downloadatracdenc-8b0e9c515ec0872bd24ea4563a733ca743fe7d1f.tar.gz
Implementation of atrac3plus analysis pqf
-rw-r--r--src/atrac/atrac3plus_pqf/atrac3plus_pqf.c188
-rw-r--r--src/atrac/atrac3plus_pqf/atrac3plus_pqf.h44
-rw-r--r--src/atrac/atrac3plus_pqf/atrac3plus_pqf_prototype.h411
-rw-r--r--src/atrac/atrac3plus_pqf/tools/plot/main.py69
-rw-r--r--src/atrac/atrac3plus_pqf/tools/plot/pqf/pqf_binding.c187
-rw-r--r--src/atrac/atrac3plus_pqf/tools/plot/pqf/setup.py6
-rw-r--r--src/atrac/atrac3plus_pqf/tools/plot/run.sh12
-rw-r--r--src/config.h2
8 files changed, 919 insertions, 0 deletions
diff --git a/src/atrac/atrac3plus_pqf/atrac3plus_pqf.c b/src/atrac/atrac3plus_pqf/atrac3plus_pqf.c
new file mode 100644
index 0000000..2515a6d
--- /dev/null
+++ b/src/atrac/atrac3plus_pqf/atrac3plus_pqf.c
@@ -0,0 +1,188 @@
+/*
+ * 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
+ */
+
+/*
+ * Musepack pqf implementation was used as reference.
+ * see svn.musepack.net
+ */
+
+#include <stdlib.h>
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "atrac3plus_pqf.h"
+#include "atrac3plus_pqf_prototype.h"
+
+/*
+ * Number of subbands to split input signal
+ */
+#define SUBBANDS_NUM 16
+/*
+ * Number of samples in each subband
+ */
+#define SUBBAND_SIZE 128
+/*
+ * Size of filter prototype
+ */
+#define PROTO_SZ 384
+
+#define FRAME_SZ ((SUBBANDS_NUM * SUBBAND_SIZE))
+#define EXTRA_SZ ((PROTO_SZ - SUBBANDS_NUM))
+
+const uint16_t at3plus_pqf_frame_sz = FRAME_SZ;
+const uint16_t at3plus_pqf_proto_sz = PROTO_SZ;
+
+static float C[PROTO_SZ];
+static float M[256];
+
+struct at3plus_pqf_a_ctx {
+ float buf[FRAME_SZ + EXTRA_SZ];
+};
+
+static void init(void)
+{
+ int i;
+ int j;
+ const float* const t = at3plus_pqf_prototype;
+ static int inited = 0;
+
+ if (inited)
+ return;
+ inited = 1;
+
+ for (i = 0; i < 16; i++) {
+ for (j = 0; j < 16; j++) {
+ M[i*16 + j] = (float)cos(((2 * i + 1) * j & 127) * M_PI / 32);
+ }
+ }
+
+ for (i = 0; i < 6; i++) {
+ for (j = 0; j < 32; j++) {
+ if (i & 1) {
+ C[j * 12 + i] = 1.489 * t[j * 2 + 64 * i];
+ C[j * 12 + 6 + i] = 1.489 * t[j * 2 + 1 + 64 * i];
+ } else {
+ C[j * 12 + i] = -1.489 * t[j * 2 + 64 * i];
+ C[j * 12 + 6 + i] = -1.489 * t[j * 2 + 1 + 64 * i];
+ }
+ }
+ }
+}
+
+static void vectoring(const float* x, float* y)
+{
+ int i;
+ int j;
+ const float* c = C;
+
+ for ( i = 0; i < SUBBANDS_NUM * 2; i++, c += 12, x += 1, y += 1 ) {
+ y[0] = 0;
+ for (j = 0; j < 12; j++) {
+ y[0] += c[j] * x[j * 32];
+ }
+ }
+}
+
+static void matrixing(const float* mi, const float* y, float* samples )
+{
+ int i;
+ for (i = 0; i < SUBBANDS_NUM; i++, mi += 16, samples += SUBBAND_SIZE) {
+ samples[0] = y[8] + mi[ 1] * (y[7]+y[9])
+ + mi[ 2] * (y[6]+y[10]) + mi[ 3] * (y[5]+y[11])
+ + mi[ 4] * (y[4]+y[12]) + mi[ 5] * (y[3]+y[13])
+ + mi[ 6] * (y[2]+y[14]) + mi[ 7] * (y[ 1]+y[15])
+ + mi[ 8] * (y[ 0]+y[16])
+ + mi[15] * (y[23]-y[25]) + mi[14] * (y[22]-y[26])
+ + mi[13] * (y[21]-y[27]) + mi[12] * (y[20]-y[28])
+ + mi[11] * (y[19]-y[29]) + mi[10] * (y[18]-y[30])
+ + mi[ 9] * (y[17]-y[31]);
+ }
+}
+
+static void a_init(at3plus_pqf_a_ctx_t ctx)
+{
+ float y[SUBBANDS_NUM * 2];
+ float out[FRAME_SZ];
+ float* x;
+ int n, i;
+
+ float* buf = ctx->buf;
+ init();
+
+ memcpy ( buf + FRAME_SZ, buf, EXTRA_SZ * sizeof(*buf) );
+ x = buf + FRAME_SZ;
+
+ for ( n = 0; n < SUBBAND_SIZE; n++ ) {
+ x -= SUBBANDS_NUM;
+
+ for (i = 0; i < SUBBANDS_NUM; i++)
+ x[i] = 0.0;
+
+ vectoring(x, y);
+ matrixing (M, y, &out[n]);
+ }
+}
+
+at3plus_pqf_a_ctx_t at3plus_pqf_create_a_ctx()
+{
+ int i = 0;
+ at3plus_pqf_a_ctx_t ctx = (at3plus_pqf_a_ctx_t)malloc(sizeof(struct at3plus_pqf_a_ctx));
+ for (i = 0; i < FRAME_SZ + EXTRA_SZ; i++) {
+ ctx->buf[i] = 0.0;
+ }
+
+ a_init(ctx);
+ return ctx;
+}
+
+void at3plus_pqf_free_a_ctx(at3plus_pqf_a_ctx_t ctx)
+{
+ free(ctx);
+}
+
+void at3plus_pqf_do_analyse(at3plus_pqf_a_ctx_t ctx, const float* in, float* out)
+{
+ float y[SUBBANDS_NUM * 2];
+ float* x;
+ const float* pcm;
+ int n, i;
+
+ float* buf = ctx->buf;
+
+ memcpy(buf + FRAME_SZ, buf, EXTRA_SZ * sizeof(float));
+ x = buf + FRAME_SZ;
+
+ pcm = in + (SUBBANDS_NUM - 1);
+
+ for (n = 0; n < SUBBAND_SIZE; n++, pcm += SUBBANDS_NUM * 2) {
+ x -= SUBBANDS_NUM;
+ for (i = 0; i < SUBBANDS_NUM; i++) {
+ x[i] = *pcm--;
+ }
+ vectoring(x, y);
+ matrixing (M, y, &out[n]);
+ }
+}
+
+const float* at3plus_pqf_get_proto(void)
+{
+ return at3plus_pqf_prototype;
+}
+
diff --git a/src/atrac/atrac3plus_pqf/atrac3plus_pqf.h b/src/atrac/atrac3plus_pqf/atrac3plus_pqf.h
new file mode 100644
index 0000000..1be44d0
--- /dev/null
+++ b/src/atrac/atrac3plus_pqf/atrac3plus_pqf.h
@@ -0,0 +1,44 @@
+/*
+ * 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 ATRAC3PLUSPQF_H
+#define ATRAC3PLUSPQF_H
+
+#include <stdint.h>
+
+typedef struct at3plus_pqf_a_ctx *at3plus_pqf_a_ctx_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const uint16_t at3plus_pqf_frame_sz;
+extern const uint16_t at3plus_pqf_proto_sz;
+
+at3plus_pqf_a_ctx_t at3plus_pqf_create_a_ctx(void);
+void at3plus_pqf_free_a_ctx(at3plus_pqf_a_ctx_t ctx);
+void at3plus_pqf_do_analyse(at3plus_pqf_a_ctx_t ctx, const float* in, float* out);
+
+// Debug functions
+const float* at3plus_pqf_get_proto(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/atrac/atrac3plus_pqf/atrac3plus_pqf_prototype.h b/src/atrac/atrac3plus_pqf/atrac3plus_pqf_prototype.h
new file mode 100644
index 0000000..6cfa070
--- /dev/null
+++ b/src/atrac/atrac3plus_pqf/atrac3plus_pqf_prototype.h
@@ -0,0 +1,411 @@
+/*
+ * 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 ATRAC3PLUSPQFPROTOTPE_H
+#define ATRAC3PLUSPQFPROTOTPE_H
+
+const float at3plus_pqf_prototype[384] =
+{
+0.00000058336207,
+0.00000080604229,
+0.00000042005411,
+0.00000004440057,
+-0.00000003226247,
+-0.00000003530856,
+-0.00000001266038,
+-0.00001051678282,
+0.00001183861787,
+-0.00000060053890,
+-0.00000143337536,
+-0.00000231086847,
+-0.00000325697420,
+-0.00000461924219,
+-0.00000638942583,
+-0.00000703029718,
+-0.00000052268200,
+-0.00000091714480,
+-0.00000108977838,
+-0.00000023649704,
+0.00000027792686,
+0.00000052588763,
+0.00000046299544,
+-0.00001084099222,
+-0.00001220357626,
+-0.00002196196510,
+-0.00002134877286,
+-0.00001990710552,
+-0.00001734808211,
+-0.00001198405243,
+-0.00000727012593,
+-0.00000629902070,
+-0.00000916228237,
+-0.00001050293486,
+-0.00000792127867,
+-0.00000417120236,
+-0.00000263366292,
+-0.00000154329177,
+-0.00000057168614,
+0.00000181119538,
+0.00002353085074,
+0.00002780561954,
+0.00003230232323,
+0.00003696891872,
+0.00004157561489,
+0.00004533784522,
+0.00004604394780,
+0.00004858558168,
+0.00000991988691,
+0.00001313118355,
+0.00001478948616,
+0.00001984130540,
+0.00002653474803,
+0.00003386474418,
+0.00004157788862,
+0.00004978773723,
+0.00002968751687,
+0.00003634074528,
+0.00003947730875,
+0.00004292758240,
+0.00004713382441,
+0.00005426778807,
+0.00006174868031,
+0.00006414738891,
+0.00006446454790,
+0.00006830695202,
+0.00007308147178,
+0.00007612784975,
+0.00007485075184,
+0.00007020850899,
+0.00006228515122,
+0.00005827044151,
+0.00005629632869,
+0.00004988881119,
+0.00003561532503,
+0.00001853294270,
+-0.00000166573534,
+-0.00002610587035,
+-0.00005339706695,
+-0.00008079566032,
+-0.00011279431783,
+-0.00014691354590,
+-0.00018116166757,
+-0.00021972040122,
+-0.00025986303808,
+-0.00030001782579,
+-0.00033926189644,
+-0.00036942670704,
+-0.00042499689152,
+-0.00045358928037,
+-0.00048466061708,
+-0.00051135791000,
+-0.00053276919061,
+-0.00054783461383,
+-0.00055472925305,
+-0.00055432377849,
+-0.00054488552269,
+-0.00052537227748,
+-0.00049731286708,
+-0.00045777999912,
+-0.00040612387238,
+-0.00034301576670,
+-0.00026866336702,
+-0.00018248900597,
+-0.00008430792514,
+0.00002508115722,
+0.00014135583478,
+0.00026649952633,
+0.00039945056778,
+0.00053928449051,
+0.00068422866752,
+0.00083093711874,
+0.00097943725996,
+0.00112581404392,
+0.00126854737755,
+0.00140469032340,
+0.00153207418043,
+0.00164810777642,
+0.00175017165020,
+0.00183808000293,
+0.00189900479745,
+0.00194506184198,
+0.00196531717665,
+0.00195937906392,
+0.00192521407735,
+0.00186084536836,
+0.00176518992521,
+0.00163768627681,
+0.00147714314517,
+0.00128322700039,
+0.00105668208562,
+0.00079780723900,
+0.00050782406470,
+0.00018855913368,
+-0.00015771533072,
+-0.00052769453032,
+-0.00091862218687,
+-0.00132635701448,
+-0.00174694834277,
+-0.00217548245564,
+-0.00260676839389,
+-0.00303528923541,
+-0.00345493946224,
+-0.00385913741775,
+-0.00424182694405,
+-0.00459594465792,
+-0.00491465069354,
+-0.00519145652652,
+-0.00541948433965,
+-0.00559201091528,
+-0.00570259056985,
+-0.00574458623305,
+-0.00571426097304,
+-0.00560342334211,
+-0.00540914759040,
+-0.00512683158740,
+-0.00475297635421,
+-0.00428478466347,
+-0.00372032052837,
+-0.00305867753923,
+-0.00229951413348,
+-0.00144354603253,
+-0.00049266568385,
+0.00055068987422,
+0.00168289500289,
+0.00289928726852,
+0.00419431505725,
+0.00556147377938,
+0.00699351215735,
+0.00848235655576,
+0.01001896336675,
+0.01159386243671,
+0.01319687161595,
+0.01481730863452,
+0.01644404232502,
+0.01806553266943,
+0.01967016234994,
+0.02124618366361,
+0.02278177253902,
+0.02426535822451,
+0.02568554319441,
+0.02703126519918,
+0.02829195372760,
+0.02945766039193,
+0.03051890246570,
+0.03146736323833,
+0.03229522705078,
+0.03299576789141,
+0.03356324881315,
+0.03399298712611,
+0.03428143635392,
+0.03442628309131,
+0.03442628309131,
+0.03428143635392,
+0.03399298712611,
+0.03356324881315,
+0.03299576789141,
+0.03229522705078,
+0.03146736323833,
+0.03051890246570,
+0.02945766039193,
+0.02829195372760,
+0.02703126519918,
+0.02568554319441,
+0.02426535822451,
+0.02278177253902,
+0.02124618366361,
+0.01967016234994,
+0.01806553266943,
+0.01644404232502,
+0.01481730863452,
+0.01319687161595,
+0.01159386243671,
+0.01001896336675,
+0.00848235655576,
+0.00699351215735,
+0.00556147377938,
+0.00419431505725,
+0.00289928726852,
+0.00168289500289,
+0.00055068987422,
+-0.00049266568385,
+-0.00144354603253,
+-0.00229951413348,
+-0.00305867753923,
+-0.00372032052837,
+-0.00428478466347,
+-0.00475297635421,
+-0.00512683158740,
+-0.00540914759040,
+-0.00560342334211,
+-0.00571426097304,
+-0.00574458623305,
+-0.00570259056985,
+-0.00559201091528,
+-0.00541948433965,
+-0.00519145652652,
+-0.00491465069354,
+-0.00459594465792,
+-0.00424182694405,
+-0.00385913741775,
+-0.00345493946224,
+-0.00303528923541,
+-0.00260676839389,
+-0.00217548245564,
+-0.00174694834277,
+-0.00132635701448,
+-0.00091862218687,
+-0.00052769453032,
+-0.00015771533072,
+0.00018855913368,
+0.00050782406470,
+0.00079780723900,
+0.00105668208562,
+0.00128322700039,
+0.00147714314517,
+0.00163768627681,
+0.00176518992521,
+0.00186084536836,
+0.00192521407735,
+0.00195937906392,
+0.00196531717665,
+0.00194506184198,
+0.00189900479745,
+0.00183808000293,
+0.00175017165020,
+0.00164810777642,
+0.00153207418043,
+0.00140469032340,
+0.00126854737755,
+0.00112581404392,
+0.00097943725996,
+0.00083093711874,
+0.00068422866752,
+0.00053928449051,
+0.00039945056778,
+0.00026649952633,
+0.00014135583478,
+0.00002508115722,
+-0.00008430792514,
+-0.00018248900597,
+-0.00026866336702,
+-0.00034301576670,
+-0.00040612387238,
+-0.00045777999912,
+-0.00049731286708,
+-0.00052537227748,
+-0.00054488552269,
+-0.00055432377849,
+-0.00055472925305,
+-0.00054783461383,
+-0.00053276919061,
+-0.00051135791000,
+-0.00048466061708,
+-0.00045358928037,
+-0.00042499689152,
+-0.00036942670704,
+-0.00033926189644,
+-0.00030001782579,
+-0.00025986303808,
+-0.00021972040122,
+-0.00018116166757,
+-0.00014691354590,
+-0.00011279431783,
+-0.00008079566032,
+-0.00005339706695,
+-0.00002610587035,
+-0.00000166573534,
+0.00001853294270,
+0.00003561532503,
+0.00004988881119,
+0.00005629632869,
+0.00005827044151,
+0.00006228515122,
+0.00007020850899,
+0.00007485075184,
+0.00007612784975,
+0.00007308147178,
+0.00006830695202,
+0.00006446454790,
+0.00006414738891,
+0.00006174868031,
+0.00005426778807,
+0.00004713382441,
+0.00004292758240,
+0.00003947730875,
+0.00003634074528,
+0.00002968751687,
+0.00004978773723,
+0.00004157788862,
+0.00003386474418,
+0.00002653474803,
+0.00001984130540,
+0.00001478948616,
+0.00001313118355,
+0.00000991988691,
+0.00004858558168,
+0.00004604394780,
+0.00004533784522,
+0.00004157561489,
+0.00003696891872,
+0.00003230232323,
+0.00002780561954,
+0.00002353085074,
+0.00000181119538,
+-0.00000057168614,
+-0.00000154329177,
+-0.00000263366292,
+-0.00000417120236,
+-0.00000792127867,
+-0.00001050293486,
+-0.00000916228237,
+-0.00000629902070,
+-0.00000727012593,
+-0.00001198405243,
+-0.00001734808211,
+-0.00001990710552,
+-0.00002134877286,
+-0.00002196196510,
+-0.00001220357626,
+-0.00001084099222,
+0.00000046299544,
+0.00000052588763,
+0.00000027792686,
+-0.00000023649704,
+-0.00000108977838,
+-0.00000091714480,
+-0.00000052268200,
+-0.00000703029718,
+-0.00000638942583,
+-0.00000461924219,
+-0.00000325697420,
+-0.00000231086847,
+-0.00000143337536,
+-0.00000060053890,
+0.00001183861787,
+-0.00001051678282,
+-0.00000001266038,
+-0.00000003530856,
+-0.00000003226247,
+0.00000004440057,
+0.00000042005411,
+0.00000080604229,
+0.00000058336207
+};
+
+#endif
+
diff --git a/src/atrac/atrac3plus_pqf/tools/plot/main.py b/src/atrac/atrac3plus_pqf/tools/plot/main.py
new file mode 100644
index 0000000..2296196
--- /dev/null
+++ b/src/atrac/atrac3plus_pqf/tools/plot/main.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+import argparse
+
+import numpy as np
+import matplotlib.pyplot as plt
+import scipy.fftpack
+
+import pqf
+
+SAMPLES = pqf.frame_sz
+RUNS = 3
+SAMPLERATE = 44100
+
+def show_proto():
+ proto = pqf.prototype()
+ fig = plt.figure()
+
+ yf = scipy.fftpack.fft(proto[:len(proto)])
+
+ fig.add_subplot(111).plot(10 * np.log10(np.abs(yf[:len(proto)//2])))
+ fig.add_subplot(222).plot(proto)
+ plt.show()
+
+
+def do_an(ctx, time, data, shift):
+ data_slice = data[shift : SAMPLES + shift]
+ time_slice = time[shift : SAMPLES + shift]
+
+ res = ctx.do(data_slice);
+
+ fig = plt.figure()
+
+ a = fig.add_subplot(111)
+ a.plot(time_slice, res)
+ a.set_title("output")
+ b = fig.add_subplot(222)
+ b.plot(time_slice, data_slice)
+ b.set_title("input");
+ plt.show()
+
+
+def process_freq(freq):
+ ctx = pqf.AnalyzeCtx()
+
+ time = np.arange(0, SAMPLES * RUNS, 1)
+ amplitude = 0.01 * np.sin(2 * np.pi * freq * time / SAMPLERATE).astype(np.float32)
+
+ do_an(ctx, time, amplitude, 0);
+ do_an(ctx, time, amplitude, SAMPLES);
+
+
+def main():
+ parser = argparse.ArgumentParser()
+
+ parser.add_argument('--freq', type=int, help="generate sine with given frequency", action='store')
+ parser.add_argument('--proto', help="show filter prototype", action='store_true')
+
+ args = parser.parse_args()
+
+ if (args.proto):
+ show_proto()
+ else:
+ process_freq(args.freq)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/src/atrac/atrac3plus_pqf/tools/plot/pqf/pqf_binding.c b/src/atrac/atrac3plus_pqf/tools/plot/pqf/pqf_binding.c
new file mode 100644
index 0000000..8ddf5ee
--- /dev/null
+++ b/src/atrac/atrac3plus_pqf/tools/plot/pqf/pqf_binding.c
@@ -0,0 +1,187 @@
+#include <Python.h>
+#include <structmember.h>
+
+#include <stdio.h>
+
+
+#include <atrac3plus_pqf.h>
+
+typedef struct {
+ PyObject_HEAD;
+ at3plus_pqf_a_ctx_t ctx;
+} AnalyzeCtxObject;
+
+static PyObject *
+AnalyzeCtx_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ AnalyzeCtxObject *self;
+ self = (AnalyzeCtxObject*)type->tp_alloc(type, 0);
+ if (self == NULL) {
+ fprintf(stderr, "Unable to allocate analyze context\n");
+ return NULL;
+ }
+ return (PyObject*)self;
+}
+
+static int
+AnalyzeCtx_init(AnalyzeCtxObject *self, PyObject *args, PyObject *kwds)
+{
+ self->ctx = at3plus_pqf_create_a_ctx();
+ return 0;
+}
+
+static void
+AnalyzeCtx_dealloc(AnalyzeCtxObject *self)
+{
+ at3plus_pqf_free_a_ctx(self->ctx);
+}
+
+static PyObject* prototype(PyObject* self, PyObject* unused)
+{
+ int i;
+ const float* proto = at3plus_pqf_get_proto();
+
+ PyObject *my_list = PyList_New(0);
+ if(my_list == NULL) {
+ return NULL;
+ }
+
+ for (i = 0; i < at3plus_pqf_proto_sz; i++) {
+ PyObject *o = Py_BuildValue("f", proto[i]);
+ if(PyList_Append(my_list, o) == -1) {
+ return NULL;
+ }
+ }
+
+ return my_list;
+}
+
+static PyObject* analyzectx_do(PyObject* self, PyObject* args)
+{
+ int i = 0;
+ int len = 0;
+ float* in;
+ float* out;
+
+ AnalyzeCtxObject* ctx;
+ PyObject *seq;
+
+ if (!PyArg_ParseTuple(args, "O", &seq)) {
+ return NULL;
+ }
+
+ seq = PySequence_Fast(seq, "argument must be iterable");
+
+ if (!seq) {
+ return NULL;
+ }
+
+ len = PySequence_Fast_GET_SIZE(seq);
+
+ if (len != at3plus_pqf_frame_sz) {
+ fprintf(stderr, "wrong frame size, expected: %d, got: %d", (int)at3plus_pqf_frame_sz, len);
+ return NULL;
+ }
+
+ in = (float*)malloc(len * sizeof(float));
+ if(!in) {
+ Py_DECREF(seq);
+ return PyErr_NoMemory( );
+ }
+
+ for (i = 0; i < len; i++) {
+ PyObject *fitem;
+ PyObject *item = PySequence_Fast_GET_ITEM(seq, i);
+ if(!item) {
+ Py_DECREF(seq);
+ free(in);
+ return NULL;
+ }
+ fitem = PyNumber_Float(item);
+ if(!fitem) {
+ Py_DECREF(seq);
+ free(in);
+ PyErr_SetString(PyExc_TypeError, "all items must be numbers");
+ return NULL;
+ }
+ in[i] = PyFloat_AS_DOUBLE(fitem);
+ Py_DECREF(fitem);
+ }
+
+ PyObject *my_list = PyList_New(0);
+ if(my_list == NULL) {
+ Py_DECREF(seq);
+ free(in);
+ return NULL;
+ }
+
+ out = (float*)calloc(at3plus_pqf_frame_sz, sizeof(float));
+ if (out == NULL) {
+ Py_DECREF(seq);
+ free(in);
+ return NULL;
+ }
+
+ ctx = (AnalyzeCtxObject*)self;
+
+ at3plus_pqf_do_analyse(ctx->ctx, in, out);
+
+ for (i = 0; i < len; i++) {
+ PyObject *o = Py_BuildValue("f", out[i]);
+ if(PyList_Append(my_list, o) == -1) {
+ Py_DECREF(seq);
+ free(in);
+ return NULL;
+ }
+ }
+
+ free(in);
+ return my_list;
+}
+
+static PyMethodDef methods[] = {
+ { "prototype", prototype, METH_NOARGS, "Show atrac3plus pqf filter prototype"},
+ { NULL, NULL, 0, NULL }
+};
+
+static PyMethodDef AnalyzeCtx_methods[] = {
+ {"do", (PyCFunction)analyzectx_do, METH_VARARGS, NULL},
+ {NULL}
+};
+
+static PyTypeObject AnalyzeCtxType = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = "pqf.AnalyzeCtx",
+ .tp_doc = "AnalyzeCtx",
+ .tp_basicsize = sizeof(AnalyzeCtxObject),
+ .tp_itemsize = 0,
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ .tp_new = AnalyzeCtx_new,
+ .tp_init = (initproc)AnalyzeCtx_init,
+ .tp_dealloc = (destructor)AnalyzeCtx_dealloc,
+ .tp_methods = AnalyzeCtx_methods,
+};
+
+static struct PyModuleDef module = {
+ PyModuleDef_HEAD_INIT,
+ .m_name = "pqf",
+ .m_doc = "pqf library test binding",
+ .m_size = -1,
+ .m_methods = methods
+};
+
+PyMODINIT_FUNC PyInit_pqf(void)
+{
+ PyObject *m;
+ if (PyType_Ready(&AnalyzeCtxType) < 0)
+ return NULL;
+
+ m = PyModule_Create(&module);
+ if (m == NULL)
+ return NULL;
+
+ Py_INCREF(&AnalyzeCtxType);
+ PyModule_AddObject(m, "AnalyzeCtx", (PyObject*)&AnalyzeCtxType);
+ PyModule_AddIntConstant(m, "frame_sz", at3plus_pqf_frame_sz);
+ return m;
+}
diff --git a/src/atrac/atrac3plus_pqf/tools/plot/pqf/setup.py b/src/atrac/atrac3plus_pqf/tools/plot/pqf/setup.py
new file mode 100644
index 0000000..bf2b87f
--- /dev/null
+++ b/src/atrac/atrac3plus_pqf/tools/plot/pqf/setup.py
@@ -0,0 +1,6 @@
+from distutils.core import setup, Extension
+
+setup(name = 'pqf', version = '1.0', \
+ ext_modules = [Extension('pqf', \
+ sources=['pqf_binding.c', '../../../atrac3plus_pqf.c'], \
+ include_dirs=['../../../'])])
diff --git a/src/atrac/atrac3plus_pqf/tools/plot/run.sh b/src/atrac/atrac3plus_pqf/tools/plot/run.sh
new file mode 100644
index 0000000..06e7788
--- /dev/null
+++ b/src/atrac/atrac3plus_pqf/tools/plot/run.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+
+set -e
+
+cd pqf
+
+python3.7 setup.py build
+
+cd ..
+
+export PYTHONPATH=./pqf/build/lib.mingw-3.7/
+./main.py "$@"
diff --git a/src/config.h b/src/config.h
index 0e2fd8d..ed5a149 100644
--- a/src/config.h
+++ b/src/config.h
@@ -20,7 +20,9 @@
#define CONFIG_DOUBLE
+#ifndef NOMINMAX
#define NOMINMAX
+#endif
#ifdef CONFIG_DOUBLE
# define kiss_fft_scalar double