ts404保存的.pat文件数据结构分析
https://wwzs.lanzouu.com/ihf2U2y90sgf ts404下载
文件头:56 31 2E 30 41 V1.0A
osc1波形:
0x00000026 00 saw
0x00000026 03 wave2
0x00000026 02 sin
0x00000026 01 square
osc2波形
0x00000028 00 saw
0x00000028 03 wave2
0x00000028 02 sin
0x00000028 01 square
ADSR max
A 0x000008CE-0x000008D4 7字节
D 0x000008D6-0x000008D8 3字节 int
S 0x000008DA-0x000008DC 3字节
R 0x000008DE-0x000008E4 7字节
LFO
0x000008A6 00 osc1/2
0x000008A6 01 reso
0x000008A6 02 cutoff
LFO TYPE
0x000008A8 00 sin
0x000008A8 01 square
MasterVolume
0x00000012-0x00000013 2字节
音序器第一个音
0x000008F6 hex:03 c1
0x000008F6 hex:0f c2
0x000008F6 hex:10 c#2
0x000008F6 hex:11 d2
0x000008F6 hex:33 c5
音序器1note on/off
0x00000906 hex:00 off
音序列器16个16分音符的音高
0x000008F6-0x00000905 每个字节表示一个音高note
音序列器16个16分音符on/off
hex:00 表示off hex:01表示on 每个字节表示on/off
0x00000906-0x00000915
音序列器16个16分音符silde on/off
hex:00 表示off hex:01表示on 每个字节表示on/off
0x00000916-0x00000925
滤波器:
0x0000088C hex:00 lo12
0x0000088C hex:01 lo24
0x0000088C hex:02 hi12
0x0000088C hex:03 Band
0x0000088C hex:04 ByPass
滤波器cutoff
0x0000088F hex:40 最大值
滤波器NnvAmt
0x0896-0x0897(0x00000896-0x00000897) 2字节 hex:00 7D 最大值
滤波器Reso
0x0892 -0x0893(0x00000892-0x00000893) 2字节
hex:FF 7F 最小值 hex:00 00 最大值
bpm
0x000008F2 一个字节int
代码
#include <iostream> #include <fstream> #include <array> #include <cstdint> template<size_t N> void print_array(const std::array<uint8_t, N>& arr, const std::string& name = "") { if (!name.empty()) { std::cout << name << ": "; } std::cout << "["; for (size_t i = 0; i < N; ++i) { std::cout << static_cast<int>(arr[i]); if (i != N - 1) std::cout << ", "; } std::cout << "]" << std::endl; } const char* read_wave_type(std::ifstream& file,std::streamoff offest) { file.seekg(offest); uint8_t byte; file.read(reinterpret_cast<char*>(&byte), sizeof(byte)); switch(byte) { case 0: return "saw"; case 3: return "wave2"; case 2: return "sin"; case 1: return "square"; default: return "unknown"; } file.close(); } const char* read_lfo_type(std::ifstream& file,std::streamoff offest) { uint8_t byte; file.seekg(offest); file.read(reinterpret_cast<char*>(&byte), sizeof(byte)); switch(byte) { case 0: return "sin"; case 1: return "square"; default: return "unknown"; } } const char* read_lfo_target(std::ifstream& file,std::streamoff offest) { uint8_t byte; file.seekg(offest); file.read(reinterpret_cast<char*>(&byte), sizeof(byte)); switch(byte) { case 0: return "osc1/2"; case 1: return "reso"; case 2: return "cutoff"; default: return "unknown"; } } uint16_t read_master(std::ifstream& file,std::streamoff offest) { file.seekg(offest); uint16_t byte; file.read(reinterpret_cast<char*>(&byte), sizeof(byte)); return byte; } /*float read_adsr_a(std::ifstream& file,std:streamoff offest) { file.seekg(offest); return read(offest); } */ // 范围 hex:01 00 - 00 40 float read_filter_cutoff(std::ifstream &file,std::streamoff offest) { const uint16_t min = 1; const uint16_t max = 0x4000; file.seekg(offest); uint16_t value; file.read(reinterpret_cast<char*>(&value), sizeof(value)); return (static_cast<float>(value-min)/(max-min)); } float read_filter_envamt(std::ifstream &file,std::streamoff offest) { uint16_t value; file.seekg(offest); file.read(reinterpret_cast<char*>(&value), sizeof(value)); return (static_cast<float>(value)); } float read_filter_reso(std::ifstream &file,std::streamoff offest) { uint16_t value; file.seekg(offest); file.read(reinterpret_cast<char*>(&value), sizeof(value)); return (static_cast<float>(value)); } const char* read_filter_type(std::ifstream &file,std::streamoff offest) { uint8_t byte; file.seekg(offest); file.read(reinterpret_cast<char*>(&byte), sizeof(byte)); switch(byte) { case 0: return "lo12"; case 1: return "lo24"; case 2: return "hi12"; case 3: return "Band"; case 4: return "ByPass"; default: return "unknown"; } } int read_bpm(std::ifstream& file,std::streamoff offest) { file.seekg(offest); uint8_t byte; file.read(reinterpret_cast<char*>(&byte), sizeof(byte)); return static_cast<int>(byte); } // 读取音序器的音高数据 std::array<uint8_t,16> read_note(std::ifstream &file,std::streamoff offest) { //uint8_t notes[16]; std::array<uint8_t,16> notes{}; file.seekg(offest); for (int i = 0; i < 16; i++) { uint8_t byte; file.read(reinterpret_cast<char*>(&byte), sizeof(byte)); notes[i] = byte; } return notes; } std::array<uint8_t,16> read_note_on_off(std::ifstream &file,std::streamoff offest) { std::array<uint8_t,16> onoff{}; for(int i=0;i<16;i++) { uint8_t byte; file.read(reinterpret_cast<char*>(&byte), sizeof(byte)); onoff[i] = byte; } return onoff; } std::array<uint8_t,16> read_note_slide(std::ifstream &file,std::streamoff offest) { std::array<uint8_t,16> slide{}; for(int i=0;i<16;i++) { uint16_t byte; file.read(reinterpret_cast<char*>(&byte), sizeof(byte)); slide[i] = byte; } return slide; } int main(int argc,char** argv) { char *filename = argv[1]; std::ifstream file(filename,std::ios::binary); const char* osc1_wave = read_wave_type(file,0x00000026); const char* osc2_wave = read_wave_type(file,0x00000028); int bpm = read_bpm(file,0x000008F2); const char* lfo_type = read_lfo_type(file,0x000008A8); const char* lfo_target = read_lfo_target(file,0x000008A6); uint16_t master_vol = read_master(file,0x00000012); const char* filter_type = read_filter_type(file,0x0000088C); float cutoff = read_filter_cutoff(file,0x0000088F)*20000; float envamt = read_filter_envamt(file,0x00000896); float reso = read_filter_reso(file,0x0892); auto notes = read_note(file,0x000008F6); auto on_off = read_note_on_off(file,0x00000906); auto slide = read_note_slide(file,0x00000916); file.close(); // 目前不清楚adsr的每个bit是什么意思 //float asdr_a = read_adsr_a(0x000008CE,7); /*float adsr_d = read_adsr_d(0x000008D6,3); float adsr_s = read_asdr_s(0x000008DA,3); float adsr_r = read_adsr_r(0x000008DE,7) */ std::cout << "Osc1 Wave: " << osc1_wave << std::endl; std::cout << "Osc2 Wave: " << osc2_wave << std::endl; std::cout << "LFO Type: " << lfo_type << std::endl; std::cout << "LFO Target: " << lfo_target << std::endl; std::cout << "Filter Type: " << filter_type << std::endl; std::cout << "Cutoff: " << cutoff << std::endl; std::cout << "Filter Env Amount: " << envamt << std::endl; std::cout << "Resonance: " << reso << std::endl; print_array(notes,"Notes"); print_array(on_off,"Note On/Off"); print_array(slide,"Note Slide"); /*std::cout << "notes: " << notes << std::endl; std::cout << "noteOnOff: " << on_off << std::endl; std::cout << "noteSlide: " << slide << std::endl;*/ std::cout << "BPM: " << bpm << std::endl; std::cout << "Master Volume: " << master_vol << std::endl; return 0; }
浙公网安备 33010602011771号