{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install nb-black > /dev/null","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-04-03T15:28:18.210409Z","iopub.execute_input":"2022-04-03T15:28:18.211334Z","iopub.status.idle":"2022-04-03T15:28:29.474518Z","shell.execute_reply.started":"2022-04-03T15:28:18.211232Z","shell.execute_reply":"2022-04-03T15:28:29.473475Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport warnings\n\nfrom multiprocessing import Pool\n\nwarnings.filterwarnings(\"ignore\")\n\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport soundfile as sf\n\nimport librosa\nimport librosa.display\nimport IPython.display as ipd\n\nfrom tqdm.notebook import tqdm\n\nplt.style.use(\"default\")\n\n%load_ext lab_black\n%load_ext autoreload\n%autoreload 2","metadata":{"execution":{"iopub.status.busy":"2022-04-03T15:28:29.476565Z","iopub.execute_input":"2022-04-03T15:28:29.477077Z","iopub.status.idle":"2022-04-03T15:28:32.107438Z","shell.execute_reply.started":"2022-04-03T15:28:29.477038Z","shell.execute_reply":"2022-04-03T15:28:32.106485Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"librosa.__version__","metadata":{"execution":{"iopub.status.busy":"2022-04-03T15:28:32.108662Z","iopub.execute_input":"2022-04-03T15:28:32.108918Z","iopub.status.idle":"2022-04-03T15:28:32.151273Z","shell.execute_reply.started":"2022-04-03T15:28:32.10889Z","shell.execute_reply":"2022-04-03T15:28:32.150421Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def create_mel_spectrogram(audio_data, **spec_params):\n    sr, hop_length, n_fft, n_mels, fmin, fmax = [\n        spec_params[k] for k in [\"sr\", \"hop_length\", \"n_fft\", \"n_mels\", \"fmin\", \"fmax\"]\n    ]\n    melspec = librosa.feature.melspectrogram(\n        audio_data,\n        sr=sr,\n        n_fft=n_fft,\n        hop_length=hop_length,\n        n_mels=n_mels,\n        fmin=fmin,\n        fmax=fmax,\n        power=1,\n    )\n    return melspec\n\n\ndef pcen_bird(melspec, **spec_params):\n    \"\"\"\n    parameters are taken from [1]:\n        - [1] Lostanlen, et. al. Per-Channel Energy Normalization: Why and How. IEEE Signal Processing Letters, 26(1), 39-43.\n    \"\"\"\n    sr, hop_length = [spec_params[k] for k in [\"sr\", \"hop_length\"]]\n    return librosa.pcen(\n        melspec * (2 ** 31),\n        time_constant=0.06,\n        eps=1e-6,\n        gain=0.8,\n        power=0.25,\n        bias=10,\n        sr=sr,\n        hop_length=hop_length,\n    )\n\n\ndef get_fullpath(filename, audio_path=\"../input/birdclef-2022/train_audio\"):\n    return f\"{audio_path}/{filename}\"\n\n\ndef play_audio(audio_file):\n    print(f\"audio_file: {audio_file}\")\n    display(ipd.Audio(audio_file))","metadata":{"execution":{"iopub.status.busy":"2022-04-03T15:28:32.153571Z","iopub.execute_input":"2022-04-03T15:28:32.153901Z","iopub.status.idle":"2022-04-03T15:28:32.214369Z","shell.execute_reply.started":"2022-04-03T15:28:32.153859Z","shell.execute_reply":"2022-04-03T15:28:32.213379Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = pd.read_csv(\n    \"../input/birdclef-2022-train-metadata-with-audio-metadata/train_ext.csv\"\n)","metadata":{"execution":{"iopub.status.busy":"2022-04-03T15:28:32.215459Z","iopub.execute_input":"2022-04-03T15:28:32.216207Z","iopub.status.idle":"2022-04-03T15:28:32.376818Z","shell.execute_reply.started":"2022-04-03T15:28:32.216165Z","shell.execute_reply":"2022-04-03T15:28:32.376168Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Config Params","metadata":{}},{"cell_type":"code","source":"spec_params = dict(\n    sr=32_000, hop_length=320, n_fft=1280, n_mels=128, fmin=0, fmax=16_000\n)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Broken file","metadata":{}},{"cell_type":"code","source":"train.query(\"length < 0.3\")","metadata":{"execution":{"iopub.status.busy":"2022-04-03T15:28:32.377677Z","iopub.execute_input":"2022-04-03T15:28:32.378233Z","iopub.status.idle":"2022-04-03T15:28:32.449599Z","shell.execute_reply.started":"2022-04-03T15:28:32.378201Z","shell.execute_reply":"2022-04-03T15:28:32.44861Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Play broken file\nThe second file is really noizy. **Watch out the Volume!**","metadata":{}},{"cell_type":"code","source":"play_audio(\"../input/birdclef-2022/train_audio/blkfra/XC649198.ogg\")\nplay_audio(\"../input/birdclef-2022/train_audio/normoc/XC150238.ogg\")","metadata":{"execution":{"iopub.status.busy":"2022-04-03T15:28:32.451057Z","iopub.execute_input":"2022-04-03T15:28:32.451268Z","iopub.status.idle":"2022-04-03T15:28:32.515035Z","shell.execute_reply.started":"2022-04-03T15:28:32.451244Z","shell.execute_reply":"2022-04-03T15:28:32.514157Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Remove broken file","metadata":{}},{"cell_type":"code","source":"train = train.query(\"length >= 0.3\")","metadata":{"execution":{"iopub.status.busy":"2022-04-03T15:28:32.51651Z","iopub.execute_input":"2022-04-03T15:28:32.517003Z","iopub.status.idle":"2022-04-03T15:28:32.563625Z","shell.execute_reply.started":"2022-04-03T15:28:32.516959Z","shell.execute_reply":"2022-04-03T15:28:32.562912Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(train)","metadata":{"execution":{"iopub.status.busy":"2022-04-03T15:28:32.56508Z","iopub.execute_input":"2022-04-03T15:28:32.565283Z","iopub.status.idle":"2022-04-03T15:28:32.604715Z","shell.execute_reply.started":"2022-04-03T15:28:32.565259Z","shell.execute_reply":"2022-04-03T15:28:32.604064Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train[\"fullpath\"] = \"/kaggle/input/birdclef-2022/train_audio/\" + train[\"filename\"]","metadata":{"execution":{"iopub.status.busy":"2022-04-03T15:28:32.606728Z","iopub.execute_input":"2022-04-03T15:28:32.608824Z","iopub.status.idle":"2022-04-03T15:28:32.652164Z","shell.execute_reply.started":"2022-04-03T15:28:32.608785Z","shell.execute_reply":"2022-04-03T15:28:32.650819Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def print_spec(df, display_length_sec=30, is_debug=True, **spec_params):\n    max_length = df[\"length\"].max()\n    if is_debug:\n        df = df.sample(100, random_state=123)\n    df = df[:3]\n    for i, item in enumerate(tqdm(df.itertuples(), total=len(df))):\n        fig, ax = plt.subplots(figsize=(960 / 72, 640 / 72), dpi=72)\n        sr, hop_length, fmin, fmax = [\n            spec_params[k] for k in [\"sr\", \"hop_length\", \"fmin\", \"fmax\"]\n        ]\n        audio_data, _ = librosa.core.load(item.fullpath, sr=sr, mono=True)\n        spec = create_mel_spectrogram(audio_data[: sr * 30 - 1], **spec_params)\n        spec = pcen_bird(spec, **spec_params)\n        # spec = spec[:, : (sr * display_length_sec) // hop_length]\n        print(f\"shape: {spec.shape}\")\n        im = ax.imshow(\n            spec,\n            cmap=\"magma\",\n        )\n        ax.set(title=f\"filename: {item.filename}\")\n        play_audio(item.fullpath)","metadata":{"execution":{"iopub.status.busy":"2022-04-03T15:28:32.653808Z","iopub.execute_input":"2022-04-03T15:28:32.654785Z","iopub.status.idle":"2022-04-03T15:28:32.733637Z","shell.execute_reply.started":"2022-04-03T15:28:32.654702Z","shell.execute_reply":"2022-04-03T15:28:32.73277Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print_spec(train, **spec_params)","metadata":{"execution":{"iopub.status.busy":"2022-04-03T15:30:22.15356Z","iopub.execute_input":"2022-04-03T15:30:22.153896Z","iopub.status.idle":"2022-04-03T15:30:23.482469Z","shell.execute_reply.started":"2022-04-03T15:30:22.153864Z","shell.execute_reply":"2022-04-03T15:30:23.481378Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Convert audio to spectrogram","metadata":{}},{"cell_type":"code","source":"def create_directory_if_not_exist(dir_path):\n    if os.path.isdir(dir_path):\n        return\n    os.makedirs(dir_path)\n\n\ndef audio2spec_one(data):\n    _, fullpath, filename = data\n    sr = spec_params[\"sr\"]\n    audio_data, _ = librosa.core.load(fullpath, sr=sr, mono=True)\n    # spec = create_mel_spectrogram(audio_data[: sr * 30 - 1], **spec_params)\n    spec = create_mel_spectrogram(audio_data, **spec_params)\n    spec = pcen_bird(spec, **spec_params)\n    spec = spec.astype(np.float16)\n\n    out_filename = filename[:-4] + \".npy\"\n    with open(out_filename, \"wb\") as f:\n        np.save(f, spec)\n\n\ndef audio2spec(df, is_debug=False, **spec_params):\n    sr, hop_length, fmin, fmax = [\n        spec_params[k] for k in [\"sr\", \"hop_length\", \"fmin\", \"fmax\"]\n    ]\n    df = df.copy()\n    df[\"directory\"] = df[\"filename\"].apply(lambda x: x.split(\"/\")[0])\n    dir_paths = set(df[\"directory\"])\n    for dir_path in dir_paths:\n        create_directory_if_not_exist(dir_path)\n\n    if is_debug:\n        df = df.sample(100, random_state=123)\n\n    with Pool(processes=4) as pool:\n        list(\n            tqdm(\n                pool.imap(\n                    audio2spec_one, df[[\"fullpath\", \"filename\"]].itertuples(name=None)\n                ),\n                total=len(df),\n            )\n        )","metadata":{"execution":{"iopub.status.busy":"2022-04-03T15:30:23.526328Z","iopub.execute_input":"2022-04-03T15:30:23.526554Z","iopub.status.idle":"2022-04-03T15:30:23.595389Z","shell.execute_reply.started":"2022-04-03T15:30:23.526528Z","shell.execute_reply":"2022-04-03T15:30:23.594635Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\naudio2spec(train, is_debug=False, **spec_params)","metadata":{"execution":{"iopub.status.busy":"2022-04-03T15:30:23.596804Z","iopub.execute_input":"2022-04-03T15:30:23.59746Z","iopub.status.idle":"2022-04-03T15:30:37.456045Z","shell.execute_reply.started":"2022-04-03T15:30:23.597427Z","shell.execute_reply":"2022-04-03T15:30:37.454839Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_npy(npy_file):\n    fig, ax = plt.subplots(figsize=(960 / 72, 640 / 72), dpi=72)\n    img = np.load(npy_file)\n    ax.imshow(img[:, :1920], cmap=\"magma\")","metadata":{"execution":{"iopub.status.busy":"2022-04-03T15:30:37.457937Z","iopub.execute_input":"2022-04-03T15:30:37.458421Z","iopub.status.idle":"2022-04-03T15:30:37.507362Z","shell.execute_reply.started":"2022-04-03T15:30:37.458373Z","shell.execute_reply":"2022-04-03T15:30:37.506292Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_npy(\"skylar/XC630808.npy\")\nplot_npy(\"spodov/XC381365.npy\")\nplot_npy(\"normoc/XC196164.npy\")","metadata":{"execution":{"iopub.status.busy":"2022-04-03T15:30:37.509609Z","iopub.execute_input":"2022-04-03T15:30:37.50988Z","iopub.status.idle":"2022-04-03T15:30:38.36697Z","shell.execute_reply.started":"2022-04-03T15:30:37.509849Z","shell.execute_reply":"2022-04-03T15:30:38.366044Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!mkdir /tmp/train_audio\n!mv /kaggle/working/* /tmp/train_audio\n!mv /tmp/train_audio /kaggle/working","metadata":{"execution":{"iopub.status.busy":"2022-04-03T15:30:38.368467Z","iopub.execute_input":"2022-04-03T15:30:38.369051Z","iopub.status.idle":"2022-04-03T15:30:41.043662Z","shell.execute_reply.started":"2022-04-03T15:30:38.369002Z","shell.execute_reply":"2022-04-03T15:30:41.042308Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Output metadata","metadata":{}},{"cell_type":"code","source":"metadata = train.copy()\nmetadata[\"filename\"] = metadata[\"filename\"].apply(lambda x: x[:-4]) + \".npy\"\nmetadata = metadata.drop(\"fullpath\", axis=1)\nmetadata.to_csv(\"spec_metadata.csv\", index=False)","metadata":{"execution":{"iopub.status.busy":"2022-04-03T15:31:02.851492Z","iopub.execute_input":"2022-04-03T15:31:02.852333Z","iopub.status.idle":"2022-04-03T15:31:03.061846Z","shell.execute_reply.started":"2022-04-03T15:31:02.852282Z","shell.execute_reply":"2022-04-03T15:31:03.060954Z"},"trusted":true},"execution_count":null,"outputs":[]}]}