def test_wave_with_small_buffer(core): buff = np.sin(np.linspace(0, np.pi * 4, 100)) * 32000 buff = buff.astype(np.int16) wid = core.add_wave(100, 1, buff) buff2 = np.zeros(1500, dtype=np.int16) buff2[1000] = 12345 wid2 = core.add_wave(1500, 1, buff2) gid = core.add_generator(aserver.GeneratorType.WAVE) cfg = core.new_config("wave") cfg.config.flags = aserver.WaveFlags("WAVE_INDEX PLAYBACK_COMMAND").value cfg.waveIndex = wid cfg.command = aserver.PlaybackCommand.PLAY core.configure_generator(gid, cfg) core.add_source() gid = core.add_generator(aserver.GeneratorType.WAVE) cfg.waveIndex = wid2 core.configure_generator(gid, cfg) core.add_source() core.render(1) core.stop_output() rendered = core.get_output().astype(np.int16) assert all(rendered[:, 0] == rendered[:, 1]) # mono in two channels assert all(rendered[:100, 0] == buff) assert all(rendered[100:1000, 0] == 0) assert all(rendered[1001:, 0] == 0) assert rendered[1000, 0] == 12345
def test_script_loop(core): period_size = 441 render_periods = 3 wavelength = 220 should_be = np.zeros([period_size * render_periods, 2]) gid = core.add_generator(aserver.GeneratorType.SCRIPT) wave = np.random.uniform(-32000, 32000, wavelength).astype(np.int16) wid = core.add_wave(wavelength, 1, wave) n_keyframes = 2 cfg, keyframes = core.new_keyframes(n_keyframes) flags = aserver.WaveFlags("PLAYBACK_COMMAND WAVE_INDEX").value keyframes[0].wave.config.flags = flags keyframes[0].wave.waveIndex = wid keyframes[0].start = 0 keyframes[0].wave.command = aserver.PlaybackCommand.PLAY keyframes[1].start = 3 keyframes[1].wave.config.flags = aserver.KeyframeFlags.END core.configure_generator(gid, cfg) cfg.command = aserver.ScriptCommand.PLAY_LOOP core.configure_generator(gid, cfg) core.add_source() core.set_period(period_size) core.render(render_periods) core.stop_output() rendered = core.get_output().astype(np.int16) assert rendered[rendered == 0].shape[0] == 0
def test_distance_attenuation(core, hrtf): # core configuration period = 2048 core.set_period(period) core.set_output(aserver.OutputType.MEMORY) # test configuration n_periods = 10 n_positions = 5 offset = 5 * period measure_length = 2 * period distance_offset = 0 # processor configuration core.set_processor(aserver.ProcessorType.ACOUSTICAVE) cfg = core.new_config("acousticave") cfg.config.flags = aserver.AcousticaveFlags("HRTF").value cfg.hrtf = hrtf core.configure_processor(cfg) # wave generation length = 5 * 44100 wav = create_square_wave(length) wid = core.add_wave(length, 1, wav) # generator configuration gid = core.add_generator(aserver.GeneratorType.WAVE) cfg = core.new_config("wave") cfg.config.flags = aserver.WaveFlags("WAVE_INDEX PLAYBACK_COMMAND").value cfg.waveIndex = wid cfg.command = aserver.PlaybackCommand.PLAY core.configure_generator(gid, cfg) # source configuration core.add_source() for i in range(n_positions): cfg = core.new_config("source") cfg.location = [0., distance_offset + i * 2., 0.] core.configure_source(gid, cfg) core.render(n_periods) core.stop_output() rendered = core.get_output().astype(float) en_avgs = np.zeros([5, 2]) distances = np.zeros([5, 2]) distances[:, 0] = distances[:, 1] = np.arange(5, dtype=float) * 2 ref_atten = 1 / (distances + 1) for i in range(n_positions): start = offset + period * n_periods * i end = start + measure_length segment = rendered[start:end, :] seg_energy_avg = np.average(energy(segment), axis=0) en_avgs[i] = seg_energy_avg en_avgs_norm = en_avgs / en_avgs[0, :] print en_avgs_norm - ref_atten assert np.amax(en_avgs_norm - ref_atten) < 0.05
def test_script_boundaries(core, wavelength, offset): period_size = 441 render_periods = 3 should_be = np.zeros([period_size * render_periods, 2]) gid = core.add_generator(aserver.GeneratorType.SCRIPT) if (offset == -1): n_keyframes = 2 else: n_keyframes = 3 cfg, keyframes = core.new_keyframes(n_keyframes) kf_index = 0 for i in range(3): # calculate keyframe onset start = offset + i * 10 if start < 0: continue # generate and add waves wave = np.random.uniform(-32000, 32000, wavelength).astype(np.int16) wid = core.add_wave(wavelength, 1, wave) # generate and add keyframes flags = aserver.WaveFlags("PLAYBACK_COMMAND WAVE_INDEX").value keyframes[kf_index].wave.config.flags = flags keyframes[kf_index].wave.waveIndex = wid keyframes[kf_index].start = start keyframes[kf_index].wave.command = aserver.PlaybackCommand.PLAY kf_index += 1 # generate the expected output start *= 44.1 view = should_be[start:start + wavelength] view[:, 0] = wave[:view.shape[0]] view[:, 1] = wave[:view.shape[0]] core.configure_generator(gid, cfg) cfg.command = aserver.ScriptCommand.PLAY core.configure_generator(gid, cfg) core.add_source() core.set_period(period_size) core.render(3) core.stop_output() rendered = core.get_output().astype(np.int16) assert all(should_be[:, 0] == rendered[:, 0]) assert all(should_be[:, 1] == rendered[:, 1])
def test_wave(core): filename = "/tmp/test_wave.wav" data = write_test_wavefile(filename) gid = core.add_generator(aserver.GeneratorType.WAVE) cfg = core.new_config("wave") cfg.config.flags = aserver.WaveFlags("WAVE_INDEX PLAYBACK_COMMAND").value cfg.waveIndex = core.get_wave_index(filename) cfg.command = aserver.PlaybackCommand.PLAY core.configure_generator(gid, cfg) core.add_source() core.render(1) core.stop_output() rendered = core.get_output().astype(np.int16) assert all(rendered[:, 0] == rendered[:, 1]) # mono in two channels # assert the rendered data is exactly equal to the original wave assert all(rendered[:, 0] == data[:rendered.shape[0]].astype(np.int16))
def test_script_delay(core, delay): period_size = 441 render_periods = 6 wavelength = 220 should_be = np.zeros([period_size * render_periods, 2]) gid = core.add_generator(aserver.GeneratorType.SCRIPT) n_keyframes = 5 cfg, keyframes = core.new_keyframes(n_keyframes) for i in range(n_keyframes): # generate and add waves wave = np.random.uniform(-32000, 32000, wavelength).astype(np.int16) wid = core.add_wave(wavelength, 1, wave) # calculate keyframe onset start = i * 10 # generate and add keyframes flags = aserver.WaveFlags("PLAYBACK_COMMAND WAVE_INDEX").value keyframes[i].wave.config.flags = flags keyframes[i].wave.waveIndex = wid keyframes[i].start = start keyframes[i].wave.command = aserver.PlaybackCommand.PLAY # generate the expected output start += delay if start >= 0: start = start * 44100 // 1000 view = should_be[start:start + wavelength] view[:, 0] = wave[:view.shape[0]] view[:, 1] = wave[:view.shape[0]] core.configure_generator(gid, cfg) cfg.command = aserver.ScriptCommand.PLAY cfg.delay = delay core.configure_generator(gid, cfg) core.add_source() core.set_period(period_size) core.render(render_periods) core.stop_output() rendered = core.get_output().astype(np.int16) assert all(should_be[:, 0] == rendered[:, 0]) assert all(should_be[:, 1] == rendered[:, 1])
import numpy as np sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.bind(("0.0.0.0", 10101)) sock.setblocking(0) period = 132 # 1.4 ms @ 44100 Hz core = aserver.Core() core.set_period(period) core.set_processor() core.alsa_output(dump_config=True, blocking=False) gid = core.add_generator(aserver.GeneratorType.WAVE) cfg = core.new_config("wave") cfg.config.flags = aserver.WaveFlags("WAVE_INDEX PLAYBACK_COMMAND").value # cfg.waveIndex = core.get_wave_index(filename) cfg.waveIndex = core.add_wave( 441, 1, (3.2e4 * np.cos(np.linspace(0, np.pi * 10, 441))).astype(np.int16)) cfg.command = aserver.PlaybackCommand.PLAY core.add_source() core.start_render_loop() done = False while not done: try: time.sleep(1e-6) try: data, addr = sock.recvfrom(1024) except:
def test_z_is_up(core, hrtf): # core configuration period = 2048 core.set_period(period) core.set_output(aserver.OutputType.MEMORY) # processor configuration core.set_processor(aserver.ProcessorType.ACOUSTICAVE) cfg = core.new_config("acousticave") cfg.config.flags = aserver.AcousticaveFlags("HRTF").value cfg.hrtf = hrtf core.configure_processor(cfg) # noise generation length = period * 9 noise = create_noise(length) wid = core.add_wave(length, 1, noise) # generator configuration gid = core.add_generator(aserver.GeneratorType.WAVE) cfg = core.new_config("wave") cfg.config.flags = aserver.WaveFlags("WAVE_INDEX PLAYBACK_COMMAND").value cfg.waveIndex = wid cfg.command = aserver.PlaybackCommand.PLAY core.configure_generator(gid, cfg) # source configuration sid = core.add_source() cfg = core.new_config("source") cfg.location = [0., 0., 10.] core.configure_source(sid, cfg) core.render(10) cfg = core.new_config("wave") cfg.config.flags = aserver.WaveFlags("PLAYBACK_COMMAND").value cfg.command = aserver.PlaybackCommand.STOP core.configure_generator(gid, cfg) cfg = core.new_config("wave") cfg.config.flags = aserver.WaveFlags("WAVE_INDEX PLAYBACK_COMMAND").value cfg.waveIndex = wid cfg.command = aserver.PlaybackCommand.PLAY core.configure_generator(gid, cfg) cfg = core.new_config("acousticave") cfg.config.flags = aserver.AcousticaveFlags.AAVE_LISTENER_ORIENTATION cfg.orientation = [0., np.pi / 2., -np.pi / 2.] core.configure_processor(cfg) core.render(10) core.stop_output() rendered = core.get_output().astype(float) # test configuration n_periods = 10 n_positions = 2 offset = 4 * period measure_length = 5 * period en_avgs = np.zeros([2, 2]) for i in range(n_positions): start = offset + period * n_periods * i end = start + measure_length segment = rendered[start:end, :] seg_energy_avg = np.average(energy(segment), axis=0) en_avgs[i] = seg_energy_avg lr_en = en_avgs / np.amax(en_avgs, axis=1).reshape(n_positions, 1) fb_en = en_avgs / np.amax(en_avgs, axis=0) print en_avgs print lr_en print fb_en plt.plot(rendered) plt.show() # the channel closest to the listener position must have higher energy avg # the threshold for the furthest ear is ths = 0.25 assert np.absolute(lr_en[0, 1] - lr_en[0, 0]) > 0.75 assert np.absolute(lr_en[1, 0] - lr_en[1, 1]) > 0.75 # each channel, in the oposing position, must have significantly less # energy avg (ths = 0.25) assert fb_en[0, 1] - fb_en[1, 1] > 0.75 assert fb_en[1, 0] - fb_en[0, 0] > 0.75
def test_y_is_forward(core, hrtf): # core configuration period = 2048 core.set_period(period) core.set_output(aserver.OutputType.MEMORY) # processor configuration core.set_processor(aserver.ProcessorType.ACOUSTICAVE) cfg = core.new_config("acousticave") cfg.config.flags = aserver.AcousticaveFlags("HRTF").value cfg.hrtf = hrtf core.configure_processor(cfg) # noise generation length = period * 9 noise = create_noise(length) wid = core.add_wave(length, 1, noise) # generator configuration gid = core.add_generator(aserver.GeneratorType.WAVE) cfg = core.new_config("wave") cfg.config.flags = aserver.WaveFlags("WAVE_INDEX PLAYBACK_COMMAND").value cfg.waveIndex = wid cfg.command = aserver.PlaybackCommand.PLAY core.configure_generator(gid, cfg) # source configuration sid = core.add_source() cfg = core.new_config("source") cfg.location = [0., 10., 0.] core.configure_source(sid, cfg) core.render(10) cfg = core.new_config("wave") cfg.config.flags = aserver.WaveFlags("PLAYBACK_COMMAND").value cfg.command = aserver.PlaybackCommand.STOP core.configure_generator(gid, cfg) cfg = core.new_config("wave") cfg.config.flags = aserver.WaveFlags("WAVE_INDEX PLAYBACK_COMMAND").value cfg.waveIndex = wid cfg.command = aserver.PlaybackCommand.PLAY core.configure_generator(gid, cfg) # source configuration cfg = core.new_config("source") cfg.location = [0., -10., 0.] core.configure_source(sid, cfg) core.render(10) core.stop_output() rendered = core.get_output().astype(float) # test configuration n_periods = 10 n_positions = 2 offset = 4 * period measure_length = 5 * period en_avgs = np.zeros([2, 2]) for i in range(n_positions): start = offset + period * n_periods * i end = start + measure_length segment = rendered[start:end, :] seg_energy_avg = np.average(energy(segment), axis=0) en_avgs[i] = seg_energy_avg print en_avgs lr_en = en_avgs / np.amax(en_avgs, axis=1).reshape(n_positions, 1) fb_en = en_avgs / np.amax(en_avgs, axis=0) print lr_en print fb_en # the difference between the left and right channel energy in both # positions cannot be significant (ths = 0.1) assert np.absolute(lr_en[0, 0] - lr_en[0, 1]) < 0.1 assert np.absolute(lr_en[1, 0] - lr_en[1, 1]) < 0.1 # the front position must have higher energy avg than the back position assert fb_en[0, 0] > fb_en[1, 0] assert fb_en[0, 1] > fb_en[1, 1]