Task 795: .VSQX File Format

Task 795: .VSQX File Format

The .VSQX file format is a proprietary XML-based structure utilized by VOCALOID3 and VOCALOID4 software for storing vocal synthesis project data, including musical notes, lyrics, and performance parameters. This format enhances compatibility and processing compared to its predecessor, the binary .VSQ format.

The properties intrinsic to the .VSQX file format, derived from its XML structure, encompass the following key elements and attributes. These represent the core data fields for voicebanks, mixing, global sequencing, tracks, and individual notes:

Voicebank properties (under <vVoiceTable> and <vVoice>):

  • ID: Unique identifier for the voicebank.
  • Name: Descriptive name of the voicebank (e.g., "Miku V4X Original").

Mixer properties (under <mixer>):

  • General mixer attributes for audio synthesis control.

Master track properties (under <masterTrack>):

  • Time signature: Defines the rhythmic structure (e.g., beats per measure).
  • Tempo: Specifies the playback speed in beats per minute.

Track and part properties (under <vsTrack> and <vsPart>):

  • Name: Label for the track.
  • Play time: Total duration of the track in ticks.
  • Part style parameters (under <pStyle>):
  • Accent: Intensity emphasis on notes (range: 0-100).
  • Bend depth: Depth of pitch bend (range: 0-100).
  • Bend length: Duration of pitch bend (range: 0-100).
  • Decay: Rate of audio fade-out (range: 0-100, extensible beyond for custom uses).
  • Opening: Variation in mouth pronunciation (range: 0-127, extensible beyond).
  • Fall portamento: Downward pitch glide value.
  • Rise portamento: Upward pitch glide value.

Note properties (under <note> within tracks):

  • Timestamp (t): Start time of the note in ticks.
  • Duration (dur): Length of the note in ticks.
  • Note number (n): MIDI note identifier (e.g., 56 for G#3).
  • Velocity (v): Intensity or volume of the note (range: 0-127).
  • Lyrics (y): Text lyrics for the note, stored as CDATA.
  • Phoneme (p): Phonetic representation for synthesis, stored as CDATA.
  • Note style parameters (under <nStyle>):
  • Accent: Note-specific accent (range: 0-100).
  • Bend depth: Note-specific bend depth (range: 0-100).
  • Bend length: Note-specific bend length (range: 0-100).
  • Decay: Note-specific decay (range: 0-100, extensible).
  • Fall portamento: Note-specific fall portamento.
  • Opening: Note-specific opening (range: 0-127, extensible).
  • Rise portamento: Note-specific rise portamento.
  • Vibrato length: Length of vibrato effect (range: 0-100).
  • Vibrato type: Type identifier for vibrato (e.g., 0 for none).

These properties ensure the file's hierarchical organization, with extensibility in numerical ranges for parameters like decay and opening, allowing modifications without compromising core functionality.

Two direct download links for .VSQX files (provided as ZIP archives containing multiple .VSQX samples, as individual direct .VSQX links are uncommon due to typical bundling):

The following is an embedded HTML and JavaScript snippet suitable for a Ghost blog (or similar static site). It creates a drag-and-drop interface for uploading a .VSQX file, parses the XML, extracts the properties listed in item 1, and displays them on the screen in a structured format.

VSQX Property Dumper
Drag and drop a .VSQX file here
  1. The following Python class handles opening, decoding (parsing), reading, writing, and printing .VSQX file properties to the console. It utilizes the xml.etree.ElementTree module for XML processing.
import xml.etree.ElementTree as ET

class VSQXParser:
    def __init__(self, filename):
        self.filename = filename
        self.tree = None
        self.root = None
        self.parse()

    def parse(self):
        """Decode and read the VSQX file."""
        self.tree = ET.parse(self.filename)
        self.root = self.tree.getroot()

    def print_properties(self):
        """Print all properties to console."""
        print("VSQX Properties:")

        # Voicebanks
        v_voices = self.root.findall('.//vVoice')
        print("\nVoicebanks:")
        for v in v_voices:
            print(f"- ID: {v.attrib.get('id', 'N/A')}, Name: {v.attrib.get('name', 'N/A')}")

        # Mixer
        mixer = self.root.find('.//mixer')
        if mixer is not None:
            print(f"\nMixer Attributes: {ET.tostring(mixer, encoding='unicode')}")

        # Master track
        master_track = self.root.find('.//masterTrack')
        if master_track is not None:
            time_sig = master_track.find('timeSig').text if master_track.find('timeSig') else 'N/A'
            tempo = master_track.find('tempo').text if master_track.find('tempo') else 'N/A'
            print("\nMaster Track:")
            print(f"- Time Signature: {time_sig}")
            print(f"- Tempo: {tempo}")

        # Tracks
        tracks = self.root.findall('.//vsTrack')
        print("\nTracks:")
        for idx, track in enumerate(tracks, 1):
            print(f"Track {idx}:")
            name = track.find('name').text if track.find('name') else 'N/A'
            play_time = track.find('playTime').text if track.find('playTime') else 'N/A'
            print(f"- Name: {name}")
            print(f"- Play Time: {play_time}")
            p_style = track.find('.//pStyle')
            if p_style is not None:
                print("Part Style:")
                for prop in ['accent', 'bendDep', 'bendLen', 'decay', 'opening', 'fallPort', 'risePort']:
                    val = p_style.find(f"v[@id='{prop}']").text if p_style.find(f"v[@id='{prop}']") else 'N/A'
                    print(f"  - {prop}: {val}")
            # Notes
            notes = track.findall('.//note')
            print("Notes:")
            for n_idx, note in enumerate(notes, 1):
                print(f"  Note {n_idx}:")
                t = note.find('t').text if note.find('t') else 'N/A'
                dur = note.find('dur').text if note.find('dur') else 'N/A'
                n = note.find('n').text if note.find('n') else 'N/A'
                v = note.find('v').text if note.find('v') else 'N/A'
                y = note.find('y').text if note.find('y') else 'N/A'
                p = note.find('p').text if note.find('p') else 'N/A'
                print(f"    - Timestamp (t): {t}")
                print(f"    - Duration (dur): {dur}")
                print(f"    - Note Number (n): {n}")
                print(f"    - Velocity (v): {v}")
                print(f"    - Lyrics (y): {y}")
                print(f"    - Phoneme (p): {p}")
                n_style = note.find('.//nStyle')
                if n_style is not None:
                    print("    Note Style:")
                    for prop in ['accent', 'bendDep', 'bendLen', 'decay', 'fallPort', 'opening', 'risePort', 'vibLen', 'vibType']:
                        val = n_style.find(f"v[@id='{prop}']").text if n_style.find(f"v[@id='{prop}']") else 'N/A'
                        print(f"      - {prop}: {val}")

    def write(self, output_filename):
        """Write the parsed VSQX back to a file (supports modifications)."""
        self.tree.write(output_filename, encoding='utf-8', xml_declaration=True)

# Example usage:
# parser = VSQXParser('example.vsqx')
# parser.print_properties()
# parser.write('modified.vsqx')
  1. The following Java class handles opening, decoding (parsing), reading, writing, and printing .VSQX file properties to the console. It utilizes javax.xml.parsers.DocumentBuilder for XML processing.
import java.io.File;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class VSQXParser {
    private String filename;
    private Document document;

    public VSQXParser(String filename) {
        this.filename = filename;
        parse();
    }

    private void parse() {
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            document = builder.parse(new File(filename));
            document.getDocumentElement().normalize();
        } catch (ParserConfigurationException | SAXException | IOException e) {
            e.printStackTrace();
        }
    }

    public void printProperties() {
        System.out.println("VSQX Properties:");

        // Voicebanks
        NodeList vVoices = document.getElementsByTagName("vVoice");
        System.out.println("\nVoicebanks:");
        for (int i = 0; i < vVoices.getLength(); i++) {
            Element v = (Element) vVoices.item(i);
            System.out.printf("- ID: %s, Name: %s%n", v.getAttribute("id"), v.getAttribute("name"));
        }

        // Mixer
        Element mixer = (Element) document.getElementsByTagName("mixer").item(0);
        if (mixer != null) {
            System.out.printf("\nMixer Attributes: %s%n", mixer.getTextContent());
        }

        // Master track
        Element masterTrack = (Element) document.getElementsByTagName("masterTrack").item(0);
        if (masterTrack != null) {
            String timeSig = masterTrack.getElementsByTagName("timeSig").item(0) != null ? 
                masterTrack.getElementsByTagName("timeSig").item(0).getTextContent() : "N/A";
            String tempo = masterTrack.getElementsByTagName("tempo").item(0) != null ? 
                masterTrack.getElementsByTagName("tempo").item(0).getTextContent() : "N/A";
            System.out.println("\nMaster Track:");
            System.out.printf("- Time Signature: %s%n", timeSig);
            System.out.printf("- Tempo: %s%n", tempo);
        }

        // Tracks
        NodeList tracks = document.getElementsByTagName("vsTrack");
        System.out.println("\nTracks:");
        for (int t = 0; t < tracks.getLength(); t++) {
            Element track = (Element) tracks.item(t);
            System.out.printf("Track %d:%n", t + 1);
            String name = track.getElementsByTagName("name").item(0) != null ? 
                track.getElementsByTagName("name").item(0).getTextContent() : "N/A";
            String playTime = track.getElementsByTagName("playTime").item(0) != null ? 
                track.getElementsByTagName("playTime").item(0).getTextContent() : "N/A";
            System.out.printf("- Name: %s%n", name);
            System.out.printf("- Play Time: %s%n", playTime);
            Element pStyle = (Element) track.getElementsByTagName("pStyle").item(0);
            if (pStyle != null) {
                System.out.println("Part Style:");
                String[] props = {"accent", "bendDep", "bendLen", "decay", "opening", "fallPort", "risePort"};
                for (String prop : props) {
                    NodeList vs = pStyle.getElementsByTagName("v");
                    String val = "N/A";
                    for (int i = 0; i < vs.getLength(); i++) {
                        Element vEl = (Element) vs.item(i);
                        if (vEl.getAttribute("id").equals(prop)) {
                            val = vEl.getTextContent();
                            break;
                        }
                    }
                    System.out.printf("  - %s: %s%n", prop, val);
                }
            }
            // Notes
            NodeList notes = track.getElementsByTagName("note");
            System.out.println("Notes:");
            for (int n = 0; n < notes.getLength(); n++) {
                Element note = (Element) notes.item(n);
                System.out.printf("  Note %d:%n", n + 1);
                String t = note.getElementsByTagName("t").item(0) != null ? 
                    note.getElementsByTagName("t").item(0).getTextContent() : "N/A";
                String dur = note.getElementsByTagName("dur").item(0) != null ? 
                    note.getElementsByTagName("dur").item(0).getTextContent() : "N/A";
                String nn = note.getElementsByTagName("n").item(0) != null ? 
                    note.getElementsByTagName("n").item(0).getTextContent() : "N/A";
                String v = note.getElementsByTagName("v").item(0) != null ? 
                    note.getElementsByTagName("v").item(0).getTextContent() : "N/A";
                String y = note.getElementsByTagName("y").item(0) != null ? 
                    note.getElementsByTagName("y").item(0).getTextContent() : "N/A";
                String p = note.getElementsByTagName("p").item(0) != null ? 
                    note.getElementsByTagName("p").item(0).getTextContent() : "N/A";
                System.out.printf("    - Timestamp (t): %s%n", t);
                System.out.printf("    - Duration (dur): %s%n", dur);
                System.out.printf("    - Note Number (n): %s%n", nn);
                System.out.printf("    - Velocity (v): %s%n", v);
                System.out.printf("    - Lyrics (y): %s%n", y);
                System.out.printf("    - Phoneme (p): %s%n", p);
                Element nStyle = (Element) note.getElementsByTagName("nStyle").item(0);
                if (nStyle != null) {
                    System.out.println("    Note Style:");
                    String[] nProps = {"accent", "bendDep", "bendLen", "decay", "fallPort", "opening", "risePort", "vibLen", "vibType"};
                    for (String prop : nProps) {
                        NodeList vs = nStyle.getElementsByTagName("v");
                        String val = "N/A";
                        for (int i = 0; i < vs.getLength(); i++) {
                            Element vEl = (Element) vs.item(i);
                            if (vEl.getAttribute("id").equals(prop)) {
                                val = vEl.getTextContent();
                                break;
                            }
                        }
                        System.out.printf("      - %s: %s%n", prop, val);
                    }
                }
            }
        }
    }

    public void write(String outputFilename) {
        try {
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            DOMSource source = new DOMSource(document);
            StreamResult result = new StreamResult(new File(outputFilename));
            transformer.transform(source, result);
        } catch (TransformerException e) {
            e.printStackTrace();
        }
    }

    // Example usage:
    // public static void main(String[] args) {
    //     VSQXParser parser = new VSQXParser("example.vsqx");
    //     parser.printProperties();
    //     parser.write("modified.vsqx");
    // }
}
  1. The following JavaScript class handles opening, decoding (parsing), reading, writing, and printing .VSQX file properties to the console. It assumes a Node.js environment with the fs module and xml2js for parsing (install via npm if needed; for browser, adapt with FileReader and DOMParser).
const fs = require('fs');
const xml2js = require('xml2js');

class VSQXParser {
    constructor(filename) {
        this.filename = filename;
        this.data = null;
        this.parse();
    }

    parse() {
        const xmlText = fs.readFileSync(this.filename, 'utf8');
        xml2js.parseString(xmlText, (err, result) => {
            if (err) throw err;
            this.data = result;
        });
    }

    printProperties() {
        if (!this.data) return console.log('No data parsed.');
        console.log('VSQX Properties:');

        // Voicebanks
        const vVoices = this.data.vsqx?.vVoiceTable?.[0]?.vVoice || [];
        console.log('\nVoicebanks:');
        vVoices.forEach(v => {
            console.log(`- ID: ${v.$.id || 'N/A'}, Name: ${v.$.name || 'N/A'}`);
        });

        // Mixer
        const mixer = this.data.vsqx?.mixer?.[0];
        if (mixer) console.log(`\nMixer Attributes: ${JSON.stringify(mixer)}`);

        // Master track
        const masterTrack = this.data.vsqx?.masterTrack?.[0];
        if (masterTrack) {
            const timeSig = masterTrack.timeSig?.[0] || 'N/A';
            const tempo = masterTrack.tempo?.[0] || 'N/A';
            console.log('\nMaster Track:');
            console.log(`- Time Signature: ${timeSig}`);
            console.log(`- Tempo: ${tempo}`);
        }

        // Tracks
        const tracks = this.data.vsqx?.vsTrack || [];
        console.log('\nTracks:');
        tracks.forEach((track, idx) => {
            console.log(`Track ${idx + 1}:`);
            const name = track.name?.[0] || 'N/A';
            const playTime = track.playTime?.[0] || 'N/A';
            console.log(`- Name: ${name}`);
            console.log(`- Play Time: ${playTime}`);
            const pStyle = track.vsPart?.[0]?.pStyle?.[0]?.v || [];
            if (pStyle.length) {
                console.log('Part Style:');
                ['accent', 'bendDep', 'bendLen', 'decay', 'opening', 'fallPort', 'risePort'].forEach(prop => {
                    const val = pStyle.find(v => v.$.id === prop)?. _ || 'N/A';
                    console.log(`  - ${prop}: ${val}`);
                });
            }
            // Notes
            const notes = track.vsPart?.[0]?.note || [];
            console.log('Notes:');
            notes.forEach((note, nIdx) => {
                console.log(`  Note ${nIdx + 1}:`);
                const t = note.t?.[0] || 'N/A';
                const dur = note.dur?.[0] || 'N/A';
                const n = note.n?.[0] || 'N/A';
                const v = note.v?.[0] || 'N/A';
                const y = note.y?.[0] || 'N/A';
                const p = note.p?.[0] || 'N/A';
                console.log(`    - Timestamp (t): ${t}`);
                console.log(`    - Duration (dur): ${dur}`);
                console.log(`    - Note Number (n): ${n}`);
                console.log(`    - Velocity (v): ${v}`);
                console.log(`    - Lyrics (y): ${y}`);
                console.log(`    - Phoneme (p): ${p}`);
                const nStyle = note.nStyle?.[0]?.v || [];
                if (nStyle.length) {
                    console.log('    Note Style:');
                    ['accent', 'bendDep', 'bendLen', 'decay', 'fallPort', 'opening', 'risePort', 'vibLen', 'vibType'].forEach(prop => {
                        const val = nStyle.find(v => v.$.id === prop)?. _ || 'N/A';
                        console.log(`      - ${prop}: ${val}`);
                    });
                }
            });
        });
    }

    write(outputFilename) {
        const builder = new xml2js.Builder({ renderOpts: { 'pretty': true, 'indent': '  ', 'newline': '\n' } });
        const xml = builder.buildObject(this.data);
        fs.writeFileSync(outputFilename, xml);
    }
}

// Example usage:
// const parser = new VSQXParser('example.vsqx');
// parser.printProperties();
// parser.write('modified.vsqx');
  1. The following C++ class (noted as "c class" in the query, interpreted as C++ for class support) handles opening, decoding (parsing), reading, writing, and printing .VSQX file properties to the console. It utilizes the TinyXML-2 library (include via #include <tinyxml2.h>; assume it is linked or available for compilation) for XML processing.
#include <iostream>
#include <string>
#include <tinyxml2.h>

class VSQXParser {
private:
    std::string filename;
    tinyxml2::XMLDocument doc;

public:
    VSQXParser(const std::string& fn) : filename(fn) {
        parse();
    }

    void parse() {
        doc.LoadFile(filename.c_str());
    }

    void printProperties() {
        std::cout << "VSQX Properties:" << std::endl;

        // Voicebanks
        tinyxml2::XMLElement* root = doc.FirstChildElement("vsqx");
        if (!root) return;
        tinyxml2::XMLElement* vVoiceTable = root->FirstChildElement("vVoiceTable");
        if (vVoiceTable) {
            std::cout << "\nVoicebanks:" << std::endl;
            tinyxml2::XMLElement* vVoice = vVoiceTable->FirstChildElement("vVoice");
            while (vVoice) {
                std::cout << "- ID: " << (vVoice->Attribute("id") ? vVoice->Attribute("id") : "N/A")
                          << ", Name: " << (vVoice->Attribute("name") ? vVoice->Attribute("name") : "N/A") << std::endl;
                vVoice = vVoice->NextSiblingElement("vVoice");
            }
        }

        // Mixer
        tinyxml2::XMLElement* mixer = root->FirstChildElement("mixer");
        if (mixer) std::cout << "\nMixer Attributes: " << mixer->GetText() << std::endl;

        // Master track
        tinyxml2::XMLElement* masterTrack = root->FirstChildElement("masterTrack");
        if (masterTrack) {
            std::string timeSig = masterTrack->FirstChildElement("timeSig") ? masterTrack->FirstChildElement("timeSig")->GetText() : "N/A";
            std::string tempo = masterTrack->FirstChildElement("tempo") ? masterTrack->FirstChildElement("tempo")->GetText() : "N/A";
            std::cout << "\nMaster Track:" << std::endl;
            std::cout << "- Time Signature: " << timeSig << std::endl;
            std::cout << "- Tempo: " << tempo << std::endl;
        }

        // Tracks
        tinyxml2::XMLElement* track = root->FirstChildElement("vsTrack");
        int trackIdx = 1;
        std::cout << "\nTracks:" << std::endl;
        while (track) {
            std::cout << "Track " << trackIdx << ":" << std::endl;
            std::string name = track->FirstChildElement("name") ? track->FirstChildElement("name")->GetText() : "N/A";
            std::string playTime = track->FirstChildElement("playTime") ? track->FirstChildElement("playTime")->GetText() : "N/A";
            std::cout << "- Name: " << name << std::endl;
            std::cout << "- Play Time: " << playTime << std::endl;
            tinyxml2::XMLElement* vsPart = track->FirstChildElement("vsPart");
            if (vsPart) {
                tinyxml2::XMLElement* pStyle = vsPart->FirstChildElement("pStyle");
                if (pStyle) {
                    std::cout << "Part Style:" << std::endl;
                    const char* props[] = {"accent", "bendDep", "bendLen", "decay", "opening", "fallPort", "risePort"};
                    for (const char* prop : props) {
                        tinyxml2::XMLElement* v = pStyle->FirstChildElement("v");
                        std::string val = "N/A";
                        while (v) {
                            if (std::string(v->Attribute("id")) == prop) {
                                val = v->GetText() ? v->GetText() : "N/A";
                                break;
                            }
                            v = v->NextSiblingElement("v");
                        }
                        std::cout << "  - " << prop << ": " << val << std::endl;
                    }
                }
                // Notes
                tinyxml2::XMLElement* note = vsPart->FirstChildElement("note");
                int noteIdx = 1;
                std::cout << "Notes:" << std::endl;
                while (note) {
                    std::cout << "  Note " << noteIdx << ":" << std::endl;
                    std::string t = note->FirstChildElement("t") ? note->FirstChildElement("t")->GetText() : "N/A";
                    std::string dur = note->FirstChildElement("dur") ? note->FirstChildElement("dur")->GetText() : "N/A";
                    std::string n = note->FirstChildElement("n") ? note->FirstChildElement("n")->GetText() : "N/A";
                    std::string v = note->FirstChildElement("v") ? note->FirstChildElement("v")->GetText() : "N/A";
                    std::string y = note->FirstChildElement("y") ? note->FirstChildElement("y")->GetText() : "N/A";
                    std::string p = note->FirstChildElement("p") ? note->FirstChildElement("p")->GetText() : "N/A";
                    std::cout << "    - Timestamp (t): " << t << std::endl;
                    std::cout << "    - Duration (dur): " << dur << std::endl;
                    std::cout << "    - Note Number (n): " << n << std::endl;
                    std::cout << "    - Velocity (v): " << v << std::endl;
                    std::cout << "    - Lyrics (y): " << y << std::endl;
                    std::cout << "    - Phoneme (p): " << p << std::endl;
                    tinyxml2::XMLElement* nStyle = note->FirstChildElement("nStyle");
                    if (nStyle) {
                        std::cout << "    Note Style:" << std::endl;
                        const char* nProps[] = {"accent", "bendDep", "bendLen", "decay", "fallPort", "opening", "risePort", "vibLen", "vibType"};
                        for (const char* prop : nProps) {
                            tinyxml2::XMLElement* v = nStyle->FirstChildElement("v");
                            std::string val = "N/A";
                            while (v) {
                                if (std::string(v->Attribute("id")) == prop) {
                                    val = v->GetText() ? v->GetText() : "N/A";
                                    break;
                                }
                                v = v->NextSiblingElement("v");
                            }
                            std::cout << "      - " << prop << ": " << val << std::endl;
                        }
                    }
                    note = note->NextSiblingElement("note");
                    noteIdx++;
                }
            }
            track = track->NextSiblingElement("vsTrack");
            trackIdx++;
        }
    }

    void write(const std::string& outputFilename) {
        doc.SaveFile(outputFilename.c_str());
    }
};

// Example usage:
// int main() {
//     VSQXParser parser("example.vsqx");
//     parser.printProperties();
//     parser.write("modified.vsqx");
//     return 0;
// }