character-encoding - MIDI 文件中未知的日语编码
问题描述
我有一个我认为包含日语字符的 MIDI 文件(从https://www.mediafire.com/file/y8wp3bd7at1agnd/Africa.rar/file下载)。不幸的是,我尝试过的所有 MIDI 程序似乎都无法正确解码日语。
例如,一些乐器名称出现在
ƒp[ƒJƒbƒVƒ‡ƒ“‚Piƒ}ƒbƒv‚Pj•ƒeƒ“ƒ|�
# hex bytes (from od -t x1)
0000000 c2 83 70 c2 81 5b c2 83 4a c2 83 62 c2 83 56 c2
0000020 83 c2 87 c2 83 c2 93 c2 82 50 c2 81 69 c2 83 7d
0000040 c2 83 62 c2 83 76 c2 82 50 c2 81 6a c2 81 c2 95
0000060 c2 83 65 c2 83 c2 93 c2 83 7c ef bf bd
ƒMƒ^[•‰ŠúÝ’è•‚eD‚n�
# hex bytes (from od -t x1)
0000000 c2 83 4d c2 83 5e c2 81 5b c2 81 c2 95 c2 8f c2
0000020 89 c2 8a c3 ba c2 90 c3 9d c2 92 c3 a8 c2 81 c2
0000040 95 c2 82 65 c2 81 44 c2 82 6e ef bf bd
我使用了一个脚本来蛮力尝试每次转换都iconv
知道(感谢https://unix.stackexchange.com/a/184565),并且我得到了一些使用 SHIFT_JISX0213 编码几乎可读的结果。
ツパツーツカツッツシツδ傔δ督1ツ(ツマツッツプツ1ツ)ツ⊊閉テツδ督ポ魹ス
ツギツタツーツ⊊閉渉可甘コツ静敖津ィツ⊊閉Fツ.ツO魹ス
有几个可见的片假名单词穿插着ツ字符:“打击乐器”(パーカッシ)、“地图1”(マップ1)、“吉他”(ギター)。我不知道如何理解这行的其余部分(我看不懂日语,所以我依赖谷歌翻译)。
有谁知道正确的编码应该是什么?
解决方案
事实证明,上面的字节字符串不存在于原始 MIDI 文件中。它们被我使用的 MIDI 阅读器弄坏了。
在http://www.music.mcgill.ca/~ich/classes/mumt306/StandardMIDIfileformat.html的帮助下, 我能够编写一个简单的 C 程序来提取原始字节,这些字节是基本的 SHIFT-JIS 编码.
% cc extract_instruments.c -o extract_instruments
% cat AFRICA_55.MID| ./extract_instruments| iconv -f SHIFT-JIS -t UTF8
【 AFRICA / TOTO 】 for SC-55 by 染之介
...
extract_instruments.c:
#include <stdio.h>
/*
Acknowledgement:
ReadVarLen is derived from http://www.music.mcgill.ca/~ich/classes/mumt306/StandardMIDIfileformat.html#BMA2_
(c) Copyright 1999 David Back.
EMail: david@csw2.co.uk
Web: http://www.csw2.co.uk
This document may be freely copied in whole or in part provided the copy contains
this Acknowledgement.
*/
int ReadVarLen() {
register int value;
register char c;
if((value = getchar()) & 0x80) {
value &= 0x7f;
do {
value = (value << 7) + ((c = getchar()) & 0x7f);
} while (c & 0x80);
}
return(value);
}
void ReadAndPrintName(int length) {
char name[length+1];
fgets(name, length+1, stdin);
printf("%s\n", name);
}
int main() {
int c1 = 0;
int c2 = getchar();
while (c2 != EOF) {
// 0xFF03 == Sequence/Track Name
if (c1 == 0xff && c2 == 0x03) {
int length = ReadVarLen();
ReadAndPrintName(length);
}
c1 = c2;
c2 = getchar();
}
return 0;
}
推荐阅读
- c++ - 表达式 (fileNew == NULL) 是否总是正确的?
- node.js - 将翻译字符串自动添加到 JSON
- python - 如何让我的简单神经网络输出更接近标签的值?
- fancytree - 从另一棵树的节点子集创建花式树
- c# - 诊断 Linux OS 中 .net core 3.1 服务的错误
- shell - 如何从 shell 脚本中接受“是”“您确定要继续连接(是/否)吗?” 使用 ssh。不使用 StrictHostKeyChecking=no
- asp.net-core - 关闭/断开 ASP.NET Core signalR 客户端连接的正确方法是什么?
- java - 无法使用 Selenium(Java)单击屏幕外按钮并获取 ElementNotInteractableException
- vue.js - 带有 Nuxt 的 Vuex 中的项目是否被爬取?
- azure - Azure Kubernetes 服务中 PVC 的读写权限问题