Воспроизвести случайный сегмент файла .wav с python - PullRequest
2 голосов
/ 08 января 2020

Для эксперимента я использую PsychoPy 3.0, программное обеспечение с открытым исходным кодом, которое запускается Python. Я надеюсь воспроизвести два отдельных файла .wav одновременно для разборчивости эксперимента; один файл - это речевой стимул, а другой - болтовня. Суть в том, что я хотел бы, чтобы эксперимент случайно выбрал часть болтовни, которая будет воспроизводиться вместе с файлом речевых стимулов (чтобы избежать того же сегмента речевой болтовни, воспроизводимой с каждым клипом речевых стимулов).

I удалось создать эксперимент, в котором два звуковых файла представлены одновременно; тем не менее, болтовня .wav файл всегда воспроизводится с начала файла; Я бы хотел, чтобы python / PsychoPy рандомизировал, когда он воспроизводится в файле babble.wav. Я использую звуковой движок Psychtoolbox (PsychPortAudio) для управления звуком.

Я приложил часть кода для воспроизведения двух волновых файлов, скомпилированных из PsychoPy. Переменная sound_2 - это файл болтового шума, который я хотел бы рандомизировать. Спасибо за любую помощь, которую вы можете предложить!

-Brandon

# ------Prepare to start Routine "SpeakerStimPrac"-------
# update component parameters for each repeat
sound_1.setSound(Sound, secs=Duration+0.5, hamming=True)
sound_1.setVolume(1, log=False)
sound_2.setSound(Noise, secs=Duration+1.5, hamming=True)
sound_2.setVolume(0.85, log=False)
# keep track of which components have finished
SpeakerStimPracComponents = [sound_1, text_5, sound_2]
for thisComponent in SpeakerStimPracComponents:
    thisComponent.tStart = None
    thisComponent.tStop = None
    thisComponent.tStartRefresh = None
    thisComponent.tStopRefresh = None
    if hasattr(thisComponent, 'status'):
        thisComponent.status = NOT_STARTED
# reset timers
t = 0
_timeToFirstFrame = win.getFutureFlipTime(clock="now")
SpeakerStimPracClock.reset(-_timeToFirstFrame)  # t0 is time of first possible flip
frameN = -1
continueRoutine = True

# -------Run Routine "SpeakerStimPrac"-------
while continueRoutine:
    # get current time
    t = SpeakerStimPracClock.getTime()
    tThisFlip = win.getFutureFlipTime(clock=SpeakerStimPracClock)
    tThisFlipGlobal = win.getFutureFlipTime(clock=None)
    frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
    # update/draw components on each frame
    # start/stop sound_1
    if sound_1.status == NOT_STARTED and tThisFlip >= 1.5-frameTolerance:
        # keep track of start time/frame for later
        sound_1.frameNStart = frameN  # exact frame index
        sound_1.tStart = t  # local t and not account for scr refresh
        sound_1.tStartRefresh = tThisFlipGlobal  # on global time
        sound_1.play(when=win)  # sync with win flip
    if sound_1.status == STARTED:
        # is it time to stop? (based on global clock, using actual start)
        if tThisFlipGlobal > sound_1.tStartRefresh + Duration+0.5-frameTolerance:
            # keep track of stop time/frame for later
            sound_1.tStop = t  # not accounting for scr refresh
            sound_1.frameNStop = frameN  # exact frame index
            win.timeOnFlip(sound_1, 'tStopRefresh')  # time at next scr refresh
            sound_1.stop()

    # *text_5* updates
    if text_5.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
        # keep track of start time/frame for later
        text_5.frameNStart = frameN  # exact frame index
        text_5.tStart = t  # local t and not account for scr refresh
        text_5.tStartRefresh = tThisFlipGlobal  # on global time
        win.timeOnFlip(text_5, 'tStartRefresh')  # time at next scr refresh
        text_5.setAutoDraw(True)
    if text_5.status == STARTED:
        # is it time to stop? (based on global clock, using actual start)
        if tThisFlipGlobal > text_5.tStartRefresh + .5-frameTolerance:
            # keep track of stop time/frame for later
            text_5.tStop = t  # not accounting for scr refresh
            text_5.frameNStop = frameN  # exact frame index
            win.timeOnFlip(text_5, 'tStopRefresh')  # time at next scr refresh
            text_5.setAutoDraw(False)
    # start/stop sound_2
    if sound_2.status == NOT_STARTED and tThisFlip >= .5-frameTolerance:
        # keep track of start time/frame for later
        sound_2.frameNStart = frameN  # exact frame index
        sound_2.tStart = t  # local t and not account for scr refresh
        sound_2.tStartRefresh = tThisFlipGlobal  # on global time
        sound_2.play(when=win)  # sync with win flip
    if sound_2.status == STARTED:
        # is it time to stop? (based on global clock, using actual start)
        if tThisFlipGlobal > sound_2.tStartRefresh + Duration+1.5-frameTolerance:
            # keep track of stop time/frame for later
            sound_2.tStop = t  # not accounting for scr refresh
            sound_2.frameNStop = frameN  # exact frame index
            win.timeOnFlip(sound_2, 'tStopRefresh')  # time at next scr refresh
            sound_2.stop()

    # check for quit (typically the Esc key)
    if endExpNow or defaultKeyboard.getKeys(keyList=["escape"]):
        core.quit()

    # check if all components have finished
    if not continueRoutine:  # a component has requested a forced-end of Routine
        break
    continueRoutine = False  # will revert to True if at least one component still running
    for thisComponent in SpeakerStimPracComponents:
        if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
            continueRoutine = True
            break  # at least one component has not yet finished

    # refresh the screen
    if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
        win.flip()

# -------Ending Routine "SpeakerStimPrac"-------
for thisComponent in SpeakerStimPracComponents:
    if hasattr(thisComponent, "setAutoDraw"):
        thisComponent.setAutoDraw(False)
sound_1.stop()  # ensure sound has stopped at end of routine
trials_2.addData('sound_1.started', sound_1.tStartRefresh)
trials_2.addData('sound_1.stopped', sound_1.tStopRefresh)
trials_2.addData('text_5.started', text_5.tStartRefresh)
trials_2.addData('text_5.stopped', text_5.tStopRefresh)
sound_2.stop()  # ensure sound has stopped at end of routine
trials_2.addData('sound_2.started', sound_2.tStartRefresh)
trials_2.addData('sound_2.stopped', sound_2.tStopRefresh)
# the Routine "SpeakerStimPrac" was not non-slip safe, so reset the non-slip timer
routineTimer.reset()

# set up handler to look after randomisation of conditions etc
trials = data.TrialHandler(nReps=1, method='random', 
    extraInfo=expInfo, originPath=-1,
    trialList=data.importConditions('intresponse.xlsx'),
    seed=None, name='trials')
thisExp.addLoop(trials)  # add the loop to the experiment
thisTrial = trials.trialList[0]  # so we can initialise stimuli with some values
# abbreviate parameter names if possible (e.g. rgb = thisTrial.rgb)
if thisTrial != None:
    for paramName in thisTrial:
        exec('{} = thisTrial[paramName]'.format(paramName))

for thisTrial in trials:
    currentLoop = trials
    # abbreviate parameter names if possible (e.g. rgb = thisTrial.rgb)
    if thisTrial != None:
        for paramName in thisTrial:
            exec('{} = thisTrial[paramName]'.format(paramName))
...