正弦波の式
**\n", "\n", "$$\n", "y(t) = A \\sin(\\omega t + \\phi)\n", "$$\n", "\n", "- \\(y(t)\\) は時刻 \\(t\\) における振幅\n", "- \\(A\\) は振幅(波の最大変位)\n", "- \\(\\omega\\) は角周波数(単位時間あたりの角度の変化量。これは周期 \\(T\\) に対して \\(\\omega = \\frac{2\\pi}{T}\\) と表される)\n", "- \\(t\\) は時間\n", "- \\(\\phi\\) は初期位相(波の初期の位置)" ], "metadata": { "id": "8YgOSObEz0M3" } }, { "cell_type": "code", "source": [ "# データ数と波の情報を入力する関数\n", "def input_wave_data():\n", " f_sample = []\n", " n_sample = []\n", " wave_sample = []\n", "\n", " num = input(\"重ね合わせたい波の数を入力してください。 >>>\")\n", "\n", " try:\n", " num = int(num)\n", " except ValueError:\n", " print(\"無効な入力です。整数を入力してください。\")\n", " return input_wave_data()\n", "\n", " for z in range(num):\n", " f_z = float(input(str(z + 1) + \"つ目の波の周波数を入力してください。 >>>\"))\n", " n_z = float(input(str(z + 1) + \"つ目の波の振幅の係数の大きさを入力してください。 >>>\"))\n", "\n", " wave_type = input(\n", " str(z + 1) + \"つ目の波の波形を入力してください。 Sin波:1 Cos波:その他のキーを入力してください。 >>>\"\n", " )\n", " if wave_type == \"1\":\n", " w_z = n_z * np.sin(2 * np.pi * f_z * t)\n", " else:\n", " w_z = n_z * np.cos(2 * np.pi * f_z * t)\n", " wave_sample.append(w_z)\n", "\n", " return wave_sample\n", "\n", "\n", "# 波形を合成する関数\n", "def compose_waveforms(wave_sample):\n", " is_y = input(f\"データ数分の乱数を波に合成しますか?(y/n) >>>\")\n", "\n", " if is_y.lower() == \"y\":\n", " n_amp = float(input(\"乱数の振幅の係数の大きさを入力してください。 >>>\"))\n", " w_random = n_amp * np.random.randn(N)\n", " wave_sample.append(w_random)\n", " else:\n", " print(\"了解しました。\")\n", "\n", " y = sum(wave_sample)\n", " return y\n", "\n", "\n", "# 波形を表示する関数\n", "def display_waveforms(wave_sample, t):\n", " print(\"合成前の波形をそれぞれ表示します。\")\n", " fig_num = len(wave_sample)\n", " cols = 4 # 1行あたりの最大サブプロット数\n", " rows = (fig_num + cols - 1) // cols # サブプロットの行数\n", "\n", " fig, ax = plt.subplots(rows, cols, figsize=(16, rows * 4))\n", " plt.subplots_adjust(hspace=0.5, wspace=0.3)\n", " plt.suptitle(\"Sample Waveform Xlabel=Time (s), Ylabel=Amplitude\", fontsize=18)\n", "\n", " for i, a in enumerate(wave_sample):\n", " plt.subplot(rows, cols, i + 1)\n", " plt.plot(t, a)\n", " plt.title(\"Waveform\" + str(i + 1))\n", "\n", " plt.tight_layout()\n", " plt.show()\n", "\n", "\n", "# メインの処理\n", "t = np.linspace(0, 5, 5000) # ここの値を調節すると時間の長さを変えられる。\n", "N = len(t)\n", "\n", "# 波形の入力\n", "wave_sample = input_wave_data()\n", "\n", "# 波形の合成\n", "y = compose_waveforms(wave_sample)\n", "\n", "# 波形の表示\n", "display_waveforms(wave_sample, t)\n" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 455 }, "id": "rR70U3_m_tuF", "outputId": "44628009-6d33-4bbe-d59d-b90c033884a8" }, "execution_count": null, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "重ね合わせたい波の数を入力してください。 >>>0\n", "データ数分の乱数を波に合成しますか?(y/n) >>>y\n", "乱数の振幅の係数の大きさを入力してください。 >>>2\n", "合成前の波形をそれぞれ表示します。\n" ] }, { "output_type": "display_data", "data": { "text/plain": [ "高速フーリエ変換の式
**\n", "\n", "$$\n", "X[k] = \\sum_{n=0}^{N-1} x[n] \\cdot e^{-i \\frac{2\\pi}{N}kn}\n", "$$\n", "\n", "- \\( x[n] \\) は離散時間信号(離散的なサンプル)\n", "- \\( X[k] \\) は FFT の結果\n", "- \\( N \\) はサンプル数\n", "- \\( k \\) は周波数インデックス(0 から N-1 までの整数)\n", "\n", "FFT は、N 個のサンプルから成る離散信号を N/2 個の複素数から成る周波数成分に変換していて、計算量は O(N log N)となっているので、データサイズが増えても計算量があまり増加しません。\n", "\n", "これによって従来の DFT と比べて計算量を \\(O(N^2)\\) から \\(O(N \\log N)\\) に減少させられるので、大量の計算が必要になる大規模データやリアルタイム処理においてよく用いられています(数十倍から数百倍高速)。\n", "\n", "FFT も DFT の一種で非周期的な離散データを扱うので、結果から導かれる周波数特性は離散的なものになります。" ], "metadata": { "id": "dAcds5Lsy69N" } }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 529 }, "id": "JVGyDjlE5oZl", "outputId": "37c0c387-94d2-40ab-e080-ff7c69ae9c56" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "どちらの音声をフーリエ変換しますか?\n", "元の音声ファイル:1 時間で区切った音声ファイル:2 必要なデータ数のみのデータ:その他のキーを入力してください。 >>>1\n", "振幅スペクトルを表示します。\n", "最大振幅: 112.11711951104026\n", "最小振幅: 0.002156860320887937\n", "最大周波数: 7999.727474024868\n", "最小周波数: -7999.727474024868\n" ] }, { "output_type": "display_data", "data": { "text/plain": [ "