|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import { SpessaSynthWarn } from "../../utils/loggin.js"; |
|
|
|
|
|
|
|
|
const RESAMPLE_RATE = 48000; |
|
|
|
|
|
export class BasicSample |
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sampleName; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sampleRate; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
samplePitch; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
samplePitchCorrection; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sampleLink; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sampleType; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sampleLoopStartIndex; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sampleLoopEndIndex; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
isCompressed; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
compressedData = undefined; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
useCount = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sampleData = undefined; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constructor( |
|
|
sampleName, |
|
|
sampleRate, |
|
|
samplePitch, |
|
|
samplePitchCorrection, |
|
|
sampleLink, |
|
|
sampleType, |
|
|
loopStart, |
|
|
loopEnd |
|
|
) |
|
|
{ |
|
|
this.sampleName = sampleName; |
|
|
this.sampleRate = sampleRate; |
|
|
this.samplePitch = samplePitch; |
|
|
this.samplePitchCorrection = samplePitchCorrection; |
|
|
this.sampleLink = sampleLink; |
|
|
this.sampleType = sampleType; |
|
|
this.sampleLoopStartIndex = loopStart; |
|
|
this.sampleLoopEndIndex = loopEnd; |
|
|
|
|
|
this.isCompressed = (sampleType & 0x10) > 0; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getRawData() |
|
|
{ |
|
|
const uint8 = new Uint8Array(this.sampleData.length * 2); |
|
|
for (let i = 0; i < this.sampleData.length; i++) |
|
|
{ |
|
|
const sample = Math.floor(this.sampleData[i] * 32768); |
|
|
uint8[i * 2] = sample & 0xFF; |
|
|
uint8[i * 2 + 1] = (sample >> 8) & 0xFF; |
|
|
} |
|
|
return uint8; |
|
|
} |
|
|
|
|
|
resampleData(newSampleRate) |
|
|
{ |
|
|
let audioData = this.getAudioData(); |
|
|
const ratio = newSampleRate / this.sampleRate; |
|
|
const resampled = new Float32Array(Math.floor(audioData.length * ratio)); |
|
|
for (let i = 0; i < resampled.length; i++) |
|
|
{ |
|
|
resampled[i] = audioData[Math.floor(i * (1 / ratio))]; |
|
|
} |
|
|
audioData = resampled; |
|
|
this.sampleRate = newSampleRate; |
|
|
|
|
|
this.sampleLoopStartIndex = Math.floor(this.sampleLoopStartIndex * ratio); |
|
|
this.sampleLoopEndIndex = Math.floor(this.sampleLoopEndIndex * ratio); |
|
|
this.sampleData = audioData; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
compressSample(quality, encodeVorbis) |
|
|
{ |
|
|
|
|
|
if (this.isCompressed) |
|
|
{ |
|
|
return; |
|
|
} |
|
|
|
|
|
try |
|
|
{ |
|
|
|
|
|
let audioData = this.getAudioData(); |
|
|
if (this.sampleRate < 8000 || this.sampleRate > 96000) |
|
|
{ |
|
|
this.resampleData(RESAMPLE_RATE); |
|
|
audioData = this.getAudioData(); |
|
|
} |
|
|
this.compressedData = encodeVorbis([audioData], 1, this.sampleRate, quality); |
|
|
|
|
|
this.sampleType |= 0x10; |
|
|
this.isCompressed = true; |
|
|
} |
|
|
catch (e) |
|
|
{ |
|
|
SpessaSynthWarn(`Failed to compress ${this.sampleName}. Leaving as uncompressed!`); |
|
|
this.isCompressed = false; |
|
|
this.compressedData = undefined; |
|
|
|
|
|
this.sampleType &= 0xEF; |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getAudioData() |
|
|
{ |
|
|
return this.sampleData; |
|
|
} |
|
|
} |