Browse Source

fix loading undo history under different sample rate

Also fix sanity checking of audio regions.
libpanel_detach
Alexandros Theodotou 8 months ago
parent
commit
f95ffebea8
Signed by: alex
GPG Key ID: 022EAE42313D70F3
  1. 10
      inc/actions/undoable_action.h
  2. 29
      inc/audio/audio_region.h
  3. 7
      inc/audio/engine.h
  4. 5
      inc/audio/position.h
  5. 29
      inc/audio/region.h
  6. 5
      src/actions/undoable_action.c
  7. 44
      src/audio/audio_region.c
  8. 4
      src/audio/engine.c
  9. 16
      src/audio/position.c
  10. 13
      src/audio/region.c
  11. 25
      src/audio/router.c
  12. 9
      src/audio/track.c
  13. 12
      src/audio/track_lane.c
  14. 20
      src/audio/tracklist.c
  15. 56
      src/gui/backend/arranger_object.c
  16. 9
      src/gui/backend/arranger_selections.c
  17. 20
      src/project.c
  18. 77
      tests/actions/arranger_selections.c

10
inc/actions/undoable_action.h

@ -12,6 +12,7 @@ @@ -12,6 +12,7 @@
#include <stdbool.h>
#include "utils/types.h"
#include "utils/yaml.h"
typedef struct AudioClip AudioClip;
@ -88,6 +89,14 @@ typedef struct UndoableAction @@ -88,6 +89,14 @@ typedef struct UndoableAction
* action is executed. */
double frames_per_tick;
/**
* Sample rate of this action.
*
* Used to recalculate UndoableAction.frames_per_tick when
* the project is loaded under a new samplerate.
*/
sample_rate_t sample_rate;
/**
* Index in the stack.
*
@ -114,6 +123,7 @@ static const cyaml_schema_field_t undoable_action_fields_schema[] = { @@ -114,6 +123,7 @@ static const cyaml_schema_field_t undoable_action_fields_schema[] = {
type,
undoable_action_type_strings),
YAML_FIELD_FLOAT (UndoableAction, frames_per_tick),
YAML_FIELD_INT (UndoableAction, sample_rate),
YAML_FIELD_INT (UndoableAction, stack_idx),
YAML_FIELD_INT (UndoableAction, num_actions),

29
inc/audio/audio_region.h

@ -1,21 +1,5 @@ @@ -1,21 +1,5 @@
/*
* Copyright (C) 2019-2022 Alexandros Theodotou <alex at zrythm dot org>
*
* This file is part of Zrythm
*
* Zrythm is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Zrythm is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Zrythm. If not, see <https://www.gnu.org/licenses/>.
*/
// SPDX-FileCopyrightText: © 2019-2022 Alexandros Theodotou <alex@zrythm.org>
// SPDX-License-Identifier: LicenseRef-ZrythmLicense
/**
* \file
@ -159,8 +143,15 @@ audio_region_fill_stereo_ports ( @@ -159,8 +143,15 @@ audio_region_fill_stereo_ports (
float
audio_region_detect_bpm (ZRegion * self, GArray * candidates);
/**
* Sanity checking.
*
* @param frames_per_tick Frames per tick used when
* validating audio regions. Passing 0 will use the value
* from the current engine.
*/
bool
audio_region_validate (ZRegion * self);
audio_region_validate (ZRegion * self, double frames_per_tick);
/**
* Frees members only but not the audio region itself.

7
inc/audio/engine.h

@ -774,6 +774,13 @@ typedef struct AudioEngine @@ -774,6 +774,13 @@ typedef struct AudioEngine
/** Pointer to owner project, if any. */
Project * project;
/**
* True while updating frames per tick.
*
* See engine_update_frames_per_tick().
*/
bool updating_frames_per_tick;
} AudioEngine;
static const cyaml_schema_field_t engine_fields_schema[] = {

5
inc/audio/position.h

@ -151,8 +151,11 @@ typedef struct Position @@ -151,8 +151,11 @@ typedef struct Position
*
* To be used where more precision than Position.frames is
* needed.
*
* @note Does not seem needed, keep comment around for
* reference in the future.
*/
double precise_frames;
//double precise_frames;
} Position;
static const cyaml_schema_field_t position_fields_schema[] = {

29
inc/audio/region.h

@ -1,21 +1,5 @@ @@ -1,21 +1,5 @@
/*
* Copyright (C) 2018-2022 Alexandros Theodotou <alex at zrythm dot org>
*
* This file is part of Zrythm
*
* Zrythm is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Zrythm is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Zrythm. If not, see <https://www.gnu.org/licenses/>.
*/
// SPDX-FileCopyrightText: © 2018-2022 Alexandros Theodotou <alex@zrythm.org>
// SPDX-License-Identifier: LicenseRef-ZrythmLicense
/**
* \file
@ -705,9 +689,16 @@ region_get_arranger_selections (ZRegion * self); @@ -705,9 +689,16 @@ region_get_arranger_selections (ZRegion * self);
/**
* Sanity checking.
*
* @param frames_per_tick Frames per tick used when
* validating audio regions. Passing 0 will use the value
* from the current engine.
*/
bool
region_validate (ZRegion * self, bool is_project);
region_validate (
ZRegion * self,
bool is_project,
double frames_per_tick);
/**
* Disconnects the region and anything using it.

5
src/actions/undoable_action.c

@ -18,6 +18,10 @@ @@ -18,6 +18,10 @@
void
undoable_action_init_loaded (UndoableAction * self)
{
double sample_rate_ratio =
(double) AUDIO_ENGINE->sample_rate / (double) self->sample_rate;
self->frames_per_tick = self->frames_per_tick * sample_rate_ratio;
/* uppercase, camel case, snake case */
#define INIT_LOADED(uc, sc, cc) \
case UA_##uc: \
@ -62,6 +66,7 @@ undoable_action_init ( @@ -62,6 +66,7 @@ undoable_action_init (
self->num_actions = 1;
self->frames_per_tick = AUDIO_ENGINE->frames_per_tick;
self->sample_rate = AUDIO_ENGINE->sample_rate;
}
/**

44
src/audio/audio_region.c

@ -600,23 +600,49 @@ audio_region_detect_bpm (ZRegion * self, GArray * candidates) @@ -600,23 +600,49 @@ audio_region_detect_bpm (ZRegion * self, GArray * candidates)
(unsigned int) AUDIO_ENGINE->sample_rate, candidates);
}
/**
* Sanity checking.
*
* @param frames_per_tick Frames per tick used when
* validating audio regions. Passing 0 will use the value
* from the current engine.
*/
bool
audio_region_validate (ZRegion * self)
audio_region_validate (ZRegion * self, double frames_per_tick)
{
if (PROJECT->loaded)
if (PROJECT->loaded && !AUDIO_ENGINE->updating_frames_per_tick)
{
AudioClip * clip = audio_region_get_clip (self);
g_return_val_if_fail (clip, false);
signed_frame_t loop_len =
arranger_object_get_loop_length_in_frames (
(ArrangerObject *) self);
/* verify that the loop does not contain more
* frames than available in the clip */
z_return_val_if_fail_cmp (
loop_len, <=, (signed_frame_t) clip->num_frames,
false);
/* use global positions because sometimes the loop
* appears to have 1 more frame due to rounding to
* nearest frame*/
ArrangerObject * obj = (ArrangerObject *) self;
signed_frame_t loop_start_global =
position_get_frames_from_ticks (
obj->pos.ticks + obj->loop_start_pos.ticks,
frames_per_tick);
signed_frame_t loop_end_global =
position_get_frames_from_ticks (
obj->pos.ticks + obj->loop_end_pos.ticks,
frames_per_tick);
signed_frame_t loop_len =
loop_end_global - loop_start_global;
/*g_debug ("loop len: %" SIGNED_FRAME_FORMAT, loop_len);*/
if (loop_len > (signed_frame_t) clip->num_frames)
{
g_critical (
"Audio region loop length in frames (%" SIGNED_FRAME_FORMAT
") is "
"greater than the number of frames in the "
"clip (%" UNSIGNED_FRAME_FORMAT "). ",
loop_len, clip->num_frames);
return false;
}
}
return true;

4
src/audio/engine.c

@ -160,6 +160,8 @@ engine_update_frames_per_tick ( @@ -160,6 +160,8 @@ engine_update_frames_per_tick (
return;
}
self->updating_frames_per_tick = true;
/* process all recording events */
recording_manager_process_events (RECORDING_MANAGER);
@ -191,6 +193,8 @@ engine_update_frames_per_tick ( @@ -191,6 +193,8 @@ engine_update_frames_per_tick (
track_update_positions (
TRACKLIST->tracks[i], update_from_ticks, bpm_change);
}
self->updating_frames_per_tick = false;
}
/**

16
src/audio/position.c

@ -679,9 +679,19 @@ position_to_string_full ( @@ -679,9 +679,19 @@ position_to_string_full (
int sixteenths = position_get_sixteenths (pos, true);
double ticks = position_get_ticks (pos);
g_return_if_fail (bars > -80000);
sprintf (
buf, "%d.%d.%d.%.*f", bars, abs (beats), abs (sixteenths),
decimal_places, fabs (ticks));
if (ZRYTHM_TESTING)
{
sprintf (
buf, "%d.%d.%d.%.*f (%" SIGNED_FRAME_FORMAT ")", bars,
abs (beats), abs (sixteenths), decimal_places,
fabs (ticks), pos->frames);
}
else
{
sprintf (
buf, "%d.%d.%d.%.*f", bars, abs (beats),
abs (sixteenths), decimal_places, fabs (ticks));
}
}
/**

13
src/audio/region.c

@ -88,7 +88,7 @@ region_init ( @@ -88,7 +88,7 @@ region_init (
self->magic = REGION_MAGIC;
region_validate (self, false);
region_validate (self, false, 0);
}
/**
@ -476,9 +476,16 @@ region_get_type_as_string (RegionType type, char * buf) @@ -476,9 +476,16 @@ region_get_type_as_string (RegionType type, char * buf)
/**
* Sanity checking.
*
* @param frames_per_tick Frames per tick used when
* validating audio regions. Passing 0 will use the value
* from the current engine.
*/
bool
region_validate (ZRegion * self, bool is_project)
region_validate (
ZRegion * self,
bool is_project,
double frames_per_tick)
{
g_return_val_if_fail (IS_REGION (self), false);
@ -511,7 +518,7 @@ region_validate (ZRegion * self, bool is_project) @@ -511,7 +518,7 @@ region_validate (ZRegion * self, bool is_project)
automation_region_validate (self);
break;
case REGION_TYPE_AUDIO:
audio_region_validate (self);
audio_region_validate (self, frames_per_tick);
break;
default:
break;

25
src/audio/router.c

@ -1,24 +1,11 @@ @@ -1,24 +1,11 @@
// SPDX-FileCopyrightText: © 2019-2022 Alexandros Theodotou <alex@zrythm.org>
// SPDX-License-Identifier: LicenseRef-ZrythmLicense
/*
* Copyright (C) 2019-2022 Alexandros Theodotou <alex at zrythm dot org>
*
* This file is part of Zrythm
*
* Zrythm is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Zrythm is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Zrythm. If not, see <https://www.gnu.org/licenses/>.
*
* This file incorporates work covered by the following copyright and
* permission notice:
*
* ---
*
* Copyright (C) 2017, 2019 Robin Gareus <robin@gareus.org>
*
* This program is free software: you can redistribute it and/or modify
@ -33,6 +20,10 @@ @@ -33,6 +20,10 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*
* ---
*/
#include "zrythm-config.h"

9
src/audio/track.c

@ -1123,15 +1123,16 @@ track_validate (Track * self) @@ -1123,15 +1123,16 @@ track_validate (Track * self)
for (int j = 0; j < lane->num_regions; j++)
{
ZRegion * region = lane->regions[j];
region_validate (
region, track_is_in_active_project (self));
bool is_project = track_is_in_active_project (self);
region_validate (region, is_project, 0);
}
}
for (int i = 0; i < self->num_chord_regions; i++)
{
ZRegion * r = self->chord_regions[i];
region_validate (r, track_is_in_active_project (self));
region_validate (
r, track_is_in_active_project (self), 0);
}
g_debug ("done validating track '%s'", self->name);
@ -1801,7 +1802,7 @@ track_insert_region ( @@ -1801,7 +1802,7 @@ track_insert_region (
track = automation_track_get_track (at);
}
g_return_if_fail (IS_TRACK (track));
g_return_if_fail (region_validate (region, false));
g_return_if_fail (region_validate (region, false, 0));
g_return_if_fail (track_type_can_have_region_type (
track->type, region->id.type));

12
src/audio/track_lane.c

@ -240,8 +240,20 @@ track_lane_update_positions ( @@ -240,8 +240,20 @@ track_lane_update_positions (
continue;
g_return_if_fail (IS_REGION_AND_NONNULL (r_obj));
if (ZRYTHM_TESTING)
{
region_validate (
(ZRegion *) r_obj,
track_lane_is_in_active_project (self), 0);
}
arranger_object_update_positions (
r_obj, from_ticks, bpm_change, NULL);
if (ZRYTHM_TESTING)
{
region_validate (
(ZRegion *) r_obj,
track_lane_is_in_active_project (self), 0);
}
}
}

20
src/audio/tracklist.c

@ -1,21 +1,5 @@ @@ -1,21 +1,5 @@
/*
* Copyright (C) 2018-2022 Alexandros Theodotou <alex at zrythm dot org>
*
* This file is part of Zrythm
*
* Zrythm is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Zrythm is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Zrythm. If not, see <https://www.gnu.org/licenses/>.
*/
// SPDX-FileCopyrightText: © 2018-2022 Alexandros Theodotou <alex@zrythm.org>
// SPDX-License-Identifier: LicenseRef-ZrythmLicense
#include "actions/tracklist_selections.h"
#include "audio/audio_region.h"

56
src/gui/backend/arranger_object.c

@ -1070,7 +1070,8 @@ init_loaded_region (ZRegion * self) @@ -1070,7 +1070,8 @@ init_loaded_region (ZRegion * self)
arranger_object_gen_escaped_name ((ArrangerObject *) self);
region_validate (self, false);
/* TODO reenable */
/*region_validate (self, false);*/
}
/**
@ -1125,6 +1126,15 @@ arranger_object_update_positions ( @@ -1125,6 +1126,15 @@ arranger_object_update_positions (
bool bpm_change,
UndoableAction * action)
{
#if 0
g_debug ("\n\n\nobject before");
arranger_object_print (self);
if (self->type == ARRANGER_OBJECT_TYPE_REGION)
{
region_print ((ZRegion *) self);
}
#endif
long frames_len_before = 0;
if (bpm_change && arranger_object_type_has_length (self->type))
{
@ -1172,6 +1182,15 @@ arranger_object_update_positions ( @@ -1172,6 +1182,15 @@ arranger_object_update_positions (
position_update (&self->fade_out_pos, from_ticks, ratio);
}
#if 0
g_debug ("\n\n\nobject after just position updates");
arranger_object_print (self);
if (self->type == ARRANGER_OBJECT_TYPE_REGION)
{
region_print ((ZRegion *) self);
}
#endif
ZRegion * r;
switch (self->type)
{
@ -1205,11 +1224,21 @@ arranger_object_update_positions ( @@ -1205,11 +1224,21 @@ arranger_object_update_positions (
clip = audio_region_get_clip (r);
g_return_if_fail (clip);
#if 0
g_debug (
"\n\n\nobject after audio region main logic");
arranger_object_print (self);
#endif
/* sometimes due to rounding errors,
* the region frames are 1 frame more
* than the clip frames. this works
* around it by resizing the region
* by -1 frame*/
#if 0
signed_frame_t loop_len_frames =
arranger_object_get_loop_length_in_frames (self);
#endif
while (
local_frames == (signed_frame_t) clip->num_frames)
{
@ -1222,12 +1251,37 @@ arranger_object_update_positions ( @@ -1222,12 +1251,37 @@ arranger_object_update_positions (
ticks, false);
local_frames = region_timeline_frames_to_local (
r, tl_frames, F_NORMALIZE);
#if 0
loop_len_frames =
arranger_object_get_loop_length_in_frames (
self);
g_return_if_fail (
loop_len_frames
<= (signed_frame_t) clip->num_frames);
#endif
}
#if 0
arranger_object_print (self);
region_print (r);
double loop_len_ticks =
arranger_object_get_loop_length_in_ticks (self);
g_message (
"\t\t\tassert local frames %" SIGNED_FRAME_FORMAT
" < clip frames %" UNSIGNED_FRAME_FORMAT
", loop len %f ticks %" SIGNED_FRAME_FORMAT
" frames",
local_frames, clip->num_frames, loop_len_ticks,
loop_len_frames);
#endif
z_return_if_fail_cmp (
local_frames, <,
(signed_frame_t) clip->num_frames);
#if 0
z_return_if_fail_cmp (
loop_len_frames, <=,
(signed_frame_t) clip->num_frames);
#endif
}
for (int i = 0; i < r->num_midi_notes; i++)

9
src/gui/backend/arranger_selections.c

@ -45,7 +45,6 @@ @@ -45,7 +45,6 @@
* @param action To be passed when this is called from an
* undoable action.
*/
NONNULL
void
arranger_selections_init_loaded (
ArrangerSelections * self,
@ -85,12 +84,18 @@ arranger_selections_init_loaded ( @@ -85,12 +84,18 @@ arranger_selections_init_loaded (
obj, true, false, NULL); \
sel->sc##s[i] = (cc *) arranger_object_find (obj); \
} \
else \
else /* else if not project */ \
{ \
arranger_object_init_loaded ( \
(ArrangerObject *) sel->sc##s[i]); \
arranger_object_update_positions ( \
obj, true, false, action); \
if (obj->type == ARRANGER_OBJECT_TYPE_REGION) \
{ \
region_validate ( \
(ZRegion *) obj, project, \
action ? action->frames_per_tick : 0); \
} \
} \
}

20
src/project.c

@ -1029,15 +1029,6 @@ load (const char * filename, const int is_template) @@ -1029,15 +1029,6 @@ load (const char * filename, const int is_template)
* during engine pre setup */
audio_pool_init_loaded (self->audio_engine->pool);
if (self->undo_manager)
{
undo_manager_init_loaded (self->undo_manager);
}
else
{
self->undo_manager = undo_manager_new ();
}
clip_editor_init_loaded (self->clip_editor);
timeline_init_loaded (self->timeline);
tracklist_init_loaded (self->tracklist, self, NULL);
@ -1049,6 +1040,17 @@ load (const char * filename, const int is_template) @@ -1049,6 +1040,17 @@ load (const char * filename, const int is_template)
tempo_track_get_current_bpm (P_TEMPO_TRACK),
AUDIO_ENGINE->sample_rate, true, true, false);
/* undo manager must be loaded after updating engine
* frames per tick */
if (self->undo_manager)
{
undo_manager_init_loaded (self->undo_manager);
}
else
{
self->undo_manager = undo_manager_new ();
}
midi_mappings_init_loaded (self->midi_mappings);
arranger_selections_init_loaded (

77
tests/actions/arranger_selections.c

@ -284,7 +284,7 @@ test_delete_chords (void) @@ -284,7 +284,7 @@ test_delete_chords (void)
rebootstrap_timeline ();
ZRegion * r = P_CHORD_TRACK->chord_regions[0];
g_assert_true (region_validate (r, F_PROJECT));
g_assert_true (region_validate (r, F_PROJECT, 0));
/* add another chord */
ChordObject * c = chord_object_new (&r->id, 2, 2);
@ -304,7 +304,7 @@ test_delete_chords (void) @@ -304,7 +304,7 @@ test_delete_chords (void)
(ArrangerObject *) r->chord_objects[0]);
arranger_selections_action_perform_delete (
CHORD_SELECTIONS, NULL);
g_assert_true (region_validate (r, F_PROJECT));
g_assert_true (region_validate (r, F_PROJECT, 0));
undo_manager_undo (UNDO_MANAGER, NULL);
undo_manager_redo (UNDO_MANAGER, NULL);
@ -478,7 +478,6 @@ check_after_move_timeline (int new_tracks) @@ -478,7 +478,6 @@ check_after_move_timeline (int new_tracks)
static void
test_move_audio_region_and_lower_bpm (void)
{
return;
test_helper_zrythm_init ();
char audio_file_path[2000];
@ -510,9 +509,29 @@ test_move_audio_region_and_lower_bpm (void) @@ -510,9 +509,29 @@ test_move_audio_region_and_lower_bpm (void)
/* lower BPM and attempt to save */
bpm_t bpm_before =
tempo_track_get_current_bpm (P_TEMPO_TRACK);
ZRegion * r = TRACKLIST->tracks[5]->lanes[0]->regions[0];
long frames_len = arranger_object_get_length_in_frames (
(ArrangerObject *) r);
double ticks_len = arranger_object_get_length_in_ticks (
(ArrangerObject *) r);
AudioClip * clip = AUDIO_ENGINE->pool->clips[r->pool_id];
g_message (
"before | r size: %ld (ticks %f), clip size %ld",
frames_len, ticks_len, clip->num_frames);
region_print (r);
region_validate (r, true, 0);
tempo_track_set_bpm (
P_TEMPO_TRACK, bpm_before - bpm_diff, bpm_before,
Z_F_NOT_TEMPORARY, F_NO_PUBLISH_EVENTS);
frames_len = arranger_object_get_length_in_frames (
(ArrangerObject *) r);
ticks_len = arranger_object_get_length_in_ticks (
(ArrangerObject *) r);
g_message (
"after | r size: %ld (ticks %f), clip size %ld",
frames_len, ticks_len, clip->num_frames);
region_print (r);
region_validate (r, true, 0);
test_project_save_and_reload ();
/* undo lowering BPM */
@ -522,6 +541,51 @@ test_move_audio_region_and_lower_bpm (void) @@ -522,6 +541,51 @@ test_move_audio_region_and_lower_bpm (void)
test_helper_zrythm_cleanup ();
}
static void
test_move_audio_region_and_lower_samplerate (void)
{
test_helper_zrythm_init ();
char audio_file_path[2000];
sprintf (
audio_file_path, "%s%s%s", TESTS_SRCDIR,
G_DIR_SEPARATOR_S, "test.wav");
/* create audio track with region */
Position pos;
position_init (&pos);
int track_pos = TRACKLIST->num_tracks;
SupportedFile * file =
supported_file_new_from_path (audio_file_path);
Track * track = track_create_with_action (
TRACK_TYPE_AUDIO, NULL, file, &pos, track_pos, 1, NULL);
/* move the region */
arranger_object_select (
(ArrangerObject *) track->lanes[0]->regions[0], F_SELECT,
F_NO_APPEND, F_NO_PUBLISH_EVENTS);
arranger_selections_action_perform_move_timeline (
TL_SELECTIONS, MOVE_TICKS, 0, 0, F_NOT_ALREADY_MOVED,
NULL);
/* save the project */
int ret =
project_save (PROJECT, PROJECT->dir, 0, 0, F_NO_ASYNC);
g_assert_cmpint (ret, ==, 0);
char * prj_file =
g_build_filename (PROJECT->dir, PROJECT_FILE, NULL);
/* adjust the samplerate to be given at startup */
zrythm_app->samplerate = (int) AUDIO_ENGINE->sample_rate / 2;
object_free_w_func_and_null (project_free, PROJECT);
/* reload */
ret = project_load (prj_file, 0);
test_helper_zrythm_cleanup ();
}
/**
* Tests the move action.
*
@ -1432,7 +1496,7 @@ test_split (void) @@ -1432,7 +1496,7 @@ test_split (void)
g_assert_cmpint (lane2->num_regions, ==, 1);
ZRegion * region2 = lane2->regions[0];
region_validate (region2, false);
region_validate (region2, false, 0);
undo_manager_undo (UNDO_MANAGER, NULL);
undo_manager_redo (UNDO_MANAGER, NULL);
@ -1447,7 +1511,7 @@ test_split (void) @@ -1447,7 +1511,7 @@ test_split (void)
g_assert_cmpint (lane->num_regions, ==, 1);
ZRegion * region = lane->regions[0];
region_validate (region, false);
region_validate (region, false, 0);
r_obj = (ArrangerObject *) region;
arranger_object_select (
r_obj, F_SELECT, F_NO_APPEND, F_NO_PUBLISH_EVENTS);
@ -3066,6 +3130,9 @@ main (int argc, char * argv[]) @@ -3066,6 +3130,9 @@ main (int argc, char * argv[])
#define TEST_PREFIX "/actions/arranger_selections/"
g_test_add_func (
TEST_PREFIX "test move audio_region_and lower samplerate",
(GTestFunc) test_move_audio_region_and_lower_samplerate);
g_test_add_func (
TEST_PREFIX "test move audio_region_and lower bpm",
(GTestFunc) test_move_audio_region_and_lower_bpm);

Loading…
Cancel
Save