@karaplay/file-coder 1.5.0 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DEMO_ENHANCED.md +207 -134
- package/DOCUMENTATION_INDEX.md +317 -0
- package/EMK_REFERENCE_DATA.json +190 -0
- package/EMK_SONGS_INFO.md +336 -0
- package/EMK_TEST_SUITE_README.md +456 -0
- package/EMK_TEST_SUITE_SUMMARY.txt +197 -0
- package/README.md +90 -0
- package/RELEASE_v1.5.1.md +190 -0
- package/RELEASE_v1.5.2.md +238 -0
- package/SONG_LIST.txt +268 -0
- package/TEMPO_TRICKS_SUMMARY.md +240 -0
- package/demo-libs/KarFile.js +391 -0
- package/demo-libs/MIDIEvents.js +325 -0
- package/demo-libs/MIDIFile.js +450 -0
- package/demo-libs/MIDIFileHeader.js +144 -0
- package/demo-libs/MIDIFileTrack.js +111 -0
- package/demo-libs/TextEncoding.js +275 -0
- package/demo-libs/UTF8.js +151 -0
- package/demo-server.js +78 -1
- package/demo-simple.html +287 -7
- package/dist/index.d.ts +1 -0
- package/dist/index.js +5 -1
- package/dist/kar-validator.d.ts +66 -0
- package/dist/kar-validator.js +152 -0
- package/dist/ncntokar.browser.js +13 -1
- package/dist/ncntokar.js +13 -1
- package/package.json +4 -1
- package/verify-emk-reference.js +230 -0
- package/analyze-emk-cursor.js +0 -169
- package/analyze-emk-simple.js +0 -124
- package/check-real-duration.js +0 -69
- package/temp/test_output.kar +0 -0
- package/test-all-emk-durations.js +0 -109
- package/test-convert-001.js +0 -130
package/README.md
CHANGED
|
@@ -14,6 +14,8 @@ A comprehensive library for encoding/decoding karaoke files (.emk, .kar, MIDI) w
|
|
|
14
14
|
- ⚛️ Next.js compatible (both client and server side)
|
|
15
15
|
- 🌐 **NEW**: Browser-compatible API for client-side processing
|
|
16
16
|
- 🇹🇭 Thai language support (TIS-620 encoding)
|
|
17
|
+
- 🎯 **v1.5.0**: Accurate tempo handling for ZXIO format (1.24x ratio)
|
|
18
|
+
- ⏱️ **NEW**: Tempo validation and duration accuracy
|
|
17
19
|
- ✅ **FIXED v1.3.2**: Client-side EMK decoder now works correctly!
|
|
18
20
|
- ✅ 131 tests - 100% pass rate (including integration tests with real files)
|
|
19
21
|
|
|
@@ -83,6 +85,94 @@ const results = convertEmkToKarBatch(
|
|
|
83
85
|
|
|
84
86
|
See [EMK_TO_KAR_WORKFLOW.md](./EMK_TO_KAR_WORKFLOW.md) for complete documentation.
|
|
85
87
|
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## ⏱️ Tempo Handling & Duration Accuracy
|
|
91
|
+
|
|
92
|
+
### Understanding EMK Tempo Conversion
|
|
93
|
+
|
|
94
|
+
EMK files use non-standard MIDI timing that requires tempo adjustment during conversion. This library **automatically** handles tempo correction based on the EMK format:
|
|
95
|
+
|
|
96
|
+
#### ZXIO Format (v1.5.0+)
|
|
97
|
+
```
|
|
98
|
+
Original EMK: 64 BPM → Converted KAR: 79 BPM
|
|
99
|
+
Tempo Ratio: 1.24x (ticksPerBeat / 77.42)
|
|
100
|
+
Duration: 4:43 ✅ Accurate!
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
#### MThd Format
|
|
104
|
+
```
|
|
105
|
+
Tempo Ratio: 4x, 8x, or 20x (auto-detected)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Validating Conversion Accuracy
|
|
109
|
+
|
|
110
|
+
Use `@tonejs/midi` to verify tempo and duration:
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
import { Midi } from '@tonejs/midi';
|
|
114
|
+
import { convertEmkToKar } from '@karaplay/file-coder';
|
|
115
|
+
import * as fs from 'fs';
|
|
116
|
+
|
|
117
|
+
// Convert EMK to KAR
|
|
118
|
+
const result = convertEmkToKar({
|
|
119
|
+
inputEmk: 'song.emk',
|
|
120
|
+
outputKar: 'song.kar'
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Validate with Tone.js
|
|
124
|
+
const karBuffer = fs.readFileSync('song.kar');
|
|
125
|
+
const midi = new Midi(karBuffer);
|
|
126
|
+
|
|
127
|
+
console.log('✅ Validation Results:');
|
|
128
|
+
console.log(` Tempo: ${midi.header.tempos[0].bpm.toFixed(2)} BPM`);
|
|
129
|
+
console.log(` Duration: ${(midi.duration / 60).toFixed(2)} minutes`);
|
|
130
|
+
console.log(` PPQ: ${midi.header.ppq}`);
|
|
131
|
+
console.log(` Tracks: ${midi.tracks.length}`);
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### 🔧 Troubleshooting Tempo Issues
|
|
135
|
+
|
|
136
|
+
**Problem:** Converted KAR plays too fast or too slow
|
|
137
|
+
**Solution:** The library automatically applies correct tempo ratios:
|
|
138
|
+
|
|
139
|
+
| Format | Original BPM | Ratio | Converted BPM | Status |
|
|
140
|
+
|--------|--------------|-------|---------------|--------|
|
|
141
|
+
| ZXIO | 64 BPM | 1.24x | 79 BPM | ✅ v1.5.0+ |
|
|
142
|
+
| MThd | 160 BPM | 4x | 640 BPM | ✅ Auto |
|
|
143
|
+
| MThd | 142 BPM | 8x | 1136 BPM | ✅ Auto |
|
|
144
|
+
|
|
145
|
+
**Important Notes:**
|
|
146
|
+
1. ✅ **Tempo is automatically corrected** - no manual adjustment needed
|
|
147
|
+
2. ✅ **Use @tonejs/midi for accurate duration** - it handles tempo events correctly
|
|
148
|
+
3. ⚠️ **Don't use karaoke-player's getTickResolution()** - it can give incorrect timing
|
|
149
|
+
4. ✅ **Duration decrease is normal** - faster tempo = shorter playback time
|
|
150
|
+
|
|
151
|
+
### Best Practices for MIDI Playback
|
|
152
|
+
|
|
153
|
+
When implementing a player for converted KAR files:
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
import { Midi } from '@tonejs/midi';
|
|
157
|
+
|
|
158
|
+
// ✅ CORRECT: Use Tone.js for timing
|
|
159
|
+
const midi = new Midi(karBuffer);
|
|
160
|
+
const duration = midi.duration; // Accurate!
|
|
161
|
+
|
|
162
|
+
midi.tracks.forEach(track => {
|
|
163
|
+
track.notes.forEach(note => {
|
|
164
|
+
const time = note.time; // ✅ Correct time in seconds
|
|
165
|
+
const noteNum = note.midi; // MIDI note number
|
|
166
|
+
const velocity = note.velocity;
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
// ❌ INCORRECT: Don't manually calculate from ticks
|
|
171
|
+
// const time = ticks * tickResolution; // May be wrong!
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
86
176
|
### NCN to KAR Conversion
|
|
87
177
|
|
|
88
178
|
```typescript
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# Release v1.5.1 - Tempo Validation & Documentation
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-01-13
|
|
4
|
+
|
|
5
|
+
## 🎯 New Features: Tempo Validation Utilities
|
|
6
|
+
|
|
7
|
+
### Added Validation Functions
|
|
8
|
+
|
|
9
|
+
This release adds comprehensive tempo and duration validation utilities to ensure conversion accuracy.
|
|
10
|
+
|
|
11
|
+
#### 1. **`validateKarTempo()`** - Validate KAR File Accuracy
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { validateKarTempo } from '@karaplay/file-coder';
|
|
15
|
+
import * as fs from 'fs';
|
|
16
|
+
|
|
17
|
+
const karBuffer = fs.readFileSync('song.kar');
|
|
18
|
+
const validation = validateKarTempo(karBuffer);
|
|
19
|
+
|
|
20
|
+
console.log(`Valid: ${validation.valid}`);
|
|
21
|
+
console.log(`Tempo: ${validation.tempo} BPM`);
|
|
22
|
+
console.log(`Duration: ${validation.durationMinutes}`);
|
|
23
|
+
console.log(`Warnings: ${validation.warnings.length}`);
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Returns:**
|
|
27
|
+
- `valid`: boolean - Overall validation status
|
|
28
|
+
- `tempo`: number - Tempo in BPM
|
|
29
|
+
- `duration`: number - Duration in seconds
|
|
30
|
+
- `durationMinutes`: string - Formatted as "M:SS"
|
|
31
|
+
- `ppq`: number - Ticks per beat
|
|
32
|
+
- `trackCount`: number - Number of tracks
|
|
33
|
+
- `noteCount`: number - Total notes
|
|
34
|
+
- `format`: number - MIDI format (0, 1, or 2)
|
|
35
|
+
- `warnings`: string[] - Non-critical issues
|
|
36
|
+
- `errors`: string[] - Critical issues
|
|
37
|
+
|
|
38
|
+
#### 2. **`compareEmkKarTempo()`** - Compare EMK vs KAR
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import { compareEmkKarTempo } from '@karaplay/file-coder';
|
|
42
|
+
|
|
43
|
+
const emkBuffer = fs.readFileSync('song.emk');
|
|
44
|
+
const karBuffer = fs.readFileSync('song.kar');
|
|
45
|
+
|
|
46
|
+
const comparison = compareEmkKarTempo(emkBuffer, karBuffer);
|
|
47
|
+
|
|
48
|
+
console.log(`Format: ${comparison.format}`); // "ZXIO" or "MThd"
|
|
49
|
+
console.log(`Tempo Ratio: ${comparison.tempoRatio}x`); // 1.24x for ZXIO
|
|
50
|
+
console.log(`Expected: ${comparison.expectedRatio}x`); // 1.24x
|
|
51
|
+
console.log(`Match: ${comparison.ratioMatch}`); // true
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Returns:**
|
|
55
|
+
- `emkTempo`: number - Original EMK tempo
|
|
56
|
+
- `karTempo`: number - Converted KAR tempo
|
|
57
|
+
- `tempoRatio`: number - Actual ratio applied
|
|
58
|
+
- `emkDuration`: number - EMK duration
|
|
59
|
+
- `karDuration`: number - KAR duration
|
|
60
|
+
- `durationRatio`: number - Duration change
|
|
61
|
+
- `format`: string - "ZXIO" or "MThd"
|
|
62
|
+
- `expectedRatio`: number - Expected ratio for format
|
|
63
|
+
- `ratioMatch`: boolean - Whether ratio is correct
|
|
64
|
+
|
|
65
|
+
## 📚 Enhanced Documentation
|
|
66
|
+
|
|
67
|
+
### New README Section: "Tempo Handling & Duration Accuracy"
|
|
68
|
+
|
|
69
|
+
Added comprehensive guide covering:
|
|
70
|
+
|
|
71
|
+
1. **Understanding EMK Tempo Conversion**
|
|
72
|
+
- ZXIO format: 1.24x ratio
|
|
73
|
+
- MThd format: 4x, 8x, or 20x (auto-detected)
|
|
74
|
+
|
|
75
|
+
2. **Validating Conversion Accuracy**
|
|
76
|
+
- Using @tonejs/midi for verification
|
|
77
|
+
- Duration and tempo checks
|
|
78
|
+
|
|
79
|
+
3. **Troubleshooting Tempo Issues**
|
|
80
|
+
- Common problems and solutions
|
|
81
|
+
- Format-specific ratios
|
|
82
|
+
|
|
83
|
+
4. **Best Practices for MIDI Playback**
|
|
84
|
+
- ✅ Use Tone.js for timing (accurate!)
|
|
85
|
+
- ❌ Don't use karaoke-player's getTickResolution() (can be wrong!)
|
|
86
|
+
|
|
87
|
+
### Example Usage
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
import { Midi } from '@tonejs/midi';
|
|
91
|
+
import { convertEmkToKar, validateKarTempo } from '@karaplay/file-coder';
|
|
92
|
+
|
|
93
|
+
// Convert
|
|
94
|
+
const result = convertEmkToKar({
|
|
95
|
+
inputEmk: 'song.emk',
|
|
96
|
+
outputKar: 'song.kar'
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Validate
|
|
100
|
+
const karBuffer = fs.readFileSync('song.kar');
|
|
101
|
+
const midi = new Midi(karBuffer);
|
|
102
|
+
|
|
103
|
+
console.log(`✅ Tempo: ${midi.header.tempos[0].bpm.toFixed(2)} BPM`);
|
|
104
|
+
console.log(`✅ Duration: ${(midi.duration / 60).toFixed(2)} minutes`);
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## 🔧 Technical Details
|
|
108
|
+
|
|
109
|
+
### Why Use @tonejs/midi?
|
|
110
|
+
|
|
111
|
+
**Problem:** `karaoke-player`'s `getTickResolution()` can calculate incorrect timing:
|
|
112
|
+
```
|
|
113
|
+
karaoke-player: 5,208 ms/tick ❌ (660x too high!)
|
|
114
|
+
Tone.js: 7.87 ms/tick ✅ (correct!)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Solution:** Always use `@tonejs/midi` for:
|
|
118
|
+
- Accurate tempo event handling
|
|
119
|
+
- Correct duration calculations
|
|
120
|
+
- Reliable timing information
|
|
121
|
+
|
|
122
|
+
### Tempo Ratios
|
|
123
|
+
|
|
124
|
+
| Format | Original BPM | Ratio | Converted BPM | Duration Example |
|
|
125
|
+
|--------|--------------|-------|---------------|------------------|
|
|
126
|
+
| ZXIO | 64 BPM | 1.24x | 79 BPM | 4:43 ✅ |
|
|
127
|
+
| MThd | 160 BPM | 4x | 640 BPM | Auto ✅ |
|
|
128
|
+
| MThd | 142 BPM | 8x | 1136 BPM | Auto ✅ |
|
|
129
|
+
|
|
130
|
+
## ✅ Testing
|
|
131
|
+
|
|
132
|
+
**Test Results:**
|
|
133
|
+
```
|
|
134
|
+
Test 1: validateKarTempo()
|
|
135
|
+
✅ Valid: true
|
|
136
|
+
✅ Tempo: 87.00 BPM
|
|
137
|
+
✅ Duration: 4:16
|
|
138
|
+
|
|
139
|
+
Test 2: compareEmkKarTempo() - ZXIO
|
|
140
|
+
✅ Format: ZXIO
|
|
141
|
+
✅ Tempo: 64 → 79 BPM (1.24x)
|
|
142
|
+
✅ Expected: 1.24x, Match: YES ✅
|
|
143
|
+
|
|
144
|
+
Test 3: Duration Accuracy
|
|
145
|
+
✅ Expected: 283s (4:43)
|
|
146
|
+
✅ Actual: 283.5s (4:43)
|
|
147
|
+
✅ Difference: 0.5s - PASS
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## 📊 What Changed
|
|
151
|
+
|
|
152
|
+
### New Files
|
|
153
|
+
- `src/kar-validator.ts` - Validation utilities
|
|
154
|
+
- `tests/kar-validator.test.ts` - Test suite
|
|
155
|
+
- `RELEASE_v1.5.1.md` - This file
|
|
156
|
+
|
|
157
|
+
### Updated Files
|
|
158
|
+
- `README.md` - Added "Tempo Handling & Duration Accuracy" section
|
|
159
|
+
- `src/index.ts` - Exported validator functions
|
|
160
|
+
- `package.json` - Version bump to 1.5.1
|
|
161
|
+
|
|
162
|
+
## 🚀 Migration from v1.5.0
|
|
163
|
+
|
|
164
|
+
No breaking changes! Simply update:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
npm install @karaplay/file-coder@1.5.1
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
New validator functions are optional - existing code continues to work.
|
|
171
|
+
|
|
172
|
+
## 💡 Key Takeaways
|
|
173
|
+
|
|
174
|
+
1. ✅ **Automatic tempo correction** - no manual adjustment needed
|
|
175
|
+
2. ✅ **Use @tonejs/midi** for accurate timing
|
|
176
|
+
3. ✅ **New validation utilities** for quality assurance
|
|
177
|
+
4. ✅ **Comprehensive documentation** for tempo handling
|
|
178
|
+
5. ⚠️ **Duration decrease is normal** - faster tempo = shorter playback
|
|
179
|
+
|
|
180
|
+
## 📖 Documentation
|
|
181
|
+
|
|
182
|
+
- [README.md](./README.md) - Main documentation
|
|
183
|
+
- [EMK_TO_KAR_WORKFLOW.md](./EMK_TO_KAR_WORKFLOW.md) - Conversion workflow
|
|
184
|
+
- [RELEASE_v1.5.0.md](./RELEASE_v1.5.0.md) - Previous release (ZXIO fix)
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
**Status:** ✅ Ready for Production
|
|
189
|
+
|
|
190
|
+
**Recommended Action:** Update to get validation utilities and improved documentation
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# Release v1.5.2 - High PPQ File Support
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-01-13
|
|
4
|
+
**Type:** Bug Fix
|
|
5
|
+
|
|
6
|
+
## 🐛 Bug Fix: Incorrect Tempo Ratio for High PPQ Files
|
|
7
|
+
|
|
8
|
+
### Problem
|
|
9
|
+
|
|
10
|
+
The file `Z2510006.emk` (Move On แบบใด - โจอี้ ภูวศิษฐ์) was incorrectly converted with:
|
|
11
|
+
- **Tempo Ratio:** 20x ❌ (should be 1x)
|
|
12
|
+
- **Duration:** 0:12 (12.83 seconds) ❌ (should be 4:16)
|
|
13
|
+
- **Tempo:** 87 BPM → 1,740 BPM ❌ (should stay 87 BPM)
|
|
14
|
+
|
|
15
|
+
**Root Cause:**
|
|
16
|
+
The system calculated tempo ratio as `PPQ / 24`:
|
|
17
|
+
- Z2510006 has `PPQ = 480`
|
|
18
|
+
- Calculated ratio: `480 / 24 = 20x` ❌
|
|
19
|
+
- But this file already has correct tempo and doesn't need adjustment!
|
|
20
|
+
|
|
21
|
+
### Solution
|
|
22
|
+
|
|
23
|
+
Added special handling for **high PPQ files** (PPQ >= 480):
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
if (isZxioFormat) {
|
|
27
|
+
ratio = ticksPerBeat / 77.42; // ZXIO: 1.24x
|
|
28
|
+
} else if (ticksPerBeat >= 480) {
|
|
29
|
+
ratio = 1.0; // High PPQ: No adjustment needed ✅
|
|
30
|
+
} else {
|
|
31
|
+
ratio = ticksPerBeat / 24; // Standard MThd: 4x, 8x, etc.
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Results
|
|
36
|
+
|
|
37
|
+
**Before Fix:**
|
|
38
|
+
```
|
|
39
|
+
Move On แบบใด (Z2510006.emk):
|
|
40
|
+
- Tempo: 87 → 1,740 BPM (20x) ❌
|
|
41
|
+
- Duration: 0:12 ❌
|
|
42
|
+
- Status: Incorrect
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**After Fix:**
|
|
46
|
+
```
|
|
47
|
+
Move On แบบใด (Z2510006.emk):
|
|
48
|
+
- Tempo: 87 → 87 BPM (1x) ✅
|
|
49
|
+
- Duration: 4:16 ✅
|
|
50
|
+
- Matches reference KAR: 100% ✅
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 📊 Impact
|
|
56
|
+
|
|
57
|
+
### Files Affected
|
|
58
|
+
|
|
59
|
+
**Z2510006.emk only:**
|
|
60
|
+
- This is the only file in our test set with PPQ >= 480
|
|
61
|
+
- Other files (PPQ < 480) are not affected
|
|
62
|
+
- All 9/9 tests pass ✅
|
|
63
|
+
|
|
64
|
+
### Tempo Ratio Distribution (Updated)
|
|
65
|
+
|
|
66
|
+
| Ratio | Format | Count | Files |
|
|
67
|
+
|-------|--------|-------|-------|
|
|
68
|
+
| 1.00x | MThd (High PPQ) | 1 | Z2510006 ✅ **NEW** |
|
|
69
|
+
| 1.24x | ZXIO | 3 | 001, 001_original, failed01 |
|
|
70
|
+
| 4.00x | MThd | 4 | Z2510001, Z2510002, Z2510004, Z2510005 |
|
|
71
|
+
| 8.00x | MThd | 1 | Z2510003 |
|
|
72
|
+
|
|
73
|
+
**Old (incorrect):**
|
|
74
|
+
- 20x: 1 file ❌ (removed)
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## ✅ Testing
|
|
79
|
+
|
|
80
|
+
### Test Results
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
$ npm run test:emk
|
|
84
|
+
|
|
85
|
+
✅ Passed: 9/9
|
|
86
|
+
⚠️ Warnings: 0/9
|
|
87
|
+
❌ Failed: 0/9
|
|
88
|
+
|
|
89
|
+
🎉 All tests passed!
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Specific Test: Z2510006
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
Testing: Z2510006.emk
|
|
96
|
+
✅ PASS: All checks passed
|
|
97
|
+
|
|
98
|
+
Comparison with Reference KAR:
|
|
99
|
+
Converted Tempo: 87.00 BPM
|
|
100
|
+
Reference Tempo: 87.00 BPM
|
|
101
|
+
Match: YES ✅
|
|
102
|
+
|
|
103
|
+
Converted Duration: 256.64 s (4:16)
|
|
104
|
+
Reference Duration: 256.64 s (4:16)
|
|
105
|
+
Difference: 0.00 s
|
|
106
|
+
Match: YES ✅
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## 📝 Changed Files
|
|
112
|
+
|
|
113
|
+
### Core Library
|
|
114
|
+
|
|
115
|
+
1. **src/ncntokar.ts**
|
|
116
|
+
- Updated `fixEmkMidiTempo()` function
|
|
117
|
+
- Added PPQ >= 480 check
|
|
118
|
+
|
|
119
|
+
2. **src/ncntokar.browser.ts**
|
|
120
|
+
- Updated `fixEmkMidiTempoBrowser()` function
|
|
121
|
+
- Same PPQ >= 480 logic
|
|
122
|
+
|
|
123
|
+
### Documentation
|
|
124
|
+
|
|
125
|
+
3. **EMK_REFERENCE_DATA.json**
|
|
126
|
+
- Updated Z2510006 expected values
|
|
127
|
+
- Tempo: 1740 → 87 BPM
|
|
128
|
+
- Duration: 12.83 → 256.64s
|
|
129
|
+
- Ratio: 20x → 1x
|
|
130
|
+
|
|
131
|
+
4. **SONG_LIST.txt**
|
|
132
|
+
- Updated Z2510006 information
|
|
133
|
+
- Fixed duration statistics
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## 🚀 Migration
|
|
138
|
+
|
|
139
|
+
### From v1.5.1 to v1.5.2
|
|
140
|
+
|
|
141
|
+
**No Breaking Changes!**
|
|
142
|
+
|
|
143
|
+
Simply update:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
npm install @karaplay/file-coder@1.5.2
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**All existing code continues to work.**
|
|
150
|
+
|
|
151
|
+
### What Changed
|
|
152
|
+
|
|
153
|
+
If you were converting `Z2510006.emk` or similar files with PPQ >= 480:
|
|
154
|
+
|
|
155
|
+
**Before (v1.5.1):**
|
|
156
|
+
```typescript
|
|
157
|
+
// Would produce incorrect 12-second file
|
|
158
|
+
convertEmkToKar({
|
|
159
|
+
inputEmk: 'Z2510006.emk',
|
|
160
|
+
outputKar: 'output.kar'
|
|
161
|
+
});
|
|
162
|
+
// Duration: 0:12 ❌
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**After (v1.5.2):**
|
|
166
|
+
```typescript
|
|
167
|
+
// Now produces correct 4:16 file
|
|
168
|
+
convertEmkToKar({
|
|
169
|
+
inputEmk: 'Z2510006.emk',
|
|
170
|
+
outputKar: 'output.kar'
|
|
171
|
+
});
|
|
172
|
+
// Duration: 4:16 ✅
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## 🎓 Technical Details
|
|
178
|
+
|
|
179
|
+
### PPQ (Pulses Per Quarter Note)
|
|
180
|
+
|
|
181
|
+
**Common PPQ Values:**
|
|
182
|
+
- 96: Standard (ratio = 96/24 = 4x)
|
|
183
|
+
- 120: Standard (ratio = 120/24 = 5x)
|
|
184
|
+
- 480: High resolution (ratio = 1x, no conversion needed)
|
|
185
|
+
|
|
186
|
+
**Why PPQ 480 is different:**
|
|
187
|
+
- Higher temporal resolution
|
|
188
|
+
- Usually means the file is already properly timed
|
|
189
|
+
- Common in professional MIDI editors
|
|
190
|
+
- Doesn't need our EMK tempo correction
|
|
191
|
+
|
|
192
|
+
### Detection Logic
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
// ZXIO: Always 1.24x
|
|
196
|
+
if (isZxioFormat) {
|
|
197
|
+
return ticksPerBeat / 77.42;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// High PPQ: No conversion
|
|
201
|
+
if (ticksPerBeat >= 480) {
|
|
202
|
+
return 1.0; // ← NEW in v1.5.2
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Standard MThd: Calculate ratio
|
|
206
|
+
return ticksPerBeat / 24;
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## 📚 Documentation
|
|
212
|
+
|
|
213
|
+
### Updated Documentation
|
|
214
|
+
|
|
215
|
+
- [SONG_LIST.txt](./SONG_LIST.txt) - Corrected Z2510006 info
|
|
216
|
+
- [EMK_REFERENCE_DATA.json](./EMK_REFERENCE_DATA.json) - Updated test data
|
|
217
|
+
- [RELEASE_v1.5.2.md](./RELEASE_v1.5.2.md) - This file
|
|
218
|
+
|
|
219
|
+
### Related Documentation
|
|
220
|
+
|
|
221
|
+
- [TEMPO_TRICKS_SUMMARY.md](./TEMPO_TRICKS_SUMMARY.md) - Tempo handling guide
|
|
222
|
+
- [EMK_TEST_SUITE_README.md](./EMK_TEST_SUITE_README.md) - Test suite guide
|
|
223
|
+
- [EMK_SONGS_INFO.md](./EMK_SONGS_INFO.md) - Song information
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## ✨ Summary
|
|
228
|
+
|
|
229
|
+
**Fixed:** Z2510006.emk now converts correctly with proper 4:16 duration
|
|
230
|
+
**Added:** Support for high PPQ files (PPQ >= 480)
|
|
231
|
+
**Status:** All 9/9 tests pass ✅
|
|
232
|
+
**Breaking:** None - fully backward compatible
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
**Recommended Action:** Update to v1.5.2 if you're converting files with high PPQ values.
|
|
237
|
+
|
|
238
|
+
**npm:** https://www.npmjs.com/package/@karaplay/file-coder
|