MIDI Type 1 → Type 0 Converter (Frontend)
A simple utility that converts Standard MIDI files from Type 1 (multi-track) to Type 0 (single-track) for reliable playback on Yamaha Disklaviers and other player pianos. The converter merges tracks while preserving MIDI channel data so the musical performance remains unchanged, written as WordPress plugin.
by Alexander Peppe · github.com/alexs-piano-service/midi-type0-converter · website
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/alexs-piano-service/midi-type0-converter/archive/refs/heads/main.zipMIDI Type 1 -> Type 0 Converter (WordPress Plugin)
Frontend WordPress plugin that lets users upload .mid/.midi files, converts MIDI Type 1 to Type 0 asynchronously, and provides per-file or batch ZIP downloads.
Features
- Frontend upload UI via shortcode:
[midi_type0_converter] - Multi-file upload with per-job status polling
- Asynchronous conversion pipeline (
queued -> processing -> done/error) - Per-file signed download links
- Batch ZIP download link (when
ZipArchiveis available) - Private storage under
wp-content/uploads/mtc-private - Rate limits for upload/status/download endpoints
- Optional ClamAV scan before storing uploads (disabled by default)
Requirements
- WordPress (plugin architecture + AJAX + cron APIs)
- PHP 8.0+ recommended (uses modern PHP features like
match) ZipArchiveextension for "Download All (ZIP)"- Optional:
clamdscanfor antivirus scanning when enabled by filter
Installation
- Copy this project folder into
wp-content/plugins/. - Activate the plugin in WordPress admin.
- Add shortcode
[midi_type0_converter]to a page/post. - Open that page and upload MIDI files.
Usage
- Select one or more
.mid/.midifiles. - Click
Upload & Convert. - Polling starts automatically and status updates appear in the table.
- Download files individually as they complete, or use
Download All (ZIP)when available.
How It Works
- Upload endpoint:
mtc_upload(wp_ajax_*)- Validates nonce, extension, MIDI header (
MThd), size limits, and optional ClamAV scan when enabled. - Persists job row in DB table with initial
queuedstatus. - Schedules background job via
wp_schedule_single_event.
- Validates nonce, extension, MIDI header (
- Status endpoint:
mtc_status(wp_ajax_*)- Returns jobs for a
batch_id, statuses, and signed download URLs. - Nudges stale queued jobs (cron spawn + fallback inline processing for very stale items).
- Returns jobs for a
- Conversion worker:
mtc_process_job- Claims queued jobs atomically and runs pure-PHP conversion (
includes/class-mtc-midi-converter.php).
- Claims queued jobs atomically and runs pure-PHP conversion (
- Download handlers:
?mtc_download=1...for a single converted MIDI?mtc_zip=1...for batch ZIP- Links are HMAC-signed and time-limited.
Data Model
Table: {wp_prefix}mtc_jobs
idbatch_idoriginal_nameoriginal_pathconverted_pathstatus(queued,processing,done,error)error_msgcreated_atupdated_at
Configuration (Filters)
Add filters in a must-use plugin or theme functions.php.
add_filter('mtc_max_upload_bytes', fn() => 10 * 1024 * 1024);
add_filter('mtc_max_files_per_batch', fn() => 200);
add_filter('mtc_download_ttl_seconds', fn() => DAY_IN_SECONDS);
add_filter('mtc_max_queued_ui_ms', fn() => 6000);
add_filter('mtc_poll_interval_ms', fn() => 2000);
add_filter('mtc_poll_max_backoff_ms', fn() => 15000);
add_filter('mtc_rate_limit_window_seconds', fn() => 10 * MINUTE_IN_SECONDS);
add_filter('mtc_rate_limit_max_uploads_per_window', fn() => 80);
add_filter('mtc_status_rate_limit_per_batch_window_seconds', fn() => 60);
add_filter('mtc_status_rate_limit_per_batch_per_window', fn() => 240);
add_filter('mtc_status_rate_limit_ip_window_seconds', fn() => 600);
add_filter('mtc_status_rate_limit_ip_per_window', fn() => 1000);
add_filter('mtc_queue_nudge_after_seconds', fn() => 3);
add_filter('mtc_inline_process_after_seconds', fn() => 12);
// ClamAV is disabled by default. Enable it only on hosts with a working clamdscan setup.
add_filter('mtc_clamav_enabled', fn() => true);
add_filter('mtc_clamav_fail_open', fn() => false);
add_filter('mtc_clamdscan_path', fn() => '/usr/bin/clamdscan');
add_filter('mtc_clamav_cmd_timeout_seconds', fn() => 6);
add_filter('mtc_timeout_bin', fn() => '/usr/bin/timeout');
add_filter('mtc_zip_cache_ttl', fn() => 900);
add_filter('mtc_cleanup_days', fn() => 2);
Security Notes
- Nonce-protected AJAX requests (
mtc_nonce) - Signed, expiring download URLs (HMAC with
wp_salt('auth')) - Uploaded files stored in a non-public uploads subdirectory
- Direct-access blocks for Apache/IIS (
.htaccess,web.config) - MIME/header checks plus binary MIDI magic check (
MThd) - Optional AV scanning through
clamdscanwhen enabled
Operational Notes
- This plugin relies on WP-Cron for background processing.
- If your site has low traffic, cron events may fire late.
- Recent changes include queue nudging and inline fallback to reduce long
queuedwaits.
Development
Project layout:
.
├── midi-type0-converter.php # Main plugin bootstrap + AJAX/cron handlers
├── includes/
│ └── class-mtc-midi-converter.php # Pure PHP MIDI parser/merger
└── assets/
├── mtc.js # Frontend upload + polling UI
└── mtc.css # Frontend styles
Syntax checks:
php -l midi-type0-converter.php
php -l includes/class-mtc-midi-converter.php
License
GPLv2 or later.