Adds IRFFT Op to Signal Library (#2137)
Inverse-RFFT as part of Signal library ops.
Testing via current FFT Op tests.
BUG=[287346710](http://b/287346710)
diff --git a/python/tflite_micro/python_ops_resolver.cc b/python/tflite_micro/python_ops_resolver.cc
index becdcbb..e6f9cf7 100644
--- a/python/tflite_micro/python_ops_resolver.cc
+++ b/python/tflite_micro/python_ops_resolver.cc
@@ -64,6 +64,7 @@
AddGreaterEqual();
AddHardSwish();
AddIf();
+ AddIrfft();
AddL2Normalization();
AddL2Pool2D();
AddLeakyRelu();
diff --git a/python/tflite_micro/signal/ops/fft_ops.py b/python/tflite_micro/signal/ops/fft_ops.py
index 66874eb..446b878 100644
--- a/python/tflite_micro/signal/ops/fft_ops.py
+++ b/python/tflite_micro/signal/ops/fft_ops.py
@@ -80,7 +80,9 @@
rfft = _fft_wrapper(gen_fft_ops.signal_rfft, "signal_rfft")
+irfft = _fft_wrapper(gen_fft_ops.signal_irfft, "signal_irfft")
fft_auto_scale = _fft_auto_scale_wrapper(gen_fft_ops.signal_fft_auto_scale,
"signal_fft_auto_scale")
tf.no_gradient("signal_rfft")
+tf.no_gradient("signal_irfft")
tf.no_gradient("signal_fft_auto_scale")
diff --git a/python/tflite_micro/signal/ops/fft_ops_test.py b/python/tflite_micro/signal/ops/fft_ops_test.py
index fa16b69..63de824 100644
--- a/python/tflite_micro/signal/ops/fft_ops_test.py
+++ b/python/tflite_micro/signal/ops/fft_ops_test.py
@@ -251,6 +251,61 @@
with self.assertRaises((tf.errors.InvalidArgumentError, ValueError)):
self.evaluate(fft_ops.rfft(fft_input, 127))
+ def testIrfftTest(self):
+ for dtype in [np.int16, np.int32, np.float32]:
+ fft_length = fft_ops._MIN_FFT_LENGTH
+ while fft_length <= fft_ops._MAX_FFT_LENGTH:
+ if dtype == np.float32:
+ # Random input in the range [-1, 1)
+ fft_input = np.random.random(fft_length).astype(dtype) * 2 - 1
+ else:
+ fft_input = np.random.randint(
+ np.iinfo(np.int16).min,
+ np.iinfo(np.int16).max + 1, fft_length).astype(dtype)
+ fft_output = self.evaluate(fft_ops.rfft(fft_input, fft_length))
+ self.assertEqual(fft_output.shape[0], (fft_length / 2 + 1) * 2)
+ ifft_output = self.evaluate(fft_ops.irfft(fft_output, fft_length))
+ self.assertEqual(ifft_output.shape[0], fft_length)
+ # Output of integer RFFT and IRFFT is scaled by 1/fft_length
+ if dtype == np.int16:
+ self.assertArrayNear(fft_input,
+ ifft_output.astype(np.int32) * fft_length, 6500)
+ elif dtype == np.int32:
+ self.assertArrayNear(fft_input,
+ ifft_output.astype(np.int32) * fft_length, 7875)
+ else:
+ self.assertArrayNear(fft_input, ifft_output, 5e-7)
+ fft_length = 2 * fft_length
+
+ def testIrfftLargeOuterDimension(self):
+ for dtype in [np.int16, np.int32, np.float32]:
+ fft_length = fft_ops._MIN_FFT_LENGTH
+ while fft_length <= fft_ops._MAX_FFT_LENGTH:
+ if dtype == np.float32:
+ # Random input in the range [-1, 1)
+ fft_input = np.random.random([2, 5, fft_length
+ ]).astype(dtype) * 2 - 1
+ else:
+ fft_input = np.random.randint(
+ np.iinfo(np.int16).min,
+ np.iinfo(np.int16).max + 1, [2, 5, fft_length]).astype(dtype)
+ fft_output = self.evaluate(fft_ops.rfft(fft_input, fft_length))
+ self.assertEqual(fft_output.shape[-1], (fft_length / 2 + 1) * 2)
+ ifft_output = self.evaluate(fft_ops.irfft(fft_output, fft_length))
+ self.assertEqual(ifft_output.shape[-1], fft_length)
+ # Output of integer RFFT and IRFFT is scaled by 1/fft_length
+ if dtype == np.int16:
+ self.assertAllClose(fft_input,
+ ifft_output.astype(np.int32) * fft_length,
+ atol=7875)
+ elif dtype == np.int32:
+ self.assertAllClose(fft_input,
+ ifft_output.astype(np.int32) * fft_length,
+ atol=7875)
+ else:
+ self.assertAllClose(fft_input, ifft_output, rtol=5e-7, atol=5e-7)
+ fft_length = 2 * fft_length
+
def testAutoScale(self):
self.SingleFftAutoScaleTest('testdata/fft_auto_scale_test1.txt')
diff --git a/signal/micro/kernels/BUILD b/signal/micro/kernels/BUILD
index 9dab821..4d37f06 100644
--- a/signal/micro/kernels/BUILD
+++ b/signal/micro/kernels/BUILD
@@ -16,12 +16,14 @@
"filter_bank_spectral_subtraction.cc",
"filter_bank_square_root.cc",
"framer.cc",
+ "irfft.cc",
"overlap_add.cc",
"rfft.cc",
"stacker.cc",
"window.cc",
],
hdrs = [
+ "irfft.h",
"rfft.h",
],
copts = micro_copts(),
@@ -36,6 +38,7 @@
"//signal/src:filter_bank_log",
"//signal/src:filter_bank_spectral_subtraction",
"//signal/src:filter_bank_square_root",
+ "//signal/src:irfft",
"//signal/src:overlap_add",
"//signal/src:rfft",
"//signal/src:window",
diff --git a/signal/micro/kernels/fft_test.cc b/signal/micro/kernels/fft_test.cc
index 03bb3f3..e910519 100644
--- a/signal/micro/kernels/fft_test.cc
+++ b/signal/micro/kernels/fft_test.cc
@@ -303,6 +303,164 @@
g_gen_data_size_fft_length_512_int32, output, 0));
}
+TF_LITE_MICRO_TEST(IrfftTestLength64Float) {
+ constexpr int kOutputLen = 64;
+ int input_shape[] = {1, 66};
+ const float input[] = {256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0,
+ 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0,
+ 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0,
+ 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0,
+ 256, 0, 256, 0, 256, 0, 256, 0, 256, 0};
+ int output_shape[] = {1, kOutputLen};
+ const float golden[] = {256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ float output[kOutputLen];
+ const TFLMRegistration* registration =
+ tflite::tflm_signal::Register_IRFFT_FLOAT();
+ TF_LITE_MICRO_EXPECT_EQ(
+ kTfLiteOk, tflite::testing::TestFFT<float>(
+ input_shape, input, output_shape, golden, *registration,
+ g_gen_data_fft_length_64_float,
+ g_gen_data_size_fft_length_64_int16, output, 1e-7));
+}
+
+TF_LITE_MICRO_TEST(IrfftTestLength64Int16) {
+ constexpr int kOutputLen = 64;
+ int input_shape[] = {1, 66};
+ const int16_t input[] = {
+ 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0,
+ 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0,
+ 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0,
+ 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0};
+ int output_shape[] = {1, kOutputLen};
+ const int16_t golden[] = {256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int16_t output[kOutputLen];
+ const TFLMRegistration* registration =
+ tflite::tflm_signal::Register_IRFFT_INT16();
+ TF_LITE_MICRO_EXPECT_EQ(
+ kTfLiteOk, tflite::testing::TestFFT<int16_t>(
+ input_shape, input, output_shape, golden, *registration,
+ g_gen_data_fft_length_64_int16,
+ g_gen_data_size_fft_length_64_int16, output, 0));
+}
+
+TF_LITE_MICRO_TEST(IrfftTestLength64Int32) {
+ constexpr int kOutputLen = 64;
+ int input_shape[] = {1, 66};
+ const int32_t input[] = {
+ 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0,
+ 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0,
+ 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0,
+ 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0};
+ int output_shape[] = {1, kOutputLen};
+ const int32_t golden[] = {256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int32_t output[kOutputLen];
+ const TFLMRegistration* registration =
+ tflite::tflm_signal::Register_IRFFT_INT32();
+ TF_LITE_MICRO_EXPECT_EQ(
+ kTfLiteOk, tflite::testing::TestFFT<int32_t>(
+ input_shape, input, output_shape, golden, *registration,
+ g_gen_data_fft_length_64_int32,
+ g_gen_data_size_fft_length_64_int32, output, 0));
+}
+
+TF_LITE_MICRO_TEST(IrfftTestLength64Int32OuterDims4) {
+ constexpr int kOutputLen = 64;
+ constexpr int kOuterDim = 2;
+ int input_shape[] = {3, kOuterDim, kOuterDim, 66};
+ const int32_t input[] = {
+ 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0,
+ 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0,
+ 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0,
+ 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0,
+ 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0,
+ 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0,
+ 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0,
+ 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0,
+ 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0,
+ 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0,
+ 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0,
+ 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0,
+ 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0,
+ 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0,
+ 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0};
+ int output_shape[] = {3, kOuterDim, kOuterDim, kOutputLen};
+ const int32_t golden[] = {
+ 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int32_t output[kOuterDim * kOuterDim * kOutputLen];
+ const TFLMRegistration* registration =
+ tflite::tflm_signal::Register_IRFFT_INT32();
+ TF_LITE_MICRO_EXPECT_EQ(
+ kTfLiteOk, tflite::testing::TestFFT<int32_t>(
+ input_shape, input, output_shape, golden, *registration,
+ g_gen_data_fft_length_64_int32,
+ g_gen_data_size_fft_length_64_int32, output, 0));
+}
+
+TF_LITE_MICRO_TEST(IrfftTestLength512Float) {
+ constexpr int kOutputLen = 512;
+ int input_shape[] = {1, 514};
+ int output_shape[] = {1, kOutputLen};
+ float output[kOutputLen];
+ const TFLMRegistration* registration =
+ tflite::tflm_signal::Register_IRFFT_FLOAT();
+ TF_LITE_MICRO_EXPECT_EQ(
+ kTfLiteOk, tflite::testing::TestFFT<float>(
+ input_shape, tflite::kIrfftFloatLength512Input,
+ output_shape, tflite::kIrfftFloatLength512Golden,
+ *registration, g_gen_data_fft_length_512_float,
+ g_gen_data_size_fft_length_512_float, output, 1e-7));
+}
+
+TF_LITE_MICRO_TEST(IrfftTestLength512Int16) {
+ constexpr int kOutputLen = 512;
+ int input_shape[] = {1, 514};
+ int output_shape[] = {1, kOutputLen};
+ int16_t output[kOutputLen];
+ const TFLMRegistration* registration =
+ tflite::tflm_signal::Register_IRFFT_INT16();
+ TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk,
+ tflite::testing::TestFFT<int16_t>(
+ input_shape, tflite::kIrfftInt16Length512Input,
+ output_shape, tflite::kIrfftInt16Length512Golden,
+ *registration, g_gen_data_fft_length_512_int16,
+ g_gen_data_size_fft_length_512_int16, output, 0));
+}
+
+TF_LITE_MICRO_TEST(IrfftTestLength512Int32) {
+ constexpr int kOutputLen = 512;
+ int input_shape[] = {1, 514};
+ int output_shape[] = {1, kOutputLen};
+ int32_t output[kOutputLen];
+ const TFLMRegistration* registration =
+ tflite::tflm_signal::Register_IRFFT_INT32();
+ TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk,
+ tflite::testing::TestFFT<int32_t>(
+ input_shape, tflite::kIrfftInt32Length512Input,
+ output_shape, tflite::kIrfftInt32Length512Golden,
+ *registration, g_gen_data_fft_length_512_int32,
+ g_gen_data_size_fft_length_512_int32, output, 0));
+}
+
TF_LITE_MICRO_TEST(FftAutoScaleTestSmall) {
constexpr int kTensorsSize = 8;
int shape[] = {1, 8};
diff --git a/signal/micro/kernels/irfft.cc b/signal/micro/kernels/irfft.cc
new file mode 100644
index 0000000..6cb3d7c
--- /dev/null
+++ b/signal/micro/kernels/irfft.cc
@@ -0,0 +1,230 @@
+/* Copyright 2023 The TensorFlow Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+==============================================================================*/
+
+#include "signal/src/irfft.h"
+
+#include <math.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "tensorflow/lite/kernels/internal/tensor_ctypes.h"
+#include "tensorflow/lite/kernels/kernel_util.h"
+#include "tensorflow/lite/micro/flatbuffer_utils.h"
+#include "tensorflow/lite/micro/kernels/kernel_util.h"
+#include "tensorflow/lite/portable_type_to_tflitetype.h"
+
+namespace tflite {
+namespace {
+
+constexpr int kInputTensor = 0;
+constexpr int kOutputTensor = 0;
+
+// Indices into the init flexbuffer's vector.
+// The parameter's name is in the comment that follows.
+// Elements in the vectors are ordered alphabetically by parameter name.
+// 'T' is added implicitly by the TensorFlow framework when the type is resolved
+// during graph construction.
+// constexpr int kTypeIndex = 0; // 'T' (unused)
+constexpr int kFftLengthIndex = 1; // 'fft_length'
+
+struct TfLiteAudioFrontendIrfftParams {
+ int32_t fft_length;
+ int32_t input_size;
+ int32_t input_length;
+ int32_t output_length;
+ TfLiteType fft_type;
+ int8_t* state;
+};
+
+template <typename T, size_t (*get_needed_memory_func)(int32_t),
+ void* (*init_func)(int32_t, void*, size_t)>
+void* Init(TfLiteContext* context, const char* buffer, size_t length) {
+ TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr);
+
+ auto* params = static_cast<TfLiteAudioFrontendIrfftParams*>(
+ context->AllocatePersistentBuffer(
+ context, sizeof(TfLiteAudioFrontendIrfftParams)));
+
+ if (params == nullptr) {
+ return nullptr;
+ }
+
+ tflite::FlexbufferWrapper fbw(reinterpret_cast<const uint8_t*>(buffer),
+ length);
+ params->fft_length = fbw.ElementAsInt32(kFftLengthIndex);
+ params->fft_type = typeToTfLiteType<T>();
+
+ size_t state_size = (*get_needed_memory_func)(params->fft_length);
+ params->state = reinterpret_cast<int8_t*>(
+ context->AllocatePersistentBuffer(context, state_size * sizeof(int8_t)));
+
+ if (params->state == nullptr) {
+ return nullptr;
+ }
+
+ (*init_func)(params->fft_length, params->state, state_size);
+ return params;
+}
+
+template <TfLiteType TfLiteTypeEnum>
+TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
+ TF_LITE_ENSURE_EQ(context, NumInputs(node), 1);
+ TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1);
+
+ MicroContext* micro_context = GetMicroContext(context);
+
+ TfLiteTensor* input =
+ micro_context->AllocateTempInputTensor(node, kInputTensor);
+ TF_LITE_ENSURE(context, input != nullptr);
+ TfLiteTensor* output =
+ micro_context->AllocateTempOutputTensor(node, kOutputTensor);
+ TF_LITE_ENSURE(context, output != nullptr);
+
+ TF_LITE_ENSURE_EQ(context, NumDimensions(input), NumDimensions(output));
+
+ TF_LITE_ENSURE_TYPES_EQ(context, input->type, TfLiteTypeEnum);
+ TF_LITE_ENSURE_TYPES_EQ(context, output->type, TfLiteTypeEnum);
+
+ auto* params =
+ reinterpret_cast<TfLiteAudioFrontendIrfftParams*>(node->user_data);
+ RuntimeShape input_shape = GetTensorShape(input);
+ RuntimeShape output_shape = GetTensorShape(output);
+ // Divide by 2 because input is complex.
+ params->input_length =
+ input_shape.Dims(input_shape.DimensionsCount() - 1) / 2;
+ params->input_size = input_shape.FlatSize() / 2;
+ params->output_length = output_shape.Dims(output_shape.DimensionsCount() - 1);
+
+ micro_context->DeallocateTempTfLiteTensor(input);
+ micro_context->DeallocateTempTfLiteTensor(output);
+ return kTfLiteOk;
+}
+
+template <typename T, void (*apply_func)(void*, const Complex<T>* input, T*)>
+TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
+ auto* params =
+ reinterpret_cast<TfLiteAudioFrontendIrfftParams*>(node->user_data);
+
+ const TfLiteEvalTensor* input =
+ tflite::micro::GetEvalInput(context, node, kInputTensor);
+ TfLiteEvalTensor* output =
+ tflite::micro::GetEvalOutput(context, node, kOutputTensor);
+
+ const Complex<T>* input_data =
+ tflite::micro::GetTensorData<Complex<T>>(input);
+ T* output_data = tflite::micro::GetTensorData<T>(output);
+ for (int input_idx = 0, output_idx = 0; input_idx < params->input_size;
+ input_idx += params->input_length, output_idx += params->output_length) {
+ (*apply_func)(params->state, &input_data[input_idx],
+ &output_data[output_idx]);
+ }
+ return kTfLiteOk;
+}
+
+void* InitAll(TfLiteContext* context, const char* buffer, size_t length) {
+ const uint8_t* buffer_t = reinterpret_cast<const uint8_t*>(buffer);
+ const flexbuffers::Map& m = flexbuffers::GetRoot(buffer_t, length).AsMap();
+ auto tensor_type = static_cast<tflite::TensorType>(m["T"].AsInt32());
+
+ switch (tensor_type) {
+ case TensorType_INT16: {
+ return Init<int16_t, tflm_signal::IrfftInt16GetNeededMemory,
+ tflm_signal::IrfftInt16Init>(context, buffer, length);
+ }
+ case TensorType_INT32: {
+ return Init<int32_t, tflm_signal::IrfftInt32GetNeededMemory,
+ tflm_signal::IrfftInt32Init>(context, buffer, length);
+ }
+ case TensorType_FLOAT32: {
+ return Init<float, tflm_signal::IrfftFloatGetNeededMemory,
+ tflm_signal::IrfftFloatInit>(context, buffer, length);
+ }
+ default:
+ return nullptr;
+ }
+}
+
+TfLiteStatus PrepareAll(TfLiteContext* context, TfLiteNode* node) {
+ auto* params =
+ reinterpret_cast<TfLiteAudioFrontendIrfftParams*>(node->user_data);
+
+ switch (params->fft_type) {
+ case kTfLiteInt16: {
+ return Prepare<kTfLiteInt16>(context, node);
+ }
+ case kTfLiteInt32: {
+ return Prepare<kTfLiteInt32>(context, node);
+ }
+ case kTfLiteFloat32: {
+ return Prepare<kTfLiteFloat32>(context, node);
+ }
+ default:
+ return kTfLiteError;
+ }
+}
+
+TfLiteStatus EvalAll(TfLiteContext* context, TfLiteNode* node) {
+ auto* params =
+ reinterpret_cast<TfLiteAudioFrontendIrfftParams*>(node->user_data);
+
+ switch (params->fft_type) {
+ case kTfLiteInt16: {
+ return Eval<int16_t, tflm_signal::IrfftInt16Apply>(context, node);
+ }
+ case kTfLiteInt32: {
+ return Eval<int32_t, tflm_signal::IrfftInt32Apply>(context, node);
+ }
+ case kTfLiteFloat32: {
+ return Eval<float, tflm_signal::IrfftFloatApply>(context, node);
+ }
+ default:
+ return kTfLiteError;
+ }
+}
+
+} // namespace
+
+// TODO(b/286250473): remove namespace once de-duped libraries
+namespace tflm_signal {
+
+TFLMRegistration* Register_IRFFT() {
+ static TFLMRegistration r =
+ tflite::micro::RegisterOp(InitAll, PrepareAll, EvalAll);
+ return &r;
+}
+
+TFLMRegistration* Register_IRFFT_FLOAT() {
+ static TFLMRegistration r = tflite::micro::RegisterOp(
+ Init<float, IrfftFloatGetNeededMemory, IrfftFloatInit>,
+ Prepare<kTfLiteFloat32>, Eval<float, IrfftFloatApply>);
+ return &r;
+}
+
+TFLMRegistration* Register_IRFFT_INT16() {
+ static TFLMRegistration r = tflite::micro::RegisterOp(
+ Init<int16_t, IrfftInt16GetNeededMemory, IrfftInt16Init>,
+ Prepare<kTfLiteInt16>, Eval<int16_t, IrfftInt16Apply>);
+ return &r;
+}
+
+TFLMRegistration* Register_IRFFT_INT32() {
+ static TFLMRegistration r = tflite::micro::RegisterOp(
+ Init<int32_t, IrfftInt32GetNeededMemory, IrfftInt32Init>,
+ Prepare<kTfLiteInt32>, Eval<int32_t, IrfftInt32Apply>);
+ return &r;
+}
+
+} // namespace tflm_signal
+} // namespace tflite
\ No newline at end of file
diff --git a/signal/micro/kernels/irfft.h b/signal/micro/kernels/irfft.h
new file mode 100644
index 0000000..380bc3e
--- /dev/null
+++ b/signal/micro/kernels/irfft.h
@@ -0,0 +1,31 @@
+/* Copyright 2023 The TensorFlow Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+==============================================================================*/
+#ifndef SIGNAL_MICRO_KERNELS_IRFFT_H_
+#define SIGNAL_MICRO_KERNELS_IRFFT_H_
+
+#include "tensorflow/lite/micro/micro_common.h"
+
+namespace tflite {
+namespace tflm_signal {
+
+TFLMRegistration* Register_IRFFT();
+TFLMRegistration* Register_IRFFT_FLOAT();
+TFLMRegistration* Register_IRFFT_INT16();
+TFLMRegistration* Register_IRFFT_INT32();
+
+} // namespace tflm_signal
+} // namespace tflite
+
+#endif // SIGNAL_MICRO_KERNELS_IRFFT_H_
diff --git a/signal/src/BUILD b/signal/src/BUILD
index 75f5fe9..c09f608 100644
--- a/signal/src/BUILD
+++ b/signal/src/BUILD
@@ -19,6 +19,20 @@
)
cc_library(
+ name = "irfft",
+ srcs = [
+ "irfft_float.cc",
+ "irfft_int16.cc",
+ "irfft_int32.cc",
+ ],
+ hdrs = ["irfft.h"],
+ deps = [
+ ":complex",
+ "//signal/src/kiss_fft_wrappers",
+ ],
+)
+
+cc_library(
name = "max_abs",
srcs = ["max_abs.cc"],
hdrs = ["max_abs.h"],
diff --git a/signal/src/irfft.h b/signal/src/irfft.h
new file mode 100644
index 0000000..c2b54d7
--- /dev/null
+++ b/signal/src/irfft.h
@@ -0,0 +1,84 @@
+/* Copyright 2023 The TensorFlow Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+==============================================================================*/
+
+#ifndef SIGNAL_SRC_IRFFT_H_
+#define SIGNAL_SRC_IRFFT_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "signal/src/complex.h"
+
+// TODO(b/286250473): remove namespace once de-duped libraries
+namespace tflite {
+namespace tflm_signal {
+
+// IRFFT (Inverse Real Fast Fourier Transform)
+// IFFT for real valued time domain outputs.
+
+// 16-bit Integer input/output
+
+// Returns the size of the memory that an IRFFT of `fft_length` needs
+size_t IrfftInt16GetNeededMemory(int32_t fft_length);
+
+// Initialize the state of an IRFFT of `fft_length`
+// `state` points to an opaque state of size `state_size`, which
+// must be greater or equal to the value returned by
+// IrfftGetNeededMemory(fft_length). Fails if it isn't.
+void* IrfftInt16Init(int32_t fft_length, void* state, size_t state_size);
+
+// Applies IRFFT to `input` and writes the result to `output`
+// * `input` must be of size `fft_length` elements (see IRfftInit)
+// * `output` must be of size output
+void IrfftInt16Apply(void* state, const Complex<int16_t>* input,
+ int16_t* output);
+
+// 32-bit Integer input/output
+
+// Returns the size of the memory that an IRFFT of `fft_length` needs
+size_t IrfftInt32GetNeededMemory(int32_t fft_length);
+
+// Initialize the state of an IRFFT of `fft_length`
+// `state` points to an opaque state of size `state_size`, which
+// must be greater or equal to the value returned by
+// IrfftGetNeededMemory(fft_length). Fails if it isn't.
+void* IrfftInt32Init(int32_t fft_length, void* state, size_t state_size);
+
+// Applies IRFFT to `input` and writes the result to `output`
+// * `input` must be of size `fft_length` elements (see IRfftInit)
+// * `output` must be of size output
+void IrfftInt32Apply(void* state, const Complex<int32_t>* input,
+ int32_t* output);
+
+// Floating point input/output
+
+// Returns the size of the memory that an IRFFT of `fft_length` needs
+size_t IrfftFloatGetNeededMemory(int32_t fft_length);
+
+// Initialize the state of an IRFFT of `fft_length`
+// `state` points to an opaque state of size `state_size`, which
+// must be greater or equal to the value returned by
+// IrfftGetNeededMemory(fft_length). Fails if it isn't.
+void* IrfftFloatInit(int32_t fft_length, void* state, size_t state_size);
+
+// Applies IRFFT to `input` and writes the result to `output`
+// * `input` must be of size `fft_length` elements (see IRfftInit)
+// * `output` must be of size output
+void IrfftFloatApply(void* state, const Complex<float>* input, float* output);
+
+} // namespace tflm_signal
+} // namespace tflite
+
+#endif // SIGNAL_SRC_IRFFT_H_
\ No newline at end of file
diff --git a/signal/src/irfft_float.cc b/signal/src/irfft_float.cc
new file mode 100644
index 0000000..53ce0fe
--- /dev/null
+++ b/signal/src/irfft_float.cc
@@ -0,0 +1,64 @@
+/* Copyright 2023 The TensorFlow Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+==============================================================================*/
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "signal/src/complex.h"
+#include "signal/src/irfft.h"
+#include "signal/src/kiss_fft_wrappers/kiss_fft_float.h"
+
+// TODO(b/286250473): remove namespace once de-duped libraries
+namespace tflite {
+namespace tflm_signal {
+
+struct IrfftFloatState {
+ int32_t fft_length;
+ kiss_fft_float::kiss_fftr_cfg cfg;
+};
+
+size_t IrfftFloatGetNeededMemory(int32_t fft_length) {
+ size_t cfg_size = 0;
+ kiss_fft_float::kiss_fftr_alloc(fft_length, 1, nullptr, &cfg_size);
+ return sizeof(IrfftFloatState) + cfg_size;
+}
+
+void* IrfftFloatInit(int32_t fft_length, void* state, size_t state_size) {
+ IrfftFloatState* irfft_float_state = static_cast<IrfftFloatState*>(state);
+ irfft_float_state->cfg =
+ reinterpret_cast<kiss_fft_float::kiss_fftr_cfg>(irfft_float_state + 1);
+ irfft_float_state->fft_length = fft_length;
+ size_t cfg_size = state_size - sizeof(IrfftFloatState);
+ return kiss_fft_float::kiss_fftr_alloc(fft_length, 1, irfft_float_state->cfg,
+ &cfg_size);
+}
+
+void IrfftFloatApply(void* state, const Complex<float>* input, float* output) {
+ IrfftFloatState* irfft_float_state = static_cast<IrfftFloatState*>(state);
+ kiss_fft_float::kiss_fftri(
+ static_cast<kiss_fft_float::kiss_fftr_cfg>(irfft_float_state->cfg),
+ reinterpret_cast<const kiss_fft_float::kiss_fft_cpx*>(input),
+ reinterpret_cast<kiss_fft_scalar*>(output));
+ // KissFFT scales the IRFFT output by the FFT length.
+ // KissFFT's nfft is the complex FFT length, which is half the real FFT's
+ // length. Compensate.
+ const int fft_length = irfft_float_state->fft_length;
+ for (int i = 0; i < fft_length; i++) {
+ output[i] /= fft_length;
+ }
+}
+
+} // namespace tflm_signal
+} // namespace tflite
diff --git a/signal/src/irfft_int16.cc b/signal/src/irfft_int16.cc
new file mode 100644
index 0000000..f92b3c5
--- /dev/null
+++ b/signal/src/irfft_int16.cc
@@ -0,0 +1,46 @@
+/* Copyright 2023 The TensorFlow Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+==============================================================================*/
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "signal/src/complex.h"
+#include "signal/src/irfft.h"
+#include "signal/src/kiss_fft_wrappers/kiss_fft_int16.h"
+
+// TODO(b/286250473): remove namespace once de-duped libraries
+namespace tflite {
+namespace tflm_signal {
+
+size_t IrfftInt16GetNeededMemory(int32_t fft_length) {
+ size_t state_size = 0;
+ kiss_fft_fixed16::kiss_fftr_alloc(fft_length, 1, nullptr, &state_size);
+ return state_size;
+}
+
+void* IrfftInt16Init(int32_t fft_length, void* state, size_t state_size) {
+ return kiss_fft_fixed16::kiss_fftr_alloc(fft_length, 1, state, &state_size);
+}
+
+void IrfftInt16Apply(void* state, const Complex<int16_t>* input,
+ int16_t* output) {
+ kiss_fft_fixed16::kiss_fftri(
+ static_cast<kiss_fft_fixed16::kiss_fftr_cfg>(state),
+ reinterpret_cast<const kiss_fft_fixed16::kiss_fft_cpx*>(input),
+ reinterpret_cast<kiss_fft_scalar*>(output));
+}
+
+} // namespace tflm_signal
+} // namespace tflite
diff --git a/signal/src/irfft_int32.cc b/signal/src/irfft_int32.cc
new file mode 100644
index 0000000..d4802a6
--- /dev/null
+++ b/signal/src/irfft_int32.cc
@@ -0,0 +1,46 @@
+/* Copyright 2023 The TensorFlow Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+==============================================================================*/
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "signal/src/complex.h"
+#include "signal/src/irfft.h"
+#include "signal/src/kiss_fft_wrappers/kiss_fft_int32.h"
+
+// TODO(b/286250473): remove namespace once de-duped libraries
+namespace tflite {
+namespace tflm_signal {
+
+size_t IrfftInt32GetNeededMemory(int32_t fft_length) {
+ size_t state_size = 0;
+ kiss_fft_fixed32::kiss_fftr_alloc(fft_length, 1, nullptr, &state_size);
+ return state_size;
+}
+
+void* IrfftInt32Init(int32_t fft_length, void* state, size_t state_size) {
+ return kiss_fft_fixed32::kiss_fftr_alloc(fft_length, 1, state, &state_size);
+}
+
+void IrfftInt32Apply(void* state, const Complex<int32_t>* input,
+ int32_t* output) {
+ kiss_fft_fixed32::kiss_fftri(
+ static_cast<kiss_fft_fixed32::kiss_fftr_cfg>(state),
+ reinterpret_cast<const kiss_fft_fixed32::kiss_fft_cpx*>(input),
+ reinterpret_cast<kiss_fft_scalar*>(output));
+}
+
+} // namespace tflm_signal
+} // namespace tflite
diff --git a/signal/tensorflow_core/kernels/BUILD b/signal/tensorflow_core/kernels/BUILD
index bea8eef..7d412eb 100644
--- a/signal/tensorflow_core/kernels/BUILD
+++ b/signal/tensorflow_core/kernels/BUILD
@@ -19,6 +19,7 @@
srcs = ["fft_kernels.cc"],
deps = [
"//signal/src:fft_auto_scale",
+ "//signal/src:irfft",
"//signal/src:rfft",
"@tensorflow_cc_deps//:cc_library",
],
diff --git a/signal/tensorflow_core/kernels/fft_kernels.cc b/signal/tensorflow_core/kernels/fft_kernels.cc
index dc5b1cc..48db4e3 100644
--- a/signal/tensorflow_core/kernels/fft_kernels.cc
+++ b/signal/tensorflow_core/kernels/fft_kernels.cc
@@ -14,6 +14,7 @@
==============================================================================*/
#include "signal/src/fft_auto_scale.h"
+#include "signal/src/irfft.h"
#include "signal/src/rfft.h"
#include "tensorflow/core/framework/op_kernel.h"
@@ -82,6 +83,58 @@
Tensor state_tensor_;
};
+// get_needed_memory_func(), init_func(), apply_func()
+// are type specific implementations of the IRFFT functions.
+// See irfft.h included above for documentation
+template <typename T, size_t (*get_needed_memory_func)(int32_t),
+ void* (*init_func)(int32_t, void*, size_t),
+ void (*apply_func)(void*, const Complex<T>* input, T*)>
+class IrfftOp : public tensorflow::OpKernel {
+ public:
+ explicit IrfftOp(tensorflow::OpKernelConstruction* context)
+ : tensorflow::OpKernel(context) {
+ OP_REQUIRES_OK(context, context->GetAttr("fft_length", &fft_length_));
+ // Subband array size is the number of subbands * 2 because each coefficient
+ // is complex.
+ subband_array_size_ = ((fft_length_ / 2) + 1) * 2;
+
+ size_t state_size = (*get_needed_memory_func)(fft_length_);
+ OP_REQUIRES_OK(context, context->allocate_temp(
+ DT_INT8, TensorShape({(int32_t)state_size}),
+ &state_handle_));
+ state_ = state_handle_.flat<int8_t>().data();
+ (*init_func)(fft_length_, state_, state_size);
+ }
+
+ void Compute(tensorflow::OpKernelContext* context) override {
+ const tensorflow::Tensor& input_tensor = context->input(0);
+ const T* input = input_tensor.flat<T>().data();
+
+ TensorShape output_shape = input_tensor.shape();
+ output_shape.set_dim(output_shape.dims() - 1, fft_length_);
+
+ // Create an output tensor
+ tensorflow::Tensor* output_tensor = nullptr;
+ OP_REQUIRES_OK(context,
+ context->allocate_output(0, output_shape, &output_tensor));
+ T* output = output_tensor->flat<T>().data();
+
+ int outer_dims = input_tensor.flat_inner_dims<T, 2>().dimensions().at(0);
+ for (int i = 0; i < outer_dims; i++) {
+ (*apply_func)(
+ state_,
+ reinterpret_cast<const Complex<T>*>(&input[i * subband_array_size_]),
+ &output[i * fft_length_]);
+ }
+ }
+
+ private:
+ int fft_length_;
+ int subband_array_size_;
+ int8_t* state_;
+ Tensor state_handle_;
+};
+
class FftAutoScaleOp : public tensorflow::OpKernel {
public:
explicit FftAutoScaleOp(tensorflow::OpKernelConstruction* context)
@@ -125,5 +178,27 @@
RfftOp<int32_t, DT_INT32, ::tflm_signal::RfftInt32GetNeededMemory,
::tflm_signal::RfftInt32Init, ::tflm_signal::RfftInt32Apply>);
+REGISTER_KERNEL_BUILDER(
+ Name("SignalIrfft")
+ .Device(tensorflow::DEVICE_CPU)
+ .TypeConstraint<float>("T"),
+ IrfftOp<float, tflite::tflm_signal::IrfftFloatGetNeededMemory,
+ tflite::tflm_signal::IrfftFloatInit,
+ tflite::tflm_signal::IrfftFloatApply>);
+REGISTER_KERNEL_BUILDER(
+ Name("SignalIrfft")
+ .Device(tensorflow::DEVICE_CPU)
+ .TypeConstraint<int16>("T"),
+ IrfftOp<int16_t, tflite::tflm_signal::IrfftInt16GetNeededMemory,
+ tflite::tflm_signal::IrfftInt16Init,
+ tflite::tflm_signal::IrfftInt16Apply>);
+REGISTER_KERNEL_BUILDER(
+ Name("SignalIrfft")
+ .Device(tensorflow::DEVICE_CPU)
+ .TypeConstraint<int32>("T"),
+ IrfftOp<int32_t, tflite::tflm_signal::IrfftInt32GetNeededMemory,
+ tflite::tflm_signal::IrfftInt32Init,
+ tflite::tflm_signal::IrfftInt32Apply>);
+
} // namespace signal
} // namespace tensorflow
\ No newline at end of file
diff --git a/signal/tensorflow_core/ops/fft_ops.cc b/signal/tensorflow_core/ops/fft_ops.cc
index ba27d74..4f52a2b 100644
--- a/signal/tensorflow_core/ops/fft_ops.cc
+++ b/signal/tensorflow_core/ops/fft_ops.cc
@@ -33,6 +33,16 @@
return OkStatus();
}
+Status IrfftShape(InferenceContext* c) {
+ ShapeHandle out;
+ int fft_length;
+ TF_RETURN_IF_ERROR(c->GetAttr<int>("fft_length", &fft_length));
+ TF_RETURN_IF_ERROR(c->WithRankAtLeast(c->input(0), 1, &out));
+ TF_RETURN_IF_ERROR(c->ReplaceDim(out, -1, c->MakeDim(fft_length), &out));
+ c->set_output(0, out);
+ return OkStatus();
+}
+
// TODO(b/286250473): change back name after name clash resolved
REGISTER_OP("SignalRfft")
.Attr("T: {float, int16, int32}")
@@ -63,6 +73,31 @@
)doc");
// TODO(b/286250473): change back name after name clash resolved
+REGISTER_OP("SignalIrfft")
+ .Attr("T: {float, int16, int32}")
+ .Attr("fft_length: int >= 2")
+ .Input("input: T")
+ .Output("output: T")
+ .SetShapeFn(IrfftShape)
+ .Doc(R"doc(
+Computes the inverse 1-dimensional discrete Fourier transform of a real-valued
+signal over the inner-most dimension of input.
+
+The inner-most dimension of input is assumed to be the result of RFFT:
+the fft_length / 2 + 1 unique components of the DFT of a real-valued signal.
+fft_length must be provided.
+
+input: A tensor containing ((fft_length / 2) + 1) complex spectral
+ components along its innermost dimension.
+ Since there's no TF integer complex type, the array is represented using
+ ((fft_length / 2) + 1) * 2 real elements.
+output: A tensor containing fft_length time domain elements along its innermost
+ dimension.
+
+fft_length: The length of the IFFT operation.
+)doc");
+
+// TODO(b/286250473): change back name after name clash resolved
REGISTER_OP("SignalFftAutoScale")
.Input("input: int16")
.Output("output: int16")
diff --git a/signal/testdata/fft_test_data.cc b/signal/testdata/fft_test_data.cc
index 5525681..335a343 100644
--- a/signal/testdata/fft_test_data.cc
+++ b/signal/testdata/fft_test_data.cc
@@ -1,4 +1,4 @@
-/* Copyright 2023 The TensorFlow Authors. All Rights Reserved.
+/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -571,6 +571,449 @@
-5.16014671e+00, 6.53038979e+00, 5.11271954e-02, -3.40430737e-01,
-2.98720551e+00, 0.00000000e+00};
+const int16_t kIrfftInt16Length512Input[] = {
+ 8073, 0, -69, -149, 45, -261, -83, -150, -101, -24, -45, 206,
+ 159, -84, -11, 1, 107, -34, -116, 253, 124, -132, -56, 112,
+ -213, -197, 45, 106, 14, -251, -66, 53, 99, -129, -101, -86,
+ 72, -147, -52, -11, -142, 128, 55, -192, 116, 94, 36, 97,
+ 242, -401, 89, -163, -177, 93, 194, 147, 49, -104, -198, -141,
+ -133, -126, 108, -198, 90, 101, -2, 142, 62, 37, 47, -224,
+ 47, 132, -98, -388, -230, 186, 36, 282, -152, -242, -112, -100,
+ 303, -22, 63, 9, 43, 108, 38, 106, 254, -275, 25, -44,
+ -2, 139, 236, -133, 51, -233, 25, -125, -92, 112, 48, 58,
+ -193, 121, 181, 146, 6, 114, 7, 181, 22, -336, 162, 218,
+ 56, -256, 3, -205, 325, -276, -166, -173, -25, -64, 74, 95,
+ 125, -40, 156, 122, 83, -118, -7, -109, -64, -8, 13, 180,
+ 267, 144, -131, 6, 11, -10, -165, -262, -162, 84, 85, -112,
+ 171, -160, -62, 133, -15, -58, 128, -198, 393, -6, 224, -297,
+ -9, 341, -73, 104, -68, -311, -172, -31, -290, -133, -56, -40,
+ -43, -93, -170, -43, 120, -63, -104, -94, 53, -243, 79, -73,
+ -8, -139, -56, 49, -103, -87, 188, -322, 78, -85, -50, -179,
+ -106, -34, -91, -50, 37, -96, -28, -181, -180, 61, 170, 195,
+ 92, -6, -17, 251, -106, 122, 173, 31, 35, 233, -8, 91,
+ 226, 139, -82, 215, 17, 146, -169, 60, -94, -119, -40, -69,
+ 15, 213, 28, -103, 206, -23, 13, 161, 112, -315, 139, -78,
+ -71, 3, 103, -1, 77, -213, -7, -78, 89, 112, -111, -221,
+ 58, 61, -71, -38, -84, 1, 34, 42, 167, -77, 96, 107,
+ 3, -11, 56, -133, -110, 191, -340, -77, 36, 101, 55, 49,
+ 113, 105, -211, -28, -47, 175, 42, -19, 57, 244, -98, 155,
+ 66, 165, -200, -25, 49, 96, -228, -52, 24, 154, 190, -225,
+ 104, 67, -38, 81, -2, 60, 32, 95, -42, -171, -228, 261,
+ 11, 77, 206, -185, -181, 99, 60, -62, -231, 96, 90, -85,
+ 284, 94, 90, 73, -49, -141, 100, -110, -83, -107, -127, -198,
+ 268, 116, -86, 228, -67, 48, 118, -106, 148, 48, -122, -78,
+ -20, -191, 121, 96, 158, 161, -51, 57, -267, 156, -74, -21,
+ 277, 194, -157, -141, -365, 160, -274, -79, 234, 29, 38, 278,
+ -181, 4, -54, 49, 207, -338, 235, 160, 5, 100, 169, 52,
+ -1, -58, -429, -26, -41, -54, 160, 189, -37, 2, -248, -113,
+ 120, 69, -32, -256, -269, 66, 48, 279, -225, -295, 147, 191,
+ 78, -9, 32, -109, 169, -72, 139, 93, -32, 9, -190, -83,
+ 389, 207, -192, -172, 311, -188, 124, -39, -90, -86, -28, -85,
+ 0, -138, 90, -71, 107, 133, -175, -32, -162, -135, -51, -123,
+ -156, 30, 295, -141, -196, 53, 101, -181, -142, 162, 159, -16,
+ 209, 9, 37, 171, 14, 122, -38, 63, 181, 66, 178, 118,
+ -73, -56, -436, 80, -69, 140, -68, -32, -105, 67, 98, -192,
+ 74, 5, 42, -135, 41, -190, 178, -173, 43, 84, -497, -43,
+ -340, 40, -289, 117, 14, -37, 117, -238, 125, 0};
+
+const int16_t kIrfftInt16Length512Golden[] = {
+ 19, 26, 27, 23, 4, 13, 10, 26, 21, 26, 10, 3, 25, 28, 1, 5, 13, 26, 9,
+ 21, 7, 32, 11, 14, 19, 12, 29, 17, 6, 6, 3, 19, 15, 21, 20, 13, 20, 28,
+ 11, 1, 8, 10, 27, 27, 28, 28, 28, 4, 16, 10, 24, 6, 24, 8, 22, 10, 25,
+ 5, 25, 4, 25, 27, 19, 27, 25, 3, 23, 17, 20, 19, 16, 26, 21, 20, 7, 28,
+ 27, 9, 27, 13, 5, 3, 14, 20, 19, 21, 19, 10, 20, 19, 22, 25, 29, 28, 28,
+ 3, 11, 11, 2, 25, 12, 26, 6, 19, 17, 22, 9, 30, 9, 19, 16, 6, 16, 32,
+ 25, 17, 17, 2, 12, 17, 9, 5, 2, 9, 9, 22, 16, 21, 7, 24, 9, 3, 28,
+ 25, 1, 23, 3, 14, 12, 7, 4, 3, 1, 27, 14, 25, 21, 5, 27, 22, 15, 14,
+ 17, 16, 18, 16, 28, 24, 31, 3, 0, 18, 3, 8, 2, 20, 22, 24, 28, 14, 18,
+ 28, 8, 30, 9, 3, 5, 5, 19, 5, 27, 19, 22, 16, 3, 23, 24, 13, 17, 9,
+ 17, 7, 25, 29, 9, 29, 19, 22, 23, 29, 17, 12, 0, 7, 8, 30, 25, 7, 20,
+ 12, 2, 18, 21, 19, 1, 24, 5, 10, 11, 0, 26, 15, 27, 28, 27, 27, 10, 3,
+ 22, 8, 22, 9, 14, 25, 14, 27, 4, 8, 2, 20, 10, 18, 25, 3, 13, 4, 5,
+ 4, 19, 27, 9, 20, 20, 11, 6, 19, 29, 12, 21, 25, 16, 13, 28, 14, 27, 16,
+ 28, 25, 23, 28, 29, 5, 15, 26, 13, 17, 9, 18, 11, 18, 27, 8, 27, 17, 14,
+ 6, 25, 1, 5, 17, 2, 29, 6, 6, 17, 17, 18, 12, 9, 27, 6, 18, 22, 12,
+ 16, 24, 24, 8, 10, 4, 30, 30, -1, 19, 11, 24, 5, 19, 23, 7, 19, 21, 25,
+ 27, 26, 3, 16, 28, 27, 22, 1, 12, 3, 15, 1, 11, 31, 3, 14, 16, 7, 25,
+ 5, 8, 14, 15, 26, 23, 31, 8, 22, 19, 7, 27, 18, 5, 24, 10, 8, 1, 11,
+ 10, 31, 2, 27, 31, 14, 12, 24, 24, 23, 3, 27, 8, 28, 7, 3, 31, 4, 17,
+ 29, 16, 16, 25, 5, 6, -1, 13, 28, 13, 21, 21, 5, 20, 30, 5, 12, 17, 1,
+ 27, 22, 15, 29, 5, 17, 24, 3, 18, 1, 12, 6, 14, 20, 24, 17, 25, 12, 4,
+ 31, 2, 24, 2, 2, 2, 6, 16, 30, 18, 6, 8, 29, 17, 23, 17, 13, 5, 23,
+ 5, 14, 16, 17, 13, 12, 3, 29, 13, 17, 11, 19, 19, 27, 7, 27, 12, 25, 5,
+ 27, 6, 4, 5, 10, 6, 23, 17, 16, 2, 18, 18, 13, 11, 19, 2, 5, 24, 9,
+ 28, 2, 1, 3, 22, 23, 27, 6, 19, 6, 0, 16, 11, 30, 19, 14, 13, 28, 22,
+ 16, 2, 14, 30, 23, 1, 11, 22, 7, 28, 9, 13, 5, 14, 14, 3, 2, 19};
+
+const int32_t kIrfftInt32Length512Input[] = {
+ 839741641, 0, -810680242, 314550700, -188375954, -646098985,
+ 661169493, 40565493, -727406866, -519447225, -601282802, 610281511,
+ -564231793, -658060998, 940197365, -556253639, 166244617, 855736360,
+ -352017590, -472086, -512664325, -29124321, 318599191, -1008807581,
+ -1045052452, 654632137, 262024233, -650480570, -328981456, -305628084,
+ -311905089, 643377399, -788794832, -697362958, 195418849, -450270913,
+ 450274221, -132831079, 954455789, 627087353, 443800117, 581556743,
+ 721497498, 312576274, 917731184, -119726646, -478746763, -890057048,
+ 1010851532, -192880372, 311180932, -504532787, 671816327, -655964390,
+ 791656581, -446266278, -666354330, -196814596, -825177916, 1066606457,
+ -396384718, 253036626, 1023033179, -536587536, 439268736, 56644895,
+ 490515745, -918121214, -399642466, 733537340, 550908995, -710689258,
+ -811550611, -1019377090, 812667220, -627899586, 36487869, -407910896,
+ -681856276, 176316030, -467027200, -109112451, 95733568, -196757477,
+ 640458216, 649718695, 947089218, -106860637, -608229423, -264877883,
+ 1070169157, -864364665, -940770876, 903330942, -858862934, -874506798,
+ -1024456516, 335288045, -584203446, -681487864, 174713039, 562868290,
+ -909240239, -303892838, 342417869, 720484621, -262340309, -36238617,
+ -143340078, 756047229, 977080186, -601657929, -929420577, 909799187,
+ -483272786, 569161464, 237577775, -170309809, -140492719, 235865688,
+ -2584061, 738538012, 899139379, -514114503, 92589619, -2186856,
+ -96582858, 406814228, 938450837, 483109475, -717748004, -97252289,
+ 456879462, -182572080, 901717931, 460303603, -478409198, 13082064,
+ 883057018, 191217882, -971905039, -633268629, -161171179, 40177094,
+ 311234817, 469147409, -35952715, -699453017, -491443043, -266920521,
+ -84504724, -218798599, -1051333289, -319487510, 464546366, 193917497,
+ 958715420, 445681947, -779515017, 870946655, 798123864, 375422608,
+ -49151236, 228702869, -586909787, 956237786, -817062805, 49259295,
+ 617384758, -568956241, -676306782, -236673390, 593537713, -846550375,
+ -725553331, -755214027, -960900289, -600629057, -992578727, 860277560,
+ 91143911, 325074385, -904098818, 523032277, 330057148, -200544851,
+ -534746367, 134080917, -704766790, -449694111, -871675761, -736092292,
+ -470441479, 649973251, 184524500, -940746981, -853401135, 292173632,
+ -351333019, 629238289, -923163881, 55704296, 67245329, 321644032,
+ -150272289, 1016711520, 685132142, 1036980538, 909268554, 341575246,
+ -679580804, -613922226, 219169932, 151510727, -31229903, -1023519836,
+ 488301536, -605189867, -847401037, -711134196, -389183573, 125069877,
+ 925139073, 740652197, 366040867, 846434837, 1027886779, -846326106,
+ -966541876, 460961009, -904504464, -667422902, 595819763, 548076246,
+ 658533296, 831784878, 1018563409, 657002928, 1018623967, -312804064,
+ -609590993, -632152641, 282353650, 23124988, 842050529, 331536663,
+ -74218221, 188032000, 912832168, -256904460, -834426583, 989582172,
+ -606592232, -1011932019, -317445477, -981620621, -509888019, 411955653,
+ -889686515, -450075112, -369653544, 124736966, 189435676, -107810364,
+ 881698145, -753413726, 421033515, 373856924, -782249185, 927665742,
+ 335053664, -291584084, 23011324, -561481341, -659027643, -157231698,
+ 325630443, -766882742, 445882611, -93371261, 839265875, -82182728,
+ -1066287105, -151409292, 934991293, 464520547, -125074754, -221788043,
+ -1053884159, -866025647, -369369912, 106829399, -245123315, 20663469,
+ -806806422, 552869387, -9053710, -491056522, -686021696, -1038270895,
+ -125006845, 266429965, 1050001488, -406006535, -365326480, -966938945,
+ 110681188, -1021078355, 254091936, 121108495, 1027070826, -165470882,
+ 393915655, 1045537081, 6669269, 919678730, 281326605, -680536894,
+ 98307878, -230289089, -1060913156, -784329119, -870588988, 886334526,
+ 185033052, 523745961, -524629656, -233118673, 1015175033, -229774783,
+ -220068882, 328818397, -728044888, 123650067, -866623422, -371919688,
+ -140437309, -573584939, -13729139, 477487249, -39276346, 574137018,
+ 875867641, -873697644, -651969810, -485128371, -438795254, 686955274,
+ -1025030795, -644894666, -1056623940, 937246325, 627094533, -88519660,
+ -293430525, 60332339, -783010005, 693207812, -531488433, -439215652,
+ -652852140, 235512897, 416183897, 602327072, 217920384, -262296603,
+ 702674563, 323600358, -819073332, 660032637, 859607695, -736547587,
+ 899965281, 705990533, 700629412, 12532222, 867184362, -460331313,
+ -244276307, 56341729, 156969129, -322096971, -783707309, 276427177,
+ 1056930269, -765923003, -949113397, -163145401, -892934786, -442050707,
+ 137838318, 217340531, 285489000, -39973091, -267480349, -310094927,
+ -976524654, 895571227, -659112325, -228839076, -242345827, 876628479,
+ 511335719, -310742223, 1039081559, 512276681, 705312780, 578575064,
+ -598271655, 762867207, 912370057, 98648217, 503193745, 864713114,
+ -889332887, -439505808, -544266224, -751632504, 956453792, -692262886,
+ -91642341, -894188411, 876053978, 199193167, 604157121, -383140183,
+ -342950535, -943692226, 496727456, -237254976, -50419762, 947862958,
+ -996090040, 997591942, -413303925, -710352945, -579101581, 177736107,
+ 672137235, -891910735, -764102135, -963051915, -635556501, -946768907,
+ -796637162, 733678632, -630011293, 544470901, 736121924, 203332022,
+ -164480811, 414318422, 1023442078, -800490289, -85638979, 520154045,
+ -797352137, 1028499935, -405997043, -159904358, -697856807, 339622536,
+ -745174445, -250872450, -15376813, -81848980, 159907818, -604901490,
+ 449408277, -199909799, 747859167, -780656655, 495243813, -305468980,
+ 379086080, -339583326, -234468731, 715773698, -140870306, -297028384,
+ 796524920, -812985836, 805155911, 551254707, 390593322, -471644369,
+ -642074940, -688579515, 660561660, 961580918, -205220858, -585147906,
+ 538115796, 157278134, 585918447, 539709994, -683717882, -169044522,
+ -555579704, 358607056, -197892766, 903698583, -388508755, 462213245,
+ 874204812, -712527806, -757899104, 402482925, 786917228, -798119015,
+ -476098139, 552677178, 300423706, 0};
+
+extern const int32_t kIrfftInt32Length512Golden[] = {
+ -34280174, 8022307, 19780085, 9662521, 43799799, 40100445,
+ -41211729, -11739138, 58486622, -22044189, -44097652, -79357304,
+ -72117147, 15744462, 13915851, 28166395, -15520437, 57070719,
+ -7305489, 27500351, 28306007, -86631061, 67560922, -28806729,
+ 39817325, 95989071, 897984, 3648535, -30375028, -37041021,
+ 88781593, -23843719, -57361166, 9011180, 1666315, -17359414,
+ -35138121, -28118417, 22293673, -5471988, -33560810, -66596308,
+ -37497959, 28878058, 43901353, 56802879, 14536133, 15417154,
+ 41299987, 67932041, 63865770, -12329743, -41649482, -55364898,
+ -9358326, 20864173, -35866369, -8116787, -7470926, 56999653,
+ 1043351, 49630166, -15330039, 5309138, -21684440, 1281894,
+ 44467472, -72973186, 50966857, 39752660, -14061082, -21241948,
+ 7736123, 49012458, -38765179, 32821490, -91494618, 9082358,
+ 80530972, 34091460, -80566348, -15556794, 44506352, 6554114,
+ 46780869, 26642366, -45175459, 34982841, -76742845, -63052738,
+ -12151434, 38025909, -41759399, -67582145, 27092456, -14738429,
+ 77549391, -13529057, 5800415, 6508249, 32040133, 20067661,
+ 6739354, -75492401, 49035483, 31075816, -59397318, -13887185,
+ -37275775, -28354015, 14549583, -60431580, 5713520, 5774464,
+ 48008598, -6982879, -37770644, 7652162, 36293574, 19866120,
+ 8689099, -6952246, 2529586, -915507, -45824611, 4908732,
+ 14144902, -66462468, 5204479, 21154766, -31563680, -63787764,
+ 19742867, 66808977, -10940667, 944126, 15969624, -24865057,
+ -16783943, 1317981, -33103183, -30551484, 34187135, 32679187,
+ 6747414, -18842426, -44799486, 43191326, 4603856, 28972218,
+ -2997445, -14440478, 55584797, -8586169, 12792009, 32599422,
+ -44154192, -11805483, -25614802, 101394256, 18403401, -9366015,
+ -2773809, 27905480, -15595130, 25214356, 18003057, -3796290,
+ 31428249, 35181313, 11896714, -6089797, 30417284, -51721564,
+ -23623684, -34906421, 18630637, 50253333, 38298996, -6032889,
+ 5008328, -77010982, -73036463, 14698362, 38033709, -40956695,
+ 101755464, 16586257, -66754901, 26886084, 37055264, 49973097,
+ 38835881, 26088109, 29315128, 23485156, -34186633, 27365092,
+ -4305884, -16934542, -52437371, 30437566, -40186223, 15784414,
+ 30092258, 12742434, 72775874, 37936704, 41446581, -47950761,
+ -40043570, -25891900, 22904631, -19131832, -67828932, -4494550,
+ 38761919, -51880330, 56229588, -42618597, -38294494, -67942872,
+ 47777144, -43953283, 38847552, -41095030, -78497360, 45354768,
+ 8883342, -56316876, -8391759, 12931546, 75368371, 4571884,
+ 24159982, 30656523, 3463399, 19137413, 58400688, -40423089,
+ 29534607, -21556205, -7211564, -9219271, 18973775, 45833761,
+ -7272585, -69115849, -18959925, -29283534, 45159378, 22606489,
+ 14732883, 4940580, 142802, -6593094, 3439368, -76696477,
+ -52430789, -89970783, 33615669, -48017657, 28880767, 32409006,
+ 49693514, -3426601, -9611900, -22412354, -5194037, -7028292,
+ -45522423, -56836163, 6162975, 11247381, 64776667, 64968977,
+ -16816131, -7031433, 13389996, -10859561, 20066035, 74140789,
+ -2595790, 8986611, -21203364, 38877279, 67752097, -42426157,
+ 41011742, 4298962, -24038197, 12191958, -39762301, -1825759,
+ 34953189, 62321632, 63258494, 79493646, 6154979, 72713374,
+ 5751929, -44326151, 27859895, -11950382, 36015249, 21090111,
+ -20606384, 732179, -7758986, 22196782, -9918264, 3238981,
+ -24966605, 24182609, -20739710, 13524349, -41468505, -8935286,
+ 116405313, 48070952, -14947048, 2481984, 19035184, 11853862,
+ -54909833, 15799738, -38720324, 113225658, 14960079, -1700298,
+ -10592205, 41679128, -55354432, 7485444, -22756394, 115271330,
+ -2697232, -81339788, 2763460, -7145026, 18287951, -1434620,
+ -1147363, 909555, -4734645, 7471510, 4204346, 47711049,
+ -34546617, -65808093, 48449712, -71939373, 10686041, -23107713,
+ 45728005, 11280853, -42519241, -397607, -14902756, -27840989,
+ 45312015, 26630552, 4078644, 60485257, 25279575, 66459123,
+ 40351793, 45709228, 21003916, 15565038, -54737790, 7196745,
+ 54625336, 39327144, 12209500, 51127752, 43333991, -25539938,
+ 29762930, 9115261, 38835591, 8559430, -28015932, -7811926,
+ -6752397, 18832848, -35364284, 25481402, 21986597, -25030237,
+ 43594329, -20793566, -7029448, 10848687, -86344081, -27910439,
+ -18685609, 52777722, -37713487, 51928065, 52133060, -46594790,
+ 32997528, 23793214, -35724240, -20062160, -15586165, 2879812,
+ -29894045, -84401847, -9628799, -35762356, 26153072, -16698747,
+ -55021068, -23994604, 43170951, -17771303, -52726245, 43538460,
+ -11882492, 3401144, -41231423, -26190758, -18363885, -47011479,
+ -27288266, 21942417, 47541674, 29862620, -3911136, 57336809,
+ -6790237, 72562751, 19857054, 3022121, 10589312, 2359890,
+ 7953397, -4637060, -29962427, -25230703, 45532452, -28510971,
+ -32665965, -42952368, 48927802, 4331065, -61462593, 45265693,
+ -38315556, 7308700, 39647849, 38045194, 53011682, -2051408,
+ 6745501, -433214, -15448637, 13422836, -10231156, 21668412,
+ 38837116, -100216222, 33292355, 9284671, 72602174, -81000636,
+ -45456135, -9439562, -56228566, 37764314, -9751637, 43380666,
+ -29511356, -19398853, 31603418, -68044438, 16906880, 8372405,
+ -25911348, -37697844, 37349908, -42433050, -19502746, 42059402,
+ 56373933, -917272, -17142837, 40227000, 8460368, 1281257,
+ -15998615, 40858839, -42157880, 24580073, -28704215, -2332549,
+ 3896928, 35426477, -66365675, -42157899, -871713, -4490567,
+ -1425633, -42870670, -32070326, -54410387, -1836127, 4115382,
+ 34466160, -13424784};
+
+const float kIrfftFloatLength512Input[] = {
+ -30.237963, 0., -0.8870227, -16.70994, -16.188946, -7.837169,
+ -11.782056, -9.808029, -9.120637, -16.412685, 2.2228887, 6.0699377,
+ 0.8525604, -7.8473816, -3.728829, 11.6801, -5.047578, -8.966889,
+ -8.341611, -12.121087, -2.014905, -1.1014754, 5.350008, -6.0458236,
+ -7.680677, -0.7340172, -2.153996, -11.128706, 6.927712, 15.9215555,
+ -3.3578932, -2.3223252, 10.998084, 3.0689626, -7.26421, 1.7153641,
+ 5.2599764, 14.555982, -3.2174952, 3.122578, 3.540863, -0.07593922,
+ 9.771112, 12.02481, 2.2330835, -5.610757, 8.759598, -11.710923,
+ -0.933854, 3.487685, -7.4957643, 3.510248, -5.6749268, -8.372976,
+ 7.5864186, 8.883432, -3.238809, -2.7004075, 0.13749301, -0.21802016,
+ 1.5948814, 10.145043, -4.777312, -16.068268, 3.108986, -12.656892,
+ 8.464096, -1.3835825, 9.3863, 0.08924354, -5.8932724, -0.83083385,
+ -8.587713, -6.48424, -0.44568732, -5.9496527, 2.3838944, -0.09875517,
+ 10.801603, 3.9324691, 3.17346, 13.255524, 3.966665, -5.839878,
+ -3.3029196, 0.43704662, -3.6640527, 16.11661, 16.218079, 1.9934207,
+ 2.6740897, -3.9145885, 18.744654, -8.516122, 0.2746967, 16.56623,
+ -10.398819, 6.5646763, 13.364323, -18.21934, -12.42878, 10.884242,
+ 7.111711, 5.42487, -2.685089, -10.922701, -2.1506147, 3.0457373,
+ -21.245033, 12.652777, 7.518374, -3.6027377, -12.345767, -10.408322,
+ -0.45039272, -13.521866, 12.301129, -7.3925786, 3.6123064, -27.47004,
+ 0.06317914, -15.495375, 14.397725, -2.7989936, 1.4894583, -1.1805921,
+ 5.011081, -4.577404, -15.920375, -3.943976, -11.309841, -8.585617,
+ -2.277856, -8.83419, -15.505757, -0.9834521, -5.5173364, -16.236353,
+ -22.883762, 14.5666, -1.1154052, -4.2594385, 18.848545, 11.113267,
+ -7.9029818, -7.9614487, -8.73291, 9.273985, 2.7331648, -4.3628683,
+ 8.791882, -19.129395, 0.40214744, 12.770975, -0.38946837, -11.569212,
+ -3.261552, -10.017079, 12.063712, -8.527597, 0.8519457, 5.638602,
+ -0.72109884, 7.438573, -4.971101, -9.484696, 9.00311, 12.11723,
+ 2.113377, -0.46248603, -20.24738, 0.4090347, -0.6018856, 9.518283,
+ -17.040405, -2.8654642, 27.70458, -10.235462, -12.795219, -1.599763,
+ -0.7757828, -9.712138, -18.633558, -21.917002, -7.086175, 1.6413045,
+ -1.0107656, 9.344263, 12.549336, 8.784375, -4.48422, 3.1921742,
+ -9.637408, 5.126716, -9.416565, 0.34341943, 9.598896, -4.811465,
+ 7.468513, -5.018967, -10.314449, -12.268959, 16.794994, 3.6410797,
+ -30.120907, 2.0361273, 0.28818926, -14.163082, -4.502911, 4.268754,
+ -1.3731043, -8.439607, 11.7638235, 0.58137584, 8.78262, -4.1122336,
+ -14.586955, -0.6115846, 5.721377, 3.9643157, 3.9812503, -6.7656417,
+ -8.288948, 4.735382, 9.98983, 0.2826367, 6.6927032, -7.960859,
+ -1.972462, -3.5999422, 4.6700177, 7.5491548, -13.338051, 5.372325,
+ 4.1976047, -2.290505, -2.4447436, 2.6495414, -0.1646954, -14.162679,
+ -13.492944, -10.066321, 4.8790317, 3.0568714, 25.861683, 7.7827787,
+ -11.021672, -1.0221997, -12.1969385, 4.14404, 2.7906785, 1.2038546,
+ -12.202317, 2.6063862, 0.47595504, 3.833782, 5.459406, -1.1311115,
+ 2.1462953, -9.798795, 0.5092611, -1.7780461, 10.847251, 4.7227964,
+ 3.6416945, -6.267557, 1.8228995, 7.153564, -8.377606, -1.7705457,
+ -8.363819, 16.272038, 10.777103, 6.118911, 18.839758, -11.079164,
+ 8.046534, 6.3055205, -13.714934, 6.8472624, -0.5491477, 10.665407,
+ 9.522111, -2.2350516, -2.151148, 13.554076, -0.7024065, 24.318254,
+ 11.075853, -5.6310024, 1.792298, 0.8913419, -3.198663, -3.4226098,
+ 3.294247, 6.4590416, -3.6266904, -15.735353, 21.041748, -4.4707165,
+ -10.486909, 7.0881767, 2.338044, 8.936833, 20.289284, -15.834369,
+ -6.27957, -2.51897, 7.2220874, -13.127552, -13.336818, -1.617663,
+ 3.2618418, 14.497984, 10.053407, 7.88479, -10.618643, 15.016601,
+ -8.472935, 26.100227, -6.0125732, 1.8380505, 3.5892081, 2.7994452,
+ 7.5647445, -6.7973204, -2.226884, -11.008526, 10.130876, 20.727829,
+ -2.8447893, 1.2786244, 4.782782, 8.294365, -1.3854954, 0.8973222,
+ 5.240392, -2.2681866, 0.06863499, 7.980012, -5.467104, -13.789669,
+ 4.4801216, 0.5506569, -2.4283018, -1.9574064, 9.8034, -7.8538375,
+ -1.3211169, -6.0888257, -8.8751, 0.18552934, 0.32884428, 4.6578417,
+ -17.806314, 4.283429, 2.8675492, 5.5130286, 3.292803, 8.645252,
+ 2.487952, 6.951849, -4.8785276, 11.139262, 10.62336, 1.9926109,
+ -12.535589, -14.7336235, -1.9293493, 12.427337, 3.9960144, -0.23418498,
+ -0.2729544, 7.5376987, -9.694464, 3.6965284, -6.12123, -0.21720974,
+ 6.542181, 16.833439, -0.5240893, -3.9085722, 2.2004304, -19.755825,
+ 4.3837647, 1.4074985, 5.2781444, 3.5348754, -12.352237, -1.0562972,
+ -3.0493338, -11.641172, 19.914968, 3.4238126, 0.04836255, -15.394404,
+ -8.4243555, 13.519465, 24.039753, 1.8650069, 1.4495964, -12.118086,
+ -2.9114485, -3.8421676, 9.094493, 10.687737, 10.193869, 12.889424,
+ 1.5644586, 13.14207, 8.611605, -16.365925, 7.35201, -12.98773,
+ -4.5951047, -9.6856575, 7.538099, 18.039642, -4.5050077, -0.17203662,
+ 7.9955363, -3.8898702, -20.541094, -8.317646, 9.275174, -6.687724,
+ 13.356739, -8.14045, 2.304177, 4.748354, 1.789078, 2.6287572,
+ 5.2520447, -4.5307264, 0.7956459, -5.7576833, -8.241041, 1.2976674,
+ 0.9751119, -1.9878949, -0.28155094, 15.819839, -13.472967, -1.2520658,
+ -6.4520116, -8.267247, 14.64433, 1.4102879, -2.906583, 6.742353,
+ -5.8997235, -21.359184, 10.482071, -6.8071265, -4.318058, 0.61369,
+ 5.1886477, 0.20163095, -4.9314857, -6.725615, -6.1213217, -3.3096085,
+ -5.5520887, -21.814417, -0.45328552, -5.7754235, 9.9567795, -6.1869125,
+ -1.71723, 11.038221, -4.8242254, 7.3808165, 2.751095, 15.0145,
+ 3.2840607, 1.0826187, -2.1640933, -2.6346276, -12.111668, -1.9144021,
+ 13.436047, 9.108638, 14.142464, -5.0205646, 0.3507184, 7.511046,
+ 11.356239, -14.513865, 5.2194257, -0.9989464, -5.064783, -1.1407975,
+ 2.210063, -4.8482714, -11.814263, 6.240137, 23.587172, 12.757468,
+ -6.7067065, 20.231493, 8.244574, 13.610065, -0.93495035, -26.816973,
+ 7.8878307, -10.253602, -1.8279042, -7.402954, 4.1620474, 11.353777,
+ 14.372957, 8.991498, 4.456106, 0.};
+
+const float kIrfftFloatLength512Golden[] = {
+ 0.29982752, -0.5864359, 0.8097371, 0.6964922, -0.56286454,
+ -0.65686744, -0.67477304, -0.68269503, -0.039257757, -0.8854418,
+ 0.8713772, -0.13664988, 0.07726803, -0.2444637, -0.31025574,
+ -0.40032005, -0.6156, -0.5220901, 0.67751265, 0.701784,
+ 0.12668014, 0.74386156, 0.20080262, -0.5919206, -0.11498103,
+ 0.84945625, -0.30784115, 0.47987163, 0.8023895, -0.83630186,
+ -0.27433932, -0.2790887, 0.26171675, -0.5266397, 0.69136655,
+ 0.38648325, 0.49699098, -0.15258673, -0.6069461, -0.96661866,
+ -0.71334004, 0.19891304, 0.02852476, 0.5386789, -0.7791545,
+ 0.4138639, -0.35693097, 0.49731624, 0.9427581, 0.03335625,
+ -0.4437948, 0.6297895, -0.08721806, 0.50569916, 0.18831411,
+ -0.08267924, -0.45396042, 0.8013768, -0.2406537, -0.29676312,
+ 0.21887437, -0.72747946, -0.2328647, 0.40174174, 0.91527927,
+ 0.28560296, -0.74036396, 0.27275884, 0.7930955, -0.59212196,
+ 0.74610806, 0.6267803, 0.30080235, -0.35472846, 0.7505894,
+ -0.22452751, 0.41838533, -0.6592845, 0.92467225, -0.65168047,
+ 0.8869605, -0.33984357, 0.60530996, 0.01847987, -0.90627366,
+ -0.88029194, 0.23383015, 0.19796571, 0.61636496, -0.42383894,
+ -0.04506364, 0.0021984428, 0.9393822, 0.7032502, 0.06971514,
+ -0.21672109, -0.48139384, -0.07382688, 0.65374225, -0.7207461,
+ 0.801925, 0.07295595, 0.16882896, -0.3152274, 0.35198689,
+ 0.98689663, -0.6578901, -0.95485187, 0.88367236, -0.36234283,
+ 0.3330723, -0.79546535, -0.64958787, 0.23861185, -0.09088708,
+ 0.45268735, 0.30978698, 0.3372508, 0.29718608, -0.8574079,
+ -0.6692782, 0.98987687, -0.8064702, -0.2624596, 0.28159115,
+ 0.16167887, -0.8035746, -0.17733437, 0.30414638, -0.77497596,
+ 0.8938695, 0.8159308, 0.32125, -0.920919, -0.6462177,
+ 0.6036651, 0.15566209, -0.03488487, 0.73239374, 0.9670948,
+ 0.47241682, 0.21456543, -0.02800268, -0.22529918, -0.84989154,
+ -0.7086431, 0.33786222, 0.6490326, -0.8384799, 0.985114,
+ -0.4101424, 0.52377456, 0.5921588, -0.66899574, -0.11188361,
+ -0.9822213, -0.84196454, 0.14232291, -0.49214405, 0.8419358,
+ 0.8897716, -0.8406141, -0.8259247, -0.6908918, 0.8471942,
+ 0.06140751, -0.23359495, 0.7398038, 0.40779343, 0.6734735,
+ -0.6377568, -0.7646455, 0.5685402, 0.04187375, -0.73311013,
+ -0.00512114, -0.5814765, 0.5903504, 0.09171531, -0.60802567,
+ 0.61080986, -0.16245437, -0.25096723, 0.6190915, -0.7142277,
+ -0.1600728, 0.8851507, 0.22585803, 0.9604035, 0.32320845,
+ 0.14618382, -0.774544, 0.54813004, 0.69257534, -0.61747944,
+ -0.6833777, 0.8879458, -0.02535102, -0.21824743, -0.12814242,
+ 0.95946985, -0.31030154, 0.8825775, 0.7767198, -0.8839602,
+ -0.5129694, 0.02521834, -0.27255273, -0.55642307, 0.7032525,
+ -0.30640435, 0.5164734, -0.7563333, 0.42620268, -0.15225667,
+ 0.41989022, -0.6318542, -0.941096, -0.9745337, 0.9156874,
+ -0.3268398, 0.6331186, 0.6416864, -0.20460913, -0.76695883,
+ -0.38052237, -0.41319558, 0.798747, -0.6520171, -0.09593515,
+ -0.8481627, -0.83059865, -0.85499376, 0.80575806, 0.34889475,
+ -0.8980855, -0.6174965, -0.5200427, -0.6607752, 0.3307703,
+ -0.24054858, -0.5670337, -0.16636248, 0.23672634, 0.62885606,
+ 0.10166144, -0.53354776, -0.56768334, -0.7641135, 0.11442101,
+ 0.96315515, 0.37573636, -0.67078173, 0.70057774, -0.24168986,
+ -0.44688666, 0.16544406, -0.88838553, 0.76889133, -0.8447937,
+ 0.62266135, -0.48719126, 0.32826036, -0.02810439, -0.05936452,
+ -0.8128048, -0.3129079, -0.34860566, 0.6167735, -0.5991243,
+ -0.3610302, -0.08637966, -0.16619909, 0.63647974, -0.09442633,
+ -0.5581384, -0.9811046, -0.904086, 0.61326873, 0.7258482,
+ 0.7736206, 0.8774062, -0.5009506, 0.1289413, 0.16396654,
+ 0.6514738, -0.28721195, 0.2236729, 0.45609203, 0.8358965,
+ 0.61307096, -0.84580654, 0.01509422, 0.7686187, -0.3121697,
+ 0.19145107, -0.55658674, -0.829964, -0.97910535, 0.13230643,
+ -0.07734007, -0.9984317, 0.81237555, 0.9640697, -0.840312,
+ -0.540831, -0.5787534, -0.96849644, 0.3838457, -0.12022042,
+ 0.05475989, -0.8009591, -0.94171214, -0.9488497, 0.9111394,
+ 0.7597446, 0.16971052, 0.45299768, -0.45736474, 0.5264327,
+ 0.21037662, -0.6699108, -0.9796896, 0.16691494, 0.45532888,
+ 0.01740798, 0.04102591, 0.03489509, -0.72302973, -0.52516407,
+ -0.47465584, -0.63662803, -0.8904173, 0.57405806, 0.23835278,
+ 0.360155, -0.55155194, 0.4478792, -0.0044243336, 0.46832967,
+ 0.08410877, -0.8455095, -0.7263971, -0.3361347, 0.97136617,
+ -0.44052413, -0.5978838, -0.25358623, -0.79874134, 0.23619038,
+ -0.6827136, -0.29381457, -0.8461834, -0.12056583, -0.13932818,
+ 0.61767286, 0.8580666, 0.26251537, 0.5273094, -0.48985696,
+ 0.88013256, -0.18916833, -0.7348702, 0.7566979, -0.7458619,
+ 0.58176005, -0.78658605, 0.08736417, 0.7823663, -0.1001814,
+ -0.22595143, -0.19375435, -0.83492655, -0.929291, 0.12090784,
+ -0.5844915, 0.13852149, 0.02745366, 0.92406005, -0.71191204,
+ -0.8899623, 0.24317105, 0.32496578, -0.98552567, -0.04174611,
+ -0.35492605, 0.07938504, -0.8233126, 0.3008612, 0.71700615,
+ 0.8915528, -0.54795, -0.16213202, -0.829112, -0.8182144,
+ 0.6964699, 0.011892006, 0.03424544, -0.42607868, -0.46533448,
+ -0.20733991, 0.1982342, 0.6151171, 0.92954826, 0.37436712,
+ -0.15674892, 0.09278384, -0.23512769, 0.3352527, -0.0011435747,
+ -0.6721728, 0.8579683, -0.9896936, 0.42651695, -0.3006128,
+ 0.6946872, -0.48047653, -0.6129973, 0.9572243, 0.7357151,
+ 0.43445703, 0.7255762, -0.8190884, 0.9089385, 0.09615627,
+ -0.16862187, -0.07288834, -0.49054247, -0.9336225, 0.01190421,
+ 0.09707063, 0.45260486, -0.8358802, 0.79366636, -0.26704386,
+ 0.95498896, -0.02372235, 0.319471, -0.976424, -0.79633594,
+ 0.66040134, -0.54345655, -0.66035926, -0.17302102, 0.37924033,
+ 0.1720984, 0.56285584, -0.8860738, -0.5180471, -0.0959073,
+ 0.25083944, -0.82610506, -0.29493344, 0.9925902, -0.5277084,
+ -0.4763626, -0.47927397, -0.36397856, -0.8729958, -0.52953005,
+ 0.00983614, 0.01398262, 0.9101522, -0.88808525, -0.664688,
+ -0.73161906, -0.0665354, -0.6483232, 0.63685423, 0.2964374,
+ 0.09099909, -0.23442702, 0.12380677, -0.5504641, 0.16258523,
+ -0.541228, -0.3874128, -0.6291951, 0.58925194, 0.8938799,
+ -0.3282175, 0.02617104, -0.6951823, -0.5767481, -0.48668635,
+ 0.08838533, 0.7840834, -0.5293897, 0.18453985, 0.26299042,
+ -0.8357302, -0.97141516, -0.29869047, -0.8049868, -0.6597811,
+ -0.6783894, -0.742311, 0.35633904, -0.18960063, 0.37161434,
+ -0.21649535, -0.639291, -0.38328207, -0.88131666, -0.1099996,
+ -0.20276618, -0.59563124, -0.45079857, 0.8347442, -0.60460365,
+ -0.5660544, -0.82730365};
+
const int16_t kFftAutoScaleLength512Input[] = {
27728, 28180, -23037, -999, 7627, 19097, 4809, -28251, 25421,
21584, 5775, -514, 31389, -13221, 28700, 3928, -32678, 9413,
diff --git a/signal/testdata/fft_test_data.h b/signal/testdata/fft_test_data.h
index 78c5f4a..35a0b46 100644
--- a/signal/testdata/fft_test_data.h
+++ b/signal/testdata/fft_test_data.h
@@ -1,4 +1,4 @@
-/* Copyright 2023 The TensorFlow Authors. All Rights Reserved.
+/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -31,6 +31,15 @@
extern const float kRfftFloatLength512Input[];
extern const float kRfftFloatLength512Golden[];
+extern const int16_t kIrfftInt16Length512Input[];
+extern const int16_t kIrfftInt16Length512Golden[];
+
+extern const int32_t kIrfftInt32Length512Input[];
+extern const int32_t kIrfftInt32Length512Golden[];
+
+extern const float kIrfftFloatLength512Input[];
+extern const float kIrfftFloatLength512Golden[];
+
extern const int16_t kFftAutoScaleLength512Input[];
extern const int16_t kFftAutoScaleLength512Golden[];
diff --git a/tensorflow/lite/micro/kernels/micro_ops.h b/tensorflow/lite/micro/kernels/micro_ops.h
index 770669c..5bffa09 100644
--- a/tensorflow/lite/micro/kernels/micro_ops.h
+++ b/tensorflow/lite/micro/kernels/micro_ops.h
@@ -15,6 +15,7 @@
#ifndef TENSORFLOW_LITE_MICRO_KERNELS_MICRO_OPS_H_
#define TENSORFLOW_LITE_MICRO_KERNELS_MICRO_OPS_H_
+#include "signal/micro/kernels/irfft.h"
#include "signal/micro/kernels/rfft.h"
#include "tensorflow/lite/c/common.h"
diff --git a/tensorflow/lite/micro/micro_mutable_op_resolver.h b/tensorflow/lite/micro/micro_mutable_op_resolver.h
index 7f74c7b..5e4bd47 100644
--- a/tensorflow/lite/micro/micro_mutable_op_resolver.h
+++ b/tensorflow/lite/micro/micro_mutable_op_resolver.h
@@ -343,6 +343,12 @@
return AddBuiltin(BuiltinOperator_IF, tflite::Register_IF(), ParseIf);
}
+ TfLiteStatus AddIrfft(const TFLMRegistration* registration =
+ tflite::tflm_signal::Register_IRFFT()) {
+ // TODO(b/286250473): change back name and remove namespace
+ return AddCustom("SignalIrfft", registration);
+ }
+
TfLiteStatus AddL2Normalization() {
return AddBuiltin(BuiltinOperator_L2_NORMALIZATION,
Register_L2_NORMALIZATION(), ParseL2Normalization);
diff --git a/tensorflow/lite/micro/tools/make/Makefile b/tensorflow/lite/micro/tools/make/Makefile
index d02d840..badd0ca 100644
--- a/tensorflow/lite/micro/tools/make/Makefile
+++ b/tensorflow/lite/micro/tools/make/Makefile
@@ -320,6 +320,7 @@
$(TENSORFLOW_ROOT)signal/micro/kernels/filter_bank_square_root.cc \
$(TENSORFLOW_ROOT)signal/micro/kernels/filter_bank_spectral_subtraction.cc \
$(TENSORFLOW_ROOT)signal/micro/kernels/framer.cc \
+$(TENSORFLOW_ROOT)signal/micro/kernels/irfft.cc \
$(TENSORFLOW_ROOT)signal/micro/kernels/rfft.cc \
$(TENSORFLOW_ROOT)signal/micro/kernels/stacker.cc \
$(TENSORFLOW_ROOT)signal/micro/kernels/overlap_add.cc \
@@ -331,6 +332,9 @@
$(TENSORFLOW_ROOT)signal/src/filter_bank_log.cc \
$(TENSORFLOW_ROOT)signal/src/filter_bank_square_root.cc \
$(TENSORFLOW_ROOT)signal/src/filter_bank_spectral_subtraction.cc \
+$(TENSORFLOW_ROOT)signal/src/irfft_float.cc \
+$(TENSORFLOW_ROOT)signal/src/irfft_int16.cc \
+$(TENSORFLOW_ROOT)signal/src/irfft_int32.cc \
$(TENSORFLOW_ROOT)signal/src/log.cc \
$(TENSORFLOW_ROOT)signal/src/max_abs.cc \
$(TENSORFLOW_ROOT)signal/src/msb_32.cc \