{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Assignment 3, Direction 2 (Technical): Clone an instrument\n",
    "\n",
    "Authored by `[your AndrewID]` for 15-322/15-622 at Carnegie Mellon University.\n",
    "\n",
    "This starter code is a **suggestion**, not a requirement. You are free to\n",
    "restructure it however you like, as long as your submission satisfies the\n",
    "requirements in the assignment description."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "\n",
    "import pyquist as pq\n",
    "from pyquist.helper import db_to_amplitude, frequency_to_pitch, pitch_to_frequency\n",
    "\n",
    "# OPTION A: download from FreeSound (also gives you the attribution metadata).\n",
    "# from pyquist.web import fetch_freesound\n",
    "# source, metadata = fetch_freesound(\"https://freesound.org/people/<user>/sounds/<id>/\")\n",
    "# print(metadata[\"name\"], \"|\", metadata[\"license\"], \"|\", metadata[\"username\"])\n",
    "\n",
    "# OPTION B: load a file you downloaded yourself.\n",
    "source = pq.Audio.from_file(\"source.wav\")\n",
    "\n",
    "# Keep exactly the sound you analyzed next to your code (required: src/source.wav).\n",
    "source.write(\"source.wav\")\n",
    "pq.play(source)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# STEP 1: Analyze the amplitude envelope.\n",
    "pq.plot(source)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# STEP 2: Analyze the frequency spectrum.\n",
    "# NOTE: The spectrum during the attack transient looks quite different from the\n",
    "#       spectrum during the sustain, so choose your analysis window carefully.\n",
    "OFFSET = 0.5  # seconds into the note\n",
    "DURATION = 0.5  # seconds\n",
    "\n",
    "pq.plot_freq(source, offset=OFFSET, duration=DURATION, log_frequency=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Optional: a spectrogram shows how the spectrum evolves over the whole note.\n",
    "pq.plot_spec(source)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# STEP 3: Implement your clone. Record what you measured above as constants so\n",
    "# your code and your write-up agree.\n",
    "SOURCE_F0 = 440.0  # Hz, the fundamental frequency of the source recording\n",
    "\n",
    "\n",
    "def cloned_instrument(\n",
    "    pitch: float,\n",
    "    duration: float,\n",
    "    sample_rate: int = 44100,\n",
    "    **kwargs,\n",
    ") -> pq.Audio:\n",
    "    \"\"\"Returns `duration` seconds of your cloned instrument at MIDI `pitch`.\"\"\"\n",
    "    raise NotImplementedError(\"Implement your cloned instrument here!\")\n",
    "\n",
    "\n",
    "# Audition a single note against the original above: same pitch, same duration.\n",
    "clone = cloned_instrument(pitch=frequency_to_pitch(SOURCE_F0), duration=source.duration)\n",
    "clone.write(\"clone.wav\")\n",
    "pq.play(clone)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# STEP 4: Hear your instrument play a song.\n",
    "def play_song():\n",
    "    from pyquist.web.theorytab import fetch_theorytab\n",
    "\n",
    "    # Melody events carry {\"pitch\", \"duration\"}, matching cloned_instrument.\n",
    "    metronome, melody, harmony = fetch_theorytab(\n",
    "        \"https://hookpad.hooktheory.com/?idOfSong=d_gw_QPzrgG\"\n",
    "    )\n",
    "    # Passing `metronome` is what converts event times from beats to seconds.\n",
    "    audio = melody.render(cloned_instrument, metronome=metronome)\n",
    "    audio.write(\"song.wav\")\n",
    "    pq.play(audio)\n",
    "    return audio\n",
    "\n",
    "\n",
    "song = play_song()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "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.10.20"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
