{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":70203,"databundleVersionId":8068726,"sourceType":"competition"}],"dockerImageVersionId":30673,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"### BirdCLEF 2024 Mel Spectrograms Generator\n\nThis code used to proceed BirdCLEF 2024 train_audio files to Mel-Spectrograms in NPY format. The output of this notebook available as a [BirdCLEF 2024 Mel-Spectrograms Dataset](https://www.kaggle.com/datasets/samvelkoch/birdclef-2024-mel-spectrograms)\n\n---\n\nCreated by [Samvel Kocharyan](https://www.linkedin.com/in/samvelkoch/) (2024)","metadata":{}},{"cell_type":"code","source":"import os\nimport numpy as np\nimport librosa\nimport zipfile\nfrom joblib import Parallel, delayed\nfrom tqdm import tqdm\nimport shutil\n\n# Input folder\ninput_folder = '/kaggle/input/birdclef-2024/train_audio/'\n\n# Archive zip\nzip_file_path = '/kaggle/working/mel_spectrograms.zip'\n\n# Output folder for NPY files\noutput_folder = '/kaggle/working/mel_spectrograms/'\n\n# Function for processing audio files in a folder\ndef process_audio_folder(folder_path):\n    # The path to the output folder for this processed folder\n    output_subfolder = os.path.join(output_folder, os.path.relpath(folder_path, input_folder))\n    os.makedirs(output_subfolder, exist_ok=True)\n\n    # Processing audio files in a folder\n    for filename in os.listdir(folder_path):\n        if filename.endswith('.ogg'):\n            process_audio(os.path.join(folder_path, filename), output_subfolder)\n\n# A function for processing a single audio file and saving it\ndef process_audio(file_path, output_subfolder):\n    # Audio loading\n    y, sr = librosa.load(file_path, sr=None)\n    \n    # Create Mel-Spectrogram\n    mel_spectrogram = librosa.feature.melspectrogram(y=y, sr=sr)\n    log_mel_spectrogram = librosa.amplitude_to_db(mel_spectrogram)\n\n    # Path to save\n    npy_file_path = os.path.join(output_subfolder, f'{os.path.splitext(os.path.basename(file_path))[0]}.npy')\n\n    # Save as NPY\n    np.save(npy_file_path, log_mel_spectrogram)\n\n# Step by step ZIP creation\nwith zipfile.ZipFile(zip_file_path, 'w', zipfile.ZIP_DEFLATED) as zip_file:\n    # All folders with audio\n    audio_folders = [os.path.join(input_folder, folder) for folder in os.listdir(input_folder) if os.path.isdir(os.path.join(input_folder, folder))]\n\n    # The processing cycle of audio files from folders\n    total_folders = len(audio_folders)\n    processed_folders = 0\n    with tqdm(total=total_folders) as pbar:\n        while audio_folders:\n            # Processing up to 4 folders in parallel\n            current_folders = audio_folders[:4]\n            audio_folders = audio_folders[4:]\n\n            # Parallel processing of audio files in folders\n            Parallel(n_jobs=4, backend=\"threading\")(delayed(process_audio_folder)(folder) for folder in current_folders)\n\n            # Adding processed files to the archive\n            for folder in current_folders:\n                output_subfolder = os.path.join(output_folder, os.path.relpath(folder, input_folder))\n                for root, dirs, files in os.walk(output_subfolder):\n                    for file in files:\n                        zip_file.write(os.path.join(root, file), os.path.relpath(os.path.join(root, file), output_folder))\n                processed_folders += 1\n                pbar.update(1)\n                \n            # Deleting processed folders\n            for folder in current_folders:\n                output_subfolder = os.path.join(output_folder, os.path.relpath(folder, input_folder))\n                shutil.rmtree(output_subfolder)\n                \n            print(f\"Folders proceeded: {processed_folders}, Folders left: {total_folders - processed_folders}\")\n\n# Archive Size\nprint(f\"Archive size: {os.path.getsize(zip_file_path)} bytes\")\n","metadata":{"execution":{"iopub.status.busy":"2024-04-05T09:48:08.203598Z","iopub.execute_input":"2024-04-05T09:48:08.203964Z","iopub.status.idle":"2024-04-05T11:05:09.829553Z","shell.execute_reply.started":"2024-04-05T09:48:08.203935Z","shell.execute_reply":"2024-04-05T11:05:09.827927Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"That's all folks! ","metadata":{}}]}