PageSourceSearch

https://webassemblymusic.pages.dev/4klangsequencer/editorfunctions.js

js webassemblymusic.pages.dev collected 2026-10-03 06:04:59 UTC 6,215 bytes, 143 lines download raw bytes

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.