From: Takenori Y. <tak...@us...> - 2017-01-13 06:49:35
|
Update of /cvsroot/sp-tk/SPTK4/src In directory sfp-cvs-1.v30.ch3.sourceforge.com:/tmp/cvs-serv5277 Added Files: fftr.cc Log Message: add fftr command --- NEW FILE: fftr.cc --- // ----------------------------------------------------------------- // // The Speech Signal Processing Toolkit (SPTK) // // developed by SPTK Working Group // // http://sp-tk.sourceforge.net/ // // ----------------------------------------------------------------- // // // // Copyright (c) 1984-2007 Tokyo Institute of Technology // // Interdisciplinary Graduate School of // // Science and Engineering // // // // 1996-2016 Nagoya Institute of Technology // // Department of Computer Science // // // // All rights reserved. // // // // Redistribution and use in source and binary forms, with or // // without modification, are permitted provided that the following // // conditions are met: // // // // - Redistributions of source code must retain the above copyright // // notice, this list of conditions and the following disclaimer. // // - Redistributions in binary form must reproduce the above // // copyright notice, this list of conditions and the following // // disclaimer in the documentation and/or other materials provided // // with the distribution. // // - Neither the name of the SPTK working group nor the names of its // // contributors may be used to endorse or promote products derived // // from this software without specific prior written permission. // // // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND // // CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, // // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS // // BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED // // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, // // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // // POSSIBILITY OF SUCH DAMAGE. // // ----------------------------------------------------------------- // #include <unistd.h> #include <cmath> #include <fstream> #include <iostream> #include <sstream> #include <vector> #include "fast_fourier_transform_for_real_sequence.h" #include "sptk_utils.h" namespace { enum OutputFormats { kOutputRealAndImaginaryParts = 0, kOutputRealPart, kOutputImaginaryPart, kOutputAmplitude, kOutputPower, kNumOutputFormats }; const int kDefaultFftSize(256); const bool kDefaultHalfSizeOutputFlag(false); void PrintUsage(std::ostream* stream) { // clang-format off *stream << std::endl; *stream << " fftr - FFT for real sequence" << std::endl; *stream << std::endl; *stream << " usage:" << std::endl; *stream << " fftr [ options ] [ infile ] > stdout" << std::endl; *stream << " options:" << std::endl; *stream << " -l l : FFT size [" << kDefaultFftSize << "]" << std::endl; // NOLINT *stream << " -m m : order of sequence [l-1]" << std::endl; *stream << " -o o : output format [0]" << std::endl; *stream << " 0 (real and imaginary parts)" << std::endl; *stream << " 1 (real part)" << std::endl; *stream << " 2 (imaginary part)" << std::endl; *stream << " 3 (amplitude)" << std::endl; *stream << " 4 (power)" << std::endl; *stream << " -H : output half size [" << sptk::ConvertBooleanToString(kDefaultHalfSizeOutputFlag) << "]" << std::endl; // NOLINT *stream << " -h : print this message" << std::endl; *stream << " infile:" << std::endl; *stream << " data sequence (double) [stdin]" << std::endl; // NOLINT *stream << " stdout:" << std::endl; *stream << " FFT sequence (double)" << std::endl; *stream << std::endl; *stream << " SPTK: version " << sptk::kVersion << std::endl; *stream << std::endl; // clang-format on } } // namespace int main(int argc, char* argv[]) { int fft_size(kDefaultFftSize); int num_order(kDefaultFftSize - 1); bool is_num_order_specified(false); bool half_size_output_flag(kDefaultHalfSizeOutputFlag); OutputFormats output_format(kOutputRealAndImaginaryParts); for (;;) { const char option_char(getopt(argc, argv, "l:m:o:Hh")); if (-1 == option_char) break; switch (option_char) { case 'l': { if (!sptk::ConvertStringToInteger(optarg, &fft_size)) { std::ostringstream error_message; error_message << "The argument for the -l option must be an integer"; sptk::PrintErrorMessage("fftr", error_message); return 1; } break; } case 'm': { if (!sptk::ConvertStringToInteger(optarg, &num_order) || num_order < 0) { std::ostringstream error_message; error_message << "The argument for the -m option must be a " << "non-negative integer"; sptk::PrintErrorMessage("fft", error_message); return 1; } is_num_order_specified = true; break; } case 'o': { int given_integer(-1); if (!sptk::ConvertStringToInteger(optarg, &given_integer)) { std::ostringstream error_message; error_message << "The argument for the -o option must be an integer"; sptk::PrintErrorMessage("fftr", error_message); return 1; } const int min(0); const int max(static_cast<int>(kNumOutputFormats) - 1); if (!sptk::IsInRange(given_integer, min, max)) { std::ostringstream error_message; error_message << "The argument for the -o option must be in range" << " (" << min << " .. " << max << ")"; sptk::PrintErrorMessage("fftr", error_message); return 1; } output_format = static_cast<OutputFormats>(given_integer); break; } case 'H': { half_size_output_flag = true; break; } case 'h': { PrintUsage(&std::cout); return 0; } default: { PrintUsage(&std::cerr); return 1; } } } // check order if (is_num_order_specified) { if (fft_size <= num_order) { std::ostringstream error_message; error_message << "The order of a sequence " << num_order << " should be less than the FFT size " << fft_size; sptk::PrintErrorMessage("fftr", error_message); return 1; } } else { num_order = fft_size - 1; } // get input file const char* input_file((optind < argc) ? argv[argc - 1] : NULL); // open stream std::ifstream ifs; ifs.open(input_file, std::ios::in | std::ios::binary); if (ifs.fail() && NULL != input_file) { std::ostringstream error_message; error_message << "Cannot open file " << input_file; sptk::PrintErrorMessage("fftr", error_message); return 1; } std::istream& input_stream(ifs.fail() ? std::cin : ifs); // prepare for fast Fourier transform sptk::FastFourierTransformForRealSequence fft(num_order, fft_size, false); sptk::FastFourierTransformForRealSequence::Buffer buffer; if (!fft.IsValid()) { std::ostringstream error_message; error_message << "FFT size must be a power of 2 and greater than 4"; sptk::PrintErrorMessage("fftr", error_message); return 1; } const int input_length(num_order + 1); const int output_length(half_size_output_flag ? (fft_size / 2 + 1) : fft_size); std::vector<double> input_x(input_length); std::vector<double> output_x(fft_size); std::vector<double> output_y(fft_size); while (sptk::ReadStream(true, input_length, &input_x, &input_stream)) { if (!fft.Run(input_x, &output_x, &output_y, &buffer)) { std::ostringstream error_message; error_message << "Failed to run fast Fourier transform"; sptk::PrintErrorMessage("fftr", error_message); return 1; } if (kOutputAmplitude == output_format) { for (int i(0); i < output_length; ++i) { output_x[i] = std::sqrt(output_x[i] * output_x[i] + output_y[i] * output_y[i]); } } else if (kOutputPower == output_format) { for (int i(0); i < output_length; ++i) { output_x[i] = output_x[i] * output_x[i] + output_y[i] * output_y[i]; } } if (kOutputImaginaryPart != output_format && !sptk::WriteStream(output_length, output_x, &std::cout)) { std::ostringstream error_message; error_message << "Failed to write an output sequence"; sptk::PrintErrorMessage("fftr", error_message); return 1; } if ((kOutputRealAndImaginaryParts == output_format || kOutputImaginaryPart == output_format) && !sptk::WriteStream(output_length, output_y, &std::cout)) { std::ostringstream error_message; error_message << "Failed to write an output sequence"; sptk::PrintErrorMessage("fftr", error_message); return 1; } } return 0; } |