1export function insertRecording(insertStringIntoEditor) { 2 const recorded = window.recordedSongData; 3 4 const recordings = {}; 5 6 // find first song position with recorded data 7 const firstSongPositionWithData = recorded.instrumentPatternLists 8 .map(patternIndexList => 9 patternIndexList.findIndex(patternIndex => patternIndex > 0)) 10 .filter(songPosition => songPosition > -1) 11 .sort()[0]; 12 13 // find last song position with recorded data 14 const lastSongPositionWithData = recorded.instrumentPatternLists 15 .map(patternIndexList => 16 patternIndexList.reduce( 17 // using reduce to find last element with value > 0 18 (currentSongPosition, patternIndex, songPosition) => 19 patternIndex > 0 ? songPosition : currentSongPosition, 20 -1 21 ) 22 ) 23 .filter(songPosition => songPosition > -1) 24 .sort((a, b) => b - a)[0]; 25 26 recorded.instrumentPatternLists.forEach((instrumentPatternList, instrumentIndex) => { 27 if(instrumentPatternList.find(patternIndex => patternIndex > 0)) { 28 // go through pattern list for each instrument that has recorded data: 29 instrumentPatternList.forEach((patternIndex, songPosition) => { 30 if(!recordings[instrumentNames[instrumentIndex]]) { 31 recordings[instrumentNames[instrumentIndex]] = []; 32 } 33 34 if( songPosition >= firstSongPositionWithData && 35 songPosition <= lastSongPositionWithData 36 ) { 37 // start with an empty pattern 38 let patternData = new Array(recorded.patterns[0].length).fill(0); 39 40 if (patternIndex > 0 ) { 41 // get data from recorded pattern ( if there is one ) 42 patternData = recorded.patterns[patternIndex-1]; 43 } 44 45 patternData.forEach(val => 46 // push each note from recorded pattern to recordings array per instrument 47 recordings[instrumentNames[instrumentIndex]].push(val) 48 ); 49 } 50 }) 51 } 52 }); 53 54 const groupRecordings = {}; 55 Object.keys(recordings).forEach(instrumentName => { 56 let patterndata = recordings[instrumentName]; 57 58 patterndata = patterndata.map((v, ndx) => { 59 if(v > 0) { 60 if(instrumentDefs[instrumentName].type === 'number') { 61 return v + ''; 62 } else if(instrumentDefs[instrumentName].type === 'note') { 63 let noteLen = 1; 64 while(patterndata[ndx + noteLen] === 1 && 65 (ndx + noteLen) < patterndata.length 66 ) { 67 // Detect how long the note is held 68 noteLen ++; 69 } 70 const beatLength = window.ticksperbeat(); 71 let divisor = beatLength; 72 while ( (noteLen %2) === 0 && (divisor % 2) === 0) { 73 noteLen /= 2; 74 divisor /= 2; 75 } 76 77 const lengthExpression = noteLen === 1 && divisor === beatLength ? '' : 78 divisor === 1 ? `(${noteLen})` : `(${noteLen}/${divisor})`; 79 80 return v > 1 ? `${window.noteValues[v]}${lengthExpression}` : ''; 81 } 82 } else { 83 return ''; 84 } 85 }); 86 87 let groupInstrumentIndex; 88 const groupName = Object.keys(instrumentGroupMap).find(groupname => { 89 groupInstrumentIndex = instrumentGroupMap[groupname].findIndex(instr => instr === instrumentName); 90 return groupInstrumentIndex > -1; 91 }); 92 93 if(groupName) { 94 if(!groupRecordings[groupName]) { 95 groupRecordings[groupName] = new Array(instrumentGroupMap[groupName].length); 96 } 97 groupRecordings[groupName][groupInstrumentIndex] = patterndata; 98 } else { 99 const stepsPerBeat = ticksperbeat(); 100 const recordingString = `"${instrumentName}": pp(${stepsPerBeat}, [${ 101 patterndata 102 .map((val, ndx) => ndx > 0 && ndx % stepsPerBeat === 0 ? `\n${val}` : val) 103 .join(',') 104 }]),\n`; 105 insertStringIntoEditor(recordingString); 106 } 107 });
108 Object.keys(groupRecordings).forEach(group => { 109 const recordings = groupRecordings[group]; 110 const recordingArr = []; 111 recordings.forEach((recording, instrIndex) => { 112 recording.forEach((val, ndx) => { 113 if(!recordingArr[ndx]) { 114 recordingArr[ndx] = []; 115 } 116 recordingArr[ndx][instrIndex] = val; 117 }); 118 }); 119 const stepsPerBeat = ticksperbeat(); 120 const recordingdatastring = recordingArr.map((values, ndx) => { 121 let newLine = ''; 122 if(ndx > 0 && ndx % stepsPerBeat === 0) { 123 newLine = '\n'; 124 } 125 if(values.filter(val => val ? true: false).length === 0) { 126 return `${newLine}`; 127 } else if(values[0] && values.filter(val => val ? true: false).length === 1) { 128 return `${newLine}${values[0]}`; 129 } else { 130 return `${newLine}[${values.join(',')}]`; 131 } 132 }).join(','); 133 134 const recordingString = `"${group}": pp(${stepsPerBeat}, [${recordingdatastring}], ${recordings.length}),\n`; 135 insertStringIntoEditor(recordingString); 136 }); 137 138 // Clear recordings 139 window.recordedSongData = { 140 instrumentPatternLists: recorded.instrumentPatternLists.map(pl => new Array(pl.length).fill(0)), 141 patterns: recorded.patterns.map(p => new Array(p.length).fill(0)) 142 }; 143}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.