{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import gc\nimport numpy as np\nimport librosa\nimport librosa.display\nimport matplotlib.pyplot as plt\nimport pandas as pd\nimport os\nfrom pathlib import Path\nimport IPython.display as ipd\n%matplotlib inline","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","collapsed":true,"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":false},"cell_type":"markdown","source":"## Explanation\n\nI started this kernel to using the 'Fart' sound to mess with my family and try engage my kids in coding. After a while I got sick of listening to farts and my wife was noticeably mad, so I switched to other tags for my experiments. However, many of the variable names still have fart references, so if you are offended by fart themed functions and variables please turn back now. I currently have a few functions set up for the visualization of various sounds that I think might be useful when determining how to preprocess the sounds. \n\n1. `line_graph_with_mel` will give you a line graph and melspectrogram visulazation. I also added the `ipd.Audio( os.fspath(file_path) )` so that the user can listen to the sound they are looking at.\n\n2. `grid_melspectrogram` the user can compare two sounds using a grid fo melspectrograms. \n\nAny comments are greatly appreciated!"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Here is my set up cell. Getting access to the sound files is a little intimidating \n# at first, but it is pretty close to what you would do with images which has already \n# been 'solved' just watch fastai classes with the man Jeremy Howard\n\n# Set up paths to sound containing folders\npath_crtd = Path('../input/train_curated')\npath_nsy = Path('../input/train_noisy')\npath_test = Path('../input/test')\nFART_TAG = ['Electric_guitar'] # ['Fart']\n\n# list of files to be read in\ncur_wv = [path_crtd/fname for fname in os.listdir(path_crtd)]\nnsy_wv = [path_nsy/fname for fname in os.listdir(path_nsy)]\ntst_wv = [path_test/fname for fname in os.listdir(path_test)]\n\n# label and sample submission dfs\ncur_df = pd.read_csv(\"../input/train_curated.csv\")\nnsy_df = pd.read_csv(\"../input/train_noisy.csv\")\nsam_sub = pd.read_csv('../input/sample_submission.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"## Here are a few handy helper functions to seperate and look at the data:\n## Remember, this cell can be hidden to keep a close eye on your variables.\n\ndef seperate_sound_tag(file_path, label_df, sound_tag):\n    \"\"\"This function expects a list of file paths, a df with labels and file names, and a label.\n    Returns a list of file paths that contain the sound tag and no other tags.\n    \n    parameters\n    ----------\n    file_path(Path): path to .wav files\n    label_df(df): df containing filenames and labels\n    sound_tag(string): one of the labels included in df.lables\n    \n    returns\n    -------\n    list of files containing the sound_tag string\n    \"\"\"    \n   \n    df_st = label_df[ label_df.labels == sound_tag ]\n    ## dictionary with filenames as keys and file paths as values\n    file_dict = {fname:file_path/fname for fname in os.listdir(file_path)}\n    tag_file_names = list(df_st['fname'])\n    tag_files = {key:value for key,value in file_dict.items() if key in tag_file_names}    \n    return list(tag_files.values())\n\ndef random_file(file_list, label_df=None, sound_tag=None):\n    \"\"\"Returns random file from list.\"\"\"    \n    if type(label_df) == pd.DataFrame:\n        file_list = seperate_sound_tag(file_path=file_list, label_df=label_df, \n                    sound_tag=sound_tag)\n    \n    file_path = file_list[np.random.randint(len(file_list))] \n    return file_path\n\ndef make_spectrogram(file_path=None, clip=None, sample_rate=None):\n    \"\"\"Expects a numpy array and returns a melspectogram\"\"\"\n    if file_path:\n        clip, sample_rate = librosa.load(file_path, sr=None)\n    spectrogram = librosa.feature.melspectrogram(clip, sr=44100)\n    spectrogram = librosa.power_to_db(spectrogram)\n    spectrogram = spectrogram.astype(np.float32)\n    return spectrogram\n\ndef line_graph_with_mel(file_path, df=cur_df):\n    \"\"\"\"\"\"\n    clip, sample_rate = librosa.load(str(file_path), sr=None)\n    spect = make_spectrogram(file_path=file_path)\n    ## grab the tags from the label df for the title\n    tags = df[df['fname'] == file_path.parts[-1]].labels.iloc[0]\n    \n    f, axs = plt.subplots(nrows=2, figsize=(12,6))\n    axs[0].plot(np.array( range(len(clip) ) )/sample_rate, clip, )\n    axs[0].set_xlabel('Seconds', size=15)\n    axs[0].set_title(f'{tags} lineplot', size=22)\n    axs[0].grid()\n    librosa.display.specshow(spect, x_axis='time', y_axis='mel', hop_length=100, ax=axs[1])\n    # plt.colorbar()\n    axs[1].set_title(f'{tags} Mel Spectogram', size=22)\n    plt.tight_layout()\n    \ndef grid_melspectrogram(data_files, tags, label_df, num_graphs=10):\n    \"\"\"Makes a grid of melspectrograms with tags.\n    \n    Args:\n        data_files(Path): path to a group of .wav files\n        tags(list or str): list of tags or string with single tag\n        label_df(pd.DataFrame): containing filename and coorisponding tag(s)\n        num_graphs(int): number of graphs in figure\n    Returns:\n        matplotlib object ?\n        \"\"\"\n    \n    ## Get a list of .wav files and coorisponding tags\n    file_list = []\n    new_tags = []\n    if type(tags) == list:\n        for graph_number in range(num_graphs):\n            tag_ix = graph_number % len(tags)\n            tag = tags[tag_ix]\n            sound_files = seperate_sound_tag(file_path=data_files, label_df=label_df, sound_tag=tag)\n            sound_file = random_file(sound_files)\n            file_list.append(sound_file)\n            new_tags.append(tag)\n    \n    else:\n        sound_files = seperate_sound_tag(tags)\n        for graph_number in range(num_graphs):\n            file_list.append(random_file(file_list = sound_files))\n            new_tags.append(tags)\n    \n    ## Cycle through tag list and file paths to make graphs\n    ## Cycle through tag list and file paths to make graphs\n    \n    row_number = int(np.ceil(num_graphs/2))\n    f, axs = plt.subplots(nrows=row_number, ncols=2, figsize=(12,row_number*3))\n    axs = axs.ravel()\n    for i in range(num_graphs):\n        spec = make_spectrogram(file_path=file_list[i])\n        librosa.display.specshow(spec, x_axis='time', y_axis='mel', hop_length=100, ax=axs[i])\n        axs[i].set_title(new_tags[i])\n\n    plt.tight_layout()\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"## Run this cell to get get a list of (top 10) individual tags and how many files there are in the curated dataset\n# cur_df['len'] = cur_df.iloc[:,1].apply(lambda x: len(x.split(',')))\n# training_set = cur_df[cur_df['len'] == 1]\n# training_set['labels'].value_counts().iloc[:10]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"SOUND_TO_VIEW = 'Fart'\n\nfile_path = random_file(path_crtd, cur_df, SOUND_TO_VIEW)\n\nline_graph_with_mel(file_path=file_path, df=cur_df)\nipd.Audio( os.fspath(file_path) ) # load a local WAV file\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"## Question how to add a colorbar to the mel spectogram visulization\n\nSOUNDS_TO_COMPARE=['Fart', 'Electric_guitar',]\n\ngrid_melspectrogram(data_files=path_crtd, tags=SOUNDS_TO_COMPARE, label_df=cur_df)","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}