END_TEST START_TEST(Initial_tempo_is_set_correctly) { set_audio_rate(mixing_rates[MIXING_RATE_LOW]); set_mix_volume(0); setup_debug_instrument(); setup_debug_single_pulse(); int tempos[] = { 30, 60, 120, 240, 0 }; // 0 is guard, shouldn't be used set_data("album/p_manifest.json", "{}"); set_data("album/p_tracks.json", "[0]"); set_data("song_00/p_manifest.json", "{}"); set_data("song_00/p_order_list.json", "[ [0, 0] ]"); char tempo_data[128] = ""; snprintf(tempo_data, sizeof(tempo_data), "%d", tempos[_i]); set_data("song_00/p_tempo.json", tempo_data); set_data("pat_000/p_manifest.json", "{}"); set_data("pat_000/p_length.json", "[4, 0]"); set_data("pat_000/instance_000/p_manifest.json", "{}"); set_data("pat_000/col_00/p_triggers.json", "[ [[0, 0], [\"n+\", \"0\"]], [[1, 0], [\"n+\", \"0\"]] ]"); validate(); float actual_buf[buf_len] = { 0.0f }; mix_and_fill(actual_buf, buf_len); float expected_buf[buf_len] = { 1.0f }; expected_buf[mixing_rates[MIXING_RATE_LOW] * 60 / tempos[_i]] = 1.0f; check_buffers_equal(expected_buf, actual_buf, buf_len, 0.0f); }
END_TEST START_TEST(Pattern_delay_inserts_gap_between_adjacent_triggers) { set_audio_rate(mixing_rates[MIXING_RATE_LOW]); set_mix_volume(0); setup_debug_instrument(); setup_debug_single_pulse(); set_data("album/p_manifest.json", "{}"); set_data("album/p_tracks.json", "[0]"); set_data("song_00/p_manifest.json", "{}"); set_data("song_00/p_order_list.json", "[ [0, 0] ]"); set_data("pat_000/p_manifest.json", "{}"); set_data("pat_000/p_length.json", "[4, 0]"); set_data("pat_000/instance_000/p_manifest.json", "{}"); char triggers[128] = ""; snprintf(triggers, sizeof(triggers), "[ [[0, 0], [\"n+\", \"0\"]]," " [[0, 0], [\"mpd\", \"%d\"]]," " [[0, 0], [\"n+\", \"0\"]] ]", _i * 2); set_data("pat_000/col_00/p_triggers.json", triggers); validate(); float actual_buf[buf_len] = { 0.0f }; mix_and_fill(actual_buf, buf_len); float expected_buf[buf_len] = { 0.0f }; expected_buf[0] = 1.0f; expected_buf[mixing_rates[MIXING_RATE_LOW] * _i] += 1.0f; check_buffers_equal(expected_buf, actual_buf, buf_len, 0.0f); }
END_TEST START_TEST(Note_end_is_reached_correctly_during_note_off) { set_audio_rate(440); set_mix_volume(0); setup_debug_instrument(); pause(); float actual_buf[buf_len] = { 0.0f }; const int note_off_frame = 70; kqt_Handle_fire_event(handle, 0, Note_On_55_Hz); check_unexpected_error(); mix_and_fill(actual_buf, note_off_frame); // Note Off kqt_Handle_fire_event(handle, 0, "[\"n-\", null]"); check_unexpected_error(); mix_and_fill(actual_buf + note_off_frame, buf_len - note_off_frame); float expected_buf[buf_len] = { 0.0f }; float seq_on[] = { 1.0f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f }; int offset = repeat_seq_local(expected_buf, 8, seq_on); float seq_on_tail[] = { 1.0f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f }; offset += repeat_seq_local(expected_buf + offset, 1, seq_on_tail); float seq_off[] = { -0.5f, -0.5f, -1.0f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f }; repeat_seq_local(expected_buf + offset, 1, seq_off); check_buffers_equal(expected_buf, actual_buf, buf_len, 0.0f); }
END_TEST START_TEST(Independent_notes_mix_correctly) { set_audio_rate(220); set_mix_volume(0); setup_debug_instrument(); pause(); float actual_buf[buf_len] = { 0.0f }; const int note_2_frame = 2; kqt_Handle_fire_event(handle, 0, Note_On_55_Hz); check_unexpected_error(); mix_and_fill(actual_buf, note_2_frame); kqt_Handle_fire_event(handle, 1, Note_On_55_Hz); check_unexpected_error(); mix_and_fill(actual_buf + note_2_frame, buf_len - note_2_frame); float expected_buf[buf_len] = { 0.0f }; float single_seq[] = { 1.0f, 0.5f, 0.5f, 0.5f }; repeat_seq_local(expected_buf, 10, single_seq); for (int i = 40; i >= 0; --i) expected_buf[i + note_2_frame] += expected_buf[i]; check_buffers_equal(expected_buf, actual_buf, buf_len, 0.0f); }
void child_sound_init_mac() { OSStatus err; mac_printf("In mac child\n"); fflush(stdout); mac_printf("pid: %d\n", getpid()); fflush(stdout); //return; //g_snd_channel_ptr = 0; err = SndNewChannel(&g_snd_channel_ptr, sampledSynth, initStereo, NewSndCallBackUPP(mac_snd_callback)); mac_printf("SndNewChannel ret: %d\n", (int)err); fflush(stdout); memset(&g_snd_hdr, 0, sizeof(g_snd_hdr)); g_snd_hdr.sampleSize = 16; g_snd_hdr.numChannels = 2; g_audio_rate = 44100; g_snd_hdr.sampleRate = g_audio_rate << 16; g_snd_hdr.numFrames = 0; // will be set in mac_send_audio g_snd_hdr.encode = extSH; g_snd_hdr.baseFrequency = 0; g_snd_hdr.samplePtr = 0; set_audio_rate(g_audio_rate); mac_printf("End of child_sound_init_mac\n"); fflush(stdout); }
END_TEST START_TEST(Implicit_note_off_is_triggered_correctly) { set_audio_rate(220); set_mix_volume(0); setup_debug_instrument(); pause(); float actual_buf[buf_len] = { 0.0f }; const int note_2_frame = 2; kqt_Handle_fire_event(handle, 0, Note_On_55_Hz); check_unexpected_error(); mix_and_fill(actual_buf, note_2_frame); kqt_Handle_fire_event(handle, 0, Note_On_55_Hz); check_unexpected_error(); mix_and_fill(actual_buf + note_2_frame, buf_len - note_2_frame); float expected_buf[buf_len] = { 0.0f }; float seq_1_on[] = { 1.0f, 0.5f }; int offset = repeat_seq_local(expected_buf, 1, seq_1_on); float seq_1_off[] = { 0.5f, 0.0f, -0.5f, 0.0f }; offset += repeat_seq_local(expected_buf + offset, 2, seq_1_off); float seq_2[] = { 1.0f, 0.5f, 0.5f, 0.5f }; repeat_seq_local(expected_buf + offset, 8, seq_2); check_buffers_equal(expected_buf, actual_buf, buf_len, 0.0f); }
END_TEST START_TEST(Pattern_playback_pauses_zero_length_pattern) { set_audio_rate(mixing_rates[MIXING_RATE_LOW]); set_mix_volume(0); setup_debug_instrument(); setup_debug_single_pulse(); set_data("album/p_manifest.json", "{}"); set_data("album/p_tracks.json", "[0]"); set_data("song_00/p_manifest.json", "{}"); set_data("song_00/p_order_list.json", "[ [1, 0], [0, 0], [1, 1] ]"); set_data("pat_000/p_manifest.json", "{}"); set_data("pat_000/p_length.json", "[0, 0]"); set_data("pat_000/instance_000/p_manifest.json", "{}"); set_data("pat_000/col_00/p_triggers.json", "[ [[0, 0], [\"n+\", \"0\"]] ]"); set_data("pat_001/p_manifest.json", "{}"); set_data("pat_001/p_length.json", "[16, 0]"); set_data("pat_001/instance_000/p_manifest.json", "{}"); set_data("pat_001/instance_001/p_manifest.json", "{}"); set_data("pat_001/col_01/p_triggers.json", "[ [[0, 0], [\"n+\", \"0\"]], [[1, 0], [\"n+\", \"0\"]] ]"); validate(); kqt_Handle_fire_event(handle, 0, "[\"cpattern\", [0, 0]]"); float actual_buf[buf_len] = { 0.0f }; long frames_left = buf_len; long buf_offset = 0; for (int i = 0; i < 100 && frames_left > 0; ++i) { kqt_Handle_play(handle, frames_left); check_unexpected_error(); const long frames_available = kqt_Handle_get_frames_available(handle); const float* ret_buf = kqt_Handle_get_audio(handle, 0); check_unexpected_error(); memcpy(actual_buf + buf_offset, ret_buf, (size_t)frames_available * sizeof(float)); buf_offset += frames_available; frames_left -= frames_available; } fail_if(frames_left == buf_len, "Pattern playback of zero-length pattern produces no audio"); float expected_buf[buf_len] = { 0.0f }; expected_buf[0] = 1.0f; check_buffers_equal(expected_buf, actual_buf, buf_len, 0.0f); }
END_TEST START_TEST(Empty_pattern_contains_silence) { set_audio_rate(mixing_rates[_i]); setup_debug_instrument(); set_data("album/p_manifest.json", "{}"); set_data("album/p_tracks.json", "[0]"); set_data("song_00/p_manifest.json", "{}"); set_data("song_00/p_order_list.json", "[ [0, 0] ]"); set_data("pat_000/p_manifest.json", "{}"); set_data("pat_000/p_length.json", "[16, 0]"); set_data("pat_000/instance_000/p_manifest.json", "{}"); validate(); const long expected_length = 8 * mixing_rates[_i]; long actual_length = 0; kqt_Handle_play(handle, 4096); check_unexpected_error(); while (!kqt_Handle_has_stopped(handle)) { const long nframes = kqt_Handle_get_frames_available(handle); check_unexpected_error(); actual_length += nframes; // Don't want to spend too much time on this... if (_i == MIXING_RATE_LOW) { const float* bufs[] = { kqt_Handle_get_audio(handle, 0), kqt_Handle_get_audio(handle, 1), }; check_unexpected_error(); float expected_buf[128] = { 0.0f }; assert(nframes <= 128); check_buffers_equal(expected_buf, bufs[0], nframes, 0.0f); check_buffers_equal(expected_buf, bufs[1], nframes, 0.0f); } kqt_Handle_play(handle, 4096); check_unexpected_error(); } const long nframes = kqt_Handle_get_frames_available(handle); check_unexpected_error(); actual_length += nframes; fail_unless(actual_length == expected_length, "Wrong number of frames rendered" KT_VALUES("%ld", expected_length, actual_length)); }
void x_snd_child_init() { printf("x_snd_child_init"); if (!dev) { printf("err: async_sound_init not called\n"); return ; } set_audio_rate(g_sound.g_audio_rate); }
END_TEST START_TEST(Query_voice_count_with_silence) { set_audio_rate(220); pause(); kqt_Handle_play(handle, 128); kqt_Handle_fire_event(handle, 0, "[\"qvoices\", null]"); const char* events = kqt_Handle_receive_events(handle); const char* expected = "[[0, [\"qvoices\", null]], [0, [\"Avoices\", 0]]]"; fail_if(strcmp(events, expected) != 0, "Received event list %s instead of %s", events, expected); }
END_TEST START_TEST(Effect_with_double_volume_dsp_and_bypass_triples_volume) { set_audio_rate(220); set_mix_volume(0); pause(); set_data("p_control_map.json", "[ [0, 0] ]"); set_data("control_00/p_manifest.json", "{}"); make_debug_instrument(); set_data("au_01/p_manifest.json", "{ \"type\": \"effect\" }"); set_data("au_01/in_00/p_manifest.json", "{}"); set_data("au_01/out_00/p_manifest.json", "{}"); set_data("au_01/proc_00/p_manifest.json", "{ \"type\": \"volume\" }"); set_data("au_01/proc_00/p_signal_type.json", "\"mixed\""); set_data("au_01/proc_00/in_00/p_manifest.json", "{}"); set_data("au_01/proc_00/out_00/p_manifest.json", "{}"); set_data("au_01/proc_00/c/p_f_volume.json", "6"); set_data("au_01/p_connections.json", "[ [\"in_00\", \"out_00\"]," " [\"in_00\", \"proc_00/C/in_00\"]," " [\"proc_00/C/out_00\", \"out_00\"] ]"); set_data("out_00/p_manifest.json", "{}"); set_data("p_connections.json", "[ [\"au_00/out_00\", \"au_01/in_00\"]," " [\"au_01/out_00\", \"out_00\"] ]"); validate(); float actual_buf[buf_len] = { 0.0f }; kqt_Handle_fire_event(handle, 0, Note_On_55_Hz); check_unexpected_error(); mix_and_fill(actual_buf, buf_len); float expected_buf[buf_len] = { 0.0f }; float seq[] = { 3.0f, 1.5f, 1.5f, 1.5f }; repeat_seq_local(expected_buf, 10, seq); check_buffers_equal(expected_buf, actual_buf, buf_len, 0.0f); }
END_TEST START_TEST(Tempo_change_affects_playback_cursor) { set_audio_rate(mixing_rates[MIXING_RATE_LOW]); set_mix_volume(0); setup_debug_instrument(); setup_debug_single_pulse(); int tempos[] = { 30, 60, 120, 240, 0 }; // 0 is guard, shouldn't be used set_data("album/p_manifest.json", "{}"); set_data("album/p_tracks.json", "[0]"); set_data("song_00/p_manifest.json", "{}"); set_data("song_00/p_order_list.json", "[ [0, 0] ]"); set_data("pat_000/p_manifest.json", "{}"); set_data("pat_000/p_length.json", "[4, 0]"); set_data("pat_000/instance_000/p_manifest.json", "{}"); char triggers[256] = ""; snprintf(triggers, sizeof(triggers), "[ [[0, 0], [\"n+\", \"0\"]]," " [[1, 0], [\"n+\", \"0\"]]," " [[1, 0], [\"m.t\", \"%d\"]]," " [[2, 0], [\"n+\", \"0\"]] ]", tempos[_i]); set_data("pat_000/col_00/p_triggers.json", triggers); validate(); float actual_buf[buf_len] = { 0.0f }; mix_and_fill(actual_buf, buf_len); float expected_buf[buf_len] = { 0.0f }; expected_buf[0] = 1.0f; const long second_offset = mixing_rates[MIXING_RATE_LOW] / 2; expected_buf[second_offset] = 1.0f; const long beat_len = mixing_rates[MIXING_RATE_LOW] * 60 / tempos[_i]; expected_buf[second_offset + beat_len] = 1.0f; check_buffers_equal(expected_buf, actual_buf, buf_len, 0.0f); }
END_TEST START_TEST(Query_final_location) { set_audio_rate(220); setup_query_patterns(); kqt_Handle_play(handle, 2048); kqt_Handle_fire_event(handle, 0, "[\"qlocation\", null]"); const char* events = kqt_Handle_receive_events(handle); const char* expected = "[[0, [\"qlocation\", null]]" ", [0, [\"Atrack\", 0]], [0, [\"Asystem\", 1]]" ", [0, [\"Apattern\", [0, 1]]], [0, [\"Arow\", [4, 0]]]" "]"; fail_if(strcmp(events, expected) != 0, "Received event list %s instead of %s", events, expected); }
END_TEST START_TEST(Skipping_moves_position_forwards) { set_audio_rate(mixing_rates[MIXING_RATE_LOW]); set_mix_volume(0); setup_debug_instrument(); setup_debug_single_pulse(); set_data("album/p_manifest.json", "{}"); set_data("album/p_tracks.json", "[0]"); set_data("song_00/p_manifest.json", "{}"); set_data("song_00/p_order_list.json", "[ [0, 0] ]"); set_data("pat_000/p_manifest.json", "{}"); set_data("pat_000/p_length.json", "[8, 0]"); set_data("pat_000/instance_000/p_manifest.json", "{}"); set_data("pat_000/col_00/p_triggers.json", "[ [[0, 0], [\"n+\", \"0\"]]," " [[1, 0], [\"n+\", \"0\"]]," " [[2, 0], [\"n+\", \"0\"]]," " [[3, 0], [\"n+\", \"0\"]]," " [[4, 0], [\"n+\", \"0\"]] ]"); validate(); static const long long second = 1000000000LL; kqt_Handle_set_position(handle, 0, _i * second / 2); //Player_skip(player, _i * mixing_rates[MIXING_RATE_LOW] / 2); check_unexpected_error(); float actual_buf[buf_len] = { 0.0f }; mix_and_fill(actual_buf, buf_len); float expected_buf[buf_len] = { 0.0f }; for (int i = 0; i < 5 - _i; ++i) expected_buf[i * mixing_rates[MIXING_RATE_LOW] / 2] = 1.0f; check_buffers_equal(expected_buf, actual_buf, buf_len, 0.0f); }
END_TEST START_TEST(Note_on_at_pattern_end_is_handled) { set_audio_rate(mixing_rates[MIXING_RATE_LOW]); set_mix_volume(0); setup_debug_instrument(); setup_debug_single_pulse(); set_data("album/p_manifest.json", "{}"); set_data("album/p_tracks.json", "[0]"); set_data("song_00/p_manifest.json", "{}"); set_data("song_00/p_order_list.json", "[ [0, 0], [1, 0] ]"); char pat0_length[128] = ""; snprintf(pat0_length, sizeof(pat0_length), "[%d, 0]", _i); set_data("pat_000/p_manifest.json", "{}"); set_data("pat_000/p_length.json", pat0_length); set_data("pat_000/instance_000/p_manifest.json", "{}"); char col_def[128] = ""; snprintf(col_def, sizeof(col_def), "[ [[%d, 0], [\"n+\", \"0\"]] ]", _i); set_data("pat_000/col_00/p_triggers.json", col_def); set_data("pat_001/p_manifest.json", "{}"); set_data("pat_001/p_length.json", "[8, 0]"); set_data("pat_001/instance_000/p_manifest.json", "{}"); validate(); float actual_buf[buf_len] = { 0.0f }; mix_and_fill(actual_buf, buf_len); float expected_buf[buf_len] = { 0.0f }; expected_buf[mixing_rates[MIXING_RATE_LOW] * _i / 2] = 1.0f; check_buffers_equal(expected_buf, actual_buf, buf_len, 0.0f); }
END_TEST START_TEST(Jump_backwards_creates_a_loop) { set_audio_rate(mixing_rates[MIXING_RATE_LOW]); set_mix_volume(0); setup_debug_instrument(); setup_debug_single_pulse(); set_data("album/p_manifest.json", "{}"); set_data("album/p_tracks.json", "[0]"); set_data("song_00/p_manifest.json", "{}"); set_data("song_00/p_order_list.json", "[ [0, 0] ]"); set_data("pat_000/p_manifest.json", "{}"); set_data("pat_000/p_length.json", "[4, 0]"); set_data("pat_000/instance_000/p_manifest.json", "{}"); char triggers[256] = ""; snprintf(triggers, sizeof(triggers), "[ [[0, 0], [\"n+\", \"0\"]]," " [[2, 0], [\"m.jc\", \"%d\"]]," " [[2, 0], [\"mj\", null]] ]", _i); set_data("pat_000/col_00/p_triggers.json", triggers); validate(); float actual_buf[buf_len] = { 0.0f }; mix_and_fill(actual_buf, buf_len); float expected_buf[buf_len] = { 0.0f }; expected_buf[0] = 1.0f; for (int i = 0; i < _i; ++i) { const long dist = mixing_rates[MIXING_RATE_LOW]; expected_buf[dist + (i * dist)] = 1.0f; } check_buffers_equal(expected_buf, actual_buf, buf_len, 0.0f); }
END_TEST START_TEST(Pattern_playback_repeats_pattern) { set_audio_rate(mixing_rates[MIXING_RATE_LOW]); set_mix_volume(0); setup_debug_instrument(); setup_debug_single_pulse(); set_data("album/p_manifest.json", "{}"); set_data("album/p_tracks.json", "[0]"); set_data("song_00/p_manifest.json", "{}"); set_data("song_00/p_order_list.json", "[ [1, 0], [0, 0], [1, 1] ]"); set_data("pat_000/p_manifest.json", "{}"); set_data("pat_000/p_length.json", "[1, 0]"); set_data("pat_000/instance_000/p_manifest.json", "{}"); set_data("pat_000/col_00/p_triggers.json", "[ [[0, 0], [\"n+\", \"0\"]] ]"); set_data("pat_001/p_manifest.json", "{}"); set_data("pat_001/p_length.json", "[16, 0]"); set_data("pat_001/instance_000/p_manifest.json", "{}"); set_data("pat_001/instance_001/p_manifest.json", "{}"); validate(); kqt_Handle_fire_event(handle, 0, "[\"cpattern\", [0, 0]]"); float actual_buf[buf_len] = { 0.0f }; mix_and_fill(actual_buf, buf_len); float expected_buf[buf_len] = { 0.0f }; for (long i = 0; i < buf_len; i += mixing_rates[MIXING_RATE_LOW] / 2) expected_buf[i] = 1.0f; check_buffers_equal(expected_buf, actual_buf, buf_len, 0.0f); }
END_TEST START_TEST(Setting_type_syncs_keys) { set_mix_volume(0); set_audio_rate(220); pause(); setup_debug_single_pulse(); setup_debug_instrument(); float actual_buf[buf_len] = { 0.0f }; kqt_Handle_fire_event(handle, 0, Note_On_55_Hz); check_unexpected_error(); mix_and_fill(actual_buf, buf_len); float expected_buf[buf_len] = { 0.0f }; expected_buf[0] = 1.0f; check_buffers_equal(expected_buf, actual_buf, buf_len, 0.0f); }
END_TEST START_TEST(Query_voice_count_with_note) { set_audio_rate(220); setup_debug_instrument(); pause(); kqt_Handle_fire_event(handle, 0, Note_On_55_Hz); kqt_Handle_play(handle, 1); kqt_Handle_fire_event(handle, 0, "[\"qvoices\", null]"); const char* events2 = kqt_Handle_receive_events(handle); const char* expected2 = "[[0, [\"qvoices\", null]], [0, [\"Avoices\", 2]]]"; fail_if(strcmp(events2, expected2) != 0, "Received event list %s instead of %s", events2, expected2); kqt_Handle_play(handle, 2048); kqt_Handle_fire_event(handle, 0, "[\"qvoices\", null]"); const char* events1 = kqt_Handle_receive_events(handle); const char* expected1 = "[[0, [\"qvoices\", null]], [0, [\"Avoices\", 1]]]"; fail_if(strcmp(events1, expected1) != 0, "Received event list %s instead of %s", events1, expected1); kqt_Handle_play(handle, 1); kqt_Handle_fire_event(handle, 0, "[\"qvoices\", null]"); const char* events0 = kqt_Handle_receive_events(handle); const char* expected0 = "[[0, [\"qvoices\", null]], [0, [\"Avoices\", 0]]]"; fail_if(strcmp(events0, expected0) != 0, "Received event list %s instead of %s", events0, expected0); }
END_TEST START_TEST(Infinite_mode_loops_composition) { set_audio_rate(mixing_rates[MIXING_RATE_LOW]); set_mix_volume(0); setup_debug_instrument(); setup_debug_single_pulse(); set_data("album/p_manifest.json", "{}"); set_data("album/p_tracks.json", "[0]"); set_data("song_00/p_manifest.json", "{}"); set_data("song_00/p_order_list.json", "[ [0, 0] ]"); set_data("pat_000/p_manifest.json", "{}"); set_data("pat_000/p_length.json", "[2, 0]"); set_data("pat_000/instance_000/p_manifest.json", "{}"); set_data("pat_000/col_00/p_triggers.json", "[ [[0, 0], [\"n+\", \"0\"]] ]"); validate(); kqt_Handle_fire_event(handle, 0, "[\"cinfinite+\", null]"); check_unexpected_error(); float actual_buf[buf_len] = { 0.0f }; const long mixed = mix_and_fill(actual_buf, buf_len); fail_unless(mixed == buf_len, "Wrong number of frames mixed" KT_VALUES("%ld", buf_len, mixed)); float expected_buf[buf_len] = { 0.0f }; for (long i = 0; i < buf_len; i += mixing_rates[MIXING_RATE_LOW]) expected_buf[i] = 1.0f; check_buffers_equal(expected_buf, actual_buf, buf_len, 0.0f); }
END_TEST START_TEST(Add_and_remove_internal_effect_and_render) { set_audio_rate(220); set_mix_volume(0); setup_debug_instrument(); setup_debug_single_pulse(); float actual_buf[buf_len] = { 0.0f }; // Add silence set_data("album/p_manifest.json", "{}"); set_data("album/p_tracks.json", "[0]"); set_data("song_00/p_manifest.json", "{}"); set_data("song_00/p_order_list.json", "[ [0, 0] ]"); set_data("pat_000/p_manifest.json", "{}"); set_data("pat_000/p_length.json", "[16, 0]"); set_data("pat_000/instance_000/p_manifest.json", "{}"); // Add internal audio unit set_data("au_00/au_00/p_manifest.json", "{ \"type\": \"effect\" }"); set_data("au_00/au_00/in_00/p_manifest.json", "{}"); set_data("au_00/au_00/out_00/p_manifest.json", "{}"); set_data( "au_00/p_connections.json", "[ [\"proc_00/C/out_00\", \"out_00\"]" ", [\"proc_00/C/out_00\", \"au_00/in_00\"]" ", [\"au_00/out_00\", \"out_00\"] ]"); // Add processor inside the internal audio unit set_data("au_00/au_00/proc_00/in_00/p_manifest.json", "{}"); set_data("au_00/au_00/proc_00/out_00/p_manifest.json", "{}"); set_data("au_00/au_00/proc_00/p_manifest.json", "{ \"type\": \"volume\" }"); set_data("au_00/au_00/proc_00/p_signal_type.json", "\"mixed\""); set_data( "au_00/au_00/p_connections.json", "[ [\"in_00\", \"proc_00/C/in_00\"]" ", [\"proc_00/C/out_00\", \"out_00\"] ]"); validate(); check_unexpected_error(); // Test rendering mix_and_fill(actual_buf, buf_len); // Remove the internal audio unit set_data("au_00/p_connections.json", "[ [\"proc_00/C/out_00\", \"out_00\"] ]"); set_data("au_00/au_00/in_00/p_manifest.json", ""); set_data("au_00/au_00/out_00/p_manifest.json", ""); set_data("au_00/au_00/p_connections.json", ""); set_data("au_00/au_00/p_manifest.json", ""); set_data("au_00/au_00/proc_00/in_00/p_manifest.json", ""); set_data("au_00/au_00/proc_00/out_00/p_manifest.json", ""); set_data("au_00/au_00/proc_00/p_manifest.json", ""); set_data("au_00/au_00/proc_00/p_signal_type.json", ""); validate(); check_unexpected_error(); // Test rendering again kqt_Handle_set_position(handle, 0, 0); mix_and_fill(actual_buf, buf_len); }
END_TEST #endif START_TEST(Input_map_maintains_indices) { set_audio_rate(220); set_mix_volume(0); pause(); // Set up two debug instruments set_data("p_dc_blocker_enabled.json", "false"); set_data("out_00/p_manifest.json", "{}"); set_data("p_connections.json", "[ [\"au_00/out_00\", \"out_00\"]," " [\"au_01/out_00\", \"out_00\"] ]"); set_data("p_control_map.json", "[[0, 0], [1, 1]]"); set_data("control_00/p_manifest.json", "{}"); set_data("control_01/p_manifest.json", "{}"); set_data("au_00/p_manifest.json", "{ \"type\": \"instrument\" }"); set_data("au_00/out_00/p_manifest.json", "{}"); set_data("au_00/p_connections.json", "[ [\"proc_00/C/out_00\", \"out_00\"] ]"); set_data("au_00/proc_00/p_manifest.json", "{ \"type\": \"debug\" }"); set_data("au_00/proc_00/p_signal_type.json", "\"voice\""); set_data("au_00/proc_00/out_00/p_manifest.json", "{}"); set_data("au_00/proc_00/c/p_b_single_pulse.json", "true"); set_data("au_01/p_manifest.json", "{ \"type\": \"instrument\" }"); set_data("au_01/out_00/p_manifest.json", "{}"); set_data("au_01/p_connections.json", "[ [\"proc_00/C/out_00\", \"out_00\"]" ", [\"proc_01/C/out_00\", \"proc_00/C/in_00\"]" "]"); set_data("au_01/proc_00/p_manifest.json", "{ \"type\": \"debug\" }"); set_data("au_01/proc_00/p_signal_type.json", "\"voice\""); set_data("au_01/proc_00/in_00/p_manifest.json", "{}"); set_data("au_01/proc_00/out_00/p_manifest.json", "{}"); set_data("au_01/proc_01/p_manifest.json", "{ \"type\": \"pitch\" }"); set_data("au_01/proc_01/p_signal_type.json", "\"voice\""); set_data("au_01/proc_01/out_00/p_manifest.json", "{}"); validate(); check_unexpected_error(); // Test rendering float actual_buf[buf_len] = { 0.0f }; kqt_Handle_fire_event(handle, 0, "[\".a\", 0]"); kqt_Handle_fire_event(handle, 0, Note_On_55_Hz); check_unexpected_error(); const int note_offset = 10; mix_and_fill(actual_buf, note_offset); kqt_Handle_fire_event(handle, 1, "[\".a\", 1]"); kqt_Handle_fire_event(handle, 1, Note_On_55_Hz); check_unexpected_error(); mix_and_fill(actual_buf + note_offset, buf_len - note_offset); float expected_buf[buf_len] = { 0.0f }; expected_buf[0] = 1.0f; const float seq[] = { 1.0f, 0.5f, 0.5f, 0.5f }; repeat_seq_local(expected_buf + note_offset, 10, seq); check_buffers_equal(expected_buf, actual_buf, buf_len, 0.0f); }
END_TEST START_TEST(Tempo_slide_affects_playback_cursor) { set_audio_rate(mixing_rates[MIXING_RATE_LOW]); set_mix_volume(0); setup_debug_instrument(); setup_debug_single_pulse(); int tempos[] = { 30, 60, 120, 240, 0 }; // 0 is guard, shouldn't be used set_data("album/p_manifest.json", "{}"); set_data("album/p_tracks.json", "[0]"); set_data("song_00/p_manifest.json", "{}"); set_data("song_00/p_order_list.json", "[ [0, 0] ]"); set_data("pat_000/p_manifest.json", "{}"); set_data("pat_000/p_length.json", "[4, 0]"); set_data("pat_000/instance_000/p_manifest.json", "{}"); char triggers[256] = ""; snprintf(triggers, sizeof(triggers), "[ [[0, 0], [\"n+\", \"0\"]]," " [[1, 0], [\"n+\", \"0\"]]," " [[1, 0], [\"m/t\", \"%d\"]]," " [[1, 0], [\"m/=t\", \"1\"]]," " [[2, 0], [\"n+\", \"0\"]]," " [[3, 0], [\"n+\", \"0\"]] ]", tempos[_i]); set_data("pat_000/col_00/p_triggers.json", triggers); validate(); float actual_buf[buf_len] = { 0.0f }; mix_and_fill(actual_buf, buf_len); float expected_buf[buf_len] = { 0.0f }; expected_buf[0] = 1.0f; const long second_offset = mixing_rates[MIXING_RATE_LOW] / 2; expected_buf[second_offset] = 1.0f; long third_offset = 0; for (long i = second_offset + 1; i < buf_len; ++i) { if (actual_buf[i] == 1.0f) { third_offset = i; expected_buf[i] = 1.0f; break; } } fail_if(third_offset == 0, "Third pulse not found"); if (tempos[_i] < 120) { fail_unless((third_offset - second_offset) >= second_offset, "Pulse interval was not increased during slide down"); } else if (tempos[_i] > 120) { fail_unless((third_offset - second_offset) <= second_offset, "Pulse interval was not decreased during slide up"); } else { fail_unless((third_offset - second_offset) == second_offset, "Pulse interval was changed without slide"); } const long beat_len = mixing_rates[MIXING_RATE_LOW] * 60 / tempos[_i]; expected_buf[third_offset + beat_len] = 1.0f; check_buffers_equal(expected_buf, actual_buf, buf_len, 0.0f); }