{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": [],
      "authorship_tag": "ABX9TyOW4OkTmphTrvw2IQLr+kxP",
      "include_colab_link": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/CPJKU/beat_this/blob/main/beat_this_example.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "# Beat This! inference example\n",
        "\n",
        "We first need to install and load the package."
      ],
      "metadata": {
        "id": "87X_GXfoGwmj"
      }
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "sxhsMCKdLOLO",
        "collapsed": true
      },
      "outputs": [],
      "source": [
        "# install the beat_this package\n",
        "!pip install https://github.com/CPJKU/beat_this/archive/main.zip\n",
        "\n",
        "# load the Python class for beat tracking\n",
        "from beat_this.inference import File2Beats\n",
        "from beat_this.inference import File2File"
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## Run on demo file\n",
        "\n",
        "Now that all the dependencies have been installed and imported, let's run our system.\n",
        "\n",
        "In the next cell we:\n",
        "- define the audio file we want to use as input. For now we use the example provided in the beat_this repo, but this can be changed (see instructions later);\n",
        "- load the File2Beats class that produce a list of beats and downbeats given an audio file;\n",
        "- apply the class to the audio file\n",
        "- print the position in seconds of the first 20 beats and first 20 downbeats.\n"
      ],
      "metadata": {
        "id": "_0oYbH6P6Ji7"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "!wget -c \"https://github.com/CPJKU/beat_this/raw/main/tests/It%20Don't%20Mean%20A%20Thing%20-%20Kings%20of%20Swing.mp3\"\n",
        "audio_path = \"/content/It Don't Mean A Thing - Kings of Swing.mp3\"\n",
        "\n",
        "file2beats = File2Beats(checkpoint_path=\"final0\", dbn=False)\n",
        "beats, downbeats = file2beats(audio_path)\n",
        "\n",
        "print(\"First 20 beats\", beats[:20])\n",
        "print(\"First 20 downbeats\", downbeats[:20])"
      ],
      "metadata": {
        "id": "DHT6v-a-TbZx"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "We can sonify the beats and downbeats as click on top of the audio file."
      ],
      "metadata": {
        "id": "lRjJFiexDGdn"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "import IPython.display as ipd\n",
        "import librosa\n",
        "import numpy as np\n",
        "import soundfile as sf\n",
        "\n",
        "audio, sr = sf.read(audio_path)\n",
        "# make it mono if stereo\n",
        "if len(audio.shape) > 1:\n",
        "  audio = np.mean(audio, axis=1)\n",
        "\n",
        "# sonify the beats and downbeats\n",
        "# remove the beats that are also downbeats for a nicer sonification\n",
        "beats = [b for b in beats if b not in downbeats]\n",
        "audio_beat = librosa.clicks(times = beats, sr=sr, click_freq=1000, length=len(audio))\n",
        "audio_downbeat = librosa.clicks(times = downbeats, sr=sr, click_freq=1500, length=len(audio))\n",
        "\n",
        "ipd.display(ipd.Audio(audio + audio_beat + audio_downbeat, rate=sr))"
      ],
      "metadata": {
        "id": "otG0NS_uCXSo"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "## Run on your own file\n",
        "\n",
        "If you want to run on your own audio files follow the following instructions:\n",
        "1. Click on the folder icon in the left vertical menu.\n",
        "2. Click on the \"Upload to session storage\" icon with the upward pointing arrow.\n",
        "\n",
        "    This will add an audio file to the current colab runtime (it could take some time, and you may need to refresh the file manager using the dedicated button to see the new file). You can copy the audio path by clicking on the three dots next to the file, then \"copy path\".\n",
        "\n",
        "    For example, if you upload a file called `my_song.mp3`, the path will be `/content/my_song.mp3`.\n",
        "\n",
        "3. change the `audio_path` in the cell above with the path of your uploaded audio"
      ],
      "metadata": {
        "id": "hn83Sn1pWmt5"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "You can also produce a list of beat and downbeat as tsv file, that you can download and import in Sonic Visualizer.\n",
        "\n",
        "To do this this, use the File2File function as below:"
      ],
      "metadata": {
        "id": "kP2gyplIEcWT"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "file2file = File2File(checkpoint_path=\"final0\", dbn=False)\n",
        "file2file(audio_path,output_path=\"output.beats\")"
      ],
      "metadata": {
        "id": "kTQK-d4JEbL7"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "As you can see, the system is fast enough to work in a reasonable time even on CPU.\n",
        "\n",
        "For even faster inference, you can start a GPU session in Colab!"
      ],
      "metadata": {
        "id": "1Y1d-DvXFtVz"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "## Batch processing multiple files\n",
        "\n",
        "To process multiple of your own audio files, upload them as described above, then run the `beat_this` command line tool:"
      ],
      "metadata": {
        "id": "vpoM0RvQdAMF"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "!beat_this --model final0 /content/"
      ],
      "metadata": {
        "id": "qNOLbBplc_Nq"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "It will produce a `.beats` file for every audio file that you can download again."
      ],
      "metadata": {
        "id": "_xNY_9DEdSEt"
      }
    }
  ]
}