def hearing_test_audio(example_num): """ Retrieve audio for hearing test Parameters ---------- example_num : str The index of the example audio (1 or 2) Return ------ flask.Response """ if example_num == '0': # calibration if app.config['TEST_TYPE'] == 'segmentation': file_path = 'hearing_test_audio/seg_hearing.wav' else: file_path = 'hearing_test_audio/1000Hz.wav' else: hearing_test_audio_index = int( utilities.decrypt_data(session['hearing_test_audio_index%s' % example_num])) num_tones = hearing_test_audio_index / configuration.HEARING_TEST_AUDIO_FILES_PER_TONES file_num = hearing_test_audio_index % configuration.HEARING_TEST_AUDIO_FILES_PER_TONES logger.info('hearing_test %s - %d %d' % (example_num, num_tones, file_num)) file_path = 'hearing_test_audio/tones%d_%d.wav' % (num_tones, file_num) with open(file_path, 'rb') as f: response = make_response(f.read()) response.headers['Content-Type'] = 'audio/wav' response.headers['Accept-Ranges'] = 'bytes' return response
def audio(audio_file_key): """ Return audio from audio file URL in `audio_file_key` Parameters ---------- audio_file_key: str The encrypted key that contains a dictionary that included an item keyed by 'path' which is the location of the audio file Returns ------- flask.Response """ if app.config['ENCRYPT_AUDIO_STIMULI_URLS']: try: audio_file_dict = utilities.decrypt_data(str(audio_file_key)) # can also assert that this file is for this specific participant and condition assert (audio_file_dict['p_id'] == session['participant_id']) assert (audio_file_dict['g_id'] in session['condition_group_ids']) filename = audio_file_dict['URL'] except (ValueError, TypeError): filename = audio_file_key + '.wav' else: filename = audio_file_key + '.wav' return send_file_partial( safe_join(safe_join(app.root_path, app.config['AUDIO_FILE_DIRECTORY']), filename))
def hearing_test_audio(example_num): """ Retrieve audio for hearing test Parameters ---------- example_num : str The index of the example audio (1 or 2) Return ------ flask.Response """ if example_num == '0': # calibration if app.config['TEST_TYPE'] == 'segmentation': file_path = 'hearing_test_audio/seg_hearing.wav' else: file_path = 'hearing_test_audio/1000Hz.wav' else: hearing_test_audio_index = int(utilities.decrypt_data(session['hearing_test_audio_index%s' % example_num])) num_tones = hearing_test_audio_index / configuration.HEARING_TEST_AUDIO_FILES_PER_TONES file_num = hearing_test_audio_index % configuration.HEARING_TEST_AUDIO_FILES_PER_TONES logger.info('hearing_test %s - %d %d' % (example_num, num_tones, file_num)) file_path = 'hearing_test_audio/tones%d_%d.wav' % (num_tones, file_num) with open(file_path, 'rb') as f: response = make_response(f.read()) response.headers['Content-Type'] = 'audio/wav' response.headers['Accept-Ranges'] = 'bytes' return response
def audio(audio_file_key): """ Return audio from audio file URL in `audio_file_key` Parameters ---------- audio_file_key: str The encrypted key that contains a dictionary that included an item keyed by 'path' which is the location of the audio file Returns ------- flask.Response """ if app.config['AUDIO_CODEC'] == 'wav': file_format = '.wav' elif app.config['AUDIO_CODEC'] == 'mp3': file_format = '.mp3' if app.config['ENCRYPT_AUDIO_STIMULI_URLS']: try: audio_file_dict = utilities.decrypt_data(str(audio_file_key)) # can also assert that this file is for this specific participant and condition assert (audio_file_dict['p_id'] == session['participant_id']) assert (audio_file_dict['g_id'] in session['condition_group_ids']) filename = audio_file_dict['URL'] except (ValueError, TypeError): filename = audio_file_key + file_format else: filename = audio_file_key + file_format if app.config['EXTERNAL_FILE_HOST']: # return send_file_partial(app.config['AUDIO_FILE_DIRECTORY']+filename) return send_file_partial_hack(safe_join(app.config['AUDIO_FILE_DIRECTORY'], filename)) else: return send_file_partial(safe_join(safe_join(app.root_path, app.config['AUDIO_FILE_DIRECTORY']), filename))
def hearing_test(): """ Determines if the user is eligible to take the hearing test (i.e. has not exceeded `MAX_HEARING_TEST_ATTEMPTS`, and then renders the hearing test, which consists of the assessor counting the tones in two audio files. If caqe.settings.HEARING_TEST_REJECTION_ENABLED is set to False, then pass them through after they had their 2 attempts. Returns ------- flask.Response """ participant = get_current_participant(session) if request.method == 'GET': if participant.hearing_test_attempts >= app.config[ 'MAX_HEARING_TEST_ATTEMPTS']: logger.info('Max hearing test attempts reached - %r' % participant) return render_template( 'sorry.html', message='Sorry. You have exceed the number of allowed attempts. ' 'Please try again tomorrow.') while True: hearing_test_audio_index1 = random.randint( configuration.MIN_HEARING_TEST_AUDIO_INDEX, configuration.MAX_HEARING_TEST_AUDIO_INDEX) hearing_test_audio_index2 = random.randint( configuration.MIN_HEARING_TEST_AUDIO_INDEX, configuration.MAX_HEARING_TEST_AUDIO_INDEX) if hearing_test_audio_index1 != hearing_test_audio_index2: # encrypt the data so that someone can't figure out the pattern on the client side logger.info('Hearing test indices %d and %d assigned to %r' % (hearing_test_audio_index1, hearing_test_audio_index2, participant)) session['hearing_test_audio_index1'] = utilities.encrypt_data( hearing_test_audio_index1) session['hearing_test_audio_index2'] = utilities.encrypt_data( hearing_test_audio_index2) break return render_template('hearing_screening.html') elif request.method == 'POST': try: hearing_test_audio_index1 = session['hearing_test_audio_index1'] hearing_test_audio_index2 = session['hearing_test_audio_index2'] except KeyError as e: hearing_test_audio_index1 = None hearing_test_audio_index2 = None logger.error("Invalid state - %r" % e) if (int(request.form['audiofile1_tones']) == int(int(utilities.decrypt_data(hearing_test_audio_index1)) / configuration.HEARING_TEST_AUDIO_FILES_PER_TONES)) \ and (int(request.form['audiofile2_tones']) == int(int(utilities.decrypt_data(hearing_test_audio_index2)) / configuration.HEARING_TEST_AUDIO_FILES_PER_TONES)): logger.info('Hearing test passed - %r' % participant) participant.set_passed_hearing_test(True) db.session.commit() return pre_evaluation_tasks() else: logger.info('Hearing test failed - %r' % participant) participant.set_passed_hearing_test(False) db.session.commit() if participant.hearing_test_attempts < app.config[ 'MAX_HEARING_TEST_ATTEMPTS']: flash( 'You answered incorrectly. If you are unable to pass this test, it is likely that your output ' 'device (e.g. your headphones) is not producing the full range of frequencies required for this ' 'task. Try using better headphones.', 'danger') else: if not app.config['HEARING_TEST_REJECTION_ENABLED']: # They attempted, but they failed, but pass them through since rejection is not enabled logger.info( 'Hearing test rejection enabled. Passing failed participant to evaluation.' ) return pre_evaluation_tasks() return redirect( url_for('hearing_test', _method='GET', _external=True, _scheme=app.config['PREFERRED_URL_SCHEME']))
def _decode_url(encrypted_url): # remove /audio/ encrypted_data = encrypted_url[7:] # remove .wav encrypted_data = encrypted_data[:-4] return utilities.decrypt_data(str(encrypted_data))
def hearing_test(): """ Determines if the user is eligible to take the hearing test (i.e. has not exceeded `MAX_HEARING_TEST_ATTEMPTS`, and then renders the hearing test, which consists of the assessor counting the tones in two audio files. If caqe.settings.HEARING_TEST_REJECTION_ENABLED is set to False, then pass them through after they had their 2 attempts. Returns ------- flask.Response """ participant = get_current_participant(session) if request.method == 'GET': if participant.hearing_test_attempts >= app.config['MAX_HEARING_TEST_ATTEMPTS']: logger.info('Max hearing test attempts reached - %r' % participant) return render_template('sorry.html', message='Sorry. You have exceed the number of allowed attempts. ' 'Please try again tomorrow.') while True: hearing_test_audio_index1 = random.randint(configuration.MIN_HEARING_TEST_AUDIO_INDEX, configuration.MAX_HEARING_TEST_AUDIO_INDEX) hearing_test_audio_index2 = random.randint(configuration.MIN_HEARING_TEST_AUDIO_INDEX, configuration.MAX_HEARING_TEST_AUDIO_INDEX) if hearing_test_audio_index1 != hearing_test_audio_index2: # encrypt the data so that someone can't figure out the pattern on the client side logger.info('Hearing test indices %d and %d assigned to %r' % (hearing_test_audio_index1, hearing_test_audio_index2, participant)) session['hearing_test_audio_index1'] = utilities.encrypt_data(hearing_test_audio_index1) session['hearing_test_audio_index2'] = utilities.encrypt_data(hearing_test_audio_index2) break return render_template('hearing_screening.html') elif request.method == 'POST': try: hearing_test_audio_index1 = session['hearing_test_audio_index1'] hearing_test_audio_index2 = session['hearing_test_audio_index2'] except KeyError as e: hearing_test_audio_index1 = None hearing_test_audio_index2 = None logger.error("Invalid state - %r" % e) if (int(request.form['audiofile1_tones']) == (int(utilities.decrypt_data(hearing_test_audio_index1)) / configuration.HEARING_TEST_AUDIO_FILES_PER_TONES)) \ and (int(request.form['audiofile2_tones']) == (int(utilities.decrypt_data(hearing_test_audio_index2)) / configuration.HEARING_TEST_AUDIO_FILES_PER_TONES)): logger.info('Hearing test passed - %r' % participant) participant.set_passed_hearing_test(True) db.session.commit() return pre_evaluation_tasks() else: logger.info('Hearing test failed - %r' % participant) participant.set_passed_hearing_test(False) db.session.commit() if participant.hearing_test_attempts < app.config['MAX_HEARING_TEST_ATTEMPTS']: flash('You answered incorrectly. If you are unable to pass this test, it is likely that your output ' 'device (e.g. your headphones) is not producing the full range of frequencies required for this ' 'task. Try using better headphones.', 'danger') else: if not app.config['HEARING_TEST_REJECTION_ENABLED']: # They attempted, but they failed, but pass them through since rejection is not enabled logger.info('Hearing test rejection enabled. Passing failed participant to evaluation.') return pre_evaluation_tasks() return redirect(url_for('hearing_test', _method='GET', _external=True, _scheme=app.config['PREFERRED_URL_SCHEME']))