木星劲乐团

 找回密码
 立即注册
搜索
查看: 6415|回复: 3
打印 上一主题 下一主题

[分享] ojn字节集

[复制链接]

制作团队

Rank: 7Rank: 7Rank: 7

UID
57098
主题
2
帖子
151
金钱
3118
积分
3269
在线时间
490 小时
注册时间
2016-4-15
楼主
发表于 2016-11-22 15:06 | 显示全部楼层
ojm 的格式是什么?
我在这里查到一个 https://github.com/djzmo/render- ... rc/Nx/O2Jam/OJM.hpp

求详解
回复

使用道具 举报

制作团队

Rank: 7Rank: 7Rank: 7

UID
57098
主题
2
帖子
151
金钱
3118
积分
3269
在线时间
490 小时
注册时间
2016-4-15
沙发
发表于 2016-12-11 02:38 | 显示全部楼层
本帖最后由 ZackLee 于 2016-12-11 02:40 编辑

我来说明下 ojm 格式。

参考链接:https://open2jam.wordpress.com/the-ojm-documentation/

ojm 的整体格式为:M30_header + (M30_sample_header + 音乐数据区)*sample_count。

ojm 首先是一个 header,28字节:
struct M30_header {
    char signature[4]; // 固定字符串 "M30"
    int file_format_version;  //  internal version of the OJM format.
    int encryption_flag;  // encrypted format: 1 scramble1; 2 scramble2; 4 decode; 8 decrypt; 16 nami
    int sample_count;  // the number of sound files inside the OJM(we don’t rely on this much)
    int samples_offset;  
//  where the data actually starts, usually after the header(28)
    int payload_size;  // the size of the rest of the file, usually total_file_size – 28(header), in bytes
    int padding;
};


这部分结束后,每个 sample 还有一个 header 元信息,52字节:
struct M30_sample_header {
    char sample_name[32];  //
    int sample_size;
    short codec_code;
    short unk_fixed;
    int unk_music_flag;
    short ref;
    short unk_zero;
    int pcm_samples;
};


其中最重要的就是 sample_size,因为之后每个 sample_size 都是一个独立的音乐数据区,只要抓取出来就是一个 key 音。

需要注意的是,如果 M30_header encryption_flag 为 16,则说明文件使用了 nami 加密,此时需要解密 sample_size 所代表的音乐数据区:
for(int i=0; i+3 < data.length; i=i+4) {
    data[i+0] = 'n' XOR data[i+0];
    data[i+1] = 'a' XOR data[i+1];
    data[i+2] = 'm' XOR data[i+2];
    data[i+3] = 'i' XOR data[i+3];
}

若剩余数据不满足4个字符,或说字节,则忽略异或操作。
回复

使用道具 举报

制作团队

Rank: 7Rank: 7Rank: 7

UID
57098
主题
2
帖子
151
金钱
3118
积分
3269
在线时间
490 小时
注册时间
2016-4-15
板凳
发表于 2016-12-31 19:52 | 显示全部楼层
本帖最后由 ZackLee 于 2016-12-31 19:55 编辑

如果 signature 是“OMC”或“OJM”,那么存放音乐数据的方式为:
OMC_header + wav_count*(OMC_WAV_header + wave 数据) + ogg_count*(OMC_OGG_header + ogg 数据).

下面简单说明:
struct OMC_header {
  char signature[4];  // "OMC" or "OJM"
  short wav_count;
  short ogg_count;
  int wav_start;
  int ogg_start;
  int filesize;
};


此元信息共 20 字节,结构非常清晰。
wav 就是 nt 中的 W###;
ogg 就是 nt 中的 M###。
count 就是实际的数量,filesize 就是整个文件的大小。

之后的数据就是 wav 数据和 ogg 数据。和 M30 相同,之前都有一个结构体保存元信息:
struct OMC_WAV_header {
  char sample_name[32];
  short audio_format;
  short num_channels;
  int sample_rate;
  int bit_rate;
  short block_align;
  short bits_per_sample;
  int unk_data;
  int chunk_size;
};


其中最重要的就是 chunk_size,其后面字节数的数据就是 wav 数据。

OMC_header.wav_count 个 wav 数据后,就是 ogg 数据。
struct OMC_OGG_header {
  char sample_name[32];
  int sample_size;
};

其中 sample_size 就是后面跟着的 ogg 数据。



===========================
此外,ojm 的 ref + 1,才等于 ojn 中 note 的 value。



===========================
最后强调下:
W###(NT)  即  wav(OMC)  即  codec_code == 0(M30)  即  note_type == 其他任何值(ojn)。
M###(NT)  即  ogg(OMC)  即  codec_code == 5(M30)  即  note_type == 4(ojn)。
回复

使用道具 举报

制作团队

Rank: 7Rank: 7Rank: 7

UID
57098
主题
2
帖子
151
金钱
3118
积分
3269
在线时间
490 小时
注册时间
2016-4-15
地板
发表于 2017-1-5 16:20 | 显示全部楼层
本帖最后由 ZackLee 于 2017-1-6 15:05 编辑

补充一下, 从 ojm 中提取 wav 格式的音乐时:
如果是 M30 格式,那么其 pcm_samples 是一个关键属性,它就是比特率。
如果为 OMC 格式,wav 的头信息可以从 OMC_WAV_header 获取,当然也包括比特率。


可以参考如下代码 https://github.com/open2jamorg/o ... mper/OJMDumper.java
其中的 225~240 行就是 OMC 格式的 wav 导出代码。


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐上一条 /6 下一条


QQ|Archiver|手机版|木星劲乐团

GMT+8, 2024-5-6 17:30 , Processed in 0.046818 second(s), 20 queries .

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表