【问题标题】:Issues parsing a MIDI file with a C program使用 C 程序解析 MIDI 文件时出现问题
【发布时间】:2015-07-21 04:23:23
【问题描述】:

我正在为一个类编写一个 MIDI 文件解析器。我正在逐字节读取值,然后将它们分配给结构中的变量。

这是有问题的代码:

unsigned long deltatime = 0;
unsigned long totaltime = 0;
unsigned char *sbyte = (unsigned char *)malloc(sizeof(unsigned char));
unsigned char meta_e;
    printf("\nTrack %d\n", i+1);
    n = 0;
    while (n<track[i].length)
    {
        sbyte[0] = 0;
        t += ReadVarLen(track[i].data, n, &deltatime);
        n += t;
        totaltime += deltatime; 
        if (t == 0) n++;
        memcpy(sbyte, &(track[i].data[n]), sizeof(unsigned char));
        printf("%lu\t %lu %.2X ",totaltime, deltatime, *sbyte);
        if (*sbyte >= 0xFF)
        {
            unsigned long length = 0;
            unsigned char *dta;
            meta_e = track[i].data[++n];
            printf("%.2X ", meta_e);
            n += ReadVarLen(track[i].data, ++n, &length);
            printf("%.2lX ", length);
            dta = (char *)malloc(sizeof(char) * length);
            memcpy(dta, &(track[i].data[++n]), length);
            for (j=0;j<length;j++) {printf("%.2X ",dta[j]);}
            n += length;
            printf("\n");
        } 
        if ((*sbyte >= 0x80) && (*sbyte < 0xF0))
        {
            if ((*sbyte >= 0x80) && (*sbyte < 0x90)) {
                unsigned char *midi_e;
                midi_e = (char *)malloc(sizeof(char) * 2);
                memcpy(midi_e, &(track[i].data[++n]), 2);
                for (i=0;i<2;i++) printf("%.2X ",midi_e[i]);
                n += 2;
                printf("\n");
            }
            if ((*sbyte >= 0x90) && (*sbyte < 0xA0)) {
                char *midi_e;
                midi_e = (char *)malloc(sizeof(char) * 2);
                memcpy(midi_e, &(track[i].data[++n]), 2);
                for (i=0;i<2;i++) printf("%.2X ",midi_e[i]);
                n += 2;
                printf("\n");
            }
            if ((*sbyte >= 0xA0) && (*sbyte < 0xB0)) {
                char *midi_e;
                midi_e = (char *)malloc(sizeof(char) * 2);
                memcpy(midi_e, &(track[i].data[++n]), 2);
                for (i=0;i<2;i++) printf("%.2X ",midi_e[i]);
                n += 2;
                printf("\n");
            }
            if ((*sbyte >= 0xB0) && (*sbyte < 0xC0)) {
                char *midi_e;
                midi_e = (char *)malloc(sizeof(char) * 2);
                memcpy(midi_e, &(track[i].data[++n]), 2);
                for (i=0;i<2;i++) printf("%.2X ",midi_e[i]);
                n += 2;
                printf("\n");
            }
            if ((*sbyte >= 0xC0) && (*sbyte < 0xD0)) {
                char *midi_e;
                midi_e = (char *)malloc(sizeof(char));
                memcpy(midi_e, &(track[i].data[++n]),1);
                printf("%.2X ",midi_e[0]);
                n++;
                printf("\n");
            }
            if ((*sbyte >= 0xD0) && (*sbyte < 0xE0)) {
                char *midi_e;
                midi_e = (char *)malloc(sizeof(char));
                memcpy(midi_e, &(track[i].data[++n]), 1);
                printf("%.2X ",midi_e[0]);
                n++;
                printf("\n");
            }
            if ((*sbyte >= 0xE0) && (*sbyte < 0xF0)) {
                char *midi_e;
                midi_e = (char *)malloc(sizeof(char) * 2);
                memcpy(midi_e, &(track[i].data[++n]), 2);
                for (i=0;i<2;i++) printf("%.2X ",midi_e[i]);
                n += 2;
                printf("\n");
            }   
        }
    }
}

我的输出如下所示:

Track 1

0        0 FF 01 27 43 6F 6D 70 6F 73 65 64 20 41 6E 64 20 53 65 71 75 65 6E 63 65 64 20 42 79 20 4D 69 63 68 61 65 6C 20 53 68 69 72 6B 
0        0 FF 54 05 00 00 00 00 00 
0        0 FF 51 03 07 A1 20 
0        0 FF 58 04 04 02 18 08 
0        0 FF 59 02 00 00 
0        0 FF 2F 00 

Track 2

0        0 FF 21 01 00 
0        0 FF 20 01 03 
0        0 B3 07 7F 
0        0 C7 05 
1800     1800 08 1808    8 97 4D 50 

输出的倒数第二行是问题所在。应该是:

0        0 C3 44 81

根据我用来检查示例 MIDI 文件的十六进制转换器工具。

我已经逐字节打印出缓冲区,它还说值应该是 C3 而不是 C7。似乎只有当我将缓冲区的值分配给变量 sbyte 时,它​​才会(在我看来莫名其妙地)更改为 0xC7。

【问题讨论】:

  • 要查看的代码相当多,如果没有输入文件,这对我们来说意义不大。请创建MCVE 以获得最佳答案。
  • 我在这里遗漏了什么吗?当数据大小为1字节时,用malloc分配内存,用memcpy复制数据有什么意义?为什么不直接声明unsigned char sbyte?我也注意到你没有free()ed sbyte 所以你有内存泄漏。 midi_e 同上,你可以声明一个数组 unsigned char midi_e[2] 并简化代码。
  • 一个程序改变事件不能有多个数据字节; 81 将是以下时间戳的一部分。您显示的代码看起来不错(如果不完整);显示输入文件的 hexdump。

标签: c arrays hex buffer midi


【解决方案1】:

当您到达以下行之一时,它开始出错:

for (i=0;i<2;i++) printf("%.2X ",midi_e[i]);

问题是您已经在循环外使用变量i 来索引曲目,因此您不想在此处更改其值。也许改用j

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-09
    • 2018-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-17
    相关资源
    最近更新 更多