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 \