{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "617b42b4-dd8e-43e1-bf4f-0eda916cf5fb",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch, torchaudio\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "7f81878f-8177-4607-8f5d-e94471d95d92",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['soundfile']\n"
     ]
    }
   ],
   "source": [
    "# !pip install PySoundFile\n",
    "print(str(torchaudio.list_audio_backends()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "c270c88a-0bec-4f98-9b65-eda083bffef8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Shape of waveform: torch.Size([1, 2183227])\n",
      "Sample rate of waveform: 16000\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 30408 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "filename = \"out.wav\"\n",
    "waveform, sample_rate = torchaudio.load(filename)\n",
    "\n",
    "print(\"Shape of waveform: {}\".format(waveform.size()))\n",
    "print(\"Sample rate of waveform: {}\".format(sample_rate))\n",
    "\n",
    "plt.figure()\n",
    "plt.grid()\n",
    "plt.plot(waveform.t().numpy())\n",
    "plt.savefig(\"after_new_spec.png\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "01707af6-66ff-4130-b084-43b5b591cdf7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Shape of spectrogram: torch.Size([1, 201, 10917])\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x1ecf2e4d450>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 14352 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "specgram = torchaudio.transforms.Spectrogram()(waveform)\n",
    "\n",
    "print(\"Shape of spectrogram: {}\".format(specgram.size()))\n",
    "\n",
    "plt.figure()\n",
    "plt.grid()\n",
    "plt.imshow(specgram.log2()[0,:,:].numpy(), cmap='bone')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "e727efb5-5531-4a1b-a348-dc3ad01f37e4",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\Peter\\AppData\\Local\\miniconda3\\Lib\\site-packages\\torchaudio\\functional\\functional.py:584: UserWarning: At least one mel filterbank has all zero values. The value for `n_mels` (128) may be set too high. Or, the value for `n_freqs` (201) may be set too low.\n",
      "  warnings.warn(\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Shape of spectrogram: torch.Size([1, 128, 10917])\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 11248 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "specgram = torchaudio.transforms.MelSpectrogram()(waveform)\n",
    "\n",
    "print(\"Shape of spectrogram: {}\".format(specgram.size()))\n",
    "\n",
    "plt.figure()\n",
    "p = plt.imshow(specgram.log2()[0,:,:].detach().numpy(), cmap='bone')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "531a5a8b-de30-46bc-8f48-779a5539ba60",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Shape of transformed waveform: torch.Size([1, 218323])\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x1ecf2451010>]"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 33248 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "new_sample_rate = sample_rate/10\n",
    "\n",
    "# Since Resample applies to a single channel, we resample first channel here\n",
    "channel = 0\n",
    "transformed = torchaudio.transforms.Resample(sample_rate, new_sample_rate)(waveform[channel,:].view(1,-1))\n",
    "\n",
    "print(\"Shape of transformed waveform: {}\".format(transformed.size()))\n",
    "\n",
    "plt.figure()\n",
    "plt.grid()\n",
    "plt.plot(transformed[0,:].numpy())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "1d53ef1b-5d80-4651-be3b-21ed82504b9d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Min of waveform: -1.0\n",
      "Max of waveform: 0.999969482421875\n",
      "Mean of waveform: 9.850016795098782e-06\n"
     ]
    }
   ],
   "source": [
    "# Let's check if the tensor is in the interval [-1,1]\n",
    "print(\"Min of waveform: {}\\nMax of waveform: {}\\nMean of waveform: {}\".format(waveform.min(), waveform.max(), waveform.mean()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "47d2e499-4cec-42f3-9ad7-d18f4e01d2e3",
   "metadata": {},
   "outputs": [],
   "source": [
    "def normalize(tensor):\n",
    "    # Subtract the mean, and scale to the interval [-1,1]\n",
    "    tensor_minusmean = tensor - tensor.mean()\n",
    "    return tensor_minusmean/tensor_minusmean.abs().max()\n",
    "\n",
    "# Let's normalize to the full interval [-1,1]\n",
    "waveform = normalize(waveform)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "b6658254-e084-4a9b-b41e-1ccbe2e2218b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Shape of transformed waveform: torch.Size([1, 2183227])\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x1ecf2e1e890>]"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 18096 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "transformed = torchaudio.transforms.MuLawEncoding()(waveform)\n",
    "\n",
    "print(\"Shape of transformed waveform: {}\".format(transformed.size()))\n",
    "\n",
    "plt.figure()\n",
    "plt.plot(transformed[0,:].numpy())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "23d2386e-c0ad-48b5-9ad4-54209cea8d97",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Shape of recovered waveform: torch.Size([1, 2183227])\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x1ec8e1c4a90>]"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 25308 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "reconstructed = torchaudio.transforms.MuLawDecoding()(transformed)\n",
    "\n",
    "print(\"Shape of recovered waveform: {}\".format(reconstructed.size()))\n",
    "\n",
    "plt.figure()\n",
    "plt.plot(reconstructed[0,:].numpy())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "583d905f-e0fa-43f0-bc8f-5e2bdc078b9d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Median relative difference between original and MuLaw reconstucted signals: 1.13%\n"
     ]
    }
   ],
   "source": [
    "# Compute median relative difference\n",
    "err = ((waveform-reconstructed).abs() / waveform.abs()).median()\n",
    "\n",
    "print(\"Median relative difference between original and MuLaw reconstucted signals: {:.2%}\".format(err))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "fd61d185-742d-4c31-9ff9-7e9dea4efce6",
   "metadata": {},
   "outputs": [],
   "source": [
    "# !pip install librosa\n",
    "import librosa"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "3af0daa8-0b1f-4491-a030-9360c70c70b2",
   "metadata": {},
   "outputs": [],
   "source": [
    "y, sr = librosa.load('out.wav')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "16b8d8f0-da76-4799-8d8f-a8421d048629",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 61028 characters]",
      "text/plain": [
       "<Figure size 1000x400 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import librosa.display\n",
    "\n",
    "# Compute MFCCs\n",
    "mfccs = librosa.feature.mfcc(y=y, sr=sr)\n",
    "\n",
    "# Display the MFCCs\n",
    "plt.figure(figsize=(10, 4))\n",
    "librosa.display.specshow(mfccs, x_axis='time')\n",
    "plt.colorbar()\n",
    "plt.title('MFCC')\n",
    "plt.tight_layout()\n",
    "plt.savefig(\"after_new_spec1.png\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "f67b7708-aae2-4e83-be4d-73f39561b979",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Estimated Tempo: [75.99954044] BPM\n",
      "Beat Frames: [   3   42   84  119  153  187  221  256  290  325  359  393  427  461\n",
      "  495  530  564  598  633  667  701  735  769  803  838  872  906  940\n",
      "  971 1005 1039 1074 1109 1146 1180 1214 1248 1283 1317 1351 1386 1420\n",
      " 1454 1488 1522 1556 1591 1625 1660 1694 1728 1762 1796 1830 1865 1899\n",
      " 1933 1968 2002 2036 2070 2104 2137 2169 2203 2241 2275 2310 2344 2378\n",
      " 2412 2446 2481 2515 2549 2583 2618 2652 2686 2720 2755 2789 2823 2857\n",
      " 2891 2926 2960 2994 3028 3062 3096 3131 3165 3199 3232 3264 3298 3336\n",
      " 3370 3405 3439 3473 3507 3541 3575 3610 3644 3679 3713 3747 3781 3815\n",
      " 3849 3883 3918 3952 3987 4021 4055 4089 4124 4158 4191 4226 4260 4295\n",
      " 4329 4363 4397 4432 4466 4500 4534 4568 4603 4637 4671 4705 4740 4774\n",
      " 4808 4842 4876 4911 4945 4979 5013 5047 5082 5116 5150 5184 5219 5253\n",
      " 5287 5321 5356 5390 5424 5458 5493 5527 5561 5595 5629 5664 5698 5732\n",
      " 5766 5800 5834 5869]\n"
     ]
    }
   ],
   "source": [
    "import scipy\n",
    "from scipy.signal.windows import hann \n",
    "scipy.signal.hann = hann # very durty hack\n",
    "\n",
    "# Estimate the tempo and beat events\n",
    "tempo, beats = librosa.beat.beat_track(y=y, sr=sr)\n",
    "\n",
    "print(f\"Estimated Tempo: {tempo} BPM\")\n",
    "print(\"Beat Frames:\", beats)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fab5ad76-25c7-4514-aefe-6696f6399ba2",
   "metadata": {},
   "source": [
    "Обнаружение начала является фундаментальной задачей обработки аудиосигнала, которая включает в себя идентификацию точек в аудиосигнале, где происходят важные события или переходные процессы. Он вычисляет огибающую силы наступления, идентифицирует события начала и визуализирует силу начала и обнаруженные начала на графике. Обнаружение начала имеет важное значение для идентификации важных событий в аудиосигнале, таких как удары и начало нот. Полученный график позволяет наблюдать за ритмическими рисунками и изменениями интенсивности звука."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "dd8717b3-c3e7-496b-aa9c-93d1c2a4902a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 80112 characters]",
      "text/plain": [
       "<Figure size 1000x400 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Compute onset strength envelope\n",
    "onset_env = librosa.onset.onset_strength(y=y, sr=sr)\n",
    "\n",
    "# Find onset events\n",
    "onsets = librosa.onset.onset_detect(onset_envelope=onset_env, sr=sr)\n",
    "\n",
    "# Plot the onset strength envelope and detected onsets\n",
    "plt.figure(figsize=(10, 4))\n",
    "plt.plot(librosa.times_like(onset_env), onset_env, label='Onset Strength')\n",
    "plt.vlines(librosa.times_like(onset_env)[onsets], 0, onset_env.max(), color='r', alpha=0.25, label='Detected Onsets')\n",
    "plt.legend()\n",
    "plt.title('Onset Detection')\n",
    "plt.tight_layout()\n",
    "plt.grid()\n",
    "plt.savefig(\"after_new_spec2.png\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dea5760c-6fc9-4ec2-99f4-099c669a3de9",
   "metadata": {},
   "source": [
    "Константно-добротное преобразование (CQT) — это частотно-временное представление, аппроксимирующее слуховое восприятие высоты звука человеком. Он особенно полезен для анализа музыкальных аудиосигналов и применяется в транскрипции, оценке высоты тона и задачах анализа музыки."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "a1590501-6224-449f-bf71-fbe797d46fb0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 313132 characters]",
      "text/plain": [
       "<Figure size 1000x600 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Load the built-in \"jazz\" audio file\n",
    "import numpy as np\n",
    "audio, sr = librosa.load('out.wav')#(librosa.example('trumpet'))\n",
    "\n",
    "# Compute the CQT representation\n",
    "cqt = librosa.cqt(audio, sr=sr)\n",
    "\n",
    "# Display the CQT representation\n",
    "plt.figure(figsize=(10, 6))\n",
    "librosa.display.specshow(librosa.amplitude_to_db(np.abs(cqt), ref=np.max), sr=sr, x_axis='time', y_axis='cqt_note')\n",
    "plt.colorbar(format='%+2.0f dB')\n",
    "plt.title('Constant-Q Transform (CQT)')\n",
    "plt.tight_layout()\n",
    "plt.grid()\n",
    "plt.savefig(\"after_new_spec3.png\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "def7768d-a7d8-4dde-97bd-9bf6dd46406d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Shape of the waveform: torch.Size([1, 2183227])\n",
      "\n",
      "Sampling rate of the audio file: 16000\n"
     ]
    }
   ],
   "source": [
    "sample_wav_file = \"out.wav\"\n",
    "\n",
    "waveform, sample_rate = torchaudio.load(sample_wav_file)\n",
    "print(f\"Shape of the waveform: {waveform.size()}\\n\")\n",
    "print(f\"Sampling rate of the audio file: {sample_rate}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 116,
   "id": "0409688e-431f-4d2c-9607-4bcbce437966",
   "metadata": {},
   "outputs": [],
   "source": [
    "save_path = \"save_erika.wav\" \n",
    "# torchaudio.save(save_path, waveform, sample_rate, encoding=\"PCM_S\", bits_per_sample=16, format=\"wav\")\n",
    "torchaudio.save(save_path, waveform, sample_rate, bits_per_sample=8, format=\"wav\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "03c852f1-2e17-41e5-b214-9421ea13b1ec",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 34024 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "def plot_waveform(waveform, sample_rate, title = \"Waveform\"):\n",
    "  waveform = waveform.numpy()\n",
    "  num_channels, num_frames = waveform.shape\n",
    "  time = np.arange(0, num_frames) / sample_rate\n",
    "\n",
    "  fig, axes = plt.subplots(num_channels, 1)\n",
    "  \n",
    "  if num_channels == 1:\n",
    "    axes = [axes]\n",
    "  for ch in range(num_channels):\n",
    "    axes[ch].plot(time, waveform[ch])\n",
    "    axes[ch].grid(True)\n",
    "\n",
    "    if num_channels > 1:\n",
    "      axes[ch].set_ylabel(f\"Channel: {ch+1}\")\n",
    "  plt.suptitle(title)\n",
    "  plt.show(block = False)\n",
    "\n",
    "plot_waveform(waveform, sample_rate)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fd9dc9c4-c435-4481-807b-b16dd409ea53",
   "metadata": {},
   "source": [
    "Спектрограмма — это визуальное представление частотного состава звукового сигнала во времени. Спектрограмма вычисляется путем применения преобразования Фурье к осциллограмме.\n",
    "Например, для создания спектрограммы аудиосэмпла с помощью torchaudio можно использовать преобразование «Спектрограмма» из модуля torchaudio.transforms.\n",
    "torchaudio.transform.Spectrogram принимает следующие аргументы:\n",
    "n_fft - Определяет размер быстрого преобразования Фурье.\n",
    "hop_length - Длина перехода между короткими окнами преобразования Фурье.\n",
    "center - Заполняет осциллограмму с обеих сторон таким образом, чтобы t-й кадр был центрирован в точке t x hop_length.\n",
    "pad_mode = Управляет методом заполнения, используемым, когда center имеет значение True."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "fee2c690-185f-424a-9352-30dacf65fd49",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torchaudio.transforms as T\n",
    "\n",
    "n_fft = 1024\n",
    "hop_length = 512\n",
    "\n",
    "spectrogram = T.Spectrogram(n_fft=n_fft,\n",
    "                            hop_length=hop_length,\n",
    "                            center=True,\n",
    "                            pad_mode=\"reflect\",\n",
    "                            power=2.0)\n",
    "spec = spectrogram(waveform)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "7e3c99fc-f612-420e-bb8e-67bd5f2e75cc",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 307776 characters]",
      "text/plain": [
       "<Figure size 640x480 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "def plot_spectrogram(spec, title=None, ylabel='freq_bin', aspect='auto', xmax=None):\n",
    "  fig, axs = plt.subplots(1, 1)\n",
    "  axs.set_title(title or 'Spectrogram (db)')\n",
    "  axs.set_ylabel(ylabel)\n",
    "  axs.set_xlabel('frame')\n",
    "  im = axs.imshow(librosa.power_to_db(spec), origin='lower', aspect=aspect)\n",
    "  if xmax:\n",
    "    axs.set_xlim((0, xmax))\n",
    "  fig.colorbar(im, ax=axs)\n",
    "  plt.savefig(\"after_new_spec4.png\")\n",
    "  plt.show(block=False)\n",
    "\n",
    "plot_spectrogram(spec[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "511d0e08-920e-492e-af64-26335659f3d2",
   "metadata": {},
   "source": [
    "Мел-спектрограмма — это спектрограмма, которая была преобразована с использованием меловой частотной шкалы, которая более тесно связана с человеческим восприятием высоты тона, чем линейная шкала частот.\n",
    "Для создания спектрограммы mel с помощью torchaudio можно использовать преобразование MelSpectrogram из модуля torchaudio.transforms. Преобразование MelSpectrogram принимает форму волны звукового образца в качестве входных данных и возвращает тензор, представляющий mel-спектрограмму аудиосэмпла."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "98acf014-0f67-47b3-bf03-46d2380c8656",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 248388 characters]",
      "text/plain": [
       "<Figure size 640x480 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "n_fft = 1024\n",
    "hop_length = 512\n",
    "n_mels = 128\n",
    "\n",
    "mel_spectrogram = T.MelSpectrogram(sample_rate=sample_rate,\n",
    "                                   n_fft=n_fft,\n",
    "                                   hop_length=hop_length,\n",
    "                                   center=True,\n",
    "                                   pad_mode=\"reflect\",\n",
    "                                   power=2.0,\n",
    "                                   norm='slaney',\n",
    "                                   #onesided=True,\n",
    "                                   n_mels=n_mels,\n",
    "                                   mel_scale=\"htk\")\n",
    "\n",
    "melspec = mel_spectrogram(waveform)\n",
    "plot_spectrogram(melspec[0], title=\"MelSpectrogram\", ylabel='mel freq')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0e5bfcd8-6987-44ec-9831-b84d95473382",
   "metadata": {},
   "source": [
    "Часто бывает полезно восстановить исходную форму звукового образца из его спектрограммы.  \n",
    "\n",
    "\n",
    "Одним из методов для этого является алгоритм Гриффина-Лима, который итеративно реконструирует форму сигнала по спектрограмме с использованием аппроксимации спектральной величины. Например, для восстановления осциллограммы из спектрограммы с помощью алгоритма Гриффина-Лима в torchaudio можно использовать преобразование GriffinLim из модуля torchaudio.transforms.\n",
    "\n",
    "\n",
    "Алгоритм Гриффина-Лима (GLA), метод фазовой реконструкции, основан на избыточности, присущей кратковременному преобразованию Фурье. Повторение двух проекций помогает обеспечить согласованность спектрограммы; спектрограмма считается согласованной, когда сохраняется ее межбункерная зависимость, возникающая в результате избыточности STFT. GLA основана только на согласованности и игнорирует предварительную информацию о целевом сигнале. Преобразование GriffinLim принимает спектрограмму аудиосэмпла в качестве входных данных и возвращает восстановленную форму волны аудиосэмпла."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "24c217ef-8c74-44f7-ba84-17639499f89c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 36560 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "n_fft = 1024\n",
    "hop_length = 512\n",
    "\n",
    "\n",
    "griffin_lim = T.GriffinLim(n_fft=n_fft,\n",
    "                           hop_length=hop_length)\n",
    "\n",
    "waveform = griffin_lim(spec)\n",
    "plot_waveform(waveform, sample_rate, title = \"Reconstructed using GriffinLim\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 123,
   "id": "2de6f0f3-d39c-425d-b83f-49ce52e4fbcf",
   "metadata": {},
   "outputs": [],
   "source": [
    "save_path = \"Reconstructed_using_GriffinLim.wav\" \n",
    "# torchaudio.save(save_path, waveform, sample_rate, encoding=\"PCM_S\", bits_per_sample=16, format=\"wav\")\n",
    "torchaudio.save(save_path, waveform, sample_rate, bits_per_sample=8, format=\"wav\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "abefc685-d4fc-4bb9-a01a-8676f797ab45",
   "metadata": {},
   "source": [
    "Извлечение признаков — это извлечение релевантных признаков или характеристик из необработанных данных, которые можно использовать в качестве входных данных для модели машинного обучения. \n",
    "\n",
    "\n",
    "Например, в контексте аудиоданных это может включать извлечение из аудиосигнала таких признаков, как спектральные характеристики, высота тона или громкость. TorchAudio предоставляет 2 модуля: torchaudio.functional и torchaudio.transforms. Функциональный модуль реализует функции как автономную функцию, в то время как модуль transforms реализует функции объектно-ориентированным образом. "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "89d95042-6dbd-4cd3-8718-936f2105e1bb",
   "metadata": {},
   "source": [
    "Банк фильтров Mel представляет собой набор фильтров, разлагающих аудиосигнал на ряд частотных диапазонов.\n",
    "\n",
    "\n",
    "Каждый фильтр в банке фильтров предназначен для пропускания определенного диапазона частот и ослабления всех остальных частот.\n",
    "\n",
    "\n",
    "Они особенно полезны для задач, связанных с моделированием спектральных характеристик звукового сигнала, так как позволяют представить сигнал в компактном и содержательном виде.\n",
    "\n",
    "\n",
    "Мы используем torchaudio.functional.melscale_fbanks. Эта функция не требует входного аудио и возвращает треугольные банки фильтров размером (n_freqs, n_mels). Функция принимает следующие аргументы: n_freqs - Количество частот для выделения/применения. f_min - Минимальная частота f_max - Максимальная частота norm - Если slaney, разделите треугольные веса mel на ширину полосы mel."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "b1172c64-e108-4390-a623-3bc1aa7f8433",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 46344 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import torchaudio.functional as F\n",
    "\n",
    "n_fft = 256\n",
    "n_mels = 64\n",
    "sample_rate = 6000\n",
    "\n",
    "mel_filters = F.melscale_fbanks(\n",
    "    int(n_fft // 2 + 1),\n",
    "    n_mels=n_mels,\n",
    "    f_min=0.0,\n",
    "    f_max=sample_rate / 2.0,\n",
    "    sample_rate=sample_rate,\n",
    "    norm=\"slaney\")\n",
    "\n",
    "def plot_fbank(fbank, title=None):\n",
    "    fig, axs = plt.subplots(1, 1)\n",
    "    axs.set_title(title or \"Filter bank\")\n",
    "    axs.imshow(fbank, aspect=\"auto\")\n",
    "    axs.set_ylabel(\"frequency bin\")\n",
    "    axs.set_xlabel(\"mel bin\")\n",
    "    plt.savefig(\"before_new_spec5.png\")\n",
    "    plt.show(block=False)\n",
    "\n",
    "plot_fbank(mel_filters, \"Mel Filter Bank - torchaudio\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b2e4e138-ddf7-4dac-9de5-549e20b6fb96",
   "metadata": {},
   "source": [
    "Мел-частотные цепстральные коэффициенты (MFCC) — это общее представление спектральной огибающей звука, которое описывает, как мощность звука распределяется по различным частотам. Преобразование MFCC реализовано в torchaudio.transforms.MFCC, этот класс принимает следующие аргументы: n_mfcc - Количество коэффициентов MFC, сохраняемых после преобразования. melkwargs - Это аргументы для создания MelSpectrogram."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "09e15f99-5be6-407c-b166-65a7cc5ea379",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 518132 characters]",
      "text/plain": [
       "<Figure size 640x480 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "n_fft = 2048\n",
    "hop_length = 512\n",
    "n_mels = 256\n",
    "n_mfcc = 256\n",
    "\n",
    "mfcc_transform = T.MFCC(sample_rate=sample_rate,\n",
    "                        n_mfcc=n_mfcc,\n",
    "                        melkwargs={\"n_fft\": n_fft,\n",
    "                                   \"n_mels\": n_mels,\n",
    "                                   \"hop_length\": hop_length,\n",
    "                                   \"mel_scale\": \"htk\"})\n",
    "\n",
    "mfcc = mfcc_transform(waveform)\n",
    "plot_spectrogram(mfcc[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "211e317c-cd96-417f-99c0-750d3c920fcd",
   "metadata": {},
   "source": [
    "Логарифмические частотные цепстральные коэффициенты (LFCC) — это вариант MFCC, который во многом похож, но вместо использования линейной шкалы частот используется логарифмическая шкала частот. В torchaudio преобразование LFCC реализовано в классе torchaudio.transforms.LFCC. Этот класс имеет API, аналогичный преобразованию MFCC, и принимает в качестве входных данных 1D- или 2D-тензор, представляющий сигнал или пакет сигналов, и возвращает 2D-тензор LFCC. Кроме того, преобразование имеет несколько необязательных аргументов, которые позволяют настроить поведение вычисления LFCC."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "7417ce83-8179-43f8-bdc1-8da24044e4c0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 494968 characters]",
      "text/plain": [
       "<Figure size 640x480 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "n_fft = 2048\n",
    "hop_length = 512\n",
    "n_lfcc = 256\n",
    "\n",
    "lfcc_transform = T.LFCC(sample_rate=sample_rate,\n",
    "                        n_lfcc=n_lfcc,\n",
    "                        speckwargs={\"n_fft\": n_fft,\n",
    "                                    \"hop_length\": hop_length})\n",
    "\n",
    "lfcc = lfcc_transform(waveform)\n",
    "plot_spectrogram(lfcc[0])"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
