{"cells":[{"metadata":{},"cell_type":"markdown","source":"In this notebook ill show haw i do to import mp3 files, preprocess and save them for ML.\n\nthis process can be done in 5 steps :\n\n* Read train csv and smaple it.\n* Apply padding to make mp3 files same length or duration.\n* trasnform this files to spectogram.\n* normalise them.\n* export as pkl format.\n\nI was inspired by Carlo Lepelaars notebook: <a href=\"https://www.kaggle.com/carlolepelaars/bidirectional-lstm-for-audio-labeling-with-keras\">referance</a>","execution_count":null},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"import numpy as np \nimport pandas as pd \n\nimport numpy as np \nimport pandas as pd\nimport os\nimport librosa\nimport matplotlib.pyplot as plt\nimport gc\nimport time\nfrom tqdm import tqdm, tqdm_notebook; tqdm.pandas() # Progress bar\nimport math\n\nfrom tensorflow.keras.utils import to_categorical\nseed = 1234\nnp.random.seed(seed)\n\nt_start = time.time()\n\nimport warnings\n\ndef fxn():\n    warnings.warn(\"deprecated\", DeprecationWarning)\n\nwith warnings.catch_warnings():\n    warnings.simplefilter(\"ignore\")\n    fxn()\nwarnings.filterwarnings(\"ignore\")\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Preprocessing parameters (it can be changed according to convenience)\nsr = 44100 # Sampling rate\nduration = 5\nhop_length = 347 # to make time steps 128\nfmin = 20\nfmax = sr // 2\nn_mels = 128\nn_fft = n_mels * 20\nsamples = sr * duration\nsmpl = 15 # size of samples from each bird code folder","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"# Read train\ndf = pd.read_csv('../input/birdsong-recognition/train.csv')\n\n# Sample train\nconcat = []\nfor label in df['species'].unique() :\n    concat.append(df[df.species == label].sample(smpl, replace = True))\ndf= pd.concat(concat)\n\n# encode labels\ni = 0\ndict_map = {}\nfor label in df['ebird_code'].unique() :\n    dict_map[label] = i\n    i+=1\ndf['num_labels'] = df['ebird_code'].map(dict_map)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Preprocessing functions\n\ndef read_audio(path):\n    '''\n    Reads in the audio file and returns\n    an array that we can turn into a melspectogram\n    '''\n    y, _ = librosa.core.load(path, sr=44100)\n    # trim silence\n    if 0 < len(y): # workaround: 0 length causes error\n        y, _ = librosa.effects.trim(y)\n    if len(y) > samples: # long enough\n        y = y[0:0+samples]\n    else: # pad blank\n        padding = samples - len(y)\n        offset = padding // 2\n        y = np.pad(y, (offset, samples - len(y) - offset), 'constant')\n    return y\n\ndef audio_to_melspectrogram(audio):\n    '''\n    Convert to melspectrogram after audio is read in\n    '''\n    spectrogram = librosa.feature.melspectrogram(audio, \n                                                 sr=sr,\n                                                 n_mels=n_mels,\n                                                 hop_length=hop_length,\n                                                 n_fft=n_fft,\n                                                 fmin=fmin,\n                                                 fmax=fmax)\n    return librosa.power_to_db(spectrogram).astype(np.float32)\n\ndef read_as_melspectrogram(path):\n    '''\n    Convert audio into a melspectrogram \n    so we can use machine learning\n    '''\n    mels = audio_to_melspectrogram(read_audio(path))\n    return mels\n\ndef convert_wav_to_image(df, path):\n    X = []\n    for _,row in tqdm_notebook(df.iterrows(), total = df['ebird_code'].unique().shape[0] * smpl):\n        if row['filename'] != 'XC195038.mp3' :\n            x = read_as_melspectrogram('{}/{}/{}'.format(path[0],str(row['ebird_code']) ,str(row['filename'])))\n            X.append(x.transpose())\n    return X\n\ndef normalize(img):\n    '''\n    Normalizes an array \n    (subtract mean and divide by standard deviation)\n    '''\n    eps = 0.001\n    if np.std(img) != 0:\n        img = (img - np.mean(img)) / np.std(img)\n    else:\n        img = (img - np.mean(img)) / eps\n    return img\n\ndef normalize_dataset(X):\n    '''\n    Normalizes list of arrays\n    (subtract mean and divide by standard deviation)\n    '''\n    normalized_dataset = []\n    for img in X:\n        normalized = normalize(img)\n        normalized_dataset.append(normalized)\n    return normalized_dataset","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Preprocess dataset and create validation sets\nX = np.array(convert_wav_to_image(df, ['../input/birdsong-recognition/train_audio']))\nX = normalize_dataset(X)\ny = df['num_labels'].values","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Visualize an melspectogram example\nplt.figure(figsize=(15,10))\nplt.title('Visualization of audio file', weight='bold')\nplt.imshow(X[0]);","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Save spectograms as PKL format\n\nimport pickle\n\nwith open('X_train.pkl', 'wb') as f:\n    pickle.dump(X, f)\n    \nwith open('y_train.pkl', 'wb') as x:\n    pickle.dump(y, x)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Here the data is ready to be consumed by an RNN, LSTM, CNN or other.\n\n**Do not hesitate to upvote if it was useful to you**","execution_count":null}],"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":4,"nbformat_minor":4}