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;
}

 

posted on 2025-06-09 14:15  小沙盒工作室  阅读(21)  评论(0)    收藏  举报