Exemplo n.º 1
0
def test_window_edges():
    """Test windowing signal edges."""
    sig = np.ones((2, 1000))
    fs = 44100
    assert_raises(ValueError, window_edges, sig, fs, window='foo')  # bad win
    assert_raises(RuntimeError, window_edges, sig, fs, dur=1.0)  # too long
    assert_raises(ValueError, window_edges, sig, fs, edges='foo')  # bad type
    x = window_edges(sig, fs, edges='leading')
    y = window_edges(sig, fs, edges='trailing')
    z = window_edges(sig, fs)
    assert_true(np.all(x[:, 0] < 1))  # make sure we actually reduced amp
    assert_true(np.all(x[:, -1] == 1))
    assert_true(np.all(y[:, 0] == 1))
    assert_true(np.all(y[:, -1] < 1))
    assert_allclose(x + y, z + 1)
Exemplo n.º 2
0
def test_window_edges():
    """Test windowing signal edges."""
    sig = np.ones((2, 1000))
    fs = 44100
    pytest.raises(ValueError, window_edges, sig, fs, window='foo')  # bad win
    pytest.raises(RuntimeError, window_edges, sig, fs, dur=1.0)  # too long
    pytest.raises(ValueError, window_edges, sig, fs, edges='foo')  # bad type
    x = window_edges(sig, fs, edges='leading')
    y = window_edges(sig, fs, edges='trailing')
    z = window_edges(sig, fs)
    assert (np.all(x[:, 0] < 1))  # make sure we actually reduced amp
    assert (np.all(x[:, -1] == 1))
    assert (np.all(y[:, 0] == 1))
    assert (np.all(y[:, -1] < 1))
    assert_allclose(x + y, z + 1)
Exemplo n.º 3
0
def gen_am_tone(stim_fs=44100,
                stim_dur=1.0,
                stim_rms=0.01,
                carrier_freq=1000,
                mod_ind=0.8,
                mod_freq=40):
    """Returns an RMS normalized amplitude modulated sinusoidal time series


    Args:
    stim_fs (int): sampling frequency for generated stimuli defaults 
                   to 44100 Hz.
    stim_dir : float
    stim_rms : float
    output_dir : string
    carrier_freq : int
    stim_db : int
    mod_ind : float
    mod_freq : int

    Returns:
    tone

    """
    t = np.arange(int(stim_fs * stim_dur)) / float(stim_fs)
    tone = np.sin(2 * np.pi * carrier_freq *
                  t) * (1 + np.sin(2 * np.pi * mod_freq * t) * mod_ind)
    tone *= stim_rms * np.sqrt(2)
    tone = stimuli.window_edges(tone, stim_fs, 0.025, edges='both')
    return tone
Exemplo n.º 4
0
Generate more advanced auditory stimuli
=======================================

This shows the methods that we provide that facilitate generation
of more advanced stimuli.
"""

import numpy as np

from expyfun.stimuli import convolve_hrtf, play_sound, window_edges

fs = 44100
dur = 0.5
freq = 500.
# let's make a square wave
sig = np.sin(freq * 2 * np.pi * np.arange(dur * fs, dtype=float) / fs)
sig = ((sig > 0) - 0.5) / 5.  # make it reasonably quiet for play_sound
sig = window_edges(sig, fs)

play_sound(sig, norm=False, wait=True)

move_sig = np.concatenate([convolve_hrtf(sig, fs, ang)
                           for ang in range(-90, 91, 15)], axis=1)
play_sound(move_sig, norm=False, wait=True)

import matplotlib.pyplot as mpl
mpl.ion()
t = np.arange(move_sig.shape[1]) / float(fs)
mpl.plot(t, move_sig.T)
mpl.xlabel('Time (sec)')
Exemplo n.º 5
0
This shows how to make simple vocoded stimuli.

@author: larsoner
"""

import numpy as np
import matplotlib.pyplot as mpl

from expyfun.stimuli import vocode, play_sound, window_edges, read_wav, rms
from expyfun import fetch_data_file

print(__doc__)


data, fs = read_wav(fetch_data_file('audio/dream.wav'))
data = window_edges(data[0], fs)
t = np.arange(data.size) / float(fs)
# noise vocoder
data_noise = vocode(data, fs, mode='noise')
data_noise = data_noise * 0.01 / rms(data_noise)
# sinewave vocoder
data_tone = vocode(data, fs, mode='tone')
data_tone = data_tone * 0.01 / rms(data_tone)
# poisson vocoder
data_click = vocode(data, fs, mode='poisson', rate=400)
data_click = data_click * 0.01 / rms(data_click)

# combine all three
cutoff = data.shape[-1] // 3
data_allthree = data_noise.copy()
data_allthree[cutoff:2 * cutoff] = data_tone[cutoff:2 * cutoff]
Exemplo n.º 6
0
This shows the methods that we provide that facilitate generation
of more advanced stimuli.
"""

import numpy as np
import matplotlib.pyplot as plt

from expyfun import building_doc
from expyfun.stimuli import convolve_hrtf, play_sound, window_edges

fs = 24414
dur = 0.5
freq = 500.
# let's make a square wave
sig = np.sin(freq * 2 * np.pi * np.arange(dur * fs, dtype=float) / fs)
sig = ((sig > 0) - 0.5) / 5.  # make it reasonably quiet for play_sound
sig = window_edges(sig, fs)

play_sound(sig, fs, norm=False, wait=True)

move_sig = np.concatenate(
    [convolve_hrtf(sig, fs, ang) for ang in range(-90, 91, 15)], axis=1)
if not building_doc:
    play_sound(move_sig, fs, norm=False, wait=True)

t = np.arange(move_sig.shape[1]) / float(fs)
plt.plot(t, move_sig.T)
plt.xlabel('Time (sec)')
plt.show()
def generate_stimuli(num_trials=10, stim_dur=0.08, fs=24414., rms=0.01,
                     ramp_noise=0.03, ramp_tone=0.06,
                     output_dir=None, save_as='mat', rand_seed=0):
    """Make stimuli and save in various formats. Optimized for saving
    as MAT files, but can also save directly as WAV files, or can return a
    python dictionary with sinewave data as values.
    Parameters
    ----------
    num_trials : int
        Number of trials you want in your experiment. Ignored if save_as is
        not 'mat'.
    stim_dur : float
        Duration of the tones in seconds.
    ramp_noise : float
        Duration of the onset and offset ramps in seconds for noiseburst stim.
    ramp_tone : float
        Duration of the onset and offset ramps in seconds for tonecomplex stim.
    fs : float | None
        Sampling frequency of resulting sinewaves.  Defaults to 24414.0625 (a
        standard rate for TDTs) if no value is specified.
    rms : float
        RMS amplitude to which all sinwaves will be scaled.
    output_dir : str | None
        Directory to output the files into. If None, the current directory
        is used.
    save_as : str
        Format in which to return the sinewaves. 'dict' returns sinewave arrays
        as values in a python dictionary; 'wav' saves them as WAV files at
        sampling frequency 'fs'; 'mat' saves them as a MAT file along with
        related variables 'fs', 'freqs', 'trial_order', and 'rms'.
    rand_seed : int | None
        Seed for the random number generator.
    Returns
    -------
    wavs : dict | None
        If `save_as` is `'dict'`, then this will be a dict, else None.
    finalstim_tc :
    finalstim_nb :
    """
    if rand_seed is None:
        rng = np.random.RandomState()
    else:
        rng = np.random.RandomState(rand_seed)

    # check input arguments
    if save_as not in ['dict', 'wav', 'mat']:
        raise ValueError('"save_as" must be "dict", "wav", or "mat"')

    if fs is None:
        fs = get_tdt_rates()['25k']

    # General params:
    n = int(stim_dur * fs)    # total number of samples
    t = np.linspace(0, stim_dur, n, endpoint=False)    # time index for ploting

#### make tone complex#########################################################

    tonecomp = np.zeros(24414. * stim_dur, float)
    fund = 250.0                                # fundamental frequency
    for x in xrange(1, 5):
        freq = fund*x
        tonecomp = tonecomp + np.sin(freq * 2 * np.pi * np.arange
                                     (int(fs * stim_dur)) / float(fs))
    # windowing and onset/offset
    finalstim_tc = window_edges(tonecomp, fs, ramp_tone, -1, 'hamming')

    return finalstim_tc

##### make noise burst#########################################################

    # add 50 points extra
    nb = np.random.normal(0, 1.0, int(fs * stim_dur) + 50)

    ### highpass cut-off freq of 1500Hz using 100th order Hamming ###
    b = sig.firwin(101, 1500. / (fs / 2), pass_zero=False)  # False - highpass
                                                        # nyq_rate = fs / 2
                                                        # have to add '1' order
    filtered_stim = sig.lfilter(b, 1.0, nb)

    ### cut off extra 50 points from noiseburst ###
    filtered_stim = filtered_stim[50:]
    # windowing and onset/offset
    nb_ramped = window_edges(nb[50:], fs, ramp_noise, -1, 'hamming')
    finalstim_nb = np.multiply(nb_ramped, filtered_stim)

    return finalstim_nb
Exemplo n.º 8
0
This shows how to make simple vocoded stimuli.

@author: larsoner
"""

import numpy as np
import matplotlib.pyplot as plt

from expyfun.stimuli import vocode, play_sound, window_edges, read_wav, rms
from expyfun import fetch_data_file

print(__doc__)

data, fs = read_wav(fetch_data_file('audio/dream.wav'))
data = window_edges(data[0], fs)
t = np.arange(data.size) / float(fs)
# noise vocoder
data_noise = vocode(data, fs, mode='noise')
data_noise = data_noise * 0.01 / rms(data_noise)
# sinewave vocoder
data_tone = vocode(data, fs, mode='tone')
data_tone = data_tone * 0.01 / rms(data_tone)
# poisson vocoder
data_click = vocode(data, fs, mode='poisson', rate=400)
data_click = data_click * 0.01 / rms(data_click)

# combine all three
cutoff = data.shape[-1] // 3
data_allthree = data_noise.copy()
data_allthree[cutoff:2 * cutoff] = data_tone[cutoff:2 * cutoff]
# White noise burst
nb = np.random.uniform(-0.5, 0.5, (int(fs * stim_dur)))

### highpass cut-off freq of 1500Hz using 100th order Hamming ###
b = sig.firwin(101, 1500. / (fs / 2), pass_zero=False)  # False - highpass
                                                    # nyq_rate = fs / 2
                                                    # have to add '1' order
#filtered_stim = sig.lfilter(b, 1.0, nb)
filtered_stim = np.convolve(nb, b)

#### cut off extra 50 points from noiseburst ###
filtered_stim = filtered_stim[50:-50]   # not sure why I end up with extra

# windowing and onset/offset
finalstim_nb = window_edges(filtered_stim, fs, ramp_noise, -1, 'hamming')
#nb_ramped *= 0.01 * np.sqrt(2) # only works for sine tones
#x /= (xs rms) # sets the rms equal to 1 so then multiply by the target rms

#finalstim_nb = nb_ramped*noiseamp

# check the rms


############################################################################
tonecomp = np.zeros(24414. * stim_dur, float)
fund = 250.0                                # fundamental frequency
for x in xrange(1, 5):
    freq = fund*x
    tonecomp = tonecomp + np.sin(freq * 2 * np.pi * np.arange
                                 (int(fs * stim_dur)) / float(fs))
Exemplo n.º 10
0
    fs = 44100
    fc = 2e3
    sound_len = int(np.round(isi * 0.8 * fs))
    sound_dur = float(sound_len) / fs
#    sounds = stim.window_edges(np.random.randn(1, sound_len), fs,
#                               sound_dur / 2.5)
#    b, a = sig.butter(2, fc / (fs / 2))
#    sounds = sig.lfilter(b, a, sounds)
    t = np.arange(sound_len, dtype=float) / fs
    sounds = np.zeros(sound_len)
    f0 = 200
    for f in range(f0, 1301, f0):
        sounds += np.sin(2 * np.pi * t * f)
    sounds *= base_vol / stim.rms(sounds, keepdims=True)
    sounds *= np.exp(-t / sound_dur * 4)
    sounds = stim.window_edges(sounds, fs, 0.01)
else:
    assert(len(sound_files) == 1)
    temp = []
    for wav in sound_files:
        temp += [stim.read_wav(wav)[0]]
    fs = stim.read_wav(sound_files[0])[1]
    lens = [w.shape[1] for w in temp]
    sounds = np.zeros((2, np.max(lens)))
    for si, l in enumerate(lens):
        sounds[si, :l] = temp[si]
    sounds = sig.resample(sounds, 44100 * sounds.shape[1] / fs, axis=1)
    fs = 44100
    sound_len = sounds.shape[1]

### highpass cut-off freq of 1500Hz using 100th order Hamming ###
b = sig.firwin(101, 1500. / (fs / 2), pass_zero=False)  # False for highpass
                                                        # nyq_rate = fs / 2
                                                        # have to add '1' order
filtered_stim = sig.lfilter(b, 1.0, nb)
#plt.plot(filtered_stim)

### cut off extra 50 points from noiseburst ###

filtered_stim = filtered_stim[50:]

### windowing - onset and offset ramps ###
toneramp = 0.006
noiseramp = 0.003

nb_ramped = window_edges(nb[50:], fs, noiseramp, -1, 'hamming')
finalstim_nb = np.multiply(nb_ramped, filtered_stim)

finalstim_tc = window_edges(tonecomp, fs, toneramp, -1, 'hamming')


### create a two beep stimulus ###
# 8ms + 50ms + 8ms = 195 + 1220 + 195 which is a total of 1610 samples
interval = 0.050
gap = np.zeros(24414. * interval, float)

# if one beep:
onebeep = np.concatenate((finalstim_tc, gap), axis=1)


# if two beep:
Exemplo n.º 12
0
import numpy as np
import matplotlib.pyplot as plt

from expyfun.stimuli import window_edges, read_wav, rms
from expyfun import fetch_data_file

print(__doc__)

###############################################################################
# Load data
# ---------
# Get 2 seconds of data
data_orig, fs = read_wav(fetch_data_file('audio/dream.wav'))
stop = int(round(fs * 2))
data_orig = window_edges(data_orig[0, :stop], fs)
t = np.arange(data_orig.size) / float(fs)

# look at the waveform
fig, ax = plt.subplots()
ax.plot(t, data_orig)
ax.set(xlabel='Time (sec)',
       ylabel='Amplitude',
       title='Original',
       xlim=t[[0, -1]])
fig.tight_layout()

###############################################################################
# Normalize it
# ------------
# :class:`expyfun.ExperimentController` by default has ``stim_rms=0.01``. This