Task 361: .LOGICX File Format
Task 361: .LOGICX File Format
File Format Specifications for the .LOGICX File Format
The .LOGICX file format is a proprietary format used by Apple Logic Pro X (LPX) for saving project files. There is no official public specification from Apple, as it is a closed, proprietary format. Based on reverse engineering and community discussions, the format is a macOS bundle (a special type of directory that appears as a single file in Finder). When shared or downloaded, .LOGICX files are often compressed as ZIP archives (with the .logicx extension retained or sometimes renamed), allowing them to be treated as zip files for parsing. The main data is stored in a binary serialized format within the "ProjectData" file, which contains chunked sections with 4-byte identifiers (e.g., "Song", "Trak", "EvSq") and includes serialized object data, MIDI, settings, and embedded text like project notes in RTF-like format. Some parts may be compressed or binary-encoded, making full decoding challenging without reverse engineering. GarageBand uses a similar structure but with XML; LPX uses binary. The format evolved from the older .logic format and is designed for storing audio projects, including tracks, plugins, media, and alternatives.
List of all the properties of this file format intrinsic to its file system:
- File Extension: .logicx
- File Type: Apple Logic Pro X Project Bundle
- Developer: Apple Inc.
- Category: Audio Project File
- Format Type: Bundle (directory structure on macOS; often ZIP-compressed for sharing)
- MIME Type: application/octet-stream (no official MIME, treated as binary or zip)
- Structure: Directory bundle with subfolders (Alternatives, Media, Resources); can be opened as ZIP if compressed
- Magic Signature: None for bundle; if ZIP-compressed, starts with "PK\003\004"
- Main Data File: Alternatives/000/ProjectData (binary serialized data with chunked sections)
- Backup System: Project File Backups subfolder with numbered directories (00, 01, etc.) containing ProjectData copies
- Media Storage: Media folder for audio/video files (e.g., WAV, AIFF, MP3)
- Resources: Resources folder for playlists (.plst), images (.jpeg), notation, etc.
- Alternatives Support: Alternatives folder with numbered subdirectories (000, 001, etc.) for project versions
- Autosave: Autosave subfolder for recovery data
- Version Compatibility: Introduced in Logic Pro X (2013); backward compatible with .logic files
- Sample Rates Supported: 44.1 kHz to 192 kHz
- Bit Depths Supported: 16, 20, 24 bits
- Maximum Project Length: >6 hours at 96 kHz; >13 hours at 44.1 kHz
- Accessibility: No built-in format features; relies on Logic Pro application settings
- Proprietary Nature: Binary serialization of internal data objects; no XML schema for ProjectData (unlike GarageBand)
- File System Integration: Treated as a single file on macOS via bundle system; on other OS, appears as directory
Two direct download links for files of format .LOGICX:
- https://downloads.sourceforge.net/project/logic-pro-x-sample-project/Logic Pro X Sample Project.logicx
- https://www.logic-templates.com/wp-content/uploads/2016/08/Free-Trance-Logic-Pro-X-Template.logicx
Ghost blog embedded HTML JavaScript for drag and drop .LOGICX file to dump properties:
Drag and Drop .LOGICX File to Dump Properties
- Python class for opening, decoding, reading, writing, and printing .LOGICX properties:
import zipfile
import os
from io import BytesIO
class LogicXHandler:
def __init__(self, filepath):
self.filepath = filepath
self.properties = {}
self.decode()
def decode(self):
# Treat as ZIP, extract properties
with zipfile.ZipFile(self.filepath, 'r') as zip_ref:
self.properties['extension'] = '.logicx'
self.properties['type'] = 'Apple Logic Pro X Project Bundle (ZIP-compressed)'
self.properties['contents'] = zip_ref.namelist()
self.properties['main_data_file'] = 'Alternatives/000/ProjectData' if 'Alternatives/000/ProjectData' in zip_ref.namelist() else None
if self.properties['main_data_file']:
with zip_ref.open(self.properties['main_data_file']) as pd:
data = pd.read()
# High-level decode: extract printable strings from binary ProjectData
printable = ''.join([chr(b) for b in data if 32 <= b < 127])
self.properties['project_data_strings'] = printable[:500] + '...' # Partial for demo
def read(self):
return self.properties
def print_properties(self):
for key, value in self.properties.items():
print(f"{key}: {value}")
def write(self, new_filepath):
# High-level write: create basic ZIP with structure (no full encode, as no spec)
with zipfile.ZipFile(new_filepath, 'w') as zip_ref:
# Create basic directories
zip_ref.writestr('Alternatives/000/', '')
zip_ref.writestr('Media/Audio/', '')
zip_ref.writestr('Resources/', '')
# Add dummy ProjectData (binary)
dummy_data = b'SongTrakEvSqDummyData'
zip_ref.writestr('Alternatives/000/ProjectData', dummy_data)
print(f"Written basic .logicx to {new_filepath}")
# Example usage
# handler = LogicXHandler('example.logicx')
# handler.print_properties()
# handler.write('new.logicx')
- Java class for opening, decoding, reading, writing, and printing .LOGICX properties:
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
public class LogicXHandler {
private String filepath;
private Map<String, Object> properties = new HashMap<>();
public LogicXHandler(String filepath) {
this.filepath = filepath;
decode();
}
private void decode() {
try (ZipFile zipFile = new ZipFile(filepath)) {
properties.put("extension", ".logicx");
properties.put("type", "Apple Logic Pro X Project Bundle (ZIP-compressed)");
StringBuilder contents = new StringBuilder();
zipFile.stream().forEach(entry -> contents.append(entry.getName()).append("\n"));
properties.put("contents", contents.toString());
ZipEntry pdEntry = zipFile.getEntry("Alternatives/000/ProjectData");
if (pdEntry != null) {
properties.put("main_data_file", pdEntry.getName());
byte[] data = zipFile.getInputStream(pdEntry).readAllBytes();
// High-level decode: extract printable strings
StringBuilder printable = new StringBuilder();
for (byte b : data) {
if (b >= 32 && b < 127) printable.append((char) b);
}
properties.put("project_data_strings", printable.substring(0, Math.min(500, printable.length())) + "...");
}
} catch (IOException e) {
System.err.println("Error decoding: " + e);
}
}
public Map<String, Object> read() {
return properties;
}
public void printProperties() {
properties.forEach((key, value) -> System.out.println(key + ": " + value));
}
public void write(String newFilepath) {
try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(newFilepath))) {
// Create basic directories
zos.putNextEntry(new ZipEntry("Alternatives/000/"));
zos.closeEntry();
zos.putNextEntry(new ZipEntry("Media/Audio/"));
zos.closeEntry();
zos.putNextEntry(new ZipEntry("Resources/"));
zos.closeEntry();
// Add dummy ProjectData
zos.putNextEntry(new ZipEntry("Alternatives/000/ProjectData"));
byte[] dummyData = "SongTrakEvSqDummyData".getBytes();
zos.write(dummyData);
zos.closeEntry();
System.out.println("Written basic .logicx to " + newFilepath);
} catch (IOException e) {
System.err.println("Error writing: " + e);
}
}
// Example usage
// public static void main(String[] args) {
// LogicXHandler handler = new LogicXHandler("example.logicx");
// handler.printProperties();
// handler.write("new.logicx");
// }
}
- JavaScript class for opening, decoding, reading, writing, and printing .LOGICX properties:
class LogicXHandler {
constructor(file) {
this.file = file;
this.properties = {};
this.decode();
}
async decode() {
const zip = await JSZip.loadAsync(this.file);
this.properties.extension = '.logicx';
this.properties.type = 'Apple Logic Pro X Project Bundle (ZIP-compressed)';
this.properties.contents = Object.keys(zip.files);
const pdPath = 'Alternatives/000/ProjectData';
if (zip.files[pdPath]) {
this.properties.main_data_file = pdPath;
const data = await zip.file(pdPath).async('arraybuffer');
const str = new TextDecoder().decode(new Uint8Array(data));
const printable = str.replace(/[\x00-\x1F\x7F-\xFF]/g, '');
this.properties.project_data_strings = printable.substring(0, 500) + '...';
}
}
read() {
return this.properties;
}
printProperties() {
console.log(this.properties);
}
async write(newFilename) {
const zip = new JSZip();
// Create basic directories
zip.folder('Alternatives/000');
zip.folder('Media/Audio');
zip.folder('Resources');
// Add dummy ProjectData
zip.file('Alternatives/000/ProjectData', 'SongTrakEvSqDummyData');
const content = await zip.generateAsync({type: 'blob'});
const url = URL.createObjectURL(content);
const a = document.createElement('a');
a.href = url;
a.download = newFilename;
a.click();
console.log(`Written basic .logicx as ${newFilename}`);
}
}
// Example usage
// const inputFile = ... // e.g., from file input
// const handler = new LogicXHandler(inputFile);
// await handler.decode(); // if not awaited in constructor
// handler.printProperties();
// await handler.write('new.logicx');
- C class (using C++ for class support) for opening, decoding, reading, writing, and printing .LOGICX properties:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <zip.h> // Requires libzip library
using namespace std;
class LogicXHandler {
private:
string filepath;
map<string, string> properties;
public:
LogicXHandler(const string& fp) : filepath(fp) {
decode();
}
void decode() {
// Use libzip to open as ZIP
int err = 0;
zip* z = zip_open(filepath.c_str(), 0, &err);
if (z) {
properties["extension"] = ".logicx";
properties["type"] = "Apple Logic Pro X Project Bundle (ZIP-compressed)";
string contents = "";
int num_entries = zip_get_num_entries(z, 0);
for (int i = 0; i < num_entries; ++i) {
contents += zip_get_name(z, i, 0) + "\n";
}
properties["contents"] = contents;
struct zip_stat st;
if (zip_stat(z, "Alternatives/000/ProjectData", 0, &st) == 0) {
properties["main_data_file"] = "Alternatives/000/ProjectData";
zip_file* f = zip_fopen(z, "Alternatives/000/ProjectData", 0);
char* data = new char[st.size];
zip_fread(f, data, st.size);
string printable = "";
for (size_t j = 0; j < st.size; ++j) {
if (data[j] >= 32 && data[j] < 127) printable += data[j];
}
properties["project_data_strings"] = printable.substr(0, 500) + "...";
delete[] data;
zip_fclose(f);
}
zip_close(z);
} else {
cerr << "Error opening ZIP: " << err << endl;
}
}
map<string, string> read() {
return properties;
}
void printProperties() {
for (const auto& pair : properties) {
cout << pair.first << ": " << pair.second << endl;
}
}
void write(const string& newFilepath) {
zip* z = zip_open(newFilepath.c_str(), ZIP_CREATE | ZIP_TRUNCATE, nullptr);
if (z) {
// Create basic directories
zip_add_dir(z, "Alternatives/000");
zip_add_dir(z, "Media/Audio");
zip_add_dir(z, "Resources");
// Add dummy ProjectData
string dummyData = "SongTrakEvSqDummyData";
zip_source* src = zip_source_buffer(z, dummyData.c_str(), dummyData.size(), 0);
zip_file_add(z, "Alternatives/000/ProjectData", src, ZIP_FL_ENC_UTF_8);
zip_close(z);
cout << "Written basic .logicx to " << newFilepath << endl;
} else {
cerr << "Error creating ZIP" << endl;
}
}
};
// Example usage
// int main() {
// LogicXHandler handler("example.logicx");
// handler.printProperties();
// handler.write("new.logicx");
// return 0;
// }