質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.84%

  • C++

    3133questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

離散フーリエ変換をしたいです.

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 137

muscle1100

score 11

 前提・実現したいこと

離散フーリエ変換をしたいのですが,現在,分割数N1とサンプリング周波数によってできたx配列の値があっていないとうまくフーリエ逆変換ができません.
サンプリング周波数が100Hzのとき1[s]までしているので配列の個数は100個になります.一周期で最低4つ値をとれば三角波になると思うのですが,うまくいきません.どなたかお願いします.
また,矩形波も作り方がいまいちわからないので,もしよければご指摘のほどお願いします.

 発生している問題・エラーメッセージ

分割数と元のデータ数が同じ出ないと逆フーリエ変換ができない.

エラーメッセージ

 該当のソースコード

//ヘッダーファイルです
#define _USE_MATH_DEFINES
#include <iostream>
#include <vector>
#include <cmath>
#include <complex>

#define N 1
#define N1 100

class Wave {
private:
    /* data */
    void Wave_Output(std::vector<double> dt);//csvファイル出力(波)
    void Fourier_Out(std::vector<double> dt_re, std::vector<double> dt_im);
    void Fourier_R_Out(std::vector<double>dt_re, std::vector<double> dt_im);

public:
    std::vector<double> x; //波
    std::vector<double> x_r;//フーリエ逆変換で生成した波
    std::vector<double> dt_re;
    std::vector<double> dt_im;
    std::vector<double> f_dt;
    void test();
    /*!---------------------------------------------------------
    @brief 正弦波信号x(t)を生成する関数

    double *dt 型の配列をキーボードから入力する
    @return dt[]に入力した値が返る.
    @attention 特になし
    @par 更新履歴
    - 2018/04/22
    - 基本的な機能の実装(by)

    */
    void Sin_Wave(double A, double B, double f);
    /*!---------------------------------------------------------
    @brief 合成波1x(t)を生成する関数

    double *dt 型の配列をキーボードから入力する
    @return dt[]に入力した値が返る.
    @attention 特になし
    @par 更新履歴
    - 2018/04/22
    - 基本的な機能の実装(by)

    */
    void Comp_Wave1(double A1, double B1, double A2, double B2, double f);
    /*!---------------------------------------------------------
    @brief 合成波2x(t)を生成する関数

    double *dt 型の配列をキーボードから入力する
    @return dt[]に入力した値が返る.
    @attention 特になし
    @par 更新履歴
    - 2018/04/22
    - 基本的な機能の実装(by )

    */
    void Comp_Wave2(double A1, double B1, double A2, double B2, double C, double f);
    /*!---------------------------------------------------------
    @brief 矩形波x(t)を生成する関数

    double *dt 型の配列をキーボードから入力する
    @return dt[]に入力した値が返る.
    @attention 特になし
    @par 更新履歴
    - 2018/04/22
    - 基本的な機能の実装(by A)

    */
    void Rect_Wave(double A, int inter,double f);
    /*!---------------------------------------------------------
    @brief 離散フーリエ変換をする関数

    double *dt 型の配列をキーボードから入力する
    @return dt[]に入力した値が返る.
    @attention 特になし
    @par 更新履歴
    - 2018/04/22
    - 基本的な機能の実装(b)

    */
    void Fourier(int N_s);
    /*!---------------------------------------------------------
    @brief 離散フーリエ逆変換をする関数

    double *dt 型の配列をキーボードから入力する
    @return dt[]に入力した値が返る.
    @attention 特になし
    @par 更新履歴
    - 2018/04/22
    - 基本的な機能の実装(by )

    */
    void Reverse_Fourier(int N_r);
    /*!---------------------------------------------------------
    @brief パワースペクトルを計算する関数

    double *dt 型の配列をキーボードから入力する
    @return dt[]に入力した値が返る.
    @attention 特になし
    @par 更新履歴
    - 2018/04/22
    - 基本的な機能の実装(byA)

    */
    void Power_Spectral(double f);
};
//関数ファイルです.
#include "****.h"

void Wave::Wave_Output(std::vector<double> dt) {
    FILE *fp;
    if ((fopen_s(&fp, "wave.csv", "w")) != 0) {
        fprintf(stderr, "ファイルのオープンに失敗");
    }
    else {
        for (int i = 0; i < dt.size(); i++) {
            fprintf(fp, "%f\n", dt[i]);
        }
        fclose(fp);
    }
}

void Wave::Fourier_Out(std::vector<double> dt_re, std::vector<double> dt_im) {
    FILE *fp;
    if ((fopen_s(&fp, "Fourier.csv", "w")) != 0) {
        fprintf(stderr, "ファイルのオープンに失敗");
    }
    else {
        for (int i = 0; i < dt_re.size(); i++) {
            fprintf(fp, "%d,%f,%f\n", i * N / N1, dt_re[i], dt_im[i]);
        }
        fclose(fp);
    }
}

void Wave::Fourier_R_Out(std::vector<double>dt_re, std::vector<double> dt_im) {
    FILE *fp;
    if ((fopen_s(&fp, "Fourier_R.csv", "w")) != 0) {
        fprintf(stderr, "ファイルのオープンに失敗");
    }
    else {
        for (int i = 0; i < dt_re.size(); i++) {
            fprintf(fp, "%d,%f,%f\n", i * N / N1, dt_re[i], dt_im[i]);
        }
        fclose(fp);
    }
}

void Wave::Power_Spectral(double f) {
    FILE *fp;
    if ((fopen_s(&fp, "Power_Spe.csv", "w")) != 0) {
        fprintf(stderr, "ファイルのオープンに失敗");
    }
    else {
        for (int i = 0; i < dt_re.size(); i++) {
            fprintf(fp, "%f,%f\n", f_dt[i], sqrt(dt_re[i] * dt_re[i] + dt_im[i] * dt_im[i]));
        }
        fclose(fp);
    }
}
void Wave::test() {
    std::cout << "test" << '\n';
}

//基本周波数は
void Wave::Sin_Wave(double A, double B, double f) {
    for (double t = 0; t < N; t += 1.0 / f) {
        /* code */
        x.push_back(A*sin(2 * M_PI * B * t));
    }
    Wave out;
    out.Wave_Output(x);
}

void Wave::Comp_Wave1(double A1, double B1, double A2, double B2, double f) {
    for (double t = 0; t < N; t += 1.0 / f) {
        /* code */
        x.push_back(A1*sin(B1*t * 2 * M_PI) + A2 * cos(B2*t * 2 * M_PI));
    }
    Wave out;
    out.Wave_Output(x);
}

void Wave::Comp_Wave2(double A1, double B1, double A2, double B2, double C, double f) {
    for (double t = 0; t < N; t += 1.0 / f) {
        /* code */
        x.push_back(C + A1 * sin(B1*t * 2 * M_PI) + A2 * cos(B2*t * 2 * M_PI));
    }
    Wave out;
    out.Wave_Output(x);
}

void Wave::Rect_Wave(double A, int inter,double f) {
    double temp = A;
    for (double t = 0; t < 2*3; t+= 1/f) {
        if (t == 3) {
            temp = -1 * temp;
        }
        x.push_back(temp);
    }
    Wave out;
    out.Wave_Output(x);
}

void Wave::Fourier(int N_s) {
    //実部と虚部を分けてフーリエ変換
    std::vector<double> re(N_s);
    std::vector<double> im(N_s);
    for (int n = 0; n < N_s; n++) {
        re[n] = 0.0;
        im[n] = 0.0;
        for (int k = 0; k < N_s; k ++) {
            re[n] += x[k] * cos(2 * M_PI*k*n / N_s) / N_s;
            im[n] += -x[k] * sin(2 * M_PI*k*n / N_s) / N_s;
        }
        f_dt.push_back(2 * M_PI*n / N_s);
    }
    Wave out;
    out.Fourier_Out(re,im);
    dt_re = re;
    dt_im = im;
}

void Wave::Reverse_Fourier(int N_r) {
    std::vector<double> re(N_r);
    std::vector<double> im(N_r);
    int k;
    for (int n = 0; n < N_r; n++) {
        re[n] = 0.0;
        im[n] = 0.0;
        for (k = 0; k < N_r; k++) {
            re[n] += (dt_re[k] * cos(2 * M_PI*k*n / N_r)) - (dt_im[k] * sin(2 * M_PI*k*n / N_r));
            im[n] += (dt_re[k] * sin(2 * M_PI*k*n / N_r)) + (dt_im[k] * cos(2 * M_PI*k*n / N_r));
        }
    }
    Wave out;
    out.Fourier_R_Out(re, im);
}
//main文です
#include "****.h"
#include <iostream>
#include <vector>



int main() {

    typedef int size_t;
    //std::vector<double> v = A_Wave(1,-1,100.0);
    Wave W;
    //W.Comp_Wave2(1.0, 2.0, 2.0, 10.0, 3.0,100);
    W.Sin_Wave(1.0,2.0,100);
    //W.Rect_Wave(1,M_PI,10);
    W.Fourier(N1);
    W.Reverse_Fourier(N1);
    W.Power_Spectral(100);
    system("pause");
    return 0;
}

 試したこと

お願いします.

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • muscle1100

    2018/04/26 20:43

    離散フーリエ変換は離散的ではない式を一定ごとに区切って離散的にすると思うのですが、そもそもの値が1/fごとの値を取っているから離散的だなと思いまして(説明下手ですみません)

    キャンセル

  • chankane

    2018/04/26 21:02

    もしかしたら私の解釈が間違っているかもしれませんが、ご指摘致します。質問者様は離散フーリエ変換を少し誤解していらっしゃるように思いました。離散フーリエ変換自体にはアナログ信号をデジタル化する機能はございません。(そもそもの音声データが既に離散的)。もしも質問者様が「そんなことしってるよヽ(゚Д゚)ノ」とお思いになったのでしたら、大変失礼いたしました。

    キャンセル

  • muscle1100

    2018/04/26 21:10

    大丈夫です!ご指摘ありがとうございます

    キャンセル

回答 1

checkベストアンサー

0

すみません。当方では質問者様のおかれている状況が完全に理解できていないので、参考になりそうなURLをのせるだけになります。
お役に立てずにすみません(´・ω・`)
Pythonで短時間フーリエ変換(STFT)と逆変換 
STFTとISTFTの秘密の関係 [フーリエ変換](https://jp.mathworks.com/discovery/fourier-transform.html)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.84%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C++

    3133questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。