Browse Source

remove empty midi tracks when importing a midi file (~alextee/zrythm-bug#141)

serd_style_docs
Alexandros Theodotou 2 years ago
parent
commit
f2ec8e1564
Signed by: alex
GPG Key ID: 022EAE42313D70F3
  1. 13
      inc/audio/midi_file.h
  2. 80
      src/audio/midi_file.c
  3. 34
      src/audio/midi_region.c
  4. 12
      tests/actions/tracklist_selections.c
  5. BIN
      tests/those_who_remain.mid

13
inc/audio/midi_file.h

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 Alexandros Theodotou <alex at zrythm dot org>
* Copyright (C) 2020-2021 Alexandros Theodotou <alex at zrythm dot org>
*
* This file is part of Zrythm
*
@ -26,6 +26,8 @@ @@ -26,6 +26,8 @@
#ifndef __AUDIO_MIDI_FILE_H__
#define __AUDIO_MIDI_FILE_H__
#include "ext/midilib/src/midifile.h"
#include <stdbool.h>
/**
@ -34,6 +36,15 @@ @@ -34,6 +36,15 @@
* @{
*/
/**
* Returns whether the given track in the midi file
* has data.
*/
bool
midi_file_track_has_data (
const char * abs_path,
int track_idx);
/**
* Returns the number of tracks in the MIDI file.
*/

80
src/audio/midi_file.c

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 Alexandros Theodotou <alex at zrythm dot org>
* Copyright (C) 2020-2021 Alexandros Theodotou <alex at zrythm dot org>
*
* This file is part of Zrythm
*
@ -23,6 +23,65 @@ @@ -23,6 +23,65 @@
#include <gtk/gtk.h>
/**
* Returns whether the given track in the midi file
* has data.
*/
bool
midi_file_track_has_data (
const char * abs_path,
int track_idx)
{
MIDI_FILE * mf = midiFileOpen (abs_path);
g_return_val_if_fail (mf, false);
MIDI_MSG msg;
midiReadInitMessage (&msg);
int ev;
g_debug ("reading MIDI Track %d", track_idx);
bool have_data = false;
while (midiReadGetNextMessage (
mf, track_idx, &msg))
{
if (msg.bImpliedMsg)
{
ev = msg.iImpliedMsg;
}
else
{
ev = msg.iType;
}
switch(ev)
{
case msgNoteOff:
case msgMetaEvent:
break;
case msgNoteOn:
case msgNoteKeyPressure:
case msgSetParameter:
case msgSetProgram:
case msgChangePressure:
case msgSetPitchWheel:
case msgSysEx1:
case msgSysEx2:
have_data = true;
break;
}
if (have_data)
{
break;
}
}
midiReadFreeMessage (&msg);
midiFileClose (mf);
return have_data;
}
/**
* Returns the number of tracks in the MIDI file.
*/
@ -35,9 +94,26 @@ midi_file_get_num_tracks ( @@ -35,9 +94,26 @@ midi_file_get_num_tracks (
midiFileOpen (abs_path);
g_return_val_if_fail (mf, -1);
int actual_num = 0;
int num = midiReadGetNumTracks (mf);
g_debug ("%s: num tracks = %d", abs_path, num);
if (!non_empty_only)
{
midiFileClose (mf);
return num;
}
for (int i = 0; i < num; i++)
{
if (midi_file_track_has_data (abs_path, i))
{
actual_num++;
}
}
midiFileClose (mf);
return num;
return actual_num;
}

34
src/audio/midi_region.c

@ -40,6 +40,7 @@ @@ -40,6 +40,7 @@
#include "audio/channel.h"
#include "audio/exporter.h"
#include "audio/midi_event.h"
#include "audio/midi_file.h"
#include "audio/midi_note.h"
#include "audio/midi_region.h"
#include "audio/region.h"
@ -413,9 +414,9 @@ midi_region_new_from_midi_file ( @@ -413,9 +414,9 @@ midi_region_new_from_midi_file (
g_return_val_if_fail (mf, NULL);
char str[128];
char txt[60000];
int ev;
MIDI_MSG msg;
int i, iNum;
unsigned int j;
Position pos, global_pos;
MidiNote * mn;
@ -429,19 +430,30 @@ midi_region_new_from_midi_file ( @@ -429,19 +430,30 @@ midi_region_new_from_midi_file (
lane_pos, idx_inside_lane);
midiReadInitMessage (&msg);
iNum = midiReadGetNumTracks(mf);
int num_tracks = midiReadGetNumTracks (mf);
double ppqn = (double) midiFileGetPPQN (mf);
double transport_ppqn =
transport_get_ppqn (TRANSPORT);
for(i = 0; i < iNum; i++)
int actual_iter = 0;
for (int i = 0; i < num_tracks; i++)
{
if (i != idx)
continue;
if (!midi_file_track_has_data (abs_path, i))
{
continue;
}
if (actual_iter != idx)
{
actual_iter++;
continue;
}
g_message (
"%s: reading MIDI Track %d", __func__, i);
while(midiReadGetNextMessage (mf, i, &msg))
g_return_val_if_fail (i < 1000, NULL);
while (midiReadGetNextMessage (mf, i, &msg))
{
/* convert time to zrythm time */
ticks =
@ -715,7 +727,6 @@ handle_note_off: @@ -715,7 +727,6 @@ handle_note_off:
}
else
{
char txt[600];
char tmp[100];
strcpy (txt, "[");
if (msg.bImpliedMsg)
@ -734,6 +745,11 @@ handle_note_off: @@ -734,6 +745,11 @@ handle_note_off:
g_debug ("%s", txt);
}
}
if (actual_iter == idx)
{
break;
}
}
midiReadFreeMessage (&msg);
@ -763,7 +779,9 @@ handle_note_off: @@ -763,7 +779,9 @@ handle_note_off:
position_is_before (
&self->base.pos, &self->base.end_pos), NULL);
g_message ("%s: done", __func__);
g_message (
"%s: done ~ %d MIDI notes read", __func__,
self->num_midi_notes);
return self;
}

12
tests/actions/tracklist_selections.c

@ -80,16 +80,13 @@ test_create_from_midi_file (void) @@ -80,16 +80,13 @@ test_create_from_midi_file (void)
char * midi_file;
/* TODO this should pass in the future */
#if 0
midi_file =
g_build_filename (
TESTS_SRCDIR,
"1_empty_track_1_track_with_data.mid",
NULL);
test_num_tracks_with_file (midi_file, 2);
test_num_tracks_with_file (midi_file, 1);
g_free (midi_file);
#endif
midi_file =
g_build_filename (
@ -103,6 +100,13 @@ test_create_from_midi_file (void) @@ -103,6 +100,13 @@ test_create_from_midi_file (void)
TRACKLIST->tracks[TRACKLIST->num_tracks - 1]->
lanes[0]->regions[0]->num_midi_notes, ==, 3);
midi_file =
g_build_filename (
TESTS_SRCDIR, "those_who_remain.mid",
NULL);
test_num_tracks_with_file (midi_file, 1);
g_free (midi_file);
test_helper_zrythm_cleanup ();
}

BIN
tests/those_who_remain.mid

Binary file not shown.
Loading…
Cancel
Save