1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- /**
- * 解析ABC曲谱, 获取最小的音符单位
- * @param abcNotation abc曲谱
- * @returns 最小的音符单位
- */
- export const getMinNoteUnit = (abcNotation: string) => {
- const lines = abcNotation.split("\n");
- let minNoteUnit = null;
- for (const line of lines) {
- const regex = /L:(\s*)(\d+\/\d+)/;
- const match = line.match(regex);
- console.log("🚀 ~ line:", line, match);
- // Extract the unit note length from the L: directive.
- const unitNoteLengthMatch = line.match(regex);
- if (unitNoteLengthMatch) {
- minNoteUnit = unitNoteLengthMatch[unitNoteLengthMatch.length - 1];
- break;
- }
- }
- return minNoteUnit;
- };
- // Convert an AudioBuffer to a Blob using WAVE representation
- export const bufferToWave = (audioBuffer: AudioBuffer) => {
- var numOfChan = audioBuffer.numberOfChannels;
- var length = audioBuffer.length * numOfChan * 2 + 44;
- var buffer = new ArrayBuffer(length);
- var view = new DataView(buffer);
- var channels = [];
- var i;
- var sample;
- var offset = 0;
- var pos = 0;
- // write WAVE header
- setUint32(0x46464952); // "RIFF"
- setUint32(length - 8); // file length - 8
- setUint32(0x45564157); // "WAVE"
- setUint32(0x20746d66); // "fmt " chunk
- setUint32(16); // length = 16
- setUint16(1); // PCM (uncompressed)
- setUint16(numOfChan);
- setUint32(audioBuffer.sampleRate);
- setUint32(audioBuffer.sampleRate * 2 * numOfChan); // avg. bytes/sec
- setUint16(numOfChan * 2); // block-align
- setUint16(16); // 16-bit (hardcoded in this demo)
- setUint32(0x61746164); // "data" - chunk
- setUint32(length - pos - 4); // chunk length
- // write interleaved data
- for(i = 0; i < numOfChan; i++)
- channels.push(audioBuffer.getChannelData(i));
- while(pos < length) {
- for(i = 0; i < channels.length; i++) { // interleave channels
- sample = Math.max(-1, Math.min(1, channels[i][offset])); // clamp
- sample = (0.5 + sample < 0 ? sample * 32768 : sample * 32767)|0; // scale to 16-bit signed int
- view.setInt16(pos, sample, true); // write 16-bit sample
- pos += 2;
- }
- offset++; // next source sample
- }
- // create Blob
- return new Blob([buffer], {type: "audio/wav"});
- function setUint16(data: any) {
- view.setUint16(pos, data, true);
- pos += 2;
- }
- function setUint32(data: any) {
- view.setUint32(pos, data, true);
- pos += 4;
- }
- }
|