{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":91844,"databundleVersionId":11361821,"sourceType":"competition"}],"dockerImageVersionId":30918,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport os \nimport librosa","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-03-29T23:08:22.840418Z","iopub.execute_input":"2025-03-29T23:08:22.840873Z","iopub.status.idle":"2025-03-29T23:08:22.845936Z","shell.execute_reply.started":"2025-03-29T23:08:22.840839Z","shell.execute_reply":"2025-03-29T23:08:22.844564Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_audio_dir = '/kaggle/input/birdclef-2025/train_audio/'\ntrain_soundscapes_dir = '/kaggle/input/birdclef-2025/train_soundscapes/'\n\ntrain, taxonomy = pd.read_csv('/kaggle/input/birdclef-2025/train.csv'), pd.read_csv('/kaggle/input/birdclef-2025/taxonomy.csv')\nsubmission =  pd.read_csv('/kaggle/input/birdclef-2025/sample_submission.csv')\ntrain.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-29T23:08:23.077269Z","iopub.execute_input":"2025-03-29T23:08:23.077693Z","iopub.status.idle":"2025-03-29T23:08:23.280160Z","shell.execute_reply.started":"2025-03-29T23:08:23.077664Z","shell.execute_reply":"2025-03-29T23:08:23.278428Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"taxonomy.sample(3)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-29T23:08:23.285000Z","iopub.execute_input":"2025-03-29T23:08:23.285552Z","iopub.status.idle":"2025-03-29T23:08:23.298380Z","shell.execute_reply.started":"2025-03-29T23:08:23.285514Z","shell.execute_reply":"2025-03-29T23:08:23.296397Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-29T23:08:23.573027Z","iopub.execute_input":"2025-03-29T23:08:23.573495Z","iopub.status.idle":"2025-03-29T23:08:23.598179Z","shell.execute_reply.started":"2025-03-29T23:08:23.573438Z","shell.execute_reply":"2025-03-29T23:08:23.597109Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 📈 convert audio files into numpy arrays by labels 🧑‍🏫","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nselected_features = ['primary_label','filename','latitude','longitude','scientific_name','common_name']\ntrain = train[selected_features]\n# Define your unique labels\nlabels = {'brtpar1', '1139490', 'compau', 'chbant1', 'yehcar1', 'yecspi2', 'watjac1', 'grasal4', 'grbhaw1', \n          'yebfly1', 'neocor', '81930', 'spbwoo1', '64862', 'grepot1', 'ruther1', 'banana', 'whttro1', \n          '1462711', '42087', '66531', 'soulap1', 'amakin1', '41970', '65373', '714022', 'bafibi1', 'blcant4', \n          'rutjac1', 'plbwoo1', 'anhing', 'yehbla2', '21211', 'recwoo1', 'blbgra1', 'creoro1', 'shtfly1', \n          'amekes', 'blchaw1', '21116', '566513', 'bugtan', 'strcuc1', '1564122', '1462737', 'purgal2', \n          'socfly1', 'gohman1', 'gycwor1', 'bubwre1', 'blhpar1', '65336', 'solsan', '134933', '24292', \n          '42113', 'plukit1', 'savhaw1', 'sobtyr1', 'chfmac1', 'yebsee1', '66016', 'blbwre1', 'mastit1', \n          'smbani', 'whfant1', 'strfly1', 'roahaw', 'rumfly1', '476537', 'butsal1', 'bucmot3', 'colcha1', \n          'bobfly1', '67082', 'rebbla1', 'pavpig2', '1192948', 'whbman1', 'verfly', 'eardov1', 'norscr1', \n          'rinkin1', '67252', 'greibi1', 'greegr', 'cattyr', 'laufal1', 'trokin', 'grekis', 'crebob1', \n          'bubcur1', 'fotfly', 'palhor2', '476538', '24322', 'tropar', 'whwswa1', 'yercac1', '517119', \n          '24272', 'cocher1', 'labter1', 'bicwre1', 'compot1', 'olipic1', 'blcjay1', 'colara1', 'spepar1', \n          'cregua1', 'cargra1', '22976', 'plctan1', '715170', 'leagre', '22973', 'bkmtou1', 'yelori1', \n          'trsowl', 'strher', 'ragmac1', 'yeofly1', '548639', 'tbsfin1', '135045', '65344', 'bkcdon', \n          'stbwoo2', 'piepuf1', '868458', '963335', 'blctit1', 'saffin', 'rtlhum', 'royfly1', '66893', \n          'rutpuf1', 'linwoo1', 'wbwwre1', 'srwswa1', '126247', 'gretin1', 'grnkin', 'littin1', 'secfly1', \n          '41778', '528041', 'bbwduc', 'greani1', 'rubsee1', 'orcpar', 'rosspo1', 'yebela1', '47067', \n          'crcwoo1', '65349', 'snoegr', 'gybmar', 'thbeup1', '66578', 'turvul', 'rugdov', 'baymac', \n          'speowl1', 'cocwoo1', 'cotfly1', 'y00678', '65419', 'bobher1', '52884', '41663', '22333', \n          'piwtyr1', '21038', '787625', 'rufmot1', '65962', 'paltan1', '48124', '555142', '65547', \n          'crbtan1', '1194042', 'ywcpar', 'shghum1', 'cinbec1', 'thlsch3', '1346504', '555086', 'sahpar1', \n          'grysee1', 'blkvul', '523060', 'strowl1', 'whbant1', 'whmtyr1', '65448', 'ampkin1', 'whtdov', \n          'yectyr1', '42007', '46010', 'pirfly1', 'woosto', 'babwar', '50186'}\n\n# Create a dictionary to store DataFrames\ndfs = {label: train[train['primary_label'] == label] for label in labels}\n\n# Example: Access one of the DataFrames\nprint(dfs['brtpar1'].head()) ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-29T23:08:25.729102Z","iopub.execute_input":"2025-03-29T23:08:25.729546Z","iopub.status.idle":"2025-03-29T23:08:26.451939Z","shell.execute_reply.started":"2025-03-29T23:08:25.729493Z","shell.execute_reply":"2025-03-29T23:08:26.449934Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%time\ndef get_audio_path(df, i, train_audio_dir):\n    \"\"\"Retrieve the audio file path using iloc for correct indexing.\"\"\"\n    return os.path.join(train_audio_dir, df.iloc[i]['filename'])\ndef extract_numpy_arrays(df):\n    numpys = []\n    train_audio_dir = '/kaggle/input/birdclef-2025/train_audio/'\n    filenames = [get_audio_path(df, i, train_audio_dir) for i in range(0,len(df))]\n    for filename in filenames:\n        y, sr = librosa.load(filename)\n        numpys.append((y,sr))\n    return numpys\n    \ndef compute_fft(y, sr):\n    sp = np.fft.fft(np.sin(y))\n    freq = np.fft.fftfreq(y.shape[-1])\n    return sp, freq\n\nnumpys = extract_numpy_arrays(dfs['solsan'])\nfouriers = [compute_fft(i,j) for i,j in numpys]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-29T23:26:46.716242Z","iopub.execute_input":"2025-03-29T23:26:46.716681Z","iopub.status.idle":"2025-03-29T23:27:09.658404Z","shell.execute_reply.started":"2025-03-29T23:26:46.716650Z","shell.execute_reply":"2025-03-29T23:27:09.657246Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\n# Extract the first audio sample\ny, sr = numpys[4]\n\n# Compute FFT for the first sample\nsp, freq = compute_fft(y, sr)\n\n# Plot the FFT (real and imaginary parts)\nplt.figure(figsize=(10, 5))\nplt.plot(freq, sp.real, label=\"Real Part\")\nplt.xlabel(\"Frequency\")\nplt.ylabel(\"Amplitude\")\nplt.title(\"FFT of First Audio Sample\")\nplt.legend()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-29T23:27:34.572257Z","iopub.execute_input":"2025-03-29T23:27:34.572657Z","iopub.status.idle":"2025-03-29T23:27:34.888921Z","shell.execute_reply.started":"2025-03-29T23:27:34.572628Z","shell.execute_reply":"2025-03-29T23:27:34.887897Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def detailed_mel_spectrogram(y, sr):\n    # Compute Mel spectrogram with more detailed parameters\n    mel_spec = librosa.feature.melspectrogram(\n        y=y, \n        sr=sr, \n        n_mels=128,  # Increase number of mel bands\n        fmax=sr/2,   # Maximum frequency\n        hop_length=512,  # Adjust hop length for more detailed time resolution\n        n_fft=2048   # Increase FFT window for better frequency resolution\n    )\n    \n    # Convert to log scale (dB)\n    log_mel_spec = librosa.power_to_db(mel_spec, ref=np.max)\n    \n    # Visualize with more details\n    plt.figure(figsize=(15, 6))\n    librosa.display.specshow(\n        log_mel_spec, \n        sr=sr, \n        x_axis='time', \n        y_axis='mel',\n        cmap='viridis'  # Try different colormaps\n    )\n    plt.colorbar(format='%+2.0f dB')\n    plt.title('Detailed Mel Spectrogram')\n    plt.tight_layout()\n    plt.show()\n    \n    return log_mel_spec\n\ndetailed_mel_spectrogram(y, sr)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-29T23:27:36.658065Z","iopub.execute_input":"2025-03-29T23:27:36.658576Z","iopub.status.idle":"2025-03-29T23:27:37.090724Z","shell.execute_reply.started":"2025-03-29T23:27:36.658540Z","shell.execute_reply":"2025-03-29T23:27:37.088922Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Insights 🕵️‍♀️🕵️‍♀️\n1. **Not all data has the same lenght**\n1. **Repeated audio files**\n2. * **Y_harmonic** extracts the sound of the bird and **y_percusion** extracts the background\n1. **There is a chance that >-40dB willl be a good treshold to create training data**","metadata":{}},{"cell_type":"code","source":"from IPython.display import Audio \nAudio(y, rate=sr)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-29T23:27:39.789971Z","iopub.execute_input":"2025-03-29T23:27:39.790384Z","iopub.status.idle":"2025-03-29T23:27:39.801641Z","shell.execute_reply.started":"2025-03-29T23:27:39.790353Z","shell.execute_reply":"2025-03-29T23:27:39.800330Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# ⛏️👷⛏️👷⛏️👷⛏️👷 Feature extractions ⛏️👷⛏️👷⛏️👷⛏️👷 ","metadata":{}},{"cell_type":"code","source":"def extract_advanced_features(y, sr):\n    # Spectral Centroid - brightness of sound\n    spectral_centroids = librosa.feature.spectral_centroid(y=y, sr=sr)[0]\n    \n    # Spectral Bandwidth - spread of spectrum\n    spectral_bandwidth = librosa.feature.spectral_bandwidth(y=y, sr=sr)[0]\n    \n    # Spectral Rolloff - frequency below which a certain percentage of total spectral energy lies\n    spectral_rolloff = librosa.feature.spectral_rolloff(y=y, sr=sr)[0]\n    \n    # Zero Crossing Rate - number of times audio signal crosses zero\n    zero_crossing_rate = librosa.feature.zero_crossing_rate(y)[0]\n    \n    # Visualize these features\n    plt.figure(figsize=(15, 10))\n    plt.subplot(4,1,1)\n    plt.plot(spectral_centroids)\n    plt.title('Spectral Centroid')\n    \n    plt.subplot(4,1,2)\n    plt.plot(spectral_bandwidth)\n    plt.title('Spectral Bandwidth')\n    \n    plt.subplot(4,1,3)\n    plt.plot(spectral_rolloff)\n    plt.title('Spectral Rolloff')\n    \n    plt.subplot(4,1,4)\n    plt.plot(zero_crossing_rate)\n    plt.title('Zero Crossing Rate')\n    \n    plt.tight_layout()\n    plt.show()\n    \n    return {\n        'spectral_centroids': spectral_centroids,\n        'spectral_bandwidth': spectral_bandwidth,\n        'spectral_rolloff': spectral_rolloff,\n        'zero_crossing_rate': zero_crossing_rate\n    }\n\nextract_advanced_features(y, sr)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-29T23:27:46.013337Z","iopub.execute_input":"2025-03-29T23:27:46.013725Z","iopub.status.idle":"2025-03-29T23:27:46.891000Z","shell.execute_reply.started":"2025-03-29T23:27:46.013694Z","shell.execute_reply":"2025-03-29T23:27:46.889761Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def harmonic_percussive_separation(y, sr):\n    # Separate harmonic and percussive components\n    y_harmonic, y_percussive = librosa.effects.hpss(y)\n    \n    # Visualize both components\n    plt.figure(figsize=(15, 10))\n    \n    plt.subplot(2,1,1)\n    librosa.display.specshow(\n        librosa.amplitude_to_db(\n            np.abs(librosa.stft(y_harmonic)), \n            ref=np.max\n        ), \n        sr=sr, \n        x_axis='time', \n        y_axis='hz'\n    )\n    plt.colorbar(format='%+2.0f dB')\n    plt.title('Harmonic Component')\n    \n    plt.subplot(2,1,2)\n    librosa.display.specshow(\n        librosa.amplitude_to_db(\n            np.abs(librosa.stft(y_percussive)), \n            ref=np.max\n        ), \n        sr=sr, \n        x_axis='time', \n        y_axis='hz'\n    )\n    plt.colorbar(format='%+2.0f dB')\n    plt.title('Percussive Component')\n    \n    plt.tight_layout()\n    plt.show()\n    \n    return y_harmonic, y_percussive\n\ny_harmonic, y_percussive = harmonic_percussive_separation(y, sr)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-29T23:27:52.308788Z","iopub.execute_input":"2025-03-29T23:27:52.309181Z","iopub.status.idle":"2025-03-29T23:27:53.494932Z","shell.execute_reply.started":"2025-03-29T23:27:52.309155Z","shell.execute_reply":"2025-03-29T23:27:53.493591Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def extract_chroma_features(y, sr):\n    # Compute chroma features\n    chroma = librosa.feature.chroma_stft(y=y, sr=sr)\n    \n    plt.figure(figsize=(15, 5))\n    librosa.display.specshow(\n        chroma, \n        x_axis='time', \n        y_axis='chroma', \n        cmap='coolwarm'\n    )\n    plt.colorbar()\n    plt.title('Chroma Feature')\n    plt.tight_layout()\n    plt.show()\n    \n    return chroma\n\nchroma = extract_chroma_features(y, sr)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-29T23:28:10.417593Z","iopub.execute_input":"2025-03-29T23:28:10.417951Z","iopub.status.idle":"2025-03-29T23:28:11.155359Z","shell.execute_reply.started":"2025-03-29T23:28:10.417915Z","shell.execute_reply":"2025-03-29T23:28:11.153358Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"Audio(y_percussive, rate=sr)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-29T23:28:11.157018Z","iopub.execute_input":"2025-03-29T23:28:11.157385Z","iopub.status.idle":"2025-03-29T23:28:11.168683Z","shell.execute_reply.started":"2025-03-29T23:28:11.157343Z","shell.execute_reply":"2025-03-29T23:28:11.167274Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"Audio(y_harmonic, rate=sr)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-29T23:28:11.170443Z","iopub.execute_input":"2025-03-29T23:28:11.170824Z","iopub.status.idle":"2025-03-29T23:28:11.181865Z","shell.execute_reply.started":"2025-03-29T23:28:11.170794Z","shell.execute_reply":"2025-03-29T23:28:11.180846Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def extract_low_amplitude_regions(spectrogram, threshold=-20):\n    \"\"\"\n    Extract regions of the spectrogram with amplitude below the specified threshold.\n    \n    Parameters:\n    - spectrogram: 2D numpy array of the spectrogram (in dB scale)\n    - threshold: dB threshold for extraction (default -20 dB)\n    \n    Returns:\n    - mask: Boolean mask of regions below the threshold\n    - extracted_spectrogram: Spectrogram with only low amplitude regions\n    \"\"\"\n    # Create a boolean mask for regions below the threshold\n    mask = spectrogram > threshold\n    \n    # Create a copy of the spectrogram with only low amplitude regions\n    extracted_spectrogram = np.where(mask, spectrogram, -np.inf)\n    \n    # Visualization\n    plt.figure(figsize=(15, 5))\n    plt.subplot(1, 2, 1)\n    plt.title('Original Spectrogram')\n    librosa.display.specshow(spectrogram, cmap='viridis')\n    plt.colorbar(format='%+2.0f dB')\n    \n    plt.subplot(1, 2, 2)\n    plt.title(f'Spectrogram (Regions < {threshold} dB)')\n    librosa.display.specshow(extracted_spectrogram, cmap='viridis')\n    plt.colorbar(format='%+2.0f dB')\n    \n    plt.tight_layout()\n    plt.show()\n    \n    return mask, extracted_spectrogram\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-29T23:28:24.412759Z","iopub.execute_input":"2025-03-29T23:28:24.413096Z","iopub.status.idle":"2025-03-29T23:28:24.419563Z","shell.execute_reply.started":"2025-03-29T23:28:24.413071Z","shell.execute_reply":"2025-03-29T23:28:24.418156Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n# Compute STFT of the harmonic component\nstft_harmonic = librosa.stft(y_harmonic)\nspectrogram_db = librosa.amplitude_to_db(np.abs(stft_harmonic), ref=np.max)\n\n# Extract low amplitude regions\nmask, low_amp_spectrogram = extract_low_amplitude_regions(spectrogram_db, threshold=-40)\n\n# Convert the masked spectrogram back to linear scale\nlow_amp_spectrogram_linear = librosa.db_to_amplitude(low_amp_spectrogram)\n\n# Ensure the phase information is retained\nstft_magnitude = low_amp_spectrogram_linear\nstft_phase = np.exp(1j * np.angle(stft_harmonic))\n\n# Reconstruct the audio using the inverse STFT\ny_reconstructed = librosa.istft(stft_magnitude * stft_phase)\n\n# Play the reconstructed audio\nAudio(data=y_reconstructed, rate=sr)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-29T23:28:44.522622Z","iopub.execute_input":"2025-03-29T23:28:44.523021Z","iopub.status.idle":"2025-03-29T23:28:45.206530Z","shell.execute_reply.started":"2025-03-29T23:28:44.522989Z","shell.execute_reply":"2025-03-29T23:28:45.205304Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n# Compute STFT of the harmonic component\nstft_harmonic = librosa.stft(y_percussive)\nspectrogram_db = librosa.amplitude_to_db(np.abs(stft_harmonic), ref=np.max)\n\n# Extract low amplitude regions\nmask, low_amp_spectrogram = extract_low_amplitude_regions(spectrogram_db, threshold=-40)\n\n# Convert the masked spectrogram back to linear scale\nlow_amp_spectrogram_linear = librosa.db_to_amplitude(low_amp_spectrogram)\n\n# Ensure the phase information is retained\nstft_magnitude = low_amp_spectrogram_linear\nstft_phase = np.exp(1j * np.angle(stft_harmonic))\n\n# Reconstruct the audio using the inverse STFT\ny_reconstructed = librosa.istft(stft_magnitude * stft_phase)\n\n# Play the reconstructed audio\nAudio(data=y_reconstructed, rate=sr)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-29T23:29:04.120012Z","iopub.execute_input":"2025-03-29T23:29:04.120451Z","iopub.status.idle":"2025-03-29T23:29:04.759605Z","shell.execute_reply.started":"2025-03-29T23:29:04.120421Z","shell.execute_reply":"2025-03-29T23:29:04.758525Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}