diff --git a/python/tflite_micro/python_ops_resolver.cc b/python/tflite_micro/python_ops_resolver.cc index becdcbb9e53..e6f9cf7f290 100644 --- a/python/tflite_micro/python_ops_resolver.cc +++ b/python/tflite_micro/python_ops_resolver.cc @@ -64,6 +64,7 @@ PythonOpsResolver::PythonOpsResolver() { 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 66874eb59c3..446b8789cce 100644 --- a/python/tflite_micro/signal/ops/fft_ops.py +++ b/python/tflite_micro/signal/ops/fft_ops.py @@ -80,7 +80,9 @@ def _fft_auto_scale(input_tensor, name=default_name): 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 fa16b695f80..63de82404d3 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 @@ def testFftLengthNoEven(self): 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 9dab8218a3b..4d37f0654bb 100644 --- a/signal/micro/kernels/BUILD +++ b/signal/micro/kernels/BUILD @@ -16,12 +16,14 @@ cc_library( "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 @@ cc_library( "//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 03bb3f3b527..e910519c62b 100644 --- a/signal/micro/kernels/fft_test.cc +++ b/signal/micro/kernels/fft_test.cc @@ -303,6 +303,164 @@ TF_LITE_MICRO_TEST(RfftTestSize512Int32) { 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( + 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( + 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( + 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( + 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( + 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( + 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( + 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 00000000000..6cb3d7c3b5e --- /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 +#include +#include + +#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 +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + + auto* params = static_cast( + context->AllocatePersistentBuffer( + context, sizeof(TfLiteAudioFrontendIrfftParams))); + + if (params == nullptr) { + return nullptr; + } + + tflite::FlexbufferWrapper fbw(reinterpret_cast(buffer), + length); + params->fft_length = fbw.ElementAsInt32(kFftLengthIndex); + params->fft_type = typeToTfLiteType(); + + size_t state_size = (*get_needed_memory_func)(params->fft_length); + params->state = reinterpret_cast( + 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 +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(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 * input, T*)> +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + auto* params = + reinterpret_cast(node->user_data); + + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + const Complex* input_data = + tflite::micro::GetTensorData>(input); + T* output_data = tflite::micro::GetTensorData(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(buffer); + const flexbuffers::Map& m = flexbuffers::GetRoot(buffer_t, length).AsMap(); + auto tensor_type = static_cast(m["T"].AsInt32()); + + switch (tensor_type) { + case TensorType_INT16: { + return Init(context, buffer, length); + } + case TensorType_INT32: { + return Init(context, buffer, length); + } + case TensorType_FLOAT32: { + return Init(context, buffer, length); + } + default: + return nullptr; + } +} + +TfLiteStatus PrepareAll(TfLiteContext* context, TfLiteNode* node) { + auto* params = + reinterpret_cast(node->user_data); + + switch (params->fft_type) { + case kTfLiteInt16: { + return Prepare(context, node); + } + case kTfLiteInt32: { + return Prepare(context, node); + } + case kTfLiteFloat32: { + return Prepare(context, node); + } + default: + return kTfLiteError; + } +} + +TfLiteStatus EvalAll(TfLiteContext* context, TfLiteNode* node) { + auto* params = + reinterpret_cast(node->user_data); + + switch (params->fft_type) { + case kTfLiteInt16: { + return Eval(context, node); + } + case kTfLiteInt32: { + return Eval(context, node); + } + case kTfLiteFloat32: { + return Eval(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, + Prepare, Eval); + return &r; +} + +TFLMRegistration* Register_IRFFT_INT16() { + static TFLMRegistration r = tflite::micro::RegisterOp( + Init, + Prepare, Eval); + return &r; +} + +TFLMRegistration* Register_IRFFT_INT32() { + static TFLMRegistration r = tflite::micro::RegisterOp( + Init, + Prepare, Eval); + 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 00000000000..380bc3e74a9 --- /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 75f5fe9d628..c09f608aff8 100644 --- a/signal/src/BUILD +++ b/signal/src/BUILD @@ -18,6 +18,20 @@ cc_library( ], ) +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"], diff --git a/signal/src/irfft.h b/signal/src/irfft.h new file mode 100644 index 00000000000..c2b54d789e4 --- /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 +#include + +#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* 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* 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* 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 00000000000..53ce0fe4eb0 --- /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 +#include + +#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(state); + irfft_float_state->cfg = + reinterpret_cast(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* input, float* output) { + IrfftFloatState* irfft_float_state = static_cast(state); + kiss_fft_float::kiss_fftri( + static_cast(irfft_float_state->cfg), + reinterpret_cast(input), + reinterpret_cast(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 00000000000..f92b3c5ff46 --- /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 +#include + +#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* input, + int16_t* output) { + kiss_fft_fixed16::kiss_fftri( + static_cast(state), + reinterpret_cast(input), + reinterpret_cast(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 00000000000..d4802a6358f --- /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 +#include + +#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* input, + int32_t* output) { + kiss_fft_fixed32::kiss_fftri( + static_cast(state), + reinterpret_cast(input), + reinterpret_cast(output)); +} + +} // namespace tflm_signal +} // namespace tflite diff --git a/signal/tensorflow_core/kernels/BUILD b/signal/tensorflow_core/kernels/BUILD index bea8eefb3b9..7d412eb00c0 100644 --- a/signal/tensorflow_core/kernels/BUILD +++ b/signal/tensorflow_core/kernels/BUILD @@ -19,6 +19,7 @@ tflm_signal_kernel_library( 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 dc5b1cc4014..48db4e3ff78 100644 --- a/signal/tensorflow_core/kernels/fft_kernels.cc +++ b/signal/tensorflow_core/kernels/fft_kernels.cc @@ -14,6 +14,7 @@ limitations under the License. ==============================================================================*/ #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 @@ class RfftOp : public tensorflow::OpKernel { 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 * 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().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().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().data(); + + int outer_dims = input_tensor.flat_inner_dims().dimensions().at(0); + for (int i = 0; i < outer_dims; i++) { + (*apply_func)( + state_, + reinterpret_cast*>(&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 @@ REGISTER_KERNEL_BUILDER( RfftOp); +REGISTER_KERNEL_BUILDER( + Name("SignalIrfft") + .Device(tensorflow::DEVICE_CPU) + .TypeConstraint("T"), + IrfftOp); +REGISTER_KERNEL_BUILDER( + Name("SignalIrfft") + .Device(tensorflow::DEVICE_CPU) + .TypeConstraint("T"), + IrfftOp); +REGISTER_KERNEL_BUILDER( + Name("SignalIrfft") + .Device(tensorflow::DEVICE_CPU) + .TypeConstraint("T"), + IrfftOp); + } // 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 ba27d744148..4f52a2bc347 100644 --- a/signal/tensorflow_core/ops/fft_ops.cc +++ b/signal/tensorflow_core/ops/fft_ops.cc @@ -33,6 +33,16 @@ Status RfftShape(InferenceContext* c) { return OkStatus(); } +Status IrfftShape(InferenceContext* c) { + ShapeHandle out; + int fft_length; + TF_RETURN_IF_ERROR(c->GetAttr("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}") @@ -62,6 +72,31 @@ fft_length: The length of the FFT operation. An input signal that's shorter will be zero padded to fft_length. )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") diff --git a/signal/testdata/fft_test_data.cc b/signal/testdata/fft_test_data.cc index 5525681957c..335a343324f 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 @@ const float kRfftFloatLength512Golden[] = { -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 78c5f4a0a20..35a0b46aa14 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 int32_t kRfftInt32Length512Golden[]; 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 770669c4d28..5bffa09b9c6 100644 --- a/tensorflow/lite/micro/kernels/micro_ops.h +++ b/tensorflow/lite/micro/kernels/micro_ops.h @@ -15,6 +15,7 @@ limitations under the License. #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 7f74c7bf2fa..5e4bd47448e 100644 --- a/tensorflow/lite/micro/micro_mutable_op_resolver.h +++ b/tensorflow/lite/micro/micro_mutable_op_resolver.h @@ -343,6 +343,12 @@ class MicroMutableOpResolver : public MicroOpResolver { 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 d02d840e281..badd0caa100 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_log.cc \ $(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.cc \ $(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 \