{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import random\n",
    "import itertools\n",
    "from typing import Dict, Set, Tuple\n",
    "\n",
    "def create_label_encoder(corruptions_dict: dict) -> Dict[str, int]:\n",
    "    \"\"\"\n",
    "    Create a mapping from all possible corruption parameter combinations to indices.\n",
    "    For corruptions with multiple parameters, creates labels for all combinations.\n",
    "    \"\"\"\n",
    "    label_to_idx = {}\n",
    "    idx = 0\n",
    "    \n",
    "    for corruption_name, corruption_info in corruptions_dict.items():\n",
    "        params = corruption_info[\"params\"]\n",
    "        \n",
    "        # If corruption has no parameters\n",
    "        if not params:\n",
    "            label = f\"{corruption_name}\"\n",
    "            label_to_idx[label] = idx\n",
    "            idx += 1\n",
    "            continue\n",
    "            \n",
    "        # Get all parameter names and their possible values\n",
    "        param_names = list(params.keys())\n",
    "        param_values = [params[name] for name in param_names]\n",
    "        \n",
    "        # Generate all possible combinations of parameter values\n",
    "        for values in itertools.product(*param_values):\n",
    "            # Create parameter string\n",
    "            param_str = \",\".join(\n",
    "                f\"{name}={value}\" \n",
    "                for name, value in zip(param_names, values)\n",
    "            )\n",
    "            label = f\"{corruption_name}:{param_str}\"\n",
    "            label_to_idx[label] = idx\n",
    "            idx += 1\n",
    "    \n",
    "    return label_to_idx\n",
    "\n",
    "# Similarly, we need to update how we generate labels in the preset function\n",
    "def generate_random_preset(\n",
    "    corruptions_dict: dict,\n",
    "    min_corruptions: int = 0,\n",
    "    max_corruptions: int = 4,\n",
    "    no_corruption_probability: float = 0.1\n",
    ") -> Tuple[Dict, Set[str]]:\n",
    "    \"\"\"\n",
    "    Generate a random preset and its corresponding labels.\n",
    "    Handles corruptions with multiple parameters.\n",
    "    \"\"\"\n",
    "    if random.random() < no_corruption_probability:\n",
    "        return {}, set()\n",
    "    \n",
    "    n_corruptions = random.randint(min_corruptions, max_corruptions)\n",
    "    if n_corruptions == 0:\n",
    "        return {}, set()\n",
    "        \n",
    "    selected_corruptions = random.sample(list(corruptions_dict.keys()), n_corruptions)\n",
    "    preset = {}\n",
    "    labels = set()\n",
    "    \n",
    "    for corruption_name in selected_corruptions:\n",
    "        corruption_info = corruptions_dict[corruption_name]\n",
    "        params = {}\n",
    "        \n",
    "        # If no parameters, just add the corruption name\n",
    "        if not corruption_info[\"params\"]:\n",
    "            preset[corruption_name] = {\"params\": {}}\n",
    "            labels.add(corruption_name)\n",
    "            continue\n",
    "            \n",
    "        # Generate parameters and create combined label\n",
    "        param_strs = []\n",
    "        for param_name, param_values in corruption_info[\"params\"].items():\n",
    "            param_value = random.choice(param_values)\n",
    "            params[param_name] = param_value\n",
    "            param_strs.append(f\"{param_name}={param_value}\")\n",
    "            \n",
    "        preset[corruption_name] = {\"params\": params}\n",
    "        # Create single label with all parameters\n",
    "        label = f\"{corruption_name}:{','.join(param_strs)}\"\n",
    "        labels.add(label)\n",
    "    \n",
    "    return preset, labels\n",
    "\n",
    "def labels_to_tensor(\n",
    "    labels: Set[str], label_encoder: Dict[str, int], device: str = \"cpu\"\n",
    ") -> torch.Tensor:\n",
    "    \"\"\"\n",
    "    Convert a set of labels to a binary tensor.\n",
    "    \"\"\"\n",
    "    output = torch.zeros(len(label_encoder), dtype=torch.float32, device=device)\n",
    "    for label in labels:\n",
    "        if label in label_encoder:\n",
    "            output[label_encoder[label]] = 1.0\n",
    "    return output\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torchaudio\n",
    "import numpy as np\n",
    "\n",
    "\n",
    "def apply_stereo_to_mono(audio: torch.Tensor, sample_rate: float):\n",
    "    return audio.mean(dim=0, keepdims=True).repeat(2, 1)\n",
    "\n",
    "\n",
    "def apply_channel_imbalance(audio: torch.Tensor, sample_rate: float, imbalance: float):\n",
    "    if not -1 <= imbalance <= 1 or audio.shape[-2] != 2:\n",
    "        raise ValueError(\"Invalid input\")\n",
    "    out = audio.clone()\n",
    "    l_gain, r_gain = (1.0 - imbalance, 1.0) if imbalance > 0 else (1.0, 1.0 + imbalance)\n",
    "    out[0, :], out[1, :] = out[0, :] * l_gain, out[1, :] * r_gain\n",
    "    return out\n",
    "\n",
    "\n",
    "def apply_highpass(audio: torch.Tensor, sample_rate: float, cutoff_hz: float):\n",
    "    return torchaudio.functional.highpass_biquad(audio, sample_rate, cutoff_hz)\n",
    "\n",
    "\n",
    "def apply_lowpass(audio: torch.Tensor, sample_rate: float, cutoff_hz: float):\n",
    "    return torchaudio.functional.lowpass_biquad(audio, sample_rate, cutoff_hz)\n",
    "\n",
    "\n",
    "def apply_bandpass(\n",
    "    audio: torch.Tensor, sample_rate: float, lowcut_hz: float, highcut_hz: float\n",
    "):\n",
    "    return torchaudio.functional.bandpass_biquad(\n",
    "        audio, sample_rate, lowcut_hz, highcut_hz\n",
    "    )\n",
    "\n",
    "\n",
    "def apply_tanh_distortion(audio: torch.Tensor, sample_rate: float, gain_db: float):\n",
    "    gain_lin = 10 ** (gain_db / 20.0)\n",
    "    return torch.tanh(audio * gain_lin)\n",
    "\n",
    "\n",
    "def apply_clipping_distortion(audio: torch.Tensor, sample_rate: float, gain_db: float):\n",
    "    gain_lin = 10 ** (gain_db / 20.0)\n",
    "    return (audio * gain_lin).clamp(-1, 1)\n",
    "\n",
    "\n",
    "def apply_white_noise(audio: torch.Tensor, sample_rate: float, gain_db: float):\n",
    "    gain_lin = 10 ** (gain_db / 20.0)\n",
    "    noise = gain_lin * torch.randn(audio.shape)\n",
    "    return noise + audio\n",
    "\n",
    "\n",
    "def apply_audio_codec(audio: torch.Tensor, sample_rate: float, bit_rate: int):\n",
    "    effector = torchaudio.io.AudioEffector(\n",
    "        format=\"mp3\",\n",
    "        codec_config=torchaudio.io.CodecConfig(bit_rate=bit_rate),\n",
    "    )\n",
    "    return effector.apply(audio.T, sample_rate).T\n",
    "\n",
    "\n",
    "def apply_hum(audio: torch.Tensor, sample_rate: float, amplitude: float):\n",
    "    t = torch.arange(audio.shape[-1], device=audio.device) / sample_rate\n",
    "    hum = amplitude * torch.sin(2 * np.pi * 60 * t)\n",
    "    # Add harmonics at 120Hz and 180Hz\n",
    "    hum += (amplitude * 0.5) * torch.sin(2 * np.pi * 120 * t)\n",
    "    hum += (amplitude * 0.25) * torch.sin(2 * np.pi * 180 * t)\n",
    "    return audio + hum.expand_as(audio)\n",
    "\n",
    "\n",
    "def apply_comb_filter(\n",
    "    audio: torch.Tensor, sample_rate: float, delay_ms: float, gain_db: float\n",
    "):\n",
    "    delay_samples = int(delay_ms * sample_rate / 1000)\n",
    "    gain_lin = 10 ** (gain_db / 20.0)\n",
    "    delayed = torch.roll(audio, shifts=delay_samples, dims=-1)\n",
    "    return audio + gain_lin * delayed\n",
    "\n",
    "\n",
    "def apply_reduce_bit_depth(audio: torch.Tensor, sample_rate: float, bits: int = 8):\n",
    "    steps = 2**bits\n",
    "    return (audio.clamp(-1, 1) * 0.5 + 0.5) * (steps - 1) // 1 / (steps - 1) * 2 - 1\n",
    "\n",
    "\n",
    "def apply_add_clicks(audio: torch.Tensor, sample_rate: float, density: float = 0.001):\n",
    "    mask = torch.rand_like(audio) < density\n",
    "    clicks = (torch.rand_like(audio) * 2 - 1) * mask\n",
    "    return audio + clicks\n",
    "\n",
    "\n",
    "def apply_reverb(\n",
    "    audio: torch.Tensor,\n",
    "    sample_rate: float,\n",
    "    reverberance: int = 50,  # 0-100\n",
    "    hf_damping: int = 50,  # 0-100\n",
    "    room_scale: int = 100,  # 0-100\n",
    "    stereo_depth: int = 100,  # 0-100\n",
    "    pre_delay: float = 0,  # 0-200ms\n",
    "    wet_gain: float = 0,\n",
    "):  # -10-10 dB\n",
    "\n",
    "    effects = [\n",
    "        [\n",
    "            \"reverb\",\n",
    "            str(reverberance),\n",
    "            str(hf_damping),\n",
    "            str(room_scale),\n",
    "            str(stereo_depth),\n",
    "            str(pre_delay),\n",
    "            str(wet_gain),\n",
    "        ]\n",
    "    ]\n",
    "    out, _ = torchaudio.sox_effects.apply_effects_tensor(audio, sample_rate, effects)\n",
    "    return out\n",
    "\n",
    "\n",
    "\n",
    "corruptions = {\n",
    "    \"stereo_to_mono\": {\"fn\": apply_stereo_to_mono, \"params\": {}},\n",
    "    \"channel_imbalance\": {\n",
    "        \"fn\": apply_channel_imbalance,\n",
    "        \"params\": {\"imbalance\": [-1, -0.9, -0.75, -0.5, 0.5, 0.75, 0.9, 1]},\n",
    "    },\n",
    "    \"lowpass\": {\n",
    "        \"fn\": apply_lowpass,\n",
    "        \"params\": {\"cutoff_hz\": [1000, 2000, 4000, 6000, 8000, 10000]},\n",
    "    },\n",
    "    \"highpass\": {\n",
    "        \"fn\": apply_highpass,\n",
    "        \"params\": {\"cutoff_hz\": [60, 100, 250, 500, 1000, 2000, 4000]},\n",
    "    },\n",
    "    \"tanh_distortion\": {\n",
    "        \"fn\": apply_tanh_distortion,\n",
    "        \"params\": {\"gain_db\": [8, 12, 16, 20, 24, 32]},\n",
    "    },\n",
    "    \"clipping_distortion\": {\n",
    "        \"fn\": apply_clipping_distortion,\n",
    "        \"params\": {\"gain_db\": [8, 12, 16, 20, 24, 32]},\n",
    "    },\n",
    "    \"white_noise\": {\n",
    "        \"fn\": apply_white_noise,\n",
    "        \"params\": {\"gain_db\": [-52, -48, -42, -36]},\n",
    "    },\n",
    "    \"hum\": {\"fn\": apply_hum, \"params\": {\"amplitude\": [0.01, 0.02, 0.04, 0.08]}},\n",
    "    \"comb_filter\": {\n",
    "        \"fn\": apply_comb_filter,\n",
    "        \"params\": {\n",
    "            \"delay_ms\": [0.1, 0.4, 0.8, 1.6, 3.2, 6.4, 12.8, 25.6],\n",
    "            \"gain_db\": [6, 12, 24],\n",
    "        },\n",
    "    },\n",
    "    \"reduce_bit_depth\": {\n",
    "        \"fn\": apply_reduce_bit_depth,\n",
    "        \"params\": {\"bits\": [4, 6, 8, 10, 12]},\n",
    "    },\n",
    "    \"add_clicks\": {\n",
    "        \"fn\": apply_add_clicks,\n",
    "        \"params\": {\"density\": [0.00001, 0.0001, 0.001, 0.01]},\n",
    "    },\n",
    "    \"reverb\": {\n",
    "        \"fn\": apply_reverb,\n",
    "        \"params\": {\n",
    "            \"reverberance\": [10, 50, 100],\n",
    "            \"hf_damping\": [75],\n",
    "            \"room_scale\": [10, 50, 100],\n",
    "            \"stereo_depth\": [100],\n",
    "            \"pre_delay\": [25],\n",
    "            \"wet_gain\": [-10, -5, 0],\n",
    "        },\n",
    "    },\n",
    "    \"audio_codec\": {\n",
    "        \"fn\": apply_audio_codec,\n",
    "        \"params\": {\n",
    "            \"bit_rate\": [\n",
    "                8_000,\n",
    "                16_000,\n",
    "                24_000,\n",
    "                32_000,\n",
    "                40_000,\n",
    "                48_000,\n",
    "                64_000,\n",
    "                80_000,\n",
    "                96_000,\n",
    "                112_000,\n",
    "                128_000,\n",
    "            ]\n",
    "        },\n",
    "    },\n",
    "}\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "113\n",
      "0: stereo_to_mono\n",
      "1: channel_imbalance:imbalance=-1\n",
      "2: channel_imbalance:imbalance=-0.9\n",
      "3: channel_imbalance:imbalance=-0.75\n",
      "4: channel_imbalance:imbalance=-0.5\n",
      "5: channel_imbalance:imbalance=0.5\n",
      "6: channel_imbalance:imbalance=0.75\n",
      "7: channel_imbalance:imbalance=0.9\n",
      "8: channel_imbalance:imbalance=1\n",
      "9: lowpass:cutoff_hz=1000\n",
      "10: lowpass:cutoff_hz=2000\n",
      "11: lowpass:cutoff_hz=4000\n",
      "12: lowpass:cutoff_hz=6000\n",
      "13: lowpass:cutoff_hz=8000\n",
      "14: lowpass:cutoff_hz=10000\n",
      "15: highpass:cutoff_hz=60\n",
      "16: highpass:cutoff_hz=100\n",
      "17: highpass:cutoff_hz=250\n",
      "18: highpass:cutoff_hz=500\n",
      "19: highpass:cutoff_hz=1000\n",
      "20: highpass:cutoff_hz=2000\n",
      "21: highpass:cutoff_hz=4000\n",
      "22: tanh_distortion:gain_db=8\n",
      "23: tanh_distortion:gain_db=12\n",
      "24: tanh_distortion:gain_db=16\n",
      "25: tanh_distortion:gain_db=20\n",
      "26: tanh_distortion:gain_db=24\n",
      "27: tanh_distortion:gain_db=32\n",
      "28: clipping_distortion:gain_db=8\n",
      "29: clipping_distortion:gain_db=12\n",
      "30: clipping_distortion:gain_db=16\n",
      "31: clipping_distortion:gain_db=20\n",
      "32: clipping_distortion:gain_db=24\n",
      "33: clipping_distortion:gain_db=32\n",
      "34: white_noise:gain_db=-52\n",
      "35: white_noise:gain_db=-48\n",
      "36: white_noise:gain_db=-42\n",
      "37: white_noise:gain_db=-36\n",
      "38: hum:amplitude=0.01\n",
      "39: hum:amplitude=0.02\n",
      "40: hum:amplitude=0.04\n",
      "41: hum:amplitude=0.08\n",
      "42: comb_filter:delay_ms=0.1,gain_db=6\n",
      "43: comb_filter:delay_ms=0.1,gain_db=12\n",
      "44: comb_filter:delay_ms=0.1,gain_db=24\n",
      "45: comb_filter:delay_ms=0.4,gain_db=6\n",
      "46: comb_filter:delay_ms=0.4,gain_db=12\n",
      "47: comb_filter:delay_ms=0.4,gain_db=24\n",
      "48: comb_filter:delay_ms=0.8,gain_db=6\n",
      "49: comb_filter:delay_ms=0.8,gain_db=12\n",
      "50: comb_filter:delay_ms=0.8,gain_db=24\n",
      "51: comb_filter:delay_ms=1.6,gain_db=6\n",
      "52: comb_filter:delay_ms=1.6,gain_db=12\n",
      "53: comb_filter:delay_ms=1.6,gain_db=24\n",
      "54: comb_filter:delay_ms=3.2,gain_db=6\n",
      "55: comb_filter:delay_ms=3.2,gain_db=12\n",
      "56: comb_filter:delay_ms=3.2,gain_db=24\n",
      "57: comb_filter:delay_ms=6.4,gain_db=6\n",
      "58: comb_filter:delay_ms=6.4,gain_db=12\n",
      "59: comb_filter:delay_ms=6.4,gain_db=24\n",
      "60: comb_filter:delay_ms=12.8,gain_db=6\n",
      "61: comb_filter:delay_ms=12.8,gain_db=12\n",
      "62: comb_filter:delay_ms=12.8,gain_db=24\n",
      "63: comb_filter:delay_ms=25.6,gain_db=6\n",
      "64: comb_filter:delay_ms=25.6,gain_db=12\n",
      "65: comb_filter:delay_ms=25.6,gain_db=24\n",
      "66: reduce_bit_depth:bits=4\n",
      "67: reduce_bit_depth:bits=6\n",
      "68: reduce_bit_depth:bits=8\n",
      "69: reduce_bit_depth:bits=10\n",
      "70: reduce_bit_depth:bits=12\n",
      "71: add_clicks:density=1e-05\n",
      "72: add_clicks:density=0.0001\n",
      "73: add_clicks:density=0.001\n",
      "74: add_clicks:density=0.01\n",
      "75: reverb:reverberance=10,hf_damping=75,room_scale=10,stereo_depth=100,pre_delay=25,wet_gain=-10\n",
      "76: reverb:reverberance=10,hf_damping=75,room_scale=10,stereo_depth=100,pre_delay=25,wet_gain=-5\n",
      "77: reverb:reverberance=10,hf_damping=75,room_scale=10,stereo_depth=100,pre_delay=25,wet_gain=0\n",
      "78: reverb:reverberance=10,hf_damping=75,room_scale=50,stereo_depth=100,pre_delay=25,wet_gain=-10\n",
      "79: reverb:reverberance=10,hf_damping=75,room_scale=50,stereo_depth=100,pre_delay=25,wet_gain=-5\n",
      "80: reverb:reverberance=10,hf_damping=75,room_scale=50,stereo_depth=100,pre_delay=25,wet_gain=0\n",
      "81: reverb:reverberance=10,hf_damping=75,room_scale=100,stereo_depth=100,pre_delay=25,wet_gain=-10\n",
      "82: reverb:reverberance=10,hf_damping=75,room_scale=100,stereo_depth=100,pre_delay=25,wet_gain=-5\n",
      "83: reverb:reverberance=10,hf_damping=75,room_scale=100,stereo_depth=100,pre_delay=25,wet_gain=0\n",
      "84: reverb:reverberance=50,hf_damping=75,room_scale=10,stereo_depth=100,pre_delay=25,wet_gain=-10\n",
      "85: reverb:reverberance=50,hf_damping=75,room_scale=10,stereo_depth=100,pre_delay=25,wet_gain=-5\n",
      "86: reverb:reverberance=50,hf_damping=75,room_scale=10,stereo_depth=100,pre_delay=25,wet_gain=0\n",
      "87: reverb:reverberance=50,hf_damping=75,room_scale=50,stereo_depth=100,pre_delay=25,wet_gain=-10\n",
      "88: reverb:reverberance=50,hf_damping=75,room_scale=50,stereo_depth=100,pre_delay=25,wet_gain=-5\n",
      "89: reverb:reverberance=50,hf_damping=75,room_scale=50,stereo_depth=100,pre_delay=25,wet_gain=0\n",
      "90: reverb:reverberance=50,hf_damping=75,room_scale=100,stereo_depth=100,pre_delay=25,wet_gain=-10\n",
      "91: reverb:reverberance=50,hf_damping=75,room_scale=100,stereo_depth=100,pre_delay=25,wet_gain=-5\n",
      "92: reverb:reverberance=50,hf_damping=75,room_scale=100,stereo_depth=100,pre_delay=25,wet_gain=0\n",
      "93: reverb:reverberance=100,hf_damping=75,room_scale=10,stereo_depth=100,pre_delay=25,wet_gain=-10\n",
      "94: reverb:reverberance=100,hf_damping=75,room_scale=10,stereo_depth=100,pre_delay=25,wet_gain=-5\n",
      "95: reverb:reverberance=100,hf_damping=75,room_scale=10,stereo_depth=100,pre_delay=25,wet_gain=0\n",
      "96: reverb:reverberance=100,hf_damping=75,room_scale=50,stereo_depth=100,pre_delay=25,wet_gain=-10\n",
      "97: reverb:reverberance=100,hf_damping=75,room_scale=50,stereo_depth=100,pre_delay=25,wet_gain=-5\n",
      "98: reverb:reverberance=100,hf_damping=75,room_scale=50,stereo_depth=100,pre_delay=25,wet_gain=0\n",
      "99: reverb:reverberance=100,hf_damping=75,room_scale=100,stereo_depth=100,pre_delay=25,wet_gain=-10\n",
      "100: reverb:reverberance=100,hf_damping=75,room_scale=100,stereo_depth=100,pre_delay=25,wet_gain=-5\n",
      "101: reverb:reverberance=100,hf_damping=75,room_scale=100,stereo_depth=100,pre_delay=25,wet_gain=0\n",
      "102: audio_codec:bit_rate=8000\n",
      "103: audio_codec:bit_rate=16000\n",
      "104: audio_codec:bit_rate=24000\n",
      "105: audio_codec:bit_rate=32000\n",
      "106: audio_codec:bit_rate=40000\n",
      "107: audio_codec:bit_rate=48000\n",
      "108: audio_codec:bit_rate=64000\n",
      "109: audio_codec:bit_rate=80000\n",
      "110: audio_codec:bit_rate=96000\n",
      "111: audio_codec:bit_rate=112000\n",
      "112: audio_codec:bit_rate=128000\n"
     ]
    }
   ],
   "source": [
    "label_encoder = create_label_encoder(corruptions)\n",
    "print(len(label_encoder))\n",
    "\n",
    "for i, label in enumerate(label_encoder):\n",
    "    print(f\"{i}: {label}\")\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'tanh_distortion': {'params': {'gain_db': 16}}, 'add_clicks': {'params': {'density': 1e-05}}}\n",
      "{'add_clicks:density=1e-05', 'tanh_distortion:gain_db=16'}\n"
     ]
    }
   ],
   "source": [
    "preset, labels = generate_random_preset(corruptions)\n",
    "print(preset)\n",
    "print(labels)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "corruptions_config = {\n",
    "    \"stereo_to_mono\": {\n",
    "        \"params\": {}\n",
    "    },\n",
    "    \"channel_imbalance\": {\n",
    "        \"params\": {\n",
    "            \"imbalance\": [-1, -0.9, -0.75, -0.5, 0.5, 0.75, 0.9, 1]\n",
    "        }\n",
    "    },\n",
    "    \"lowpass\": {\n",
    "        \"params\": {\n",
    "            \"cutoff_hz\": [1000, 2000, 4000, 6000, 8000, 10000]\n",
    "        }\n",
    "    },\n",
    "    \"highpass\": {\n",
    "        \"params\": {\n",
    "            \"cutoff_hz\": [60, 100, 250, 500, 1000, 2000, 4000]\n",
    "        }\n",
    "    },\n",
    "    \"tanh_distortion\": {\n",
    "        \"params\": {\n",
    "            \"gain_db\": [8, 12, 16, 20, 24, 32]\n",
    "        }\n",
    "    },\n",
    "    \"clipping_distortion\": {\n",
    "        \"params\": {\n",
    "            \"gain_db\": [8, 12, 16, 20, 24, 32]\n",
    "        }\n",
    "    },\n",
    "    \"white_noise\": {\n",
    "        \"params\": {\n",
    "            \"gain_db\": [-52, -48, -42, -36]\n",
    "        }\n",
    "    },\n",
    "    \"hum\": {\n",
    "        \"params\": {\n",
    "            \"amplitude\": [0.01, 0.02, 0.04, 0.08]\n",
    "        }\n",
    "    },\n",
    "    \"comb_filter\": {\n",
    "        \"params\": {\n",
    "            \"delay_ms\": [0.1, 0.4, 0.8, 1.6, 3.2, 6.4, 12.8, 25.6],\n",
    "            \"gain_db\": [3, 6, 12, 24]\n",
    "        }\n",
    "    },\n",
    "    \"reduce_bit_depth\": {\n",
    "        \"params\": {\n",
    "            \"bits\": [4, 6, 8, 10, 12]\n",
    "        }\n",
    "    },\n",
    "    \"add_clicks\": {\n",
    "        \"params\": {\n",
    "            \"density\": [0.00001, 0.0001, 0.001, 0.01]\n",
    "        }\n",
    "    },\n",
    "    \"reverb\": {\n",
    "        \"params\": {\n",
    "            \"reverberance\": [0, 10, 25, 50, 100],\n",
    "            \"hf_damping\": [75],\n",
    "            \"room_scale\": [0, 10, 25, 50, 100],\n",
    "            \"stereo_depth\": [100],\n",
    "            \"pre_delay\": [25],\n",
    "            \"wet_gain\": [-10, -5, 0, 5, 10]\n",
    "        }\n",
    "    },\n",
    "    \"audio_codec\": {\n",
    "        \"params\": {\n",
    "            \"bit_rate\": [\n",
    "                8000, 16000, 24000, 32000, 40000, 48000,\n",
    "                64000, 80000, 96000, 112000, 128000\n",
    "            ]\n",
    "        }\n",
    "    }\n",
    "}\n",
    "\n",
    "\n",
    "# Save to JSON\n",
    "import json\n",
    "\n",
    "def save_corruptions_config(config, filename):\n",
    "    with open(filename, 'w') as f:\n",
    "        json.dump(config, f, indent=4)\n",
    "\n",
    "def load_corruptions_config(filename):\n",
    "    with open(filename, 'r') as f:\n",
    "        return json.load(f)\n",
    "\n",
    "# Save config\n",
    "save_corruptions_config(corruptions_config, '/home/christian/code/christian/metadata/corruptions.json')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "suno_env",
   "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.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
