Пример #1
0
def test_rms_extractor():
    audio = AudioStim(join(AUDIO_DIR, 'barber.wav'))
    ext = RMSExtractor()
    df = ext.transform(audio).to_df()
    assert df.shape == (1221, 5)
    assert np.isclose(df['onset'][2], 0.092880)
    assert np.isclose(df['duration'][2], 0.04644)
    assert np.isclose(df['rms'][2], 0.229993)
    
    assert np.isclose(df['onset'][4], 0.185760)
    assert np.isclose(df['duration'][4], 0.04644)
    assert np.isclose(df['rms'][4], 0.184349)
    
    assert np.isclose(df['onset'][1219], 56.610249)
    assert np.isclose(df['duration'][1219], 0.04644)
    assert np.isclose(df['rms'][1219], 0.001348, rtol = 1e-03)
Пример #2
0
def test_resample():
    ext = RMSExtractor()
    res = ext.transform(join(get_test_data_path(), 'audio/homer.wav'))

    df = res.to_df(format='long')

    # Test downsample
    downsampled_df = resample(df, 3)

    assert np.allclose(downsampled_df.iloc[0].onset, 0)
    assert np.allclose(downsampled_df.iloc[1].onset, 0.33333)

    assert set(downsampled_df.columns) == {
        'duration', 'onset', 'feature', 'value'}

    assert downsampled_df['feature'].unique() == 'rms'

    # This checks that the filtering has happened. If it has not, then
    # this value for this frequency bin will be an alias and have a
    # very different amplitude
    assert downsampled_df[downsampled_df.onset == 0]['value'].values[0] != \
        df[df.onset == 0]['value'].values[0]
    assert downsampled_df[downsampled_df.onset == 0]['value'].values[0] != \
        df[df.onset == 0]['value'].values[0]

    assert np.allclose(downsampled_df[downsampled_df.onset == 2]['value'].values[0],
                       0.2261582761938699)


    # Test upsample
    ext = RMSExtractor(frame_length=1500, hop_length=1500,)
    res = ext.transform(join(get_test_data_path(), 'audio/homer.wav'))
    df = res.to_df(format='long')

    upsampled_df = resample(df, 10)

    assert np.allclose(upsampled_df.iloc[0].onset, 0)
    assert np.allclose(upsampled_df.iloc[1].onset, 0.1)

    assert set(upsampled_df.columns) == {
        'duration', 'onset', 'feature', 'value'}

    assert upsampled_df['feature'].unique() == 'rms'

    # This checks that the filtering has happened. If it has not, then
    # this value for this frequency bin will be an alias and have a
    # very different amplitude
    assert upsampled_df[upsampled_df.onset == 0]['value'].values[0] != \
        df[df.onset == 0]['value'].values[0]
    assert upsampled_df[upsampled_df.onset == 0]['value'].values[0] != \
        df[df.onset == 0]['value'].values[0]

    # Value will be slightly different at 2s with different sampling
    assert np.allclose(
        upsampled_df[upsampled_df.onset == 2]['value'].values[0],  0.25309)
Пример #3
0
def extract_audio_features(in_file):
    """
    This function extracts audio intensity, tempo, and beats from the audio of a video file using the pliers library.
    If you use this function, please cite the pliers library directly:
    https://github.com/PsychoinformaticsLab/pliers#how-to-cite

    Parameters
    ----------
    in_file : str
        file path to video or audio file to be processed

    Returns
    -------
    low_level_audio_df : DataFrame
        Pandas dataframe with a column per low-level feature (index is time).
    """

    # compute tempo on a continuous basis
    print('Extracting dynamic tempo...')
    y, sr = librosa.load(in_file)
    onset_env = librosa.onset.onset_strength(y, sr=sr)
    time_seconds = np.arange(1, len(y)) / sr
    dtempo = librosa.beat.tempo(onset_envelope=onset_env,
                                sr=sr,
                                ac_size=10,
                                aggregate=None)
    n_samples = len(dtempo)
    dtempo_samp_rate = time_seconds[-1] / n_samples
    time_ms = np.arange(0, time_seconds[-1], dtempo_samp_rate) * 1000
    dtempo_df = pd.DataFrame(dtempo,
                             columns=['dynamic_tempo'],
                             index=pd.to_datetime(time_ms, unit='ms'))
    resamp_dtempo_df = dtempo_df.resample('10ms').mean()
    if resamp_dtempo_df['dynamic_tempo'].isnull().values.any():
        resamp_dtempo_df = dtempo_df.resample('10ms').bfill()

    # audio RMS to capture changes in intensity
    print('Extracting loudness...')
    from pliers.extractors import RMSExtractor
    rmsext = RMSExtractor()
    rmsres = rmsext.transform(in_file)
    rmsres_df = rmsres.to_df()

    # Identify major beats in audio
    print('Extracting major music beats...')
    from pliers.extractors import BeatTrackExtractor
    btext = BeatTrackExtractor()
    bteres = btext.transform(in_file)
    bteres_df = bteres.to_df()

    # combine features into one dataframe
    print('Aggregating data...')
    low_level_audio_df = pd.DataFrame()
    low_level_audio_df['onset_ms'] = rmsres_df['onset'] * 1000
    low_level_audio_df['rms'] = rmsres_df['rms']
    low_level_audio_df['beats'] = 0
    for b in bteres_df['beat_track']:
        low_level_audio_df.loc[b, 'beats'] = 1

    low_level_audio_df.index = pd.to_datetime(rmsres_df['onset'], unit='s')
    low_level_audio_df = low_level_audio_df.resample('10ms').mean()
    low_level_audio_df['onset_ms'] = low_level_audio_df[
        'onset_ms'] - low_level_audio_df['onset_ms'][0]
    low_level_audio_df['dynamic_tempo'] = resamp_dtempo_df['dynamic_tempo']
    low_level_audio_df.index.name = None
    print('Auditory feature extraction complete.')
    return low_level_audio_df
Пример #4
0

# Getting Started

The best way to see what *pliers* can offer is to jump right into an example. 

## Example 1: Audio RMS

A measure that is likely to capture a large amount of variance in auditory cortex activity during naturalistic stimulation is the power of the signal in the auditory track. A simple way to measure this is by extracting the `Root-Mean-Square (RMS)` of the audio signal across time.

*Pliers* makes this very easy. All we need to do is to import the `RMSExtractor` object, and apply it to the `ParanoiaStory` audio stimulus. 

from pliers.extractors import RMSExtractor

# Create an instance of this extractor
ext = RMSExtractor()

# Extract features from the audio stimulus
rms_result = ext.transform(paranoia_audio)

The Extractor returns an `ExtractorResult` object which contains the extracted values. 

We can easily convert this to a *Pandas DataFrame*, a familar format that could easily be fed into a data-analysis pipeline, and is easy to inspect.

rms_df = rms_result.to_df()
rms_df

We can then easily plot the timeline of `rms` across time for the *ParanoiaStory* study.

rms_df.plot('onset', 'rms')